public static MutableString GetSubstring(ConversionStorage<int>/*!*/ fixnumCast, RubyContext/*!*/ context, MutableString/*!*/ self, [NotNull]Range/*!*/ range) { int begin = Protocols.CastToFixnum(fixnumCast, context, range.Begin); int end = Protocols.CastToFixnum(fixnumCast, context, range.End); begin = NormalizeIndex(self, begin); if (begin < 0 || begin > self.Length) { return null; } end = NormalizeIndex(self, end); int count = range.ExcludeEnd ? end - begin : end - begin + 1; return (count < 0) ? self.CreateInstance().TaintBy(self) : GetSubstring(self, begin, count); }
public static MutableString GetSubstring(RubyContext/*!*/ context, MutableString/*!*/ self, [NotNull]Range/*!*/ range) { bool excludeEnd; int begin, end; Protocols.ConvertToIntegerRange(context, range, out begin, out end, out excludeEnd); begin = NormalizeIndex(self, begin); if (begin < 0 || begin > self.Length) { return null; } end = NormalizeIndex(self, end); int count = excludeEnd ? end - begin : end - begin + 1; return (count < 0) ? self.CreateInstance().TaintBy(self) : GetSubstring(self, begin, count); }
public static MutableString GetSubstring(RubyScope/*!*/ scope, MutableString/*!*/ self, [NotNull]RubyRegex/*!*/ regex, [DefaultProtocol]int occurrance) { if (regex.IsEmpty) { return self.CreateInstance().TaintBy(self).TaintBy(regex, scope); } Group group = MatchRegexp(scope, self, regex, occurrance); if (group == null || !group.Success) { return null; } return self.CreateInstance().Append(group.Value).TaintBy(self).TaintBy(regex, scope); }
public static MutableString/*!*/ Repeat(MutableString/*!*/ self, [DefaultProtocol]int times) { if (times < 0) { throw RubyExceptions.CreateArgumentError("negative argument"); } MutableString result = self.CreateInstance().TaintBy(self); for (int i = 0; i < times; i++) { result.Append(self); } return result; }
public static MutableString RemoveSubstringInPlace(RubyContext/*!*/ context, MutableString/*!*/ self, [NotNull]Range/*!*/ range) { bool excludeEnd; int begin, end; Protocols.ConvertToIntegerRange(context, range, out begin, out end, out excludeEnd); if (!InInclusiveRangeNormalized(self, ref begin)) { return null; } end = NormalizeIndex(self, end); int count = excludeEnd ? end - begin : end - begin + 1; return count < 0 ? self.CreateInstance() : RemoveSubstringInPlace(self, begin, count); }
private static RubyArray/*!*/ WhitespaceSplit(MutableString/*!*/ self, int maxComponents) { char[] separators = new char[] { ' ', '\n', '\r', '\t', '\v' }; MutableString[] elements = self.Split(separators, (maxComponents < 0) ? Int32.MaxValue : maxComponents, StringSplitOptions.RemoveEmptyEntries); RubyArray result = new RubyArray(); foreach (MutableString element in elements) { result.Add(self.CreateInstance().Append(element).TaintBy(self)); } // Strange behavior to match Ruby semantics if (maxComponents < 0) { result.Add(self.CreateInstance().TaintBy(self)); } return result; }
private static MutableString/*!*/ TrInternal(MutableString/*!*/ self, [DefaultProtocol, NotNull]MutableString/*!*/ from, [DefaultProtocol, NotNull]MutableString/*!*/ to, bool squeeze) { MutableString result = self.CreateInstance().TaintBy(self); IntervalParser parser = new IntervalParser(from); // TODO: a single pass to generate both? MutableString source = parser.ParseSequence(); BitArray bitmap = parser.Parse(); MutableString dest = new IntervalParser(to).ParseSequence(); int lastChar = dest.GetLastChar(); char? lastTranslated = null; for (int i = 0; i < self.Length; i++) { char c = self.GetChar(i); if (bitmap.Get(c)) { char? thisTranslated = null; int index = source.IndexOf(c); if (index >= dest.Length) { if (lastChar != -1) { thisTranslated = (char)lastChar; } } else { thisTranslated = dest.GetChar(index); } if (thisTranslated != null && (!squeeze || lastTranslated == null || lastTranslated.Value != thisTranslated)) { result.Append(thisTranslated.Value); } lastTranslated = thisTranslated; } else { result.Append(c); lastTranslated = null; } } return result; }
public static MutableString GetSubstring(MutableString/*!*/ self, [DefaultProtocol]int start, [DefaultProtocol]int count) { int byteCount = self.GetByteCount(); if (!NormalizeSubstringRange(byteCount, ref start, ref count)) { return (start == byteCount) ? self.CreateInstance().TaintBy(self) : null; } return self.CreateInstance().Append(self, start, count).TaintBy(self); }
public static MutableString GetSubstring(ConversionStorage<int>/*!*/ fixnumCast, MutableString/*!*/ self, [NotNull]Range/*!*/ range) { int begin, count; if (!NormalizeSubstringRange(fixnumCast, range, self.GetByteCount(), out begin, out count)) { return null; } return (count < 0) ? self.CreateInstance().TaintBy(self) : GetSubstring(self, begin, count); }
public static MutableString/*!*/ Repeat(MutableString/*!*/ self, [DefaultProtocol]int times) { if (times < 0) { throw RubyExceptions.CreateArgumentError("negative argument"); } return self.CreateInstance().TaintBy(self).AppendMultiple(self, times); }
public static MutableString RemoveSubstringInPlace(ConversionStorage<int>/*!*/ fixnumCast, MutableString/*!*/ self, [NotNull]Range/*!*/ range) { int begin = Protocols.CastToFixnum(fixnumCast, range.Begin); int end = Protocols.CastToFixnum(fixnumCast, range.End); if (!InInclusiveRangeNormalized(self, ref begin)) { return null; } end = IListOps.NormalizeIndex(self.Length, end); int count = range.ExcludeEnd ? end - begin : end - begin + 1; return count < 0 ? self.CreateInstance() : RemoveSubstringInPlace(self, begin, count); }
internal static MutableString/*!*/ Translate(MutableString/*!*/ src, MutableString/*!*/ from, MutableString/*!*/ to, bool inplace, bool squeeze, out bool anyCharacterMaps) { Assert.NotNull(src, from, to); if (from.IsEmpty) { anyCharacterMaps = false; return inplace ? src : src.Clone(); } MutableString dst; if (inplace) { dst = src; } else { dst = src.CreateInstance().TaintBy(src); } // TODO: KCODE src.RequireCompatibleEncoding(from); dst.RequireCompatibleEncoding(to); from.SwitchToCharacters(); to.SwitchToCharacters(); CharacterMap map = CharacterMap.Create(from, to); if (to.IsEmpty) { anyCharacterMaps = MutableString.TranslateRemove(src, dst, map); } else if (squeeze) { anyCharacterMaps = MutableString.TranslateSqueeze(src, dst, map); } else { anyCharacterMaps = MutableString.Translate(src, dst, map); } return dst; }
// returns true if block jumped // "result" will be null if there is no successful match private static bool BlockReplaceAll(ConversionStorage<MutableString>/*!*/ tosConversion, RubyScope/*!*/ scope, MutableString/*!*/ input, BlockParam/*!*/ block, RubyRegex/*!*/ regex, out object blockResult, out MutableString result) { var matchScope = scope.GetInnerMostClosureScope(); var matches = regex.Matches(tosConversion.Context.KCode, input); if (matches.Count == 0) { result = null; blockResult = null; matchScope.CurrentMatch = null; return false; } // create an empty result: result = input.CreateInstance().TaintBy(input); int offset = 0; foreach (MatchData match in matches) { matchScope.CurrentMatch = match; input.TrackChanges(); if (block.Yield(match.GetValue(), out blockResult)) { return true; } if (input.HasChanged) { return false; } // resets the $~ scope variable to the last match (skipd if block jumped): matchScope.CurrentMatch = match; MutableString replacement = Protocols.ConvertToString(tosConversion, blockResult); result.TaintBy(replacement); // prematch: result.Append(input, offset, match.Index - offset); // replacement (unlike ReplaceAll, don't interpolate special sequences like \1 in block return value): result.Append(replacement); offset = match.Index + match.Length; } // post-last-match: result.Append(input, offset, input.Length - offset); blockResult = null; return false; }
public static MutableString/*!*/ Dump(RubyContext/*!*/ context, MutableString/*!*/ self) { // Note that "self" could be a subclass of MutableString, and the return value should be // of the same type return self.CreateInstance().Append(GetQuotedStringRepresentation(self, context, true, '"')).TaintBy(self); }
private static MutableString/*!*/ InternalDelete(MutableString/*!*/ self, MutableString[]/*!*/ ranges) { BitArray map = new RangeParser(ranges).Parse(); MutableString result = self.CreateInstance().TaintBy(self); for (int i = 0; i < self.Length; i++) { if (!map.Get(self.GetChar(i))) { result.Append(self.GetChar(i)); } } return result; }
public static MutableString GetSubstring(RubyScope/*!*/ scope, MutableString/*!*/ self, [NotNull]RubyRegex/*!*/ regex, [DefaultProtocol]int occurrance) { if (regex.IsEmpty) { return self.CreateInstance().TaintBy(self).TaintBy(regex, scope); } MatchData match = RegexpOps.Match(scope, regex, self); if (match == null || !RegexpOps.NormalizeGroupIndex(ref occurrance, match.GroupCount)) { return null; } MutableString result = match.AppendGroupValue(occurrance, self.CreateInstance()); return result != null ? result.TaintBy(regex, scope) : null; }
private static RubyArray/*!*/ MakeRubyArray(MutableString/*!*/ self, MutableString[]/*!*/ elements, int start, int count) { RubyArray result = new RubyArray(elements.Length); for (int i = 0; i < count; i++) { result.Add(self.CreateInstance().Append(elements[start + i]).TaintBy(self)); } return result; }
public static MutableString/*!*/ Chop(MutableString/*!*/ self) { return (self.Length == 0) ? self.CreateInstance().TaintBy(self) : ChopInteral(self.Clone()); }
private static RubyArray/*!*/ InternalSplit(MutableString/*!*/ self, MutableString separator, StringSplitOptions options, int maxComponents) { if (separator == null || separator.Length == 1 && separator.GetChar(0) == ' ') { return WhitespaceSplit(self, maxComponents); } if (maxComponents <= 0) { maxComponents = Int32.MaxValue; } RubyArray result = new RubyArray(maxComponents == Int32.MaxValue ? 1 : maxComponents + 1); bool keepEmpty = (options & StringSplitOptions.RemoveEmptyEntries) != StringSplitOptions.RemoveEmptyEntries; int selfLength = self.Length; int i = 0; int next; while (maxComponents > 1 && i < selfLength && (next = IndexOf(self, separator, i)) != -1) { if (next > i || keepEmpty) { result.Add(self.CreateInstance().Append(self, i, next - i).TaintBy(self)); maxComponents--; } i = next + separator.Length; } if (i < selfLength || keepEmpty) { result.Add(self.CreateInstance().Append(self, i, selfLength - i).TaintBy(self)); } return result; }
public static MutableString/*!*/ Dump(RubyContext/*!*/ context, MutableString/*!*/ self) { StringBuilder result = new StringBuilder(); result.Append('"'); byte[] bytes = self.ToByteArray(); for (int i = 0; i < bytes.Length; i++) { AppendStringRepresentationOfChar(result, bytes[i], i + 1 < bytes.Length ? bytes[i + 1] : -1, true); } result.Append('"'); return self.CreateInstance().Append(result).TaintBy(self); }
public static MutableString/*!*/ RightJustify(MutableString/*!*/ self, [DefaultProtocol]int width, [DefaultProtocol, NotNull]MutableString/*!*/ padding) { if (padding.Length == 0) { throw RubyExceptions.CreateArgumentError("zero width padding"); } int count = width - self.Length; if (count <= 0) { return self; } int iterations = count / padding.Length; int remainder = count % padding.Length; MutableString result = self.CreateInstance().TaintBy(self).TaintBy(padding); for (int i = 0; i < iterations; i++) { result.Append(padding); } result.Append(padding.GetSlice(0, remainder)); result.Append(self); return result; }
public static object EachLine(BlockParam block, MutableString/*!*/ self, [DefaultProtocol]MutableString/*!*/ separator) { if (separator == null) { separator = MutableString.Empty; } uint version = self.Version; MutableString paragraphSeparator; if (separator.IsEmpty) { separator = _DefaultLineSeparator; paragraphSeparator = _DefaultDoubleLineSeparator; } else { paragraphSeparator = null; } // TODO: this is slow, refactor when we redo MutableString MutableString str = self; int start = 0; // In "normal" mode just split the string at the end of each seperator occurrance. // In "paragraph" mode, split the string at the end of each occurrance of two or more // successive seperators. while (start < self.Length) { int end; if (paragraphSeparator == null) { end = str.IndexOf(separator, start); if (end >= 0) { end += separator.Length; } else { end = str.Length; } } else { end = str.IndexOf(paragraphSeparator, start); if (end >= 0) { end += (2 * separator.Length); while (str.IndexOf(separator, end) == end) { end += separator.Length; } } else { end = str.Length; } } // Yield the current line if (block == null) { throw RubyExceptions.NoBlockGiven(); } object result; MutableString line = self.CreateInstance().TaintBy(self).Append(str, start, end - start); if (block.Yield(line, out result)) { return result; } start = end; } // Ensure that the underlying string has not been mutated during the iteration RequireNoVersionChange(version, self); return self; }
public static MutableString RemoveSubstringInPlace(MutableString/*!*/ self, [DefaultProtocol]int start, [DefaultProtocol]int length) { if (length < 0) { return null; } if (!InInclusiveRangeNormalized(self, ref start)) { return null; } if (start + length > self.Length) { length = self.Length - start; } MutableString result = self.CreateInstance().Append(self, start, length).TaintBy(self); self.Remove(start, length); return result; }
// returns true if block jumped // "result" will be null if there is no successful match private static bool BlockReplaceAll(RubyScope/*!*/ scope, MutableString/*!*/ input, BlockParam/*!*/ block, RubyRegex/*!*/ regex, out object blockResult, out MutableString result) { var matchScope = scope.GetInnerMostClosureScope(); MatchCollection matches = regex.Matches(input); if (matches.Count == 0) { result = null; blockResult = null; matchScope.CurrentMatch = null; return false; } // create an empty result: result = input.CreateInstance().TaintBy(input); int offset = 0; foreach (Match match in matches) { MatchData currentMatch = new MatchData(match, input); matchScope.CurrentMatch = currentMatch; uint version = input.Version; if (block.Yield(MutableString.Create(match.Value), out blockResult)) { return true; } if (input.Version != version) { return false; } // resets the $~ scope variable to the last match (skipd if block jumped): matchScope.CurrentMatch = currentMatch; MutableString replacement = Protocols.ConvertToString(scope.RubyContext, blockResult); result.TaintBy(replacement); // prematch: result.Append(input, offset, match.Index - offset); // replacement (unlike ReplaceAll, don't interpolate special sequences like \1 in block return value): result.Append(replacement); offset = match.Index + match.Length; } // post-last-match: result.Append(input, offset, input.Length - offset); blockResult = null; return false; }
public static MutableString GetSubstring(MutableString/*!*/ self, [DefaultProtocol]int start, [DefaultProtocol]int length) { start = NormalizeIndex(self, start); if (start == self.Length) { return self.CreateInstance().TaintBy(self); } if (start < 0 || start > self.Length || length < 0) { return null; } if (start + length > self.Length) { length = self.Length - start; } return self.CreateInstance().Append(self, start, length).TaintBy(self); }
private static MutableString ReplaceFirst(RubyScope/*!*/ scope, MutableString/*!*/ input, MutableString/*!*/ replacement, RubyRegex/*!*/ pattern) { MatchData match = RegexpOps.Match(scope, pattern, input); if (match == null || !match.Success) { return null; } MutableString result = input.CreateInstance().TaintBy(input).TaintBy(replacement); // prematch: result.Append(input, 0, match.Index); AppendReplacementExpression(input, match, result, replacement); // postmatch: int offset = match.Index + match.Length; result.Append(input, offset, input.Length - offset); return result; }
public static MutableString GetSubstring(RubyScope/*!*/ scope, MutableString/*!*/ self, [NotNull]RubyRegex/*!*/ regex) { if (regex.IsEmpty) { return self.CreateInstance().TaintBy(self).TaintBy(regex, scope); } MatchData match = RegexpOps.Match(scope, regex, self); if (match == null) { return null; } string result = match.Value; return (result.Length == 0) ? null : self.CreateInstance().TaintBy(self).Append(result).TaintBy(regex, scope); }
private static MutableString ReplaceAll(RubyScope/*!*/ scope, MutableString/*!*/ input, MutableString/*!*/ replacement, RubyRegex/*!*/ regex) { var matchScope = scope.GetInnerMostClosureScope(); // case of all MatchCollection matches = regex.Matches(input); if (matches.Count == 0) { matchScope.CurrentMatch = null; return null; } MutableString result = input.CreateInstance().TaintBy(input).TaintBy(replacement); int offset = 0; foreach (Match match in matches) { result.Append(input, offset, match.Index - offset); AppendReplacementExpression(input, match, result, replacement); offset = match.Index + match.Length; } result.Append(input, offset, input.Length - offset); matchScope.CurrentMatch = new MatchData(matches[matches.Count - 1], input); return result; }
public static MutableString/*!*/ Center(MutableString/*!*/ self, [DefaultProtocol]int length, [Optional, DefaultProtocol]MutableString padding) { if (padding != null && padding.Length == 0) { throw RubyExceptions.CreateArgumentError("zero width padding"); } if (self.Length >= length) { return self; } if (padding == null) { padding = _DefaultPadding; } char[] charArray = new char[length]; int n = (length - self.Length) / 2; for (int i = 0; i < n; i++) { charArray[i] = padding.GetChar(i % padding.Length); } for (int i = 0; i < self.Length; i++) { charArray[n + i] = self.GetChar(i); } int m = length - self.Length - n; for (int i = 0; i < m; i++) { charArray[n + self.Length + i] = padding.GetChar(i % padding.Length); } return self.CreateInstance().Append(new String(charArray)).TaintBy(self).TaintBy(padding); }
private static RubyArray/*!*/ CharacterSplit(MutableString/*!*/ str, int limit) { RubyArray result = new RubyArray(); var charEnum = str.GetCharacters(); int i = 0; while (limit <= 0 || result.Count < limit - 1) { if (!charEnum.MoveNext()) { break; } result.Add(str.CreateInstance().Append(charEnum.Current).TaintBy(str)); i++; } if (charEnum.HasMore || limit < 0) { result.Add(str.CreateInstance().AppendRemaining(charEnum).TaintBy(str)); } return result; }