delete: $/Dev10/feature/vs_langs01_s/Merlin/External.LCA_RESTRICTED/Languages/IronRuby/mspec/ironruby-tags/core/string/inspect_tags.txt;C807294 File: inspect_tags.txt =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/External.LCA_RESTRICTED/Languages/IronRuby/mspec/ironruby-tags/core/string/inspect_tags.txt;C807294 (server) 12/3/2009 5:57 PM +++ [no target file] @@ -1,2 +1,0 @@ -fails:String#inspect produces different output based on $KCODE -fails:String#inspect can handle malformed UTF-8 string when $KCODE is UTF-8 =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C1305319 File: RubyTests.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;C1305319 (server) 11/24/2009 5:51 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/RubyTests.cs;InspectAppendCompareTo @@ -28,8 +28,11 @@ MutableString_GetHashCode, MutableString_IsAscii, MutableString_Length, + MutableString_CompareTo, + MutableString_Equals, MutableString_Append_Byte, MutableString_Append_Char, + MutableString_Append, MutableString_Insert_Byte, MutableString_Insert_Char, MutableString_Remove_Byte, =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/MutableStringTests.cs;C1301388 File: MutableStringTests.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/MutableStringTests.cs;C1301388 (server) 12/2/2009 6:51 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/MutableStringTests.cs;InspectAppendCompareTo @@ -164,6 +164,84 @@ } [Options(NoRuntime = true)] + public void MutableString_CompareTo() { + MutableString x, y; + RubyEncoding SJIS = RubyEncoding.GetRubyEncoding("SJIS"); + + // invalid bytes <=> valid string: + var invalid = new byte[] { 0xe2, 0x85, 0x9c, 0xef }; + var alpha = new byte[] { 0xce, 0xb1 }; + + x = MS(invalid, RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(Math.Sign(x.CompareTo(y)) == Math.Sign(0xe2 - 0xce)); + + x = MS(invalid, RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(Math.Sign(y.CompareTo(x)) == Math.Sign(0xce - 0xe2)); + + x = MS(invalid, RubyEncoding.UTF8); + y = MS(invalid, RubyEncoding.UTF8); + Assert(x.CompareTo(y) == 0); + + x = MS("a", RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(x.CompareTo(y) == 0); + + // encodings orderd by code-page: + Assert(Math.Sign(RubyEncoding.UTF8.CompareTo(SJIS)) == 1); + + // difference in encodings is ignored if both strings are ascii: + x = MS("a", RubyEncoding.UTF8); + y = MS(new byte[] { (byte)'b' }, SJIS); + Assert(Math.Sign(x.CompareTo(y)) == -1); + + // difference in encodings is ignored if both strings are ascii: + x = MS("a", RubyEncoding.UTF8); + y = MS("a", SJIS); + Assert(Math.Sign(x.CompareTo(y)) == Math.Sign(RubyEncoding.UTF8.CompareTo(SJIS))); + + x = MS(new byte[] { (byte)'a' }, RubyEncoding.UTF8); + y = MS("a", SJIS); + Assert(Math.Sign(x.CompareTo(y)) == Math.Sign(RubyEncoding.UTF8.CompareTo(SJIS))); + + x = MS("a", RubyEncoding.UTF8); + y = MS("a", SJIS); + Assert(Math.Sign(x.CompareTo(y)) == Math.Sign(RubyEncoding.UTF8.CompareTo(SJIS))); + + // k-codings (the string represnetation might be the same, but their binary repr is different): + x = MS("a", RubyEncoding.KCodeUTF8); + y = MS("a", RubyEncoding.KCodeSJIS); + Assert(Math.Sign(x.CompareTo(y)) != 0); + + // same binary repr, different string repr: + x = MS(alpha, RubyEncoding.KCodeUTF8); + y = MS(alpha, RubyEncoding.KCodeSJIS); + Assert(Math.Sign(x.CompareTo(y)) == 0); + Assert(x.ToString() == "a"); + Assert(y.ToString() == "??"); + + x = MS("a", RubyEncoding.KCodeUTF8); + y = MS(BinaryEncoding.Instance.GetString(alpha), RubyEncoding.Binary); + Assert(Math.Sign(x.CompareTo(y)) == 0); + } + + [Options(NoRuntime = true)] + public void MutableString_Equals() { + byte[] bytes = Encoding.UTF8.GetBytes("a"); + + MutableString a, b, c, d; + a = MutableString.CreateBinary(bytes, RubyEncoding.Binary); + b = MutableString.CreateBinary(bytes, RubyEncoding.KCodeSJIS); + c = MutableString.CreateBinary(bytes, RubyEncoding.KCodeUTF8); + d = MutableString.Create("a", RubyEncoding.KCodeUTF8); + + Assert(a.Equals(b)); + Assert(a.Equals(c)); + Assert(a.Equals(d)); + } + + [Options(NoRuntime = true)] public void MutableString_Append_Byte() { MutableString x; x = MutableString.CreateBinary(new byte[] { 1, 2 }); @@ -244,6 +322,44 @@ } [Options(NoRuntime = true)] + public void MutableString_Append() { + MutableString x, y; + + // Appending Unicode string literal to a string doesn't check correctness of the resulting string. + // An exception is thrown during subssequent operation that needs to convert the content. + x = MS(((char)250).ToString(), RubyEncoding.Binary); + x.Append('a'); + AssertExceptionThrown(() => x.ToByteArray()); + + // invalid bytes + valid string -> invalid bytes, but not an error: + var invalid_utf8 = new byte[] { 0xe2, 0x85, 0x9c, 0xef }; + var valid_utf8 = Encoding.UTF8.GetBytes("a"); + + x = MS(invalid_utf8, RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(x.Append(y).ToByteArray().ValueEquals(ArrayUtils.AppendRange(invalid_utf8, valid_utf8))); + + x = MS(invalid_utf8, RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(y.Append(x).ToByteArray().ValueEquals(ArrayUtils.AppendRange(valid_utf8, invalid_utf8))); + + x = MS(invalid_utf8, RubyEncoding.UTF8); + Assert(x.Append(x).ToByteArray().ValueEquals(ArrayUtils.AppendRange(invalid_utf8, invalid_utf8))); + + + x = MS(invalid_utf8, RubyEncoding.UTF8); + y = MS("ßa?", RubyEncoding.UTF8); + Assert(x.Append(y, 1, 1).ToByteArray().ValueEquals(ArrayUtils.AppendRange(invalid_utf8, valid_utf8))); + + x = MS(invalid_utf8, RubyEncoding.UTF8); + y = MS("a", RubyEncoding.UTF8); + Assert(y.Append(x, 1, 2).ToByteArray().ValueEquals(ArrayUtils.AppendRange(valid_utf8, new byte[] { 0x85, 0x9c }))); + + x = MS(invalid_utf8, RubyEncoding.UTF8); + Assert(x.Append(x, 1, 2).ToByteArray().ValueEquals(ArrayUtils.AppendRange(invalid_utf8, new byte[] { 0x85, 0x9c }))); + } + + [Options(NoRuntime = true)] public void MutableString_Insert_Byte() { MutableString x; x = MutableString.CreateBinary(new byte[] { 1, 2 }); @@ -283,6 +399,12 @@ Assert(x.CompareTo(MS("83567124", e)) == 0); x.Insert(5, MS("9?", e)); Assert(x.CompareTo(MS("835679?124", e)) == 0); + + // Inserting Unicode string literal to a string doesn't check correctness of the resulting string. + // An exception is thrown during subssequent operation that needs to convert the content. + x = MS(((char)250).ToString(), RubyEncoding.Binary); + x.Insert(0, 'a'); + AssertExceptionThrown(() => x.ToByteArray()); } [Options(NoRuntime = true)] @@ -792,31 +914,31 @@ StringBuilder cs; cs = new StringBuilder(); - foreach (char c in MS("aß", RubyEncoding.UTF8).Characters) { + foreach (char c in MS("aß", RubyEncoding.UTF8).GetCharacters()) { cs.Append(c); } Assert(cs.ToString() == "aß"); cs = new StringBuilder(); - foreach (char c in MS(Encoding.UTF8.GetBytes("aß"), RubyEncoding.UTF8).Characters) { + foreach (char c in MS(Encoding.UTF8.GetBytes("aß"), RubyEncoding.UTF8).GetCharacters()) { cs.Append(c); } Assert(cs.ToString() == "aß"); cs = new StringBuilder(); - foreach (char c in MS("a", RubyEncoding.UTF8).Append('ß').Characters) { + foreach (char c in MS("a", RubyEncoding.UTF8).Append('ß').GetCharacters()) { cs.Append(c); } Assert(cs.ToString() == "aß"); cs = new StringBuilder(); - foreach (char c in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.UTF8).Characters) { + foreach (char c in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.UTF8).GetCharacters()) { cs.Append(c); } Assert(cs.ToString() == "ab"); cs = new StringBuilder(); - foreach (char c in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.Binary).Characters) { + foreach (char c in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.Binary).GetCharacters()) { cs.Append(c); } Assert(cs.ToString() == "ab"); @@ -827,31 +949,31 @@ List bs; bs = new List(); - foreach (byte b in MS("aß", RubyEncoding.UTF8).Bytes) { + foreach (byte b in MS("aß", RubyEncoding.UTF8).GetBytes()) { bs.Add(b); } Assert(bs.ToArray().ValueEquals(Encoding.UTF8.GetBytes("aß"))); bs = new List(); - foreach (byte b in MS(Encoding.UTF8.GetBytes("aß"), RubyEncoding.UTF8).Bytes) { + foreach (byte b in MS(Encoding.UTF8.GetBytes("aß"), RubyEncoding.UTF8).GetBytes()) { bs.Add(b); } Assert(bs.ToArray().ValueEquals(Encoding.UTF8.GetBytes("aß"))); bs = new List(); - foreach (byte b in MS("a", RubyEncoding.UTF8).Append('ß').Bytes) { + foreach (byte b in MS("a", RubyEncoding.UTF8).Append('ß').GetBytes()) { bs.Add(b); } Assert(bs.ToArray().ValueEquals(Encoding.UTF8.GetBytes("aß"))); bs = new List(); - foreach (byte b in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.UTF8).Bytes) { + foreach (byte b in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.UTF8).GetBytes()) { bs.Add(b); } Assert(bs.ToArray().ValueEquals(new byte[] { (byte)'a', (byte)'b' })); bs = new List(); - foreach (byte b in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.Binary).Bytes) { + foreach (byte b in MS(Encoding.UTF8.GetBytes("ab"), RubyEncoding.Binary).GetBytes()) { bs.Add(b); } Assert(bs.ToArray().ValueEquals(new byte[] { (byte)'a', (byte)'b' })); =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/StringTests.cs;C966724 File: StringTests.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/StringTests.cs;C966724 (server) 12/2/2009 6:35 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/IronRuby.Tests/Runtime/StringTests.cs;InspectAppendCompareTo @@ -263,16 +263,28 @@ s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(utf8, RubyEncoding.Binary), Context, true, sq).ToString(); Assert(s == @"'\360\222\215\205'"); + Context.KCode = RubyEncoding.KCodeUTF8; s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(utf8, RubyEncoding.KCodeUTF8), Context, false, sq).ToString(); Assert(s == "'" + utf16 + "'"); + Context.KCode = RubyEncoding.KCodeUTF8; + s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(utf8, RubyEncoding.KCodeSJIS), Context, false, sq).ToString(); + Assert(s == "'" + utf16 + "'"); + + Context.KCode = RubyEncoding.KCodeUTF8; s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(utf8, RubyEncoding.KCodeUTF8), Context, true, sq).ToString(); Assert(s == @"'\360\222\215\205'"); + Context.KCode = RubyEncoding.KCodeSJIS; s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(sjisWide, RubyEncoding.KCodeSJIS), Context, false, sq).ToString(); Assert(s == @"'?'"); - s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(sjisWide, RubyEncoding.KCodeSJIS), Context, true, sq).ToString(); + Context.KCode = RubyEncoding.KCodeSJIS; + s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(sjisWide, RubyEncoding.Binary), Context, false, sq).ToString(); + Assert(s == @"'?'"); + + Context.KCode = RubyEncoding.KCodeSJIS; + s = MutableStringOps.GetQuotedStringRepresentation(MutableString.CreateBinary(sjisWide, RubyEncoding.KCodeUTF8), Context, true, sq).ToString(); Assert(s == @"'\202\240'"); } =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/BigDecimal/BigDecimalOps.cs;C1286631 File: BigDecimalOps.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/BigDecimal/BigDecimalOps.cs;C1286631 (server) 12/3/2009 3:00 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/BigDecimal/BigDecimalOps.cs;InspectAppendCompareTo @@ -294,9 +294,9 @@ [RubyMethod("inspect")] public static MutableString/*!*/ Inspect(RubyContext/*!*/ context, BigDecimal/*!*/ self) { MutableString str = MutableString.CreateMutable(RubyEncoding.ClassName); - str.AppendFormat(CultureInfo.InvariantCulture, "#<{0}:", context.GetClassOf(self).Name); + str.AppendFormat("#<{0}:", context.GetClassOf(self).Name); RubyUtils.AppendFormatHexObjectId(str, RubyUtils.GetObjectId(context, self)); - str.AppendFormat(CultureInfo.InvariantCulture, ",'{0}',{1}({2})>", + str.AppendFormat(",'{0}',{1}({2})>", self.ToString(10), self.PrecisionDigits, self.MaxPrecisionDigits =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;C1300588 File: MutableStringOps.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;C1300588 (server) 12/2/2009 6:16 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/MutableStringOps.cs;InspectAppendCompareTo @@ -1070,11 +1070,14 @@ #region dump, inspect - public static string/*!*/ GetQuotedStringRepresentation(MutableString/*!*/ self, RubyContext/*!*/ context, bool forceEscapes, char quote) { + public static string/*!*/ GetQuotedStringRepresentation(MutableString/*!*/ self, RubyContext/*!*/ context, bool isDump, char quote) { + bool is18 = context.RubyOptions.Compatibility == RubyCompatibility.Ruby18; + return self.AppendRepresentation( - new StringBuilder().Append(quote), - context.RubyOptions.Compatibility == RubyCompatibility.Ruby18, - forceEscapes, + new StringBuilder().Append(quote), + (isDump || !is18) ? null : context.KCode ?? RubyEncoding.Binary, + is18, + isDump, quote ).Append(quote).ToString(); } @@ -1087,12 +1090,12 @@ return self.CreateInstance().Append(GetQuotedStringRepresentation(self, context, true, '"')).TaintBy(self); } - // encoding aware + // encoding aware, uses the current KCODE [RubyMethod("inspect")] public static MutableString/*!*/ Inspect(RubyContext/*!*/ context, MutableString/*!*/ self) { // Note that "self" could be a subclass of MutableString, but the return value should // always be just a MutableString - return MutableString.Create(GetQuotedStringRepresentation(self, context, false, '"'), self.Encoding).TaintBy(self); + return MutableString.Create(GetQuotedStringRepresentation(self, context, false, '"'), context.KCode ?? self.Encoding).TaintBy(self); } #endregion @@ -1920,22 +1923,25 @@ int nextIndex = GetIndexOfRightmostAlphaNumericCharacter(str, index - 1); if (c == 'z') { str.SetChar(index, 'a'); - if (nextIndex == -1) - str.Insert(index, "a"); - else + if (nextIndex == -1) { + str.Insert(index, 'a'); + } else { IncrementAlphaNumericChar(str, nextIndex); + } } else if (c == 'Z') { str.SetChar(index, 'A'); - if (nextIndex == -1) - str.Insert(index, "A"); - else + if (nextIndex == -1) { + str.Insert(index, 'A'); + } else { IncrementAlphaNumericChar(str, nextIndex); + } } else { str.SetChar(index, '0'); - if (nextIndex == -1) - str.Insert(index, "1"); - else + if (nextIndex == -1) { + str.Insert(index, '1'); + } else { IncrementAlphaNumericChar(str, nextIndex); + } } } else { IncrementChar(str, index); =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/RubyTime.cs;C1301388 File: RubyTime.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/RubyTime.cs;C1301388 (server) 12/2/2009 6:50 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/Builtins/RubyTime.cs;InspectAppendCompareTo @@ -852,7 +852,7 @@ MutableString result = MutableString.CreateMutable(format.Encoding); bool inFormat = false; - foreach (char c in format.Characters) { + foreach (char c in format.GetCharacters()) { if (!inFormat) { if (c == '%') { inFormat = true; @@ -914,7 +914,7 @@ break; case 'j': - result.AppendFormat(CultureInfo.InvariantCulture, "{0:000}", self.DateTime.DayOfYear); + result.AppendFormat("{0:000}", self.DateTime.DayOfYear); break; case 'l': { @@ -1018,7 +1018,7 @@ DateTime firstDay = dateTime.AddDays(1 - dateTime.DayOfYear); DateTime firstSunday = firstDay.AddDays((start - (int)firstDay.DayOfWeek) % 7); int week = 1 + (int)Math.Floor((dateTime - firstSunday).Days / 7.0); - result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}", week); + result.AppendFormat("{0:00}", week); } #endregion =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/OpenSSL/OpenSSL.cs;C1299354 File: OpenSSL.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/OpenSSL/OpenSSL.cs;C1299354 (server) 12/3/2009 3:00 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Libraries.LCA_RESTRICTED/OpenSSL/OpenSSL.cs;InspectAppendCompareTo @@ -362,7 +362,7 @@ return result.Append(":...>"); } bool empty = self._certificate.Handle == IntPtr.Zero; - result.AppendFormat(CultureInfo.InvariantCulture, " subject={0}, issuer={1}, serial={2}, not_before=nil, not_after=nil>", + result.AppendFormat(" subject={0}, issuer={1}, serial={2}, not_before=nil, not_after=nil>", empty ? "" : OpenSSLFormat(self._certificate.Subject), empty ? "" : OpenSSLFormat(self._certificate.Issuer), empty ? 0 : self.SerailNumber =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.BinaryContent.cs;C1301388 File: MutableString.BinaryContent.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.BinaryContent.cs;C1301388 (server) 12/3/2009 2:00 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.BinaryContent.cs;InspectAppendCompareTo @@ -75,6 +75,14 @@ } } + internal void AppendBytes(string/*!*/ str, int start, int count) { + _count = Utils.Append(ref _data, _count, str, start, count, _owner._encoding.StrictEncoding); + } + + internal void AppendBytes(char[]/*!*/ chars, int start, int count) { + _count = Utils.Append(ref _data, _count, chars, start, count, _owner._encoding.StrictEncoding); + } + #region GetHashCode, Length, Clone (read-only), Count public override bool IsBinary { @@ -186,18 +194,35 @@ #region CompareTo (read-only) - public override int CompareTo(string/*!*/ str) { - return SwitchToChars().CompareTo(str); + public override int OrdinalCompareTo(string/*!*/ str) { + // TODO + return SwitchToChars().OrdinalCompareTo(str); } - public override int CompareTo(byte[]/*!*/ bytes) { - return _data.ValueCompareTo(_count, bytes); + internal int OrdinalCompareTo(byte[]/*!*/ bytes, int count) { + return _data.ValueCompareTo(_count, bytes, count); } - public override int ReverseCompareTo(Content/*!*/ str) { - return str.CompareTo(ToByteArray()); + // this <=> content + public override int OrdinalCompareTo(Content/*!*/ content) { + return content.ReverseOrdinalCompareTo(this); } + // content.bytes <=> this.bytes + public override int ReverseOrdinalCompareTo(BinaryContent/*!*/ content) { + return content.OrdinalCompareTo(_data, _count); + } + + // content.chars <=> this.bytes + public override int ReverseOrdinalCompareTo(CharArrayContent/*!*/ content) { + return content.SwitchToBinary().OrdinalCompareTo(_data, _count); + } + + // content.chars <=> this.bytes + public override int ReverseOrdinalCompareTo(StringContent/*!*/ content) { + return content.SwitchToBinary().OrdinalCompareTo(_data, _count); + } + #endregion #region Slices (read-only) @@ -329,10 +354,38 @@ SwitchToChars().AppendFormat(provider, format, args); } - public override void AppendTo(Content/*!*/ str, int start, int count) { - str.Append(_data, start, count); + // this + content[start, count] + public override void Append(Content/*!*/ content, int start, int count) { + content.AppendTo(this, start, count); } + // content.bytes + this.bytes[start, count] + public override void AppendTo(BinaryContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.Append(_data, start, count); + } + + // content.chars + this.bytes[start, count] + public override void AppendTo(CharArrayContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.SwitchToBinary().Append(_data, start, count); + } + + // content.chars + this.bytes[start, count] + public override void AppendTo(StringContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.SwitchToBinary().Append(_data, start, count); + } + #endregion #region Insert =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.CharArrayContent.cs;C1301388 File: MutableString.CharArrayContent.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.CharArrayContent.cs;C1301388 (server) 12/3/2009 2:05 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.CharArrayContent.cs;InspectAppendCompareTo @@ -44,7 +44,7 @@ _count = count; } - private BinaryContent/*!*/ SwitchToBinary() { + internal BinaryContent/*!*/ SwitchToBinary() { return SwitchToBinary(0); } @@ -187,19 +187,34 @@ #region CompareTo (read-only) - public override int CompareTo(string/*!*/ str) { - // TODO: Ruby compares characters w/o taking locale into account: + public override int OrdinalCompareTo(string/*!*/ str) { return _data.ValueCompareTo(_count, str); } - public override int CompareTo(byte[]/*!*/ bytes) { - return SwitchToBinary().CompareTo(bytes); + internal int OrdinalCompareTo(char[]/*!*/ chars, int count) { + return _data.ValueCompareTo(_count, chars, count); } - public override int ReverseCompareTo(Content/*!*/ str) { - return str.CompareTo(ToString()); + // this <=> content + public override int OrdinalCompareTo(Content/*!*/ content) { + return content.ReverseOrdinalCompareTo(this); } + // content.bytes <=> this.chars + public override int ReverseOrdinalCompareTo(BinaryContent/*!*/ content) { + return SwitchToBinary().ReverseOrdinalCompareTo(content); + } + + // content.chars <=> this.chars + public override int ReverseOrdinalCompareTo(CharArrayContent/*!*/ content) { + return content.OrdinalCompareTo(_data, _count); + } + + // content.chars <=> this.chars + public override int ReverseOrdinalCompareTo(StringContent/*!*/ content) { + return content.OrdinalCompareTo(_data, _count); + } + #endregion #region Slices (read-only) @@ -337,10 +352,38 @@ Append(formatted, 0, formatted.Length); } - public override void AppendTo(Content/*!*/ str, int start, int count) { - str.Append(_data, start, count); + // this + content[start, count] + public override void Append(Content/*!*/ content, int start, int count) { + content.AppendTo(this, start, count); } + // content.bytes + this.chars[start, count] + public override void AppendTo(BinaryContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.AppendBytes(_data, start, count); + } + + // content.chars + this.chars[start, count] + public override void AppendTo(CharArrayContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.Append(_data, start, count); + } + + // content.chars + this.chars[start, count] + public override void AppendTo(StringContent/*!*/ content, int start, int count) { + if (start > _count - count) { + throw new ArgumentOutOfRangeException("start"); + } + + content.Append(_data, start, count); + } + #endregion #region Insert =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.Content.cs;C1301388 File: MutableString.Content.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.Content.cs;C1301388 (server) 12/3/2009 1:41 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.Content.cs;InspectAppendCompareTo @@ -87,9 +87,12 @@ public abstract IEnumerable/*!*/ GetCharacters(); public abstract IEnumerable/*!*/ GetBytes(); - public abstract int CompareTo(string/*!*/ str); - public abstract int CompareTo(byte[]/*!*/ bytes); - public abstract int ReverseCompareTo(Content/*!*/ str); + public abstract int OrdinalCompareTo(string/*!*/ str); + + public abstract int OrdinalCompareTo(Content/*!*/ content); + public abstract int ReverseOrdinalCompareTo(BinaryContent/*!*/ content); + public abstract int ReverseOrdinalCompareTo(CharArrayContent/*!*/ content); + public abstract int ReverseOrdinalCompareTo(StringContent/*!*/ content); // the owner of the result is the current owner: public abstract Content/*!*/ GetSlice(int start, int count); @@ -113,8 +116,12 @@ public abstract void Append(char[]/*!*/ chars, int start, int count); public abstract void Append(byte[]/*!*/ bytes, int start, int count); public abstract void Append(Stream/*!*/ stream, int count); - public abstract void AppendTo(Content/*!*/ str, int start, int count); + public abstract void Append(Content/*!*/ content, int start, int count); + public abstract void AppendTo(BinaryContent/*!*/ content, int start, int count); + public abstract void AppendTo(CharArrayContent/*!*/ content, int start, int count); + public abstract void AppendTo(StringContent/*!*/ content, int start, int count); + public abstract void AppendFormat(IFormatProvider provider, string/*!*/ format, object[]/*!*/ args); public abstract void Insert(int index, char c); =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.cs;C1301388 File: MutableString.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.cs;C1301388 (server) 12/2/2009 6:21 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.cs;InspectAppendCompareTo @@ -21,6 +21,7 @@ using IronRuby.Compiler; using IronRuby.Runtime; using Microsoft.Scripting.Utils; +using System.Globalization; namespace IronRuby.Builtins { @@ -661,35 +662,57 @@ #endregion - #region Comparisons (read-only) (TODO: Encodings) + #region Comparisons (read-only) - public static bool operator ==(MutableString self, MutableString other) { - return Equals(self, other); - } - - public static bool operator !=(MutableString self, MutableString other) { - return !Equals(self, other); - } - - private static bool Equals(MutableString self, MutableString other) { - if (ReferenceEquals(self, other)) return true; - if (ReferenceEquals(self, null)) return false; - if (ReferenceEquals(other, null)) return false; - return other._content.ReverseCompareTo(self._content) == 0; - } - public override bool Equals(object other) { return Equals(other as MutableString); } public bool Equals(MutableString other) { - return CompareTo(other) == 0; + if (ReferenceEquals(this, other)) return true; + if (ReferenceEquals(other, null)) return false; + + if (KnowsHashCode && other.KnowsHashCode && _hashCode != other._hashCode) { + return false; + } + + if (_encoding != other._encoding) { + if (_encoding.CompareTo(other._encoding) != 0) { + // only ASCII strings might compare equal if their encodings are different: + if (!IsAscii() || !other.IsAscii()) { + return false; + } + } else { + // we can't compare char representations if they are encoded with different k-codings: + Debug.Assert(_encoding.IsKCoding || other._encoding.IsKCoding); + SwitchToBytes(); + other.SwitchToBytes(); + } + } + + return _content.OrdinalCompareTo(other._content) == 0; } public int CompareTo(MutableString other) { if (ReferenceEquals(this, other)) return 0; if (ReferenceEquals(other, null)) return 1; - return other._content.ReverseCompareTo(_content); + + if (_encoding != other._encoding) { + int result = _encoding.CompareTo(other._encoding); + if (result != 0) { + // only ASCII strings might compare equal if their encodings are different: + if (!IsAscii() || !other.IsAscii()) { + return result; + } + } else { + // we can't compare char representations if they are encoded with different k-codings: + Debug.Assert(_encoding.IsKCoding || other._encoding.IsKCoding); + SwitchToBytes(); + other.SwitchToBytes(); + } + } + + return _content.OrdinalCompareTo(other._content); } #endregion @@ -775,12 +798,12 @@ #region Enumerations (read-only) - public IEnumerable/*!*/ Characters { - get { return _content.GetCharacters(); } + public IEnumerable/*!*/ GetCharacters() { + return _content.GetCharacters(); } - public IEnumerable/*!*/ Bytes { - get { return _content.GetBytes(); } + public IEnumerable/*!*/ GetBytes() { + return _content.GetBytes(); } #endregion @@ -1009,6 +1032,9 @@ #region Append + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(char value) { #region Optimization: MutateOne inlined uint flags = _flags; @@ -1022,6 +1048,9 @@ return this; } + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(char value, int repeatCount) { #region Optimization: MutateOne inlined uint flags = _flags; @@ -1061,6 +1090,9 @@ return this; } + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(char[] value) { if (value != null) { Mutate(); @@ -1069,6 +1101,9 @@ return this; } + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(char[]/*!*/ value, int start, int count) { ContractUtils.RequiresNotNull(value, "value"); ContractUtils.RequiresArrayRange(value, start, count, "startIndex", "count"); @@ -1078,6 +1113,9 @@ return this; } + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(string value) { if (value != null) { Mutate(); @@ -1086,6 +1124,9 @@ return this; } + /// + /// Value should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ Append(string/*!*/ value, int start, int count) { ContractUtils.RequiresNotNull(value, "value"); ContractUtils.RequiresArrayRange(value, start, count, "start", "count"); @@ -1126,20 +1167,26 @@ } public MutableString/*!*/ Append(MutableString value) { - if (value != null) { + if ((object)value != null) { Mutate(value); - value._content.AppendTo(_content, 0, value._content.Count); + _content.Append(value._content, 0, value._content.Count); } return this; } - // TODO: start, count measured in characters or bytes? + /// + /// Appends a substring of a given string to this string. + /// start and count are specified + /// in characters if the value is represented in characters and + /// in bytes if the value is represented in bytes. + /// public MutableString/*!*/ Append(MutableString/*!*/ value, int start, int count) { ContractUtils.RequiresNotNull(value, "value"); - //RequiresArrayRange(start, count); + ContractUtils.Requires(start >= 0, "start"); + ContractUtils.Requires(count >= 0, "count"); Mutate(value); - value._content.AppendTo(_content, start, count); + _content.Append(value._content, start, count); return this; } @@ -1151,27 +1198,25 @@ var other = value._content; EnsureCapacity(other.Count * repeatCount); while (repeatCount-- > 0) { - other.AppendTo(_content, 0, other.Count); + _content.Append(other, 0, other.Count); } return this; } + /// + /// Format and values should only contain characters that can be represented in the string's encoding. + /// public MutableString/*!*/ AppendFormat(string/*!*/ format, params object[] args) { - Mutate(); - return AppendFormat(null, format, args); - } - - public MutableString/*!*/ AppendFormat(IFormatProvider provider, string/*!*/ format, params object[] args) { ContractUtils.RequiresNotNull(format, "format"); Mutate(); - _content.AppendFormat(provider, format, args); + _content.AppendFormat(CultureInfo.InvariantCulture, format, args); return this; } #endregion - #region Insert + #region Insert // TODO: Insert(MS) like Append(MS) public void SetChar(int index, char value) { #region Optimization: MutateOne inlined @@ -1659,9 +1704,10 @@ result.Append((char)('0' + (c & 7))); } - private string/*!*/ ToStringWithEscapedInvalidCharacters(bool octalEscapes, out int escapePlaceholder) { - if (IsBinary) { - return ToStringWithEscapedInvalidCharacters(ToByteArray(), _encoding.Encoding, octalEscapes, out escapePlaceholder); + private string/*!*/ ToStringWithEscapedInvalidCharacters(RubyEncoding/*!*/ encoding, bool octalEscapes, out int escapePlaceholder) { + Debug.Assert(encoding != RubyEncoding.Binary); + if (IsBinary || encoding != _encoding) { + return ToStringWithEscapedInvalidCharacters(ToByteArray(), encoding.Encoding, octalEscapes, out escapePlaceholder); } else { escapePlaceholder = -1; return ToString(); @@ -1672,32 +1718,31 @@ /// Returns a string with all non-ASCII characters replaced by escaped Unicode or hexadecimal numeric sequences. /// public string/*!*/ ToAsciiString() { - var result = AppendRepresentation(new StringBuilder(), false, true, -1).ToString(); + var result = AppendRepresentation(new StringBuilder(), null, false, true, -1).ToString(); Debug.Assert(result.IsAscii()); return result; } - public StringBuilder/*!*/ AppendRepresentation(StringBuilder/*!*/ result, bool octalEscapes, bool forceEscapes, int quote) { + public StringBuilder/*!*/ AppendRepresentation(StringBuilder/*!*/ result, RubyEncoding forceEncoding, bool octalEscapes, bool forceEscapes, int quote) { ContractUtils.RequiresNotNull(result, "result"); + ContractUtils.Requires(forceEncoding == null || forceEncoding.IsKCoding || forceEncoding == RubyEncoding.Binary); - if (_encoding == RubyEncoding.Binary) { + RubyEncoding encoding = forceEncoding ?? _encoding; + + if (encoding == RubyEncoding.Binary || (forceEscapes && encoding != RubyEncoding.UTF8)) { if (IsBinary) { AppendBinaryRepresentation(result, ToByteArray(), octalEscapes, true, quote); } else { AppendStringRepresentation(result, ToString(), octalEscapes, true, quote, -1); } - } else if (_encoding == RubyEncoding.UTF8 || _encoding == RubyEncoding.KCodeUTF8 || !forceEscapes) { + } else { int escapePlaceholder; - var str = ToStringWithEscapedInvalidCharacters(octalEscapes, out escapePlaceholder); - if (_encoding == RubyEncoding.UTF8) { + var str = ToStringWithEscapedInvalidCharacters(encoding, octalEscapes, out escapePlaceholder); + if (encoding == RubyEncoding.UTF8) { AppendUnicodeRepresentation(result, str, octalEscapes, forceEscapes, quote, escapePlaceholder); - } else if (forceEscapes) { - AppendBinaryRepresentation(result, ToByteArray(), octalEscapes, true, quote); } else { AppendStringRepresentation(result, str, octalEscapes, forceEscapes, quote, escapePlaceholder); } - } else { - AppendBinaryRepresentation(result, ToByteArray(), octalEscapes, true, quote); } return result; @@ -1730,7 +1775,7 @@ } internal string/*!*/ GetDebugValue() { - return AppendRepresentation(new StringBuilder(), false, false, '"').ToString(); + return AppendRepresentation(new StringBuilder(), null, false, false, '"').ToString(); } internal string/*!*/ GetDebugType() { =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.StringContent.cs;C1301388 File: MutableString.StringContent.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.StringContent.cs;C1301388 (server) 12/3/2009 2:17 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/MutableString.StringContent.cs;InspectAppendCompareTo @@ -158,19 +158,34 @@ #region CompareTo (read-only) - public override int CompareTo(string/*!*/ str) { - // TODO: Ruby compares characters w/o taking locale into account: + public override int OrdinalCompareTo(string/*!*/ str) { return _data.ValueCompareTo(str); } - public override int CompareTo(byte[]/*!*/ bytes) { - return SwitchToBinary().CompareTo(bytes); + internal int OrdinalCompareTo(char[]/*!*/ chars, int count) { + return -chars.ValueCompareTo(count, _data); } - public override int ReverseCompareTo(Content/*!*/ str) { - return str.CompareTo(_data); + // this <=> content + public override int OrdinalCompareTo(Content/*!*/ content) { + return content.ReverseOrdinalCompareTo(this); } + // content.bytes <=> this.chars + public override int ReverseOrdinalCompareTo(BinaryContent/*!*/ content) { + return SwitchToBinary().ReverseOrdinalCompareTo(content); + } + + // content.chars <=> this.chars + public override int ReverseOrdinalCompareTo(CharArrayContent/*!*/ content) { + return content.OrdinalCompareTo(_data); + } + + // content.chars <=> this.chars + public override int ReverseOrdinalCompareTo(StringContent/*!*/ content) { + return content.OrdinalCompareTo(_data); + } + #endregion #region Slices (read-only) @@ -287,10 +302,26 @@ SwitchToMutable().AppendFormat(provider, format, args); } - public override void AppendTo(Content/*!*/ str, int start, int count) { - str.Append(_data, start, count); + // this + content[start, count] + public override void Append(Content/*!*/ content, int start, int count) { + content.AppendTo(this, start, count); } + // content.bytes + this.chars[start, count] + public override void AppendTo(BinaryContent/*!*/ content, int start, int count) { + content.AppendBytes(_data, start, count); + } + + // content.chars + this.chars[start, count] + public override void AppendTo(CharArrayContent/*!*/ content, int start, int count) { + content.Append(_data, start, count); + } + + // content.chars + this.chars[start, count] + public override void AppendTo(StringContent/*!*/ content, int start, int count) { + content.Append(_data, start, count); + } + #endregion #region Insert =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyBufferedStream.cs;C1200585 File: RubyBufferedStream.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyBufferedStream.cs;C1200585 (server) 12/3/2009 1:07 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyBufferedStream.cs;InspectAppendCompareTo @@ -301,7 +301,7 @@ return first; } - public MutableString ReadLineOrParagraph(MutableString separator, RubyEncoding encoding, bool preserveEndOfLines) { + public MutableString ReadLineOrParagraph(MutableString separator, RubyEncoding/*!*/ encoding, bool preserveEndOfLines) { if (separator == null) { var result = MutableString.CreateBinary(); return AppendBytes(result, Int32.MaxValue, preserveEndOfLines) == 0 ? null : result; @@ -312,7 +312,7 @@ } } - public MutableString ReadParagraph(RubyEncoding encoding, bool preserveEndOfLines) { + public MutableString ReadParagraph(RubyEncoding/*!*/ encoding, bool preserveEndOfLines) { var result = ReadLine(MutableString.CreateAscii("\n\n"), encoding, preserveEndOfLines); int c; @@ -326,19 +326,19 @@ return result; } - public MutableString ReadLine(MutableString/*!*/ separator, RubyEncoding encoding, bool preserveEndOfLines) { - int c = ReadByteNormalizeEoln(preserveEndOfLines); - if (c == -1) { + public MutableString ReadLine(MutableString/*!*/ separator, RubyEncoding/*!*/ encoding, bool preserveEndOfLines) { + int b = ReadByteNormalizeEoln(preserveEndOfLines); + if (b == -1) { return null; } int separatorOffset = 0; - MutableString result = MutableString.CreateMutable(encoding); + MutableString result = MutableString.CreateBinary(encoding); do { - result.Append((char)c); + result.Append((byte)b); - if (c == separator.GetChar(separatorOffset)) { + if (b == separator.GetByte(separatorOffset)) { if (separatorOffset == separator.Length - 1) { break; } @@ -347,8 +347,8 @@ separatorOffset = 0; } - c = ReadByteNormalizeEoln(preserveEndOfLines); - } while (c != -1); + b = ReadByteNormalizeEoln(preserveEndOfLines); + } while (b != -1); return result; } =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyEncoding.cs;C1286631 File: RubyEncoding.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyEncoding.cs;C1286631 (server) 12/3/2009 3:44 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Builtins/RubyEncoding.cs;InspectAppendCompareTo @@ -108,6 +108,7 @@ private readonly Encoding/*!*/ _strictEncoding; private readonly bool _isKCoding; private readonly int _maxBytesPerChar; + private readonly int _ordinal; // UTF8 for KUTF8, SJIS for KSJIS, EUC for KEUC, self for others. private readonly RubyEncoding/*!*/ _realEncoding; @@ -120,6 +121,10 @@ Assert.NotNull(encoding, strictEncoding); Debug.Assert(encoding is KCoding == strictEncoding is KCoding); _isKCoding = encoding is KCoding; + + // all k-codings compare equal to binary encoding, others are sorted by code-pages: + _ordinal = _isKCoding ? CodePageBinary : GetCodePage(encoding); + _encoding = encoding; _strictEncoding = strictEncoding; _realEncoding = realEncoding ?? this; @@ -192,6 +197,10 @@ return _isKCoding ? "KCODE: " + Name : Name; } + public int CompareTo(RubyEncoding/*!*/ other) { + return _ordinal - other._ordinal; + } + /// Unknown encoding. public static Encoding/*!*/ GetEncodingByRubyName(string/*!*/ name) { ContractUtils.RequiresNotNull(name, "name"); =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C1286631 File: RubyOptionsParser.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;C1286631 (server) 12/2/2009 5:20 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Hosting/RubyOptionsParser.cs;InspectAppendCompareTo @@ -175,7 +175,6 @@ case "--version": case "-v": CommonConsoleOptions.PrintVersion = true; - CommonConsoleOptions.Exit = true; goto case "-W2"; case "-W0": @@ -271,7 +270,6 @@ #else RubyEncoding.GetRubyEncoding(Console.InputEncoding); #endif - CommonConsoleOptions.Exit = false; } break; } =================================================================== edit: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;C1301388 File: Utils.cs =================================================================== --- $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;C1301388 (server) 12/3/2009 2:32 PM +++ Shelved Change: $/Dev10/feature/vs_langs01_s/Merlin/Main/Languages/Ruby/Ruby/Runtime/Utils.cs;InspectAppendCompareTo @@ -179,6 +179,23 @@ return newCount; } + internal static int Append(ref byte[]/*!*/ array, int byteCount, string/*!*/ other, int start, int count, Encoding/*!*/ encoding) { + // TODO: we can special case this for some encodings and calculate the byte count w/o copying the content: + char[] appendChars = other.ToCharArray(start, count); + + int newCount = byteCount + encoding.GetByteCount(appendChars, 0, appendChars.Length); + Resize(ref array, newCount); + encoding.GetBytes(appendChars, 0, appendChars.Length, array, byteCount); + return newCount; + } + + internal static int Append(ref byte[]/*!*/ array, int byteCount, char[]/*!*/ other, int start, int count, Encoding/*!*/ encoding) { + int newCount = byteCount + encoding.GetByteCount(other, start, count); + Resize(ref array, newCount); + encoding.GetBytes(other, start, count, array, byteCount); + return newCount; + } + internal static int InsertAt(ref T[]/*!*/ array, int itemCount, int index, T item, int repeatCount) { ResizeForInsertion(ref array, itemCount, index, repeatCount); Fill(array, index, item, repeatCount); @@ -305,11 +322,16 @@ } internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other) { - int min = itemCount, defaultResult; - if (min < other.Length) { + return ValueCompareTo(array, itemCount, other, other.Length); + } + + internal static int ValueCompareTo(this byte[]/*!*/ array, int itemCount, byte[]/*!*/ other, int otherCount) { + int min = itemCount; + int defaultResult; + if (min < otherCount) { defaultResult = -1; - } else if (min > other.Length) { - min = other.Length; + } else if (min > otherCount) { + min = otherCount; defaultResult = +1; } else { defaultResult = 0; @@ -324,6 +346,27 @@ return defaultResult; } + internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, char[]/*!*/ other, int otherCount) { + int min = itemCount; + int defaultResult; + if (min < otherCount) { + defaultResult = -1; + } else if (min > otherCount) { + min = otherCount; + defaultResult = +1; + } else { + defaultResult = 0; + } + + for (int i = 0; i < min; i++) { + if (array[i] != other[i]) { + return (int)array[i] - other[i]; + } + } + + return defaultResult; + } + internal static int ValueCompareTo(this char[]/*!*/ array, int itemCount, string/*!*/ other) { int min = itemCount, defaultResult; if (min < other.Length) { ===================================================================