diff options
Diffstat (limited to 'csharp/src')
-rw-r--r-- | csharp/src/Glacier2/SessionFactoryHelper.cs | 14 | ||||
-rw-r--r-- | csharp/src/Ice/CommunicatorI.cs | 2 | ||||
-rw-r--r-- | csharp/src/Ice/Incoming.cs | 5 | ||||
-rw-r--r-- | csharp/src/Ice/Instance.cs | 26 | ||||
-rw-r--r-- | csharp/src/Ice/InstrumentationI.cs | 6 | ||||
-rw-r--r-- | csharp/src/Ice/LocatorInfo.cs | 13 | ||||
-rw-r--r-- | csharp/src/Ice/ObjectAdapterI.cs | 2 | ||||
-rw-r--r-- | csharp/src/Ice/PropertyNames.cs | 3 | ||||
-rw-r--r-- | csharp/src/Ice/Reference.cs | 8 | ||||
-rw-r--r-- | csharp/src/Ice/ServantManager.cs | 14 | ||||
-rw-r--r-- | csharp/src/Ice/StringUtil.cs | 407 | ||||
-rw-r--r-- | csharp/src/Ice/TraceUtil.cs | 11 | ||||
-rw-r--r-- | csharp/src/Ice/Util.cs | 9 |
13 files changed, 349 insertions, 171 deletions
diff --git a/csharp/src/Glacier2/SessionFactoryHelper.cs b/csharp/src/Glacier2/SessionFactoryHelper.cs index e21b713944d..28832b36b5b 100644 --- a/csharp/src/Glacier2/SessionFactoryHelper.cs +++ b/csharp/src/Glacier2/SessionFactoryHelper.cs @@ -147,7 +147,7 @@ public class SessionFactoryHelper { return getProtocol().Equals("ssl"); } - + /// <summary> /// Sets the protocol that will be used by the session factory to establish the connection.. /// </summary> @@ -161,7 +161,7 @@ public class SessionFactoryHelper { throw new ArgumentException("You must use a valid protocol"); } - + if(!protocol.Equals("tcp") && !protocol.Equals("ssl") && !protocol.Equals("wss") && @@ -240,11 +240,11 @@ public class SessionFactoryHelper return getPortInternal(); } } - + private int getPortInternal() { - return _port == 0 ? ((_protocol.Equals("ssl") || + return _port == 0 ? ((_protocol.Equals("ssl") || _protocol.Equals("wss"))? GLACIER2_SSL_PORT : GLACIER2_TCP_PORT) : _port; } @@ -362,7 +362,7 @@ public class SessionFactoryHelper // plug-in has already been setup we don't want to override the // configuration so it can be loaded from a custom location. // - if((_protocol.Equals("ssl") || _protocol.Equals("wss")) && + if((_protocol.Equals("ssl") || _protocol.Equals("wss")) && initData.properties.getProperty("Ice.Plugin.IceSSL").Length == 0) { initData.properties.setProperty("Ice.Plugin.IceSSL", "IceSSL:IceSSL.PluginFactory"); @@ -383,8 +383,8 @@ public class SessionFactoryHelper { StringBuilder sb = new StringBuilder(); sb.Append("\""); - sb.Append(Ice.Util.identityToString(ident)); - sb.Append("\":"); + sb.Append(Ice.Util.identityToString(ident, Ice.ToStringMode.Unicode)); + sb.Append("\":"); sb.Append(_protocol + " -p "); sb.Append(getPortInternal()); sb.Append(" -h \""); diff --git a/csharp/src/Ice/CommunicatorI.cs b/csharp/src/Ice/CommunicatorI.cs index dade480ecc5..d4f54bdca1d 100644 --- a/csharp/src/Ice/CommunicatorI.cs +++ b/csharp/src/Ice/CommunicatorI.cs @@ -65,7 +65,7 @@ namespace Ice public string identityToString(Ice.Identity ident) { - return Ice.Util.identityToString(ident); + return Ice.Util.identityToString(ident, instance_.toStringMode()); } public ObjectAdapter createObjectAdapter(string name) diff --git a/csharp/src/Ice/Incoming.cs b/csharp/src/Ice/Incoming.cs index 84608522cdb..9df6f1625c7 100644 --- a/csharp/src/Ice/Incoming.cs +++ b/csharp/src/Ice/Incoming.cs @@ -515,10 +515,11 @@ namespace IceInternal using(StringWriter sw = new StringWriter(CultureInfo.CurrentCulture)) { IceUtilInternal.OutputBase output = new IceUtilInternal.OutputBase(sw); + Ice.ToStringMode toStringMode = _instance.toStringMode(); output.setUseTab(false); output.print("dispatch exception:"); - output.print("\nidentity: " + Ice.Util.identityToString(_current.id)); - output.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, "")); + output.print("\nidentity: " + Ice.Util.identityToString(_current.id, toStringMode)); + output.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, "", toStringMode)); output.print("\noperation: " + _current.operation); if(_current.con != null) { diff --git a/csharp/src/Ice/Instance.cs b/csharp/src/Ice/Instance.cs index 97e797f6175..572bf8d8617 100644 --- a/csharp/src/Ice/Instance.cs +++ b/csharp/src/Ice/Instance.cs @@ -336,6 +336,13 @@ namespace IceInternal return _batchAutoFlushSize; } + public Ice.ToStringMode + toStringMode() + { + // No mutex lock, immutable + return _toStringMode; + } + public int cacheMessageBuffers() { // No mutex lock, immutable. @@ -862,6 +869,24 @@ namespace IceInternal } } + string toStringModeStr = _initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode"); + if(toStringModeStr == "Unicode") + { + _toStringMode = Ice.ToStringMode.Unicode; + } + else if(toStringModeStr == "ASCII") + { + _toStringMode = Ice.ToStringMode.ASCII; + } + else if(toStringModeStr == "Compat") + { + _toStringMode = Ice.ToStringMode.Compat; + } + else + { + throw new Ice.InitializationException("The value for Ice.ToStringMode must be Unicode, ASCII or Compat"); + } + _cacheMessageBuffers = _initData.properties.getPropertyAsIntWithDefault("Ice.CacheMessageBuffers", 2); _implicitContext = Ice.ImplicitContextI.create(_initData.properties.getProperty("Ice.ImplicitContext")); @@ -1539,6 +1564,7 @@ namespace IceInternal private DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy(). private int _messageSizeMax; // Immutable, not reset by destroy(). private int _batchAutoFlushSize; // Immutable, not reset by destroy(). + private Ice.ToStringMode _toStringMode; // Immutable, not reset by destroy(). private int _cacheMessageBuffers; // Immutable, not reset by destroy(). private ACMConfig _clientACM; // Immutable, not reset by destroy(). private ACMConfig _serverACM; // Immutable, not reset by destroy(). diff --git a/csharp/src/Ice/InstrumentationI.cs b/csharp/src/Ice/InstrumentationI.cs index a6d733af7fe..3eca65b7ed6 100644 --- a/csharp/src/Ice/InstrumentationI.cs +++ b/csharp/src/Ice/InstrumentationI.cs @@ -395,7 +395,7 @@ namespace IceInternal public string getIdentity() { - return Ice.Util.identityToString(_current.id); + return _current.adapter.getCommunicator().identityToString(_current.id); } readonly private Ice.Current _current; @@ -500,7 +500,7 @@ namespace IceInternal catch(Ice.Exception) { // Either a fixed proxy or the communicator is destroyed. - os.Append(Ice.Util.identityToString(_proxy.ice_getIdentity())); + os.Append(_proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity())); os.Append(" [").Append(_operation).Append(']'); } _id = os.ToString(); @@ -532,7 +532,7 @@ namespace IceInternal { if(_proxy != null) { - return Ice.Util.identityToString(_proxy.ice_getIdentity()); + return _proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity()); } else { diff --git a/csharp/src/Ice/LocatorInfo.cs b/csharp/src/Ice/LocatorInfo.cs index 01c064b9f4e..50eccbbb5fe 100644 --- a/csharp/src/Ice/LocatorInfo.cs +++ b/csharp/src/Ice/LocatorInfo.cs @@ -523,7 +523,8 @@ namespace IceInternal } else { - s.Append("object = " + Ice.Util.identityToString(r.getIdentity()) + "\n"); + s.Append("object = " + Ice.Util.identityToString(r.getIdentity(), r.getInstance().toStringMode()) + + "\n"); } s.Append("endpoints = "); @@ -569,13 +570,13 @@ namespace IceInternal { System.Text.StringBuilder s = new System.Text.StringBuilder(); s.Append("object not found\n"); - s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity())); + s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity(), instance.toStringMode())); instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.ToString()); } Ice.NotRegisteredException e = new Ice.NotRegisteredException(ex); e.kindOfObject = "object"; - e.id = Ice.Util.identityToString(@ref.getIdentity()); + e.id = Ice.Util.identityToString(@ref.getIdentity(), instance.toStringMode()); throw e; } catch(Ice.NotRegisteredException) @@ -595,7 +596,7 @@ namespace IceInternal } else { - s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity()) + "\n"); + s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity(), instance.toStringMode()) + "\n"); } s.Append("reason = " + ex); instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.ToString()); @@ -634,7 +635,7 @@ namespace IceInternal else { s.Append("object\n"); - s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity())); + s.Append("object = " + Ice.Util.identityToString(@ref.getIdentity(), instance.toStringMode())); } instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.ToString()); } @@ -674,7 +675,7 @@ namespace IceInternal Instance instance = @ref.getInstance(); System.Text.StringBuilder s = new System.Text.StringBuilder(); s.Append("searching for object by id\nobject = "); - s.Append(Ice.Util.identityToString(@ref.getIdentity())); + s.Append(Ice.Util.identityToString(@ref.getIdentity(), instance.toStringMode())); instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.ToString()); } diff --git a/csharp/src/Ice/ObjectAdapterI.cs b/csharp/src/Ice/ObjectAdapterI.cs index bcdcd85ad3e..a1213d9ae99 100644 --- a/csharp/src/Ice/ObjectAdapterI.cs +++ b/csharp/src/Ice/ObjectAdapterI.cs @@ -926,7 +926,7 @@ namespace Ice { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); ex.kindOfObject = "object adapter with router"; - ex.id = Ice.Util.identityToString(router.ice_getIdentity()); + ex.id = Ice.Util.identityToString(router.ice_getIdentity(), instance_.toStringMode()); throw ex; } diff --git a/csharp/src/Ice/PropertyNames.cs b/csharp/src/Ice/PropertyNames.cs index ef987e7ee17..c8f412c8e34 100644 --- a/csharp/src/Ice/PropertyNames.cs +++ b/csharp/src/Ice/PropertyNames.cs @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ../config/PropertyNames.xml, Wed Oct 5 19:04:47 2016 +// Generated by makeprops.py from file PropertyNames.xml, Thu Oct 20 16:20:13 2016 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -165,6 +165,7 @@ namespace IceInternal new Property(@"^Ice\.ThreadPool\.Server\.ThreadIdleTime$", false, null), new Property(@"^Ice\.ThreadPool\.Server\.ThreadPriority$", false, null), new Property(@"^Ice\.ThreadPriority$", false, null), + new Property(@"^Ice\.ToStringMode$", false, null), new Property(@"^Ice\.Trace\.Admin\.Properties$", false, null), new Property(@"^Ice\.Trace\.Admin\.Logger$", false, null), new Property(@"^Ice\.Trace\.Locator$", false, null), diff --git a/csharp/src/Ice/Reference.cs b/csharp/src/Ice/Reference.cs index 37644c85a6e..19493d35d0a 100644 --- a/csharp/src/Ice/Reference.cs +++ b/csharp/src/Ice/Reference.cs @@ -290,12 +290,14 @@ namespace IceInternal // StringBuilder s = new StringBuilder(); + Ice.ToStringMode toStringMode = instance_.toStringMode(); + // // If the encoded identity string contains characters which // the reference parser uses as separators, then we enclose // the identity string in quotes. // - string id = Ice.Util.identityToString(identity_); + string id = Ice.Util.identityToString(identity_, toStringMode); if(IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1) { s.Append('"'); @@ -315,7 +317,7 @@ namespace IceInternal // the facet string in quotes. // s.Append(" -f "); - string fs = IceUtilInternal.StringUtil.escapeString(facet_, ""); + string fs = IceUtilInternal.StringUtil.escapeString(facet_, "", toStringMode); if(IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1) { s.Append('"'); @@ -1057,7 +1059,7 @@ namespace IceInternal // the reference parser uses as separators, then we enclose // the adapter id string in quotes. // - string a = IceUtilInternal.StringUtil.escapeString(_adapterId, null); + string a = IceUtilInternal.StringUtil.escapeString(_adapterId, null, getInstance().toStringMode()); if(IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1) { s.Append('"'); diff --git a/csharp/src/Ice/ServantManager.cs b/csharp/src/Ice/ServantManager.cs index a369af5ef1d..526e205c514 100644 --- a/csharp/src/Ice/ServantManager.cs +++ b/csharp/src/Ice/ServantManager.cs @@ -37,11 +37,11 @@ public sealed class ServantManager if(m.ContainsKey(facet)) { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, instance_.toStringMode()); ex.kindOfObject = "servant"; if(facet.Length > 0) { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "", instance_.toStringMode()); } throw ex; } @@ -87,11 +87,11 @@ public sealed class ServantManager if(m == null || !m.ContainsKey(facet)) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, instance_.toStringMode()); ex.kindOfObject = "servant"; if(facet.Length > 0) { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, "", instance_.toStringMode()); } throw ex; } @@ -138,7 +138,7 @@ public sealed class ServantManager if(m == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = Ice.Util.identityToString(ident); + ex.id = Ice.Util.identityToString(ident, instance_.toStringMode()); ex.kindOfObject = "servant"; throw ex; } @@ -251,7 +251,7 @@ public sealed class ServantManager if(l != null) { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); - ex.id = IceUtilInternal.StringUtil.escapeString(category, ""); + ex.id = IceUtilInternal.StringUtil.escapeString(category, "", instance_.toStringMode()); ex.kindOfObject = "servant locator"; throw ex; } @@ -271,7 +271,7 @@ public sealed class ServantManager if(l == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.id = IceUtilInternal.StringUtil.escapeString(category, ""); + ex.id = IceUtilInternal.StringUtil.escapeString(category, "", instance_.toStringMode()); ex.kindOfObject = "servant locator"; throw ex; } diff --git a/csharp/src/Ice/StringUtil.cs b/csharp/src/Ice/StringUtil.cs index d683cc8b92f..c8c392be86d 100644 --- a/csharp/src/Ice/StringUtil.cs +++ b/csharp/src/Ice/StringUtil.cs @@ -25,7 +25,7 @@ namespace IceUtilInternal { return findFirstOf(str, match, 0); } - + // // Return the index of the first character in str to // appear in match, starting from start. Returns -1 if none is @@ -42,10 +42,10 @@ namespace IceUtilInternal return i; } } - + return -1; } - + // // Return the index of the first character in str which does // not appear in match, starting from 0. Returns -1 if none is @@ -55,7 +55,7 @@ namespace IceUtilInternal { return findFirstNotOf(str, match, 0); } - + // // Return the index of the first character in str which does // not appear in match, starting from start. Returns -1 if none is @@ -72,114 +72,135 @@ namespace IceUtilInternal return i; } } - + return -1; } - - // - // Write the byte b as an escape sequence if it isn't a printable ASCII - // character and append the escape sequence to sb. Additional characters - // that should be escaped can be passed in special. If b is any of these - // characters, b is preceded by a backslash in sb. - // - private static void encodeChar(byte b, StringBuilder sb, string special) + + private static void + encodeChar(char c, StringBuilder sb, string special, Ice.ToStringMode toStringMode) { - switch((char)b) + switch(c) { - case '\\': + case '\\': { sb.Append("\\\\"); break; } - - case '\'': + + case '\'': { sb.Append("\\'"); break; } - - case '"': + + case '"': { sb.Append("\\\""); break; } - - case '\b': + + case '\b': { sb.Append("\\b"); break; } - - case '\f': + + case '\f': { sb.Append("\\f"); break; } - - case '\n': + + case '\n': { sb.Append("\\n"); break; } - - case '\r': + + case '\r': { sb.Append("\\r"); break; } - - case '\t': + + case '\t': { sb.Append("\\t"); break; } - - default: + default: { - if(!(b >= 32 && b <= 126)) + if(special != null && special.IndexOf(c) != -1) { sb.Append('\\'); - string octal = System.Convert.ToString(b, 8); - // - // Add leading zeroes so that we avoid problems during - // decoding. For example, consider the encoded string - // \0013 (i.e., a character with value 1 followed by - // the character '3'). If the leading zeroes were omitted, - // the result would be incorrectly interpreted by the - // decoder as a single character with value 11. - // - for(int j = octal.Length; j < 3; j++) - { - sb.Append('0'); - } - sb.Append(octal); - } - else if(special != null && special.IndexOf((char)b) != -1) - { - sb.Append('\\'); - sb.Append((char)b); + sb.Append(c); } else { - sb.Append((char)b); + int i = (int)c; + if(i < 32 || i > 126) + { + if(toStringMode == Ice.ToStringMode.Compat) + { + // + // When ToStringMode=Compat, c is a UTF-8 byte + // + Debug.Assert(i < 256); + + sb.Append('\\'); + string octal = System.Convert.ToString(i, 8); + // + // Add leading zeroes so that we avoid problems during + // decoding. For example, consider the encoded string + // \0013 (i.e., a character with value 1 followed by + // the character '3'). If the leading zeroes were omitted, + // the result would be incorrectly interpreted by the + // decoder as a single character with value 11. + // + for(int j = octal.Length; j < 3; j++) + { + sb.Append('0'); + } + sb.Append(octal); + } + else if(i < 32 || i == 127 || toStringMode == Ice.ToStringMode.ASCII) + { + // append \\unnnn + sb.Append("\\u"); + string hex = System.Convert.ToString(i, 16); + for(int j = hex.Length; j < 4; j++) + { + sb.Append('0'); + } + sb.Append(hex); + } + else + { + // keep as is + sb.Append(c); + } + } + else + { + // printable ASCII character + sb.Append(c); + } } - } break; + } } } - + // - // Add escape sequences (such as "\n", or "\007") to make a string - // readable in ASCII. Any characters that appear in special are - // prefixed with a backslash in the returned string. + // Add escape sequences (such as "\n", or "\007") to the input string // - public static string escapeString(string s, string special) + public static string escapeString(string s, string special, Ice.ToStringMode toStringMode) { if(special != null) { for(int i = 0; i < special.Length; ++i) { - if((int)special[i] < 32 || (int)special[i] > 126) + if(special[i] < 32 || special[i] > 126) { throw new System.ArgumentException("special characters must be in ASCII range 32-126", "special"); @@ -187,22 +208,64 @@ namespace IceUtilInternal } } - UTF8Encoding utf8 = new UTF8Encoding(); - byte[] bytes = utf8.GetBytes(s); + if(toStringMode == Ice.ToStringMode.Compat) + { + // Encode UTF-8 bytes + + UTF8Encoding utf8 = new UTF8Encoding(); + byte[] bytes = utf8.GetBytes(s); - StringBuilder result = new StringBuilder(bytes.Length); - for(int i = 0; i < bytes.Length; i++) + StringBuilder result = new StringBuilder(bytes.Length); + for(int i = 0; i < bytes.Length; i++) + { + encodeChar((char)bytes[i], result, special, toStringMode); + } + + return result.ToString(); + } + else { - encodeChar(bytes[i], result, special); + StringBuilder result = new StringBuilder(s.Length); + + for(int i = 0; i < s.Length; i++) + { + char c = s[i]; + if(toStringMode == Ice.ToStringMode.Unicode || !System.Char.IsSurrogate(c)) + { + encodeChar(c, result, special, toStringMode); + } + else + { + Debug.Assert(toStringMode == Ice.ToStringMode.ASCII && System.Char.IsSurrogate(c)); + if(i + 1 == s.Length) + { + throw new System.ArgumentException("High surrogate without low surrogate"); + } + else + { + i++; + int codePoint = System.Char.ConvertToUtf32(c, s[i]); + // append \Unnnnnnnn + result.Append("\\U"); + string hex = System.Convert.ToString(codePoint, 16); + for(int j = hex.Length; j < 8; j++) + { + result.Append('0'); + } + result.Append(hex); + } + } + } + + return result.ToString(); } - - return result.ToString(); } - - private static char checkChar(string s, int pos) + + private static char + checkChar(string s, int pos) { char c = s[pos]; - if(!(c >= 32 && c <= 126)) + if(c < 32 || c == 127) { string msg; if(pos > 0) @@ -219,23 +282,22 @@ namespace IceUtilInternal return c; } + // - // Decode the character or escape sequence starting at start and return it. - // end marks the one-past-the-end position of the substring to be scanned. - // nextStart is set to the index of the first character following the decoded - // character or escape sequence. + // Decode the character or escape sequence starting at start and appends it to result; + // returns the index of the first character following the decoded character + // or escape sequence. // - private static char decodeChar(string s, int start, int end, out int nextStart) + private static int + decodeChar(string s, int start, int end, StringBuilder result, UTF8Encoding utf8Encoding) { Debug.Assert(start >= 0); Debug.Assert(start < end); Debug.Assert(end <= s.Length); - char c; - if(s[start] != '\\') { - c = checkChar(s, start++); + result.Append(checkChar(s, start++)); } else { @@ -243,45 +305,98 @@ namespace IceUtilInternal { throw new System.ArgumentException("trailing backslash"); } - switch(s[++start]) + + char c = s[++start]; + + switch(c) { - case '\\': - case '\'': - case '"': + case '\\': + case '\'': + case '"': + { + ++start; + result.Append(c); + break; + } + case 'b': { - c = s[start++]; + ++start; + result.Append('\b'); break; } - case 'b': + case 'f': { ++start; - c = '\b'; + result.Append('\f'); break; } - case 'f': + case 'n': { ++start; - c = '\f'; + result.Append('\n'); break; } - case 'n': + case 'r': { ++start; - c = '\n'; + result.Append('\r'); break; } - case 'r': + case 't': { ++start; - c = '\r'; + result.Append('\t'); break; } - case 't': + case 'u': + case 'U': { + int codePoint = 0; + bool inBMP = (c == 'u'); + int size = inBMP ? 4 : 8; ++start; - c = '\t'; + while(size > 0 && start < end) + { + c = s[start++]; + int charVal = 0; + if(c >= '0' && c <= '9') + { + charVal = c - '0'; + } + else if(c >= 'a' && c <= 'f') + { + charVal = 10 + (c - 'a'); + } + else if(c >= 'A' && c <= 'F') + { + charVal = 10 + (c - 'A'); + } + else + { + break; // while + } + codePoint = codePoint * 16 + charVal; + --size; + } + if(size > 0) + { + throw new System.ArgumentException("Invalid universal character name: too few hex digits"); + } + if(inBMP && System.Char.IsSurrogate((char)codePoint)) + { + throw new System.ArgumentException("A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead"); + } + if(inBMP || codePoint <= 0xFFFF) + { + result.Append((char)codePoint); + } + else + { + result.Append(System.Char.ConvertFromUtf32(codePoint)); + } break; } + case '0': case '1': case '2': @@ -291,47 +406,63 @@ namespace IceUtilInternal case '6': case '7': { - int val = 0; - for(int j = 0; j < 3 && start < end; ++j) + // UTF-8 byte sequence encoded with octal escapes + + byte[] arr = new byte[end - start]; + int i = 0; + bool done = false; + while(!done) { - int charVal = s[start++] - '0'; - if(charVal < 0 || charVal > 7) + int val = 0; + for(int j = 0; j < 3 && start < end; ++j) { - --start; - break; + int charVal = s[start++] - '0'; + if(charVal < 0 || charVal > 7) + { + --start; + if(j == 0) + { + // first character after escape is not 0-7: + done = true; + --start; // go back to the previous backslash + } + break; // for + } + val = val * 8 + charVal; + } + + if(!done) + { + if(val > 255) + { + string msg = "octal value \\" + System.Convert.ToString(val, 8) + " (" + val + ") is out of range"; + throw new System.ArgumentException(msg); + } + arr[i++] = (byte)val; + + if((start + 1 < end) && s[start] == '\\') + { + start++; + // loop, read next octal escape sequence + } + else + { + done = true; + } } - val = val * 8 + charVal; - } - if(val > 255) - { - string msg = "octal value \\" + System.Convert.ToString(val, 8) + " (" + val + - ") is out of range"; - throw new System.ArgumentException(msg, "s"); } - c = System.Convert.ToChar(val); + + result.Append(utf8Encoding.GetString(arr, 0, i)); // May raise ArgumentException. break; } default: { - c = checkChar(s, start++); + result.Append(checkChar(s, start++)); break; } } } - nextStart = start; - return c; - } - - // - // Remove escape sequences from s and append the result to sb. - // Return true if successful, false otherwise. - // - private static void decodeString(string s, int start, int end, StringBuilder sb) - { - while(start < end) - { - sb.Append(decodeChar(s, start, end, out start)); - } + return start; } // @@ -342,18 +473,26 @@ namespace IceUtilInternal { Debug.Assert(start >= 0 && start <= end && end <= s.Length); - StringBuilder sb = new StringBuilder(); - decodeString(s, start, end, sb); - string decodedString = sb.ToString(); - - byte[] arr = new byte[decodedString.Length]; - for(int i = 0; i < arr.Length; ++i) + // Optimization for strings without escapes + if(start == end || s.IndexOf('\\', start, end - start) == -1) { - arr[i] = (byte)decodedString[i]; + int p = start; + while(p < end) + { + checkChar(s, p++); + } + return s.Substring(start, end - start); + } + else + { + StringBuilder sb = new StringBuilder(end - start); + UTF8Encoding utf8Encoding = new UTF8Encoding(false, true); + while(start < end) + { + start = decodeChar(s, start, end, sb, utf8Encoding); + } + return sb.ToString(); } - - UTF8Encoding utf8 = new UTF8Encoding(false, true); - return utf8.GetString(arr, 0, arr.Length); // May raise ArgumentException. } // @@ -402,7 +541,7 @@ namespace IceUtilInternal continue; } } - + if(pos < str.Length) { arr[n++] = str[pos++]; @@ -425,7 +564,7 @@ namespace IceUtilInternal { return checkQuote(s, 0); } - + // // If a single or double quotation mark is found at the start position, // then the position of the matching closing quote is returned. If no @@ -507,7 +646,7 @@ namespace IceUtilInternal public int Compare(string l, string r) { return string.CompareOrdinal(l, r); - } + } } public static System.Collections.Generic.IComparer<string> OrdinalStringComparer = new OrdinalStringComparerImpl(); diff --git a/csharp/src/Ice/TraceUtil.cs b/csharp/src/Ice/TraceUtil.cs index f815b712473..cb18fb957a9 100644 --- a/csharp/src/Ice/TraceUtil.cs +++ b/csharp/src/Ice/TraceUtil.cs @@ -175,15 +175,22 @@ namespace IceInternal { try { + + Ice.ToStringMode toStringMode = Ice.ToStringMode.Unicode; + if(str.instance() != null) + { + toStringMode = str.instance().toStringMode(); + } + Ice.Identity identity = new Ice.Identity(); identity.read__(str); - s.Write("\nidentity = " + Ice.Util.identityToString(identity)); + s.Write("\nidentity = " + Ice.Util.identityToString(identity, toStringMode)); string[] facet = str.readStringSeq(); s.Write("\nfacet = "); if(facet.Length > 0) { - s.Write(IceUtilInternal.StringUtil.escapeString(facet[0], "")); + s.Write(IceUtilInternal.StringUtil.escapeString(facet[0], "", toStringMode)); } string operation = str.readString(); diff --git a/csharp/src/Ice/Util.cs b/csharp/src/Ice/Util.cs index 3d97733c889..ef2ce56c6e1 100644 --- a/csharp/src/Ice/Util.cs +++ b/csharp/src/Ice/Util.cs @@ -322,17 +322,18 @@ namespace Ice /// Converts an object identity to a string. /// </summary> /// <param name="ident">The object identity to convert.</param> + /// <param name="toStringMode">Specifies if and how non-printable ASCII characters are escaped in the result.</param> /// <returns>The string representation of the object identity.</returns> - public static string identityToString(Identity ident) + public static string identityToString(Identity ident, ToStringMode toStringMode = ToStringMode.Unicode) { if(ident.category == null || ident.category.Length == 0) { - return IceUtilInternal.StringUtil.escapeString(ident.name, "/"); + return IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode); } else { - return IceUtilInternal.StringUtil.escapeString(ident.category, "/") + '/' + - IceUtilInternal.StringUtil.escapeString(ident.name, "/"); + return IceUtilInternal.StringUtil.escapeString(ident.category, "/", toStringMode) + '/' + + IceUtilInternal.StringUtil.escapeString(ident.name, "/", toStringMode); } } |