summaryrefslogtreecommitdiff
path: root/csharp/src
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src')
-rw-r--r--csharp/src/Glacier2/SessionFactoryHelper.cs14
-rw-r--r--csharp/src/Ice/CommunicatorI.cs2
-rw-r--r--csharp/src/Ice/Incoming.cs5
-rw-r--r--csharp/src/Ice/Instance.cs26
-rw-r--r--csharp/src/Ice/InstrumentationI.cs6
-rw-r--r--csharp/src/Ice/LocatorInfo.cs13
-rw-r--r--csharp/src/Ice/ObjectAdapterI.cs2
-rw-r--r--csharp/src/Ice/PropertyNames.cs3
-rw-r--r--csharp/src/Ice/Reference.cs8
-rw-r--r--csharp/src/Ice/ServantManager.cs14
-rw-r--r--csharp/src/Ice/StringUtil.cs407
-rw-r--r--csharp/src/Ice/TraceUtil.cs11
-rw-r--r--csharp/src/Ice/Util.cs9
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);
}
}