summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG-3.7.md10
-rw-r--r--config/PropertyNames.xml1
-rwxr-xr-xconfig/makeprops.py31
-rw-r--r--cpp/include/Ice/Initialize.h5
-rw-r--r--cpp/include/IceUtil/StringUtil.h23
-rw-r--r--cpp/src/Glacier2/Blobject.cpp4
-rw-r--r--cpp/src/Glacier2/ClientBlobject.cpp2
-rw-r--r--cpp/src/Glacier2/FilterManager.cpp4
-rw-r--r--cpp/src/Glacier2/Instance.h2
-rw-r--r--cpp/src/Glacier2/SessionRouterI.cpp2
-rw-r--r--cpp/src/Glacier2Lib/NullPermissionsVerifier.cpp4
-rw-r--r--cpp/src/Glacier2Lib/SessionHelper.cpp4
-rw-r--r--cpp/src/Ice/CommunicatorI.cpp2
-rw-r--r--cpp/src/Ice/Exception.cpp23
-rw-r--r--cpp/src/Ice/Incoming.cpp14
-rw-r--r--cpp/src/Ice/Initialize.cpp40
-rw-r--r--cpp/src/Ice/Instance.cpp16
-rw-r--r--cpp/src/Ice/Instance.h2
-rw-r--r--cpp/src/Ice/InstrumentationI.cpp6
-rw-r--r--cpp/src/Ice/LocatorInfo.cpp16
-rw-r--r--cpp/src/Ice/ObjectAdapterI.cpp7
-rw-r--r--cpp/src/Ice/PropertyNames.cpp3
-rw-r--r--cpp/src/Ice/PropertyNames.h2
-rw-r--r--cpp/src/Ice/Reference.cpp19
-rw-r--r--cpp/src/Ice/ReferenceFactory.cpp11
-rw-r--r--cpp/src/Ice/ServantManager.cpp16
-rw-r--r--cpp/src/Ice/StringUtil.h35
-rw-r--r--cpp/src/Ice/TraceUtil.cpp12
-rw-r--r--cpp/src/IceBox/Admin.cpp4
-rw-r--r--cpp/src/IceGrid/AdminI.cpp6
-rw-r--r--cpp/src/IceGrid/AllocatableObjectCache.cpp8
-rw-r--r--cpp/src/IceGrid/Database.cpp18
-rw-r--r--cpp/src/IceGrid/DescriptorHelper.cpp10
-rw-r--r--cpp/src/IceGrid/ObjectCache.cpp10
-rw-r--r--cpp/src/IceGrid/Parser.cpp10
-rw-r--r--cpp/src/IceGrid/ReplicaSessionManager.cpp4
-rw-r--r--cpp/src/IceGrid/Util.cpp4
-rw-r--r--cpp/src/IcePatch2Lib/Util.cpp2
-rw-r--r--cpp/src/IceStorm/IceStormDB.cpp8
-rw-r--r--cpp/src/IceStorm/InstrumentationI.cpp4
-rw-r--r--cpp/src/IceStorm/Parser.cpp6
-rw-r--r--cpp/src/IceStorm/Subscriber.cpp8
-rw-r--r--cpp/src/IceStorm/TopicI.cpp22
-rw-r--r--cpp/src/IceStorm/TopicManagerI.cpp12
-rw-r--r--cpp/src/IceStorm/TransientTopicI.cpp10
-rw-r--r--cpp/src/IceStorm/TransientTopicManagerI.cpp2
-rw-r--r--cpp/src/IceUtil/StringUtil.cpp640
-rw-r--r--cpp/src/Slice/Preprocessor.cpp6
-rw-r--r--cpp/src/icegriddb/IceGridDB.cpp8
-rw-r--r--cpp/test/Ice/interceptor/AMDInterceptorI.cpp2
-rw-r--r--cpp/test/Ice/location/AllTests.cpp2
-rw-r--r--cpp/test/Ice/operations/TestI.cpp2
-rw-r--r--cpp/test/Ice/proxy/AllTests.cpp94
-rwxr-xr-xcpp/test/Ice/proxy/run.py2
-rw-r--r--cpp/test/Ice/stringConverter/Client.cpp17
-rw-r--r--cpp/test/IceGrid/deployer/AllTests.cpp14
-rw-r--r--cpp/test/IceGrid/session/AllTests.cpp2
-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
-rw-r--r--csharp/test/Ice/location/AllTests.cs2
-rw-r--r--csharp/test/Ice/proxy/AllTests.cs72
-rwxr-xr-xcsharp/test/Ice/proxy/run.py2
-rw-r--r--java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java2
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java2
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java3
-rw-r--r--java-compat/src/Ice/src/main/java/Ice/Util.java24
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java6
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java4
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Instance.java26
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java12
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java5
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/Reference.java33
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java2
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java14
-rw-r--r--java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java10
-rw-r--r--java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java362
-rw-r--r--java-compat/src/IceBox/src/main/java/IceBox/Admin.java4
-rw-r--r--java-compat/test/src/main/java/test/Ice/location/AllTests.java2
-rw-r--r--java-compat/test/src/main/java/test/Ice/proxy/AllTests.java72
-rwxr-xr-xjava-compat/test/src/main/java/test/Ice/proxy/run.py2
-rw-r--r--java/src/Glacier2/src/main/java/com/zeroc/Glacier2/SessionFactoryHelper.java2
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/Ice/CommunicatorI.java4
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/Ice/ObjectAdapterI.java2
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/Ice/Util.java21
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/CommunicatorObserverI.java6
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/Incoming.java4
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/Instance.java26
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/LocatorInfo.java12
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java5
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/Reference.java33
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/RoutableReference.java3
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/ServantManager.java18
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceInternal/TraceUtil.java10
-rw-r--r--java/src/Ice/src/main/java/com/zeroc/IceUtilInternal/StringUtil.java375
-rw-r--r--java/src/IceBox/src/main/java/com/zeroc/IceBox/Admin.java4
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/AdapterEditor.java7
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/PropertiesField.java4
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/ReplicaGroupEditor.java6
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/TreeNode.java6
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Coordinator.java2
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/Root.java12
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/TableField.java2
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/ObjectObserverI.java2
-rw-r--r--java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java12
-rw-r--r--java/test/src/main/java/test/Ice/location/AllTests.java2
-rw-r--r--java/test/src/main/java/test/Ice/proxy/AllTests.java76
-rwxr-xr-xjava/test/src/main/java/test/Ice/proxy/run.py2
-rw-r--r--js/src/Ice/Communicator.js2
-rw-r--r--js/src/Ice/IdentityUtil.js8
-rw-r--r--js/src/Ice/IncomingAsync.js4
-rw-r--r--js/src/Ice/Instance.js25
-rw-r--r--js/src/Ice/LocatorInfo.js12
-rw-r--r--js/src/Ice/ObjectAdapterI.js2
-rw-r--r--js/src/Ice/Operation.js2
-rw-r--r--js/src/Ice/PropertyNames.js3
-rw-r--r--js/src/Ice/Reference.js9
-rw-r--r--js/src/Ice/ServantManager.js14
-rw-r--r--js/src/Ice/StringUtil.js347
-rw-r--r--js/src/Ice/ToStringMode.js12
-rw-r--r--js/src/Ice/TraceUtil.js10
-rw-r--r--js/test/Ice/proxy/Client.js76
-rw-r--r--objective-c/include/objc/Ice/Initialize.h1
-rw-r--r--objective-c/src/Ice/CommunicatorI.mm12
-rw-r--r--objective-c/src/Ice/Initialize.mm11
-rw-r--r--objective-c/src/Ice/Proxy.mm4
-rw-r--r--objective-c/test/Ice/binding/AllTests.m2
-rw-r--r--objective-c/test/Ice/proxy/AllTests.m27
-rw-r--r--php/lib/Ice.php1
-rw-r--r--php/lib/Ice_ns.php1
-rw-r--r--php/src/php5/Communicator.cpp6
-rw-r--r--php/src/php7/Communicator.cpp6
-rw-r--r--php/test/Ice/proxy/Client.php38
-rw-r--r--python/modules/IcePy/Communicator.cpp21
-rw-r--r--python/modules/IcePy/Init.cpp4
-rw-r--r--python/modules/IcePy/Operation.cpp4
-rw-r--r--python/python/Ice.py4
-rw-r--r--python/test/Ice/location/AllTests.py2
-rw-r--r--python/test/Ice/proxy/AllTests.py29
-rw-r--r--ruby/ruby/Ice.rb1
-rw-r--r--ruby/src/IceRuby/Communicator.cpp23
-rw-r--r--ruby/src/IceRuby/Util.cpp8
-rw-r--r--ruby/test/Ice/proxy/AllTests.rb26
-rw-r--r--slice/Ice/Communicator.ice32
154 files changed, 2736 insertions, 1145 deletions
diff --git a/CHANGELOG-3.7.md b/CHANGELOG-3.7.md
index 53995449484..c9770fabf4e 100644
--- a/CHANGELOG-3.7.md
+++ b/CHANGELOG-3.7.md
@@ -26,7 +26,7 @@ These are the changes since Ice 3.6.3.
As a result, the Ice::DispatchStatus enumeration has been removed. See the
Ice manual for details on the new dispatch interceptor API.
-- The ice_getConnection() method now correctly returns a connection if
+- The ice_getConnection() method now correctly returns a connection if
connection caching is disabled (it previously returned a null connection).
- The iOS SSL transport is now based on the same implementation as macOS. Most
@@ -82,10 +82,14 @@ These are the changes since Ice 3.6.3.
- Updating Windows build system to use MSBuild instead of nmake.
-- Changed the parsing of hex escape sequences (\x....) in Slice string literals:
- the parsing now stops after 2 hex digits. For example, \x0ab is now read as '\x0a'
+- Changed the parsing of hex escape sequences (\x....) in Slice string literals:
+ the parsing now stops after 2 hex digits. For example, \x0ab is now read as '\x0a'
followed by 'b'. Previously all the hex digits where read like in C++.
+- Stringified identities and proxies now support non-ASCII characters
+ and universal character names (\unnnn and \Unnnnnnnn). See the property
+ Ice.ToStringMode and the static function/method identityToString.
+
## Java Changes
- Fixed a bug where unmarshaling Ice objects was really slow when using
diff --git a/config/PropertyNames.xml b/config/PropertyNames.xml
index 615fdd86c63..2e1f222005c 100644
--- a/config/PropertyNames.xml
+++ b/config/PropertyNames.xml
@@ -383,6 +383,7 @@ generated from the section label.
<property name="ThreadPool.Client" class="threadpool" />
<property name="ThreadPool.Server" class="threadpool" />
<property name="ThreadPriority"/>
+ <property name="ToStringMode" />
<property name="Trace.Admin.Properties" />
<property name="Trace.Admin.Logger" />
<property name="Trace.Locator" />
diff --git a/config/makeprops.py b/config/makeprops.py
index 015c4815260..127eea661a3 100755
--- a/config/makeprops.py
+++ b/config/makeprops.py
@@ -102,6 +102,13 @@ cppSrcPreamble = commonPreamble + """
"""
javaPreamble = commonPreamble + """
+package com.zeroc.IceInternal;
+
+public final class %(classname)s
+{
+"""
+
+javaCompatPreamble = commonPreamble + """
package IceInternal;
public final class %(classname)s
@@ -129,7 +136,7 @@ module.exports.Ice = Ice;
def usage():
global progname
- print >> sys.stderr, "Usage: " + progname + " [--{cpp|java|cs|js} file]"
+ print >> sys.stderr, "Usage: " + progname + " [--{cpp|java|java-compat|csharp|js} file]"
def progError(msg):
global progname
@@ -456,11 +463,26 @@ class JavaPropertyHandler(PropertyHandler):
self.srcFile.write(" };\n\n")
def moveFiles(self, location):
- dest = os.path.join(location, "java", "src", "Ice", "src", "main", "java", "IceInternal")
+ dest = os.path.join(location, "java", "src", "Ice", "src", "main", "java", "com", "zeroc", "IceInternal")
+ if os.path.exists(os.path.join(dest, self.className + ".java")):
+ os.remove(os.path.join(dest, self.className + ".java"))
+ shutil.move(self.className + ".java", dest)
+
+class JavaCompatPropertyHandler(JavaPropertyHandler):
+ def __init__(self, inputfile, c):
+ JavaPropertyHandler.__init__(self, inputfile, c)
+
+ def startFiles(self):
+ self.srcFile = file(self.className + ".java", "wb")
+ self.srcFile.write(javaCompatPreamble % {'inputfile' : self.inputfile, 'classname' : self.className})
+
+ def moveFiles(self, location):
+ dest = os.path.join(location, "java-compat", "src", "Ice", "src", "main", "java", "IceInternal")
if os.path.exists(os.path.join(dest, self.className + ".java")):
os.remove(os.path.join(dest, self.className + ".java"))
shutil.move(self.className + ".java", dest)
+
class CSPropertyHandler(PropertyHandler):
def __init__(self, inputfile, c):
PropertyHandler.__init__(self, inputfile, c)
@@ -677,6 +699,8 @@ def main():
lang = "cpp"
elif option == "--java":
lang = "java"
+ elif option == "--java-compat":
+ lang = "java-compat"
elif option == "--csharp":
lang = "csharp"
elif option == "--js":
@@ -695,6 +719,7 @@ def main():
contentHandler = MultiHandler(infile, "")
contentHandler.addHandlers([CppPropertyHandler(infile, className),
JavaPropertyHandler(infile, className),
+ JavaCompatPropertyHandler(infile, className),
CSPropertyHandler(infile, className),
JSPropertyHandler(infile, className)])
else:
@@ -702,6 +727,8 @@ def main():
contentHandler = CppPropertyHandler(infile, className)
elif lang == "java":
contentHandler = JavaPropertyHandler(infile, className)
+ elif lang == "java-compat":
+ contentHandler = JavaCompatPropertyHandler(infile, className)
elif lang == "csharp":
contentHandler = CSPropertyHandler(infile, className)
elif lang == "js":
diff --git a/cpp/include/Ice/Initialize.h b/cpp/include/Ice/Initialize.h
index f64a62db13b..bbf822dff0a 100644
--- a/cpp/include/Ice/Initialize.h
+++ b/cpp/include/Ice/Initialize.h
@@ -11,7 +11,7 @@
#define ICE_INITIALIZE_H
#include <IceUtil/Timer.h>
-#include <Ice/CommunicatorF.h>
+#include <Ice/Communicator.h>
#include <Ice/PropertiesF.h>
#include <Ice/InstanceF.h>
#include <Ice/LoggerF.h>
@@ -152,7 +152,8 @@ private:
};
ICE_API Identity stringToIdentity(const std::string&);
-ICE_API std::string identityToString(const Identity&);
+ICE_API std::string identityToString(const Identity&, ToStringMode = ICE_ENUM(ToStringMode, Unicode));
+
}
namespace IceInternal
diff --git a/cpp/include/IceUtil/StringUtil.h b/cpp/include/IceUtil/StringUtil.h
index 2e0763e7a46..71497f558b5 100644
--- a/cpp/include/IceUtil/StringUtil.h
+++ b/cpp/include/IceUtil/StringUtil.h
@@ -7,8 +7,8 @@
//
// **********************************************************************
-#ifndef ICE_STRING_UTIL_H
-#define ICE_STRING_UTIL_H
+#ifndef ICE_UTIL_STRING_UTIL_H
+#define ICE_UTIL_STRING_UTIL_H
#include <IceUtil/Config.h>
#include <vector>
@@ -17,10 +17,21 @@ namespace IceUtilInternal
{
//
-// Add escape sequences (like "\n", or "\0xxx") to make a string
-// readable in ASCII.
+// Must be kept in sync with Ice::ToStringMode
//
-ICE_API std::string escapeString(const std::string&, const std::string&);
+#ifdef ICE_CPP11_MAPPING
+enum class ToStringMode : unsigned char
+#else
+enum ToStringMode
+#endif
+{ Unicode, ASCII, Compat };
+
+//
+// Add escape sequences (like "\n", or "\123") to the input string
+// (first parameter).
+// The second parameter adds characters to escape, and can be empty.
+//
+ICE_API std::string escapeString(const std::string&, const std::string&, ToStringMode);
//
// Remove escape sequences added by escapeString. Throws IllegalArgumentException
@@ -35,7 +46,7 @@ ICE_API std::string unescapeString(const std::string&, std::string::size_type, s
ICE_API bool splitString(const std::string&, const std::string&, std::vector<std::string>&);
//
-// Join a list of strings using the given delimiter.
+// Join a list of strings using the given delimiter.
//
ICE_API std::string joinString(const std::vector<std::string>&, const std::string&);
diff --git a/cpp/src/Glacier2/Blobject.cpp b/cpp/src/Glacier2/Blobject.cpp
index 4b822469c81..1f58da34ffb 100644
--- a/cpp/src/Glacier2/Blobject.cpp
+++ b/cpp/src/Glacier2/Blobject.cpp
@@ -261,7 +261,7 @@ Glacier2::Blobject::invoke(ObjectPrx& proxy, const AMD_Object_ice_invokePtr& amd
}
if(_reverseConnection)
{
- out << "\nidentity = " << identityToString(proxy->ice_getIdentity());
+ out << "\nidentity = " << _instance->communicator()->identityToString(proxy->ice_getIdentity());
}
else
{
@@ -310,7 +310,7 @@ Glacier2::Blobject::invoke(ObjectPrx& proxy, const AMD_Object_ice_invokePtr& amd
out << "routing override";
if(_reverseConnection)
{
- out << "\nidentity = " << identityToString(proxy->ice_getIdentity());
+ out << "\nidentity = " << _instance->communicator()->identityToString(proxy->ice_getIdentity());
}
else
{
diff --git a/cpp/src/Glacier2/ClientBlobject.cpp b/cpp/src/Glacier2/ClientBlobject.cpp
index f10c3d614b8..d7aef4ae401 100644
--- a/cpp/src/Glacier2/ClientBlobject.cpp
+++ b/cpp/src/Glacier2/ClientBlobject.cpp
@@ -120,7 +120,7 @@ Glacier2::ClientBlobject::ice_invoke_async(const Ice::AMD_Object_ice_invokePtr&
{
Trace out(_instance->logger(), "Glacier2");
out << "rejecting request: " << rejectedFilters << "\n";
- out << "identity: " << identityToString(current.id);
+ out << "identity: " << _instance->communicator()->identityToString(current.id);
}
ObjectNotExistException ex(__FILE__, __LINE__);
diff --git a/cpp/src/Glacier2/FilterManager.cpp b/cpp/src/Glacier2/FilterManager.cpp
index 95c52f9633a..7457367f0b9 100644
--- a/cpp/src/Glacier2/FilterManager.cpp
+++ b/cpp/src/Glacier2/FilterManager.cpp
@@ -34,7 +34,7 @@ stringToSeq(const string& str, vector<string>& seq)
}
static void
-stringToSeq(const CommunicatorPtr& comm, const string& str, vector<Identity>& seq)
+stringToSeq(const string& str, vector<Identity>& seq)
{
string const ws = " \t";
@@ -214,7 +214,7 @@ Glacier2::FilterManager::create(const InstancePtr& instance, const string& userI
//
IdentitySeq allowIdSeq;
allow = props->getProperty("Glacier2.Filter.Identity.Accept");
- stringToSeq(instance->communicator(), allow, allowIdSeq);
+ stringToSeq(allow, allowIdSeq);
Glacier2::IdentitySetIPtr identityFilter = new Glacier2::IdentitySetI(allowIdSeq);
return new Glacier2::FilterManager(instance, categoryFilter, adapterIdFilter, identityFilter);
diff --git a/cpp/src/Glacier2/Instance.h b/cpp/src/Glacier2/Instance.h
index 65b0e70a848..ed1fd76f3ba 100644
--- a/cpp/src/Glacier2/Instance.h
+++ b/cpp/src/Glacier2/Instance.h
@@ -44,7 +44,7 @@ public:
const Glacier2::Instrumentation::RouterObserverPtr& getObserver() const { return _observer; }
void destroy();
-
+
private:
friend class SessionRouterI;
diff --git a/cpp/src/Glacier2/SessionRouterI.cpp b/cpp/src/Glacier2/SessionRouterI.cpp
index 91b5e05db6f..9f774b79a8e 100644
--- a/cpp/src/Glacier2/SessionRouterI.cpp
+++ b/cpp/src/Glacier2/SessionRouterI.cpp
@@ -1150,7 +1150,7 @@ SessionRouterI::getRouterImpl(const ConnectionPtr& connection, const Ice::Identi
{
Trace out(_instance->logger(), "Glacier2");
out << "rejecting request. no session is associated with the connection.\n";
- out << "identity: " << identityToString(id);
+ out << "identity: " << _instance->communicator()->identityToString(id);
}
connection->close(true);
throw ObjectNotExistException(__FILE__, __LINE__);
diff --git a/cpp/src/Glacier2Lib/NullPermissionsVerifier.cpp b/cpp/src/Glacier2Lib/NullPermissionsVerifier.cpp
index 31d33ad00a4..abc76a3b6e8 100644
--- a/cpp/src/Glacier2Lib/NullPermissionsVerifier.cpp
+++ b/cpp/src/Glacier2Lib/NullPermissionsVerifier.cpp
@@ -111,12 +111,12 @@ Init::checkPermissionVerifier(const string& val)
// check if it's actually a stringified identity
// (with typically missing " " because the category contains a space)
- if(val == identityToString(_nullPVId))
+ if(val == _communicator->identityToString(_nullPVId))
{
createObjects();
return _adapter->createProxy(_nullPVId)->ice_toString(); // Return valid proxy to rewrite the property
}
- else if(val == identityToString(_nullSSLPVId))
+ else if(val == _communicator->identityToString(_nullSSLPVId))
{
createObjects();
return _adapter->createProxy(_nullSSLPVId)->ice_toString(); // Return valid proxy to rewrite the property
diff --git a/cpp/src/Glacier2Lib/SessionHelper.cpp b/cpp/src/Glacier2Lib/SessionHelper.cpp
index 34565f357e4..5a6c9354ae1 100644
--- a/cpp/src/Glacier2Lib/SessionHelper.cpp
+++ b/cpp/src/Glacier2Lib/SessionHelper.cpp
@@ -1215,7 +1215,9 @@ string
Glacier2::SessionFactoryHelper::createProxyStr(const Ice::Identity& ident)
{
ostringstream os;
- os << "\"" << Ice::identityToString(ident) << "\":" << _protocol << " -p " << getPortInternal() << " -h \"" << _routerHost << "\"";
+ os << "\"" << identityToString(ident, Ice::ICE_ENUM(ToStringMode, Unicode)) << "\":" << _protocol
+ << " -p " << getPortInternal() << " -h \"" << _routerHost << "\"";
+
if(_timeout > 0)
{
os << " -t " << _timeout;
diff --git a/cpp/src/Ice/CommunicatorI.cpp b/cpp/src/Ice/CommunicatorI.cpp
index 8a257ede66b..99c332f629e 100644
--- a/cpp/src/Ice/CommunicatorI.cpp
+++ b/cpp/src/Ice/CommunicatorI.cpp
@@ -89,7 +89,7 @@ Ice::CommunicatorI::stringToIdentity(const string& s) const
string
Ice::CommunicatorI::identityToString(const Identity& ident) const
{
- return Ice::identityToString(ident);
+ return Ice::identityToString(ident, _instance->toStringMode());
}
ObjectAdapterPtr
diff --git a/cpp/src/Ice/Exception.cpp b/cpp/src/Ice/Exception.cpp
index 7e2fc340c9d..95136f5339a 100644
--- a/cpp/src/Ice/Exception.cpp
+++ b/cpp/src/Ice/Exception.cpp
@@ -14,6 +14,7 @@
#include <Ice/SlicedData.h>
#include <Ice/OutputStream.h>
#include <Ice/InputStream.h>
+#include <Ice/Initialize.h>
#include <IceUtil/StringUtil.h>
#ifdef ICE_OS_WINRT
# include <Ice/StringConverter.h>
@@ -339,16 +340,7 @@ void
Ice::IllegalIdentityException::ice_print(ostream& out) const
{
Exception::ice_print(out);
- out << ":\nillegal identity: `";
- if(id.category.empty())
- {
- out << IceUtilInternal::escapeString(id.name, "/");
- }
- else
- {
- out << IceUtilInternal::escapeString(id.category, "/") << '/' << IceUtilInternal::escapeString(id.name, "/");
- }
- out << "'";
+ out << ":\nillegal identity: `" << identityToString(id, ICE_ENUM(ToStringMode, Unicode)) << "'";
}
void
@@ -362,16 +354,7 @@ Ice::IllegalServantException::ice_print(ostream& out) const
static void
printFailedRequestData(ostream& out, const RequestFailedException& ex)
{
- out << ":\nidentity: `";
- if(ex.id.category.empty())
- {
- out << IceUtilInternal::escapeString(ex.id.name, "/");
- }
- else
- {
- out << IceUtilInternal::escapeString(ex.id.category, "/") << '/' << IceUtilInternal::escapeString(ex.id.name, "/");
- }
- out << "'";
+ out << ":\nidentity: `" << identityToString(ex.id, ICE_ENUM(ToStringMode, Unicode)) << "'";
out << "\nfacet: " << ex.facet;
out << "\noperation: " << ex.operation;
}
diff --git a/cpp/src/Ice/Incoming.cpp b/cpp/src/Ice/Incoming.cpp
index 7b5e6741660..da4bb25cbc6 100644
--- a/cpp/src/Ice/Incoming.cpp
+++ b/cpp/src/Ice/Incoming.cpp
@@ -22,7 +22,7 @@
#include <Ice/Protocol.h>
#include <Ice/ReplyStatus.h>
#include <Ice/ResponseHandler.h>
-#include <IceUtil/StringUtil.h>
+#include <Ice/StringUtil.h>
#include <typeinfo>
using namespace std;
@@ -222,9 +222,12 @@ IceInternal::IncomingBase::warning(const Exception& ex) const
{
Warning out(_os.instance()->initializationData().logger);
+ ToStringMode toStringMode = _os.instance()->toStringMode();
+
out << "dispatch exception: " << ex;
- out << "\nidentity: " << Ice::identityToString(_current.id);
- out << "\nfacet: " << IceUtilInternal::escapeString(_current.facet, "");
+ out << "\nidentity: " << identityToString(_current.id, toStringMode);
+ out << "\nfacet: ";
+ out << escapeString(_current.facet, "", toStringMode);
out << "\noperation: " << _current.operation;
if(_current.con)
@@ -252,10 +255,11 @@ void
IceInternal::IncomingBase::warning(const string& msg) const
{
Warning out(_os.instance()->initializationData().logger);
+ ToStringMode toStringMode = _os.instance()->toStringMode();
out << "dispatch exception: " << msg;
- out << "\nidentity: " << Ice::identityToString(_current.id);
- out << "\nfacet: " << IceUtilInternal::escapeString(_current.facet, "");
+ out << "\nidentity: " << identityToString(_current.id, toStringMode);
+ out << "\nfacet: " << escapeString(_current.facet, "", toStringMode);
out << "\noperation: " << _current.operation;
if(_current.con)
diff --git a/cpp/src/Ice/Initialize.cpp b/cpp/src/Ice/Initialize.cpp
index 52f03678659..f1f92c3826d 100644
--- a/cpp/src/Ice/Initialize.cpp
+++ b/cpp/src/Ice/Initialize.cpp
@@ -16,7 +16,7 @@
#include <Ice/LoggerI.h>
#include <Ice/Instance.h>
#include <Ice/PluginManagerI.h>
-#include <IceUtil/StringUtil.h>
+#include <Ice/StringUtil.h>
#include <IceUtil/Mutex.h>
#include <IceUtil/MutexPtrLock.h>
#include <Ice/StringConverter.h>
@@ -357,15 +357,6 @@ IceInternal::getInstanceTimer(const CommunicatorPtr& communicator)
Identity
Ice::stringToIdentity(const string& s)
{
- //
- // This method only accepts printable ascii. Since printable ascii is a subset
- // of all narrow string encodings, it is not necessary to convert the string
- // from the native string encoding. Any characters other than printable-ASCII
- // will cause an IllegalArgumentException. Note that it can contain Unicode
- // encoded in the escaped form which is the reason why we call fromUTF8 after
- // unespcaping the printable ASCII string.
- //
-
Identity ident;
//
@@ -376,7 +367,7 @@ Ice::stringToIdentity(const string& s)
while((pos = s.find('/', pos)) != string::npos)
{
int escapes = 0;
- while(static_cast<int>(pos)- escapes > 0 && s[pos - escapes - 1] == '\\')
+ while(static_cast<int>(pos) - escapes > 0 && s[pos - escapes - 1] == '\\')
{
escapes++;
}
@@ -396,7 +387,7 @@ Ice::stringToIdentity(const string& s)
// Extra unescaped slash found.
//
IdentityParseException ex(__FILE__, __LINE__);
- ex.str = "unescaped backslash in identity `" + s + "'";
+ ex.str = "unescaped '/' in identity `" + s + "'";
throw ex;
}
}
@@ -407,7 +398,7 @@ Ice::stringToIdentity(const string& s)
{
try
{
- ident.name = IceUtilInternal::unescapeString(s, 0, s.size());
+ ident.name = unescapeString(s, 0, s.size());
}
catch(const IceUtil::IllegalArgumentException& e)
{
@@ -420,7 +411,7 @@ Ice::stringToIdentity(const string& s)
{
try
{
- ident.category = IceUtilInternal::unescapeString(s, 0, slash);
+ ident.category = unescapeString(s, 0, slash);
}
catch(const IceUtil::IllegalArgumentException& e)
{
@@ -428,11 +419,12 @@ Ice::stringToIdentity(const string& s)
ex.str = "invalid category in identity `" + s + "': " + e.reason();
throw ex;
}
+
if(slash + 1 < s.size())
{
try
{
- ident.name = IceUtilInternal::unescapeString(s, slash + 1, s.size());
+ ident.name = unescapeString(s, slash + 1, s.size());
}
catch(const IceUtil::IllegalArgumentException& e)
{
@@ -443,28 +435,18 @@ Ice::stringToIdentity(const string& s)
}
}
- ident.name = UTF8ToNative(ident.name, getProcessStringConverter());
- ident.category = UTF8ToNative(ident.category, getProcessStringConverter());
-
return ident;
}
string
-Ice::identityToString(const Identity& ident)
+Ice::identityToString(const Identity& ident, ToStringMode toStringMode)
{
- //
- // This method returns the stringified identity. The returned string only
- // contains printable ascii. It can contain UTF8 in the escaped form.
- //
- string name = nativeToUTF8(ident.name, getProcessStringConverter());
- string category = nativeToUTF8(ident.category, getProcessStringConverter());
-
- if(category.empty())
+ if(ident.category.empty())
{
- return IceUtilInternal::escapeString(name, "/");
+ return escapeString(ident.name, "/", toStringMode);
}
else
{
- return IceUtilInternal::escapeString(category, "/") + '/' + IceUtilInternal::escapeString(name, "/");
+ return escapeString(ident.category, "/", toStringMode) + '/' + escapeString(ident.name, "/", toStringMode);
}
}
diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp
index d99567e09f9..304036dec90 100644
--- a/cpp/src/Ice/Instance.cpp
+++ b/cpp/src/Ice/Instance.cpp
@@ -948,6 +948,7 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi
_messageSizeMax(0),
_batchAutoFlushSize(0),
_collectObjects(false),
+ _toStringMode(ICE_ENUM(ToStringMode, Unicode)),
_implicitContext(0),
_stringConverter(Ice::getProcessStringConverter()),
_wstringConverter(Ice::getProcessWstringConverter()),
@@ -1189,6 +1190,21 @@ IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const Initi
const_cast<bool&>(_collectObjects) = _initData.properties->getPropertyAsInt("Ice.CollectObjects") > 0;
+ string toStringModeStr = _initData.properties->getPropertyWithDefault("Ice.ToStringMode", "Unicode");
+ if(toStringModeStr == "ASCII")
+ {
+ const_cast<ToStringMode&>(_toStringMode) = ICE_ENUM(ToStringMode, ASCII);
+ }
+ else if(toStringModeStr == "Compat")
+ {
+ const_cast<ToStringMode&>(_toStringMode) = ICE_ENUM(ToStringMode, Compat);
+ }
+ else if(toStringModeStr != "Unicode")
+ {
+ throw InitializationException(__FILE__, __LINE__, "The value for Ice.ToStringMode must be Unicode, ASCII or Compat");
+ }
+
+
//
// Client ACM enabled by default. Server ACM disabled by default.
//
diff --git a/cpp/src/Ice/Instance.h b/cpp/src/Ice/Instance.h
index 22a39169c38..2e4fd503b16 100644
--- a/cpp/src/Ice/Instance.h
+++ b/cpp/src/Ice/Instance.h
@@ -110,6 +110,7 @@ public:
size_t messageSizeMax() const { return _messageSizeMax; }
size_t batchAutoFlushSize() const { return _batchAutoFlushSize; }
bool collectObjects() const { return _collectObjects; }
+ Ice::ToStringMode toStringMode() const { return _toStringMode; }
const ACMConfig& clientACM() const;
const ACMConfig& serverACM() const;
@@ -177,6 +178,7 @@ private:
const size_t _messageSizeMax; // Immutable, not reset by destroy().
const size_t _batchAutoFlushSize; // Immutable, not reset by destroy().
const bool _collectObjects; // Immutable, not reset by destroy().
+ const Ice::ToStringMode _toStringMode; // Immutable, not reset by destroy()
ACMConfig _clientACM;
ACMConfig _serverACM;
RouterManagerPtr _routerManager;
diff --git a/cpp/src/Ice/InstrumentationI.cpp b/cpp/src/Ice/InstrumentationI.cpp
index 64ff4f91e07..0f816647a11 100644
--- a/cpp/src/Ice/InstrumentationI.cpp
+++ b/cpp/src/Ice/InstrumentationI.cpp
@@ -334,7 +334,7 @@ public:
string
getIdentity() const
{
- return identityToString(_current.id);
+ return _current.adapter->getCommunicator()->identityToString(_current.id);
}
private:
@@ -443,7 +443,7 @@ public:
catch(const Exception&)
{
// Either a fixed proxy or the communicator is destroyed.
- os << identityToString(_proxy->ice_getIdentity());
+ os << _proxy->ice_getCommunicator()->identityToString(_proxy->ice_getIdentity());
os << " [" << _operation << ']';
}
}
@@ -474,7 +474,7 @@ public:
{
if(_proxy)
{
- return identityToString(_proxy->ice_getIdentity());
+ return _proxy->ice_getCommunicator()->identityToString(_proxy->ice_getIdentity());
}
else
{
diff --git a/cpp/src/Ice/LocatorInfo.cpp b/cpp/src/Ice/LocatorInfo.cpp
index 03264b5898c..74f65e2d808 100644
--- a/cpp/src/Ice/LocatorInfo.cpp
+++ b/cpp/src/Ice/LocatorInfo.cpp
@@ -785,12 +785,13 @@ IceInternal::LocatorInfo::getEndpointsException(const ReferencePtr& ref, const I
Trace out(ref->getInstance()->initializationData().logger,
ref->getInstance()->traceLevels()->locationCat);
out << "object not found" << "\n";
- out << "object = " << Ice::identityToString(ref->getIdentity());
+ out << "object = " << Ice::identityToString(ref->getIdentity(),
+ ref->getInstance()->toStringMode());
}
NotRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = "object";
- ex.id = Ice::identityToString(ref->getIdentity());
+ ex.id = Ice::identityToString(ref->getIdentity(), ref->getInstance()->toStringMode());
throw ex;
}
catch(const NotRegisteredException&)
@@ -805,7 +806,8 @@ IceInternal::LocatorInfo::getEndpointsException(const ReferencePtr& ref, const I
out << "couldn't contact the locator to retrieve adapter endpoints\n";
if(ref->getAdapterId().empty())
{
- out << "object = " << Ice::identityToString(ref->getIdentity()) << "\n";
+ out << "object = " << Ice::identityToString(ref->getIdentity(), ref->getInstance()->toStringMode())
+ << "\n";
}
else
{
@@ -840,7 +842,7 @@ IceInternal::LocatorInfo::getEndpointsTrace(const ReferencePtr& ref,
if(ref->getAdapterId().empty())
{
out << "object\n";
- out << "object = " << Ice::identityToString(ref->getIdentity());
+ out << "object = " << Ice::identityToString(ref->getIdentity(), ref->getInstance()->toStringMode());
}
else
{
@@ -863,7 +865,8 @@ IceInternal::LocatorInfo::trace(const string& msg, const ReferencePtr& ref, cons
}
else
{
- out << "object = " << Ice::identityToString(ref->getIdentity()) << '\n';
+ out << "object = " << Ice::identityToString(ref->getIdentity(), ref->getInstance()->toStringMode())
+ << '\n';
}
const char* sep = endpoints.size() > 1 ? ":" : "";
@@ -901,7 +904,8 @@ IceInternal::LocatorInfo::getObjectRequest(const ReferencePtr& ref)
if(ref->getInstance()->traceLevels()->location >= 1)
{
Trace out(ref->getInstance()->initializationData().logger, ref->getInstance()->traceLevels()->locationCat);
- out << "searching for object by id\nobject = " << Ice::identityToString(ref->getIdentity());
+ out << "searching for object by id\nobject = " << Ice::identityToString(ref->getIdentity(),
+ ref->getInstance()->toStringMode());
}
map<Ice::Identity, RequestPtr>::const_iterator p = _objectRequests.find(ref->getIdentity());
diff --git a/cpp/src/Ice/ObjectAdapterI.cpp b/cpp/src/Ice/ObjectAdapterI.cpp
index 18cc2dd87f0..0631186769d 100644
--- a/cpp/src/Ice/ObjectAdapterI.cpp
+++ b/cpp/src/Ice/ObjectAdapterI.cpp
@@ -682,7 +682,7 @@ Ice::ObjectAdapterI::getEndpoints() const
EndpointSeq endpoints;
transform(_incomingConnectionFactories.begin(), _incomingConnectionFactories.end(),
- back_inserter(endpoints),
+ back_inserter(endpoints),
#ifdef ICE_CPP11_MAPPING
[](const IncomingConnectionFactoryPtr& factory)
{
@@ -1020,8 +1020,9 @@ Ice::ObjectAdapterI::initialize(const RouterPrxPtr& router)
//
if(_routerInfo->getAdapter())
{
- throw AlreadyRegisteredException(__FILE__, __LINE__, "object adapter with router",
- Ice::identityToString(router->ice_getIdentity()));
+ throw AlreadyRegisteredException(__FILE__, __LINE__,
+ "object adapter with router",
+ _communicator->identityToString(router->ice_getIdentity()));
}
//
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index c1a1cde9335..1bf95a2df3b 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -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 ../config/PropertyNames.xml, Tue Oct 18 11:38:00 2016
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -163,6 +163,7 @@ const IceInternal::Property IcePropsData[] =
IceInternal::Property("Ice.ThreadPool.Server.ThreadIdleTime", false, 0),
IceInternal::Property("Ice.ThreadPool.Server.ThreadPriority", false, 0),
IceInternal::Property("Ice.ThreadPriority", false, 0),
+ IceInternal::Property("Ice.ToStringMode", false, 0),
IceInternal::Property("Ice.Trace.Admin.Properties", false, 0),
IceInternal::Property("Ice.Trace.Admin.Logger", false, 0),
IceInternal::Property("Ice.Trace.Locator", false, 0),
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 52e12f92225..e9c85a1e59f 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -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 ../config/PropertyNames.xml, Tue Oct 18 11:38:00 2016
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/Ice/Reference.cpp b/cpp/src/Ice/Reference.cpp
index 86328e0880a..12296b9f04f 100644
--- a/cpp/src/Ice/Reference.cpp
+++ b/cpp/src/Ice/Reference.cpp
@@ -28,8 +28,8 @@
#include <Ice/ConnectionRequestHandler.h>
#include <Ice/DefaultsAndOverrides.h>
#include <Ice/Comparable.h>
+#include <Ice/StringUtil.h>
-#include <IceUtil/StringUtil.h>
#include <IceUtil/Random.h>
#include <IceUtil/MutexPtrLock.h>
@@ -231,13 +231,18 @@ IceInternal::Reference::toString() const
//
ostringstream s;
+ ToStringMode toStringMode = _instance->toStringMode();
+ const string separators = " :@";
+
+ string id = Ice::identityToString(_identity, 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::identityToString(_identity);
- if(id.find_first_of(" :@") != string::npos)
+
+ if(id.find_first_of(separators) != string::npos)
{
s << '"' << id << '"';
}
@@ -250,14 +255,13 @@ IceInternal::Reference::toString() const
{
s << " -f ";
+ string fs = escapeString(fs, "", toStringMode);
//
// If the encoded facet string contains characters which
// the reference parser uses as separators, then we enclose
// the facet string in quotes.
//
- string fs = nativeToUTF8(_facet, _instance->getStringConverter());
- fs = IceUtilInternal::escapeString(fs, "");
- if(fs.find_first_of(" :@") != string::npos)
+ if(fs.find_first_of(separators) != string::npos)
{
s << '"' << fs << '"';
}
@@ -1224,8 +1228,7 @@ IceInternal::RoutableReference::toString() const
// reference parser uses as separators, then we enclose the
// adapter id string in quotes.
//
- string a = nativeToUTF8(_adapterId, getInstance()->getStringConverter());
- a = IceUtilInternal::escapeString(a, "");
+ string a = escapeString(_adapterId, "", getInstance()->toStringMode());
if(a.find_first_of(" :@") != string::npos)
{
result.append("\"");
diff --git a/cpp/src/Ice/ReferenceFactory.cpp b/cpp/src/Ice/ReferenceFactory.cpp
index 3788324d81d..63b8df7effe 100644
--- a/cpp/src/Ice/ReferenceFactory.cpp
+++ b/cpp/src/Ice/ReferenceFactory.cpp
@@ -24,7 +24,7 @@
#include <Ice/Properties.h>
#include <Ice/DefaultsAndOverrides.h>
#include <Ice/PropertyNames.h>
-#include <IceUtil/StringUtil.h>
+#include <Ice/StringUtil.h>
using namespace std;
using namespace Ice;
@@ -156,6 +156,7 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP
// Parsing the identity may raise IdentityParseException.
//
Identity ident = Ice::stringToIdentity(idstr);
+
if(ident.name.empty())
{
//
@@ -279,7 +280,7 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP
try
{
- facet = IceUtilInternal::unescapeString(argument, 0, argument.size());
+ facet = unescapeString(argument, 0, argument.size());
}
catch(const IceUtil::IllegalArgumentException& e)
{
@@ -288,7 +289,6 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP
throw ex;
}
- facet = UTF8ToNative(facet, _instance->getStringConverter());
break;
}
@@ -554,7 +554,7 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP
try
{
- adapter = IceUtilInternal::unescapeString(adapterstr, 0, adapterstr.size());
+ adapter = unescapeString(adapterstr, 0, adapterstr.size());
}
catch(const IceUtil::IllegalArgumentException& e)
{
@@ -569,8 +569,6 @@ IceInternal::ReferenceFactory::create(const string& str, const string& propertyP
throw ex;
}
- adapter = UTF8ToNative(adapter, _instance->getStringConverter());
-
return create(ident, facet, mode, secure, protocol, encoding, endpoints, adapter, propertyPrefix);
break;
}
@@ -934,4 +932,3 @@ IceInternal::ReferenceFactory::create(const Identity& ident,
invocationTimeout,
ctx);
}
-
diff --git a/cpp/src/Ice/ServantManager.cpp b/cpp/src/Ice/ServantManager.cpp
index 3d1f51112ae..16c5da45d1f 100644
--- a/cpp/src/Ice/ServantManager.cpp
+++ b/cpp/src/Ice/ServantManager.cpp
@@ -12,7 +12,7 @@
#include <Ice/LocalException.h>
#include <Ice/LoggerUtil.h>
#include <Ice/Instance.h>
-#include <IceUtil/StringUtil.h>
+#include <Ice/StringUtil.h>
using namespace std;
using namespace Ice;
@@ -44,11 +44,11 @@ IceInternal::ServantManager::addServant(const ObjectPtr& object, const Identity&
{
AlreadyRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = "servant";
- ex.id = Ice::identityToString(ident);
+ ToStringMode toStringMode = _instance->toStringMode();
+ ex.id = Ice::identityToString(ident, toStringMode);
if(!facet.empty())
{
- string fs = nativeToUTF8(facet, _instance->getStringConverter());
- ex.id += " -f " + IceUtilInternal::escapeString(fs, "");
+ ex.id += " -f " + escapeString(facet, "", toStringMode);
}
throw ex;
}
@@ -104,11 +104,11 @@ IceInternal::ServantManager::removeServant(const Identity& ident, const string&
{
NotRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = "servant";
- ex.id = Ice::identityToString(ident);
+ ToStringMode toStringMode = _instance->toStringMode();
+ ex.id = Ice::identityToString(ident, toStringMode);
if(!facet.empty())
{
- string fs = nativeToUTF8(facet, _instance->getStringConverter());
- ex.id += " -f " + IceUtilInternal::escapeString(fs, "");
+ ex.id += " -f " + escapeString(facet, "", toStringMode);
}
throw ex;
}
@@ -178,7 +178,7 @@ IceInternal::ServantManager::removeAllFacets(const Identity& ident)
{
NotRegisteredException ex(__FILE__, __LINE__);
ex.kindOfObject = "servant";
- ex.id = Ice::identityToString(ident);
+ ex.id = Ice::identityToString(ident, _instance->toStringMode());
throw ex;
}
diff --git a/cpp/src/Ice/StringUtil.h b/cpp/src/Ice/StringUtil.h
new file mode 100644
index 00000000000..70dab65bf88
--- /dev/null
+++ b/cpp/src/Ice/StringUtil.h
@@ -0,0 +1,35 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#ifndef ICE_STRING_UTIL_H
+#define ICE_STRING_UTIL_H
+
+#include <Ice/Initialize.h>
+#include <IceUtil/StringUtil.h>
+
+namespace IceInternal
+{
+
+//
+// Adapter for ToStringMode
+//
+inline std::string
+escapeString(const std::string& s, const std::string& special, Ice::ToStringMode mode)
+{
+ return IceUtilInternal::escapeString(s, special, static_cast<IceUtilInternal::ToStringMode>(mode));
+}
+
+//
+// Provided for consistency with escapeString
+//
+using IceUtilInternal::unescapeString;
+
+}
+
+#endif
diff --git a/cpp/src/Ice/TraceUtil.cpp b/cpp/src/Ice/TraceUtil.cpp
index 5e92c6c05d5..db7c0041b45 100644
--- a/cpp/src/Ice/TraceUtil.cpp
+++ b/cpp/src/Ice/TraceUtil.cpp
@@ -9,7 +9,7 @@
#include <IceUtil/Mutex.h>
#include <IceUtil/MutexPtrLock.h>
-#include <IceUtil/StringUtil.h>
+#include <Ice/StringUtil.h>
#include <Ice/TraceUtil.h>
#include <Ice/Instance.h>
#include <Ice/Object.h>
@@ -29,16 +29,22 @@ using namespace IceInternal;
static void
printIdentityFacetOperation(ostream& s, InputStream& stream)
{
+ ToStringMode toStringMode = ICE_ENUM(ToStringMode, Unicode);
+ if(stream.instance())
+ {
+ toStringMode = stream.instance()->toStringMode();
+ }
+
Identity identity;
stream.read(identity);
- s << "\nidentity = " << Ice::identityToString(identity);
+ s << "\nidentity = " << Ice::identityToString(identity, toStringMode);
vector<string> facet;
stream.read(facet);
s << "\nfacet = ";
if(!facet.empty())
{
- s << IceUtilInternal::escapeString(facet[0], "");
+ s << escapeString(facet[0], "", toStringMode);
}
string operation;
diff --git a/cpp/src/IceBox/Admin.cpp b/cpp/src/IceBox/Admin.cpp
index bf7fa5d5a05..c7c76bac161 100644
--- a/cpp/src/IceBox/Admin.cpp
+++ b/cpp/src/IceBox/Admin.cpp
@@ -116,7 +116,7 @@ Client::run(int argc, char* argv[])
return EXIT_FAILURE;
}
- managerProxy = "\"" + identityToString(managerIdentity) + "\" :" + managerEndpoints;
+ managerProxy = "\"" + communicator()->identityToString(managerIdentity) + "\" :" + managerEndpoints;
}
else
{
@@ -127,7 +127,7 @@ Client::run(int argc, char* argv[])
return EXIT_FAILURE;
}
- managerProxy = "\"" + identityToString(managerIdentity) + "\" @" + managerAdapterId;
+ managerProxy = "\"" + communicator()->identityToString(managerIdentity) + "\" @" + managerAdapterId;
}
base = communicator()->stringToProxy(managerProxy);
diff --git a/cpp/src/IceGrid/AdminI.cpp b/cpp/src/IceGrid/AdminI.cpp
index 60af9f7b2df..21e190250e5 100644
--- a/cpp/src/IceGrid/AdminI.cpp
+++ b/cpp/src/IceGrid/AdminI.cpp
@@ -688,7 +688,7 @@ AdminI::updateObject(const Ice::ObjectPrx& proxy, const ::Ice::Current&)
if(id.category == _database->getInstanceName())
{
DeploymentException ex;
- ex.reason = "updating object `" + identityToString(id) + "' is not allowed:\n";
+ ex.reason = "updating object `" + _database->getCommunicator()->identityToString(id) + "' is not allowed:\n";
ex.reason += "objects with identity category `" + id.category + "' are managed by IceGrid";
throw ex;
}
@@ -709,7 +709,7 @@ AdminI::addObjectWithType(const Ice::ObjectPrx& proxy, const string& type, const
if(id.category == _database->getInstanceName())
{
DeploymentException ex;
- ex.reason = "adding object `" + identityToString(id) + "' is not allowed:\n";
+ ex.reason = "adding object `" + _database->getCommunicator()->identityToString(id) + "' is not allowed:\n";
ex.reason += "objects with identity category `" + id.category + "' are managed by IceGrid";
throw ex;
}
@@ -727,7 +727,7 @@ AdminI::removeObject(const Ice::Identity& id, const Ice::Current&)
if(id.category == _database->getInstanceName())
{
DeploymentException ex;
- ex.reason = "removing object `" + identityToString(id) + "' is not allowed:\n";
+ ex.reason = "removing object `" + _database->getCommunicator()->identityToString(id) + "' is not allowed:\n";
ex.reason += "objects with identity category `" + id.category + "' are managed by IceGrid";
throw ex;
}
diff --git a/cpp/src/IceGrid/AllocatableObjectCache.cpp b/cpp/src/IceGrid/AllocatableObjectCache.cpp
index ae3294bb51c..3a9799e1eac 100644
--- a/cpp/src/IceGrid/AllocatableObjectCache.cpp
+++ b/cpp/src/IceGrid/AllocatableObjectCache.cpp
@@ -134,7 +134,7 @@ AllocatableObjectCache::add(const ObjectInfo& info, const AllocatablePtr& parent
if(getImpl(id))
{
Ice::Error out(_communicator->getLogger());
- out << "can't add duplicate allocatable object `" << identityToString(id) << "'";
+ out << "can't add duplicate allocatable object `" << _communicator->identityToString(id) << "'";
return;
}
@@ -151,7 +151,7 @@ AllocatableObjectCache::add(const ObjectInfo& info, const AllocatablePtr& parent
if(_traceLevels && _traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "added allocatable object `" << identityToString(id) << "'";
+ out << "added allocatable object `" << _communicator->identityToString(id) << "'";
}
}
@@ -177,7 +177,7 @@ AllocatableObjectCache::remove(const Ice::Identity& id)
if(!entry)
{
Ice::Error out(_communicator->getLogger());
- out << "can't remove unknown object `" << identityToString(id) << "'";
+ out << "can't remove unknown object `" << _communicator->identityToString(id) << "'";
}
removeImpl(id);
@@ -191,7 +191,7 @@ AllocatableObjectCache::remove(const Ice::Identity& id)
if(_traceLevels && _traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "removed allocatable object `" << identityToString(id) << "'";
+ out << "removed allocatable object `" << _communicator->identityToString(id) << "'";
}
}
diff --git a/cpp/src/IceGrid/Database.cpp b/cpp/src/IceGrid/Database.cpp
index 694d59c073d..5c9167b784d 100644
--- a/cpp/src/IceGrid/Database.cpp
+++ b/cpp/src/IceGrid/Database.cpp
@@ -1483,7 +1483,7 @@ Database::addObject(const ObjectInfo& info)
if(_traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "added object `" << identityToString(id) << "' (serial = `" << dbSerial << "')";
+ out << "added object `" << _communicator->identityToString(id) << "' (serial = `" << dbSerial << "')";
}
}
_objectObserverTopic->waitForSyncedSubscribers(serial);
@@ -1539,7 +1539,7 @@ Database::addOrUpdateObject(const ObjectInfo& info, Ice::Long dbSerial)
if(_traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << (!update ? "added" : "updated") << " object `" << identityToString(id) << "' (serial = `" << dbSerial << "')";
+ out << (!update ? "added" : "updated") << " object `" << _communicator->identityToString(id) << "' (serial = `" << dbSerial << "')";
}
}
_objectObserverTopic->waitForSyncedSubscribers(serial);
@@ -1556,7 +1556,7 @@ Database::removeObject(const Ice::Identity& id, Ice::Long dbSerial)
if(_objectCache.has(id))
{
DeploymentException ex;
- ex.reason = "removing object `" + identityToString(id) + "' is not allowed:\n";
+ ex.reason = "removing object `" + _communicator->identityToString(id) + "' is not allowed:\n";
ex.reason += "the object was added with the application descriptor `";
ex.reason += _objectCache.get(id)->getApplication();
ex.reason += "'";
@@ -1590,7 +1590,7 @@ Database::removeObject(const Ice::Identity& id, Ice::Long dbSerial)
if(_traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "removed object `" << identityToString(id) << "' (serial = `" << dbSerial << "')";
+ out << "removed object `" << _communicator->identityToString(id) << "' (serial = `" << dbSerial << "')";
}
}
_objectObserverTopic->waitForSyncedSubscribers(serial);
@@ -1609,7 +1609,7 @@ Database::updateObject(const Ice::ObjectPrx& proxy)
if(_objectCache.has(id))
{
DeploymentException ex;
- ex.reason = "updating object `" + identityToString(id) + "' is not allowed:\n";
+ ex.reason = "updating object `" + _communicator->identityToString(id) + "' is not allowed:\n";
ex.reason += "the object was added with the application descriptor `";
ex.reason += _objectCache.get(id)->getApplication();
ex.reason += "'";
@@ -1644,7 +1644,7 @@ Database::updateObject(const Ice::ObjectPrx& proxy)
if(_traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "updated object `" << identityToString(id) << "' (serial = `" << dbSerial << "')";
+ out << "updated object `" << _communicator->identityToString(id) << "' (serial = `" << dbSerial << "')";
}
}
_objectObserverTopic->waitForSyncedSubscribers(serial);
@@ -1833,7 +1833,7 @@ Database::getAllObjectInfos(const string& expression)
ObjectsMapROCursor cursor(_objects, txn);
while(cursor.get(id, info, MDB_NEXT))
{
- if(expression.empty() || IceUtilInternal::match(identityToString(id), expression, true))
+ if(expression.empty() || IceUtilInternal::match(_communicator->identityToString(id), expression, true))
{
infos.push_back(info);
}
@@ -2089,7 +2089,7 @@ Database::checkObjectForAddition(const Ice::Identity& objectId,
if(found)
{
DeploymentException ex;
- ex.reason = "object `" + identityToString(objectId) + "' is already registered";
+ ex.reason = "object `" + _communicator->identityToString(objectId) + "' is already registered";
throw ex;
}
}
@@ -2761,7 +2761,7 @@ Database::addObject(const IceDB::ReadWriteTxn& txn, const ObjectInfo& info, bool
catch(const IceDB::KeyTooLongException& ex)
{
throw DeploymentException("object identity `" +
- identityToString(info.proxy->ice_getIdentity())
+ _communicator->identityToString(info.proxy->ice_getIdentity())
+ "' is too long: " + ex.what());
}
try
diff --git a/cpp/src/IceGrid/DescriptorHelper.cpp b/cpp/src/IceGrid/DescriptorHelper.cpp
index 7e1a531dbb5..3eef14ff351 100644
--- a/cpp/src/IceGrid/DescriptorHelper.cpp
+++ b/cpp/src/IceGrid/DescriptorHelper.cpp
@@ -650,11 +650,11 @@ Ice::Identity
Resolver::operator()(const Ice::Identity& value, const string& name) const
{
assert(_communicator);
- string str = asId(identityToString(value), name, false);
+ string str = asId(_communicator->identityToString(value), name, false);
Ice::Identity id = Ice::stringToIdentity(str);
if(id.name.empty())
{
- exception("invalid object identity `" + identityToString(value) + "': name empty");
+ exception("invalid object identity `" + _communicator->identityToString(value) + "': name empty");
}
return id;
}
@@ -1387,7 +1387,7 @@ CommunicatorHelper::printObjectAdapter(const Ice::CommunicatorPtr& communicator,
{
out << nl << "well-known object";
out << sb;
- out << nl << "identity = `" << identityToString(p->id) << "' ";
+ out << nl << "identity = `" << communicator->identityToString(p->id) << "' ";
if(!p->type.empty())
{
out << nl << "type = `" << p->type << "'";
@@ -1402,7 +1402,7 @@ CommunicatorHelper::printObjectAdapter(const Ice::CommunicatorPtr& communicator,
{
out << nl << "allocatable";
out << sb;
- out << nl << "identity = `" << identityToString(p->id) << "' ";
+ out << nl << "identity = `" << communicator->identityToString(p->id) << "' ";
if(!p->type.empty())
{
out << nl << "type = `" << p->type << "'";
@@ -2825,7 +2825,7 @@ ApplicationHelper::ApplicationHelper(const Ice::CommunicatorPtr& communicator,
{
if(objectIds.count(*o) > 1)
{
- resolve.exception("duplicate object `" + identityToString(*o) + "'");
+ resolve.exception("duplicate object `" + _communicator->identityToString(*o) + "'");
}
}
}
diff --git a/cpp/src/IceGrid/ObjectCache.cpp b/cpp/src/IceGrid/ObjectCache.cpp
index 9d7138e7050..cc76cc2d9b7 100644
--- a/cpp/src/IceGrid/ObjectCache.cpp
+++ b/cpp/src/IceGrid/ObjectCache.cpp
@@ -82,7 +82,7 @@ ObjectCache::add(const ObjectInfo& info, const string& application)
if(getImpl(id))
{
Ice::Error out(_communicator->getLogger());
- out << "can't add duplicate object `" << identityToString(id) << "'";
+ out << "can't add duplicate object `" << _communicator->identityToString(id) << "'";
return;
}
@@ -99,7 +99,7 @@ ObjectCache::add(const ObjectInfo& info, const string& application)
if(_traceLevels && _traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "added object `" << identityToString(id) << "'";
+ out << "added object `" << _communicator->identityToString(id) << "'";
}
}
@@ -123,7 +123,7 @@ ObjectCache::remove(const Ice::Identity& id)
if(!entry)
{
Ice::Error out(_communicator->getLogger());
- out << "can't remove unknown object `" << identityToString(id) << "'";
+ out << "can't remove unknown object `" << _communicator->identityToString(id) << "'";
return;
}
removeImpl(id);
@@ -138,7 +138,7 @@ ObjectCache::remove(const Ice::Identity& id)
if(_traceLevels && _traceLevels->object > 0)
{
Ice::Trace out(_traceLevels->logger, _traceLevels->objectCat);
- out << "removed object `" << identityToString(id) << "'";
+ out << "removed object `" << _communicator->identityToString(id) << "'";
}
}
@@ -167,7 +167,7 @@ ObjectCache::getAll(const string& expression)
ObjectInfoSeq infos;
for(map<Ice::Identity, ObjectEntryPtr>::const_iterator p = _entries.begin(); p != _entries.end(); ++p)
{
- if(expression.empty() || IceUtilInternal::match(identityToString(p->first), expression, true))
+ if(expression.empty() || IceUtilInternal::match(_communicator->identityToString(p->first), expression, true))
{
infos.push_back(p->second->getObjectInfo());
}
diff --git a/cpp/src/IceGrid/Parser.cpp b/cpp/src/IceGrid/Parser.cpp
index 30f80de48c7..7a88d5247a6 100644
--- a/cpp/src/IceGrid/Parser.cpp
+++ b/cpp/src/IceGrid/Parser.cpp
@@ -2100,7 +2100,7 @@ Parser::removeObject(const list<string>& args)
try
{
- _admin->removeObject(stringToIdentity((*(args.begin()))));
+ _admin->removeObject(Ice::stringToIdentity((*(args.begin()))));
}
catch(const Ice::Exception& ex)
{
@@ -2148,7 +2148,7 @@ Parser::describeObject(const list<string>& args)
string arg = *(args.begin());
if(arg.find('*') == string::npos)
{
- ObjectInfo info = _admin->getObjectInfo(stringToIdentity(arg));
+ ObjectInfo info = _admin->getObjectInfo(Ice::stringToIdentity(arg));
cout << "proxy = `" << _communicator->proxyToString(info.proxy) << "'" << endl;
cout << "type = `" << info.type << "'" << endl;
return;
@@ -2198,7 +2198,7 @@ Parser::listObject(const list<string>& args)
for(ObjectInfoSeq::const_iterator p = objects.begin(); p != objects.end(); ++p)
{
- cout << identityToString(p->proxy->ice_getIdentity()) << endl;
+ cout << _communicator->identityToString(p->proxy->ice_getIdentity()) << endl;
}
}
catch(const Ice::Exception& ex)
@@ -2957,11 +2957,11 @@ Parser::exception(const Ice::Exception& ex)
}
catch(const ObjectNotRegisteredException& ex)
{
- error("couldn't find object `" + identityToString(ex.id) + "'");
+ error("couldn't find object `" + _communicator->identityToString(ex.id) + "'");
}
catch(const ObjectExistsException& ex)
{
- error("object `" + identityToString(ex.id) + "' already exists");
+ error("object `" + _communicator->identityToString(ex.id) + "' already exists");
}
catch(const DeploymentException& ex)
{
diff --git a/cpp/src/IceGrid/ReplicaSessionManager.cpp b/cpp/src/IceGrid/ReplicaSessionManager.cpp
index 77c324aea27..9895963a1c5 100644
--- a/cpp/src/IceGrid/ReplicaSessionManager.cpp
+++ b/cpp/src/IceGrid/ReplicaSessionManager.cpp
@@ -177,7 +177,7 @@ public:
{
ostringstream os;
os << ex << ":\n";
- os << "id: " << identityToString(info.proxy->ice_getIdentity());
+ os << "id: " << _database->getCommunicator()->identityToString(info.proxy->ice_getIdentity());
failure = os.str();
}
receivedUpdate(ObjectObserverTopicName, serial, failure);
@@ -196,7 +196,7 @@ public:
{
ostringstream os;
os << ex << ":\n";
- os << "id: " << identityToString(info.proxy->ice_getIdentity());
+ os << "id: " << _database->getCommunicator()->identityToString(info.proxy->ice_getIdentity());
failure = os.str();
}
catch(const DeploymentException& ex)
diff --git a/cpp/src/IceGrid/Util.cpp b/cpp/src/IceGrid/Util.cpp
index 8c0d04cd911..c56e30717c0 100644
--- a/cpp/src/IceGrid/Util.cpp
+++ b/cpp/src/IceGrid/Util.cpp
@@ -207,7 +207,7 @@ IceGrid::toObjectInfo(const Ice::CommunicatorPtr& communicator, const ObjectDesc
ObjectInfo info;
info.type = obj.type;
ostringstream proxyStr;
- proxyStr << "\"" << identityToString(obj.id) << "\"";
+ proxyStr << "\"" << communicator->identityToString(obj.id) << "\"";
if(!obj.proxyOptions.empty())
{
proxyStr << ' ' << obj.proxyOptions;
@@ -220,7 +220,7 @@ IceGrid::toObjectInfo(const Ice::CommunicatorPtr& communicator, const ObjectDesc
catch(const Ice::ProxyParseException&)
{
ostringstream fallbackProxyStr;
- fallbackProxyStr << "\"" << identityToString(obj.id) << "\"" << " @ \"" << adapterId << "\"";
+ fallbackProxyStr << "\"" << communicator->identityToString(obj.id) << "\"" << " @ \"" << adapterId << "\"";
info.proxy = communicator->stringToProxy(fallbackProxyStr.str());
}
return info;
diff --git a/cpp/src/IcePatch2Lib/Util.cpp b/cpp/src/IcePatch2Lib/Util.cpp
index 88798feaba5..63fc5087eeb 100644
--- a/cpp/src/IcePatch2Lib/Util.cpp
+++ b/cpp/src/IcePatch2Lib/Util.cpp
@@ -81,7 +81,7 @@ bool
IcePatch2Internal::writeFileInfo(FILE* fp, const LargeFileInfo& info)
{
int rc = fprintf(fp, "%s\t%s\t" ICE_INT64_FORMAT "\t%d\n",
- IceUtilInternal::escapeString(info.path, "").c_str(),
+ escapeString(info.path, "", IceUtilInternal::Compat).c_str(),
bytesToString(info.checksum).c_str(),
info.size,
static_cast<int>(info.executable));
diff --git a/cpp/src/IceStorm/IceStormDB.cpp b/cpp/src/IceStorm/IceStormDB.cpp
index 9a3c81022e3..b3a927c719e 100644
--- a/cpp/src/IceStorm/IceStormDB.cpp
+++ b/cpp/src/IceStorm/IceStormDB.cpp
@@ -231,8 +231,8 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " KEY = TOPIC(" << identityToString(q->first.topic)
- << ") ID(" << identityToString(q->first.id) << ")" <<endl;
+ cout << " KEY = TOPIC(" << communicator()->identityToString(q->first.topic)
+ << ") ID(" << communicator()->identityToString(q->first.id) << ")" <<endl;
}
subscriberMap.put(txn, q->first, q->second);
}
@@ -286,8 +286,8 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " KEY = TOPIC(" << identityToString(key.topic)
- << ") ID(" << identityToString(key.id) << ")" <<endl;
+ cout << " KEY = TOPIC(" << communicator()->identityToString(key.topic)
+ << ") ID(" << communicator()->identityToString(key.id) << ")" <<endl;
}
data.subscribers.insert(std::make_pair(key, record));
}
diff --git a/cpp/src/IceStorm/InstrumentationI.cpp b/cpp/src/IceStorm/InstrumentationI.cpp
index ad3495429c9..017a5196fd3 100644
--- a/cpp/src/IceStorm/InstrumentationI.cpp
+++ b/cpp/src/IceStorm/InstrumentationI.cpp
@@ -174,7 +174,7 @@ public:
}
catch(const ::Ice::FixedProxyException&)
{
- _id = identityToString(_proxy->ice_getIdentity());
+ _id = _proxy->ice_getCommunicator()->identityToString(_proxy->ice_getIdentity());
}
}
return _id;
@@ -206,7 +206,7 @@ public:
string
getIdentity() const
{
- return identityToString(_proxy->ice_getIdentity());
+ return _proxy->ice_getCommunicator()->identityToString(_proxy->ice_getIdentity());
}
private:
diff --git a/cpp/src/IceStorm/Parser.cpp b/cpp/src/IceStorm/Parser.cpp
index 6f802b11569..ca0c0c5ae7b 100644
--- a/cpp/src/IceStorm/Parser.cpp
+++ b/cpp/src/IceStorm/Parser.cpp
@@ -364,7 +364,7 @@ Parser::subscribers(const list<string>& args)
IdentitySeq subscribers = topic->getSubscribers();
for(IdentitySeq::const_iterator j = subscribers.begin(); j != subscribers.end(); ++j)
{
- cout << "\t" << identityToString(*j) << endl;
+ cout << "\t" << _communicator->identityToString(*j) << endl;
}
}
}
@@ -379,7 +379,7 @@ Parser::current(const list<string>& args)
{
if(args.empty())
{
- cout << identityToString(_defaultManager->ice_getIdentity()) << endl;
+ cout << _communicator->identityToString(_defaultManager->ice_getIdentity()) << endl;
return;
}
else if(args.size() > 1)
@@ -618,7 +618,7 @@ Parser::parse(const std::string& commands, bool debug)
TopicManagerPrx
Parser::findManagerById(const string& full, string& arg) const
{
- Ice::Identity id = stringToIdentity(full);
+ Ice::Identity id = Ice::stringToIdentity(full);
arg = id.name;
if(id.category.empty())
{
diff --git a/cpp/src/IceStorm/Subscriber.cpp b/cpp/src/IceStorm/Subscriber.cpp
index 529461f0f03..5c1740ad612 100644
--- a/cpp/src/IceStorm/Subscriber.cpp
+++ b/cpp/src/IceStorm/Subscriber.cpp
@@ -546,7 +546,7 @@ Subscriber::create(
Ice::Identity perId;
perId.category = instance->instanceName();
perId.name = "topic." + rec.topicName + ".publish." +
- identityToString(rec.obj->ice_getIdentity());
+ instance->communicator()->identityToString(rec.obj->ice_getIdentity());
Ice::ObjectPrx proxy = instance->publishAdapter()->add(per, perId);
TraceLevelsPtr traceLevels = instance->traceLevels();
SubscriberPtr subscriber;
@@ -829,7 +829,7 @@ Subscriber::error(bool dec, const Ice::Exception& e)
if(_currentRetry == 0)
{
Ice::Warning warn(traceLevels->logger);
- warn << traceLevels->subscriberCat << ":" << identityToString(_rec.id);
+ warn << traceLevels->subscriberCat << ":" << _instance->communicator()->identityToString(_rec.id);
if(traceLevels->subscriber > 1)
{
warn << " endpoints: " << IceStormInternal::describeEndpoints(_rec.obj);
@@ -842,7 +842,7 @@ Subscriber::error(bool dec, const Ice::Exception& e)
if(traceLevels->subscriber > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->subscriberCat);
- out << identityToString(_rec.id);
+ out << _instance->communicator()->identityToString(_rec.id);
if(traceLevels->subscriber > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(_rec.obj);
@@ -870,7 +870,7 @@ Subscriber::error(bool dec, const Ice::Exception& e)
if(traceLevels->subscriber > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->subscriberCat);
- out << identityToString(_rec.id);
+ out << _instance->communicator()->identityToString(_rec.id);
if(traceLevels->subscriber > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(_rec.obj);
diff --git a/cpp/src/IceStorm/TopicI.cpp b/cpp/src/IceStorm/TopicI.cpp
index 3a9c3d65a79..acea59e5c15 100644
--- a/cpp/src/IceStorm/TopicI.cpp
+++ b/cpp/src/IceStorm/TopicI.cpp
@@ -399,7 +399,7 @@ TopicImpl::TopicImpl(
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << " recreate " << identityToString(id);
+ out << _name << " recreate " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(p->obj);
@@ -418,7 +418,7 @@ TopicImpl::TopicImpl(
catch(const Ice::Exception& ex)
{
Ice::Warning out(traceLevels->logger);
- out << _name << " recreate " << identityToString(id);
+ out << _name << " recreate " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(p->obj);
@@ -491,7 +491,7 @@ trace(Ice::Trace& out, const PersistentInstancePtr& instance, const vector<Subsc
{
out << ",";
}
- out << identityToString((*p)->id());
+ out << instance->communicator()->identityToString((*p)->id());
}
out << "]";
}
@@ -516,7 +516,7 @@ TopicImpl::subscribeAndGetPublisher(const QoS& qos, const Ice::ObjectPrx& obj)
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": subscribeAndGetPublisher: " << identityToString(id);
+ out << _name << ": subscribeAndGetPublisher: " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
@@ -600,7 +600,7 @@ TopicImpl::unsubscribe(const Ice::ObjectPrx& subscriber)
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": unsubscribe: " << identityToString(id);
+ out << _name << ": unsubscribe: " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
@@ -637,7 +637,7 @@ TopicImpl::link(const TopicPrx& topic, Ice::Int cost)
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": link " << identityToString(topic->ice_getIdentity())
+ out << _name << ": link " << _instance->communicator()->identityToString(topic->ice_getIdentity())
<< " cost " << cost;
}
@@ -722,7 +722,7 @@ TopicImpl::unlink(const TopicPrx& topic)
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << " unlink " << identityToString(id);
+ out << _name << " unlink " << _instance->communicator()->identityToString(id);
}
Ice::IdentitySeq ids;
@@ -746,7 +746,7 @@ TopicImpl::reap(const Ice::IdentitySeq& ids)
{
out << ",";
}
- out << identityToString(*p);
+ out << _instance->communicator()->identityToString(*p);
}
}
@@ -1045,7 +1045,7 @@ TopicImpl::observerAddSubscriber(const LogUpdate& llu, const SubscriberRecord& r
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": add replica observer: " << identityToString(record.id);
+ out << _name << ": add replica observer: " << _instance->communicator()->identityToString(record.id);
if(traceLevels->topic > 1)
{
@@ -1072,7 +1072,7 @@ TopicImpl::observerAddSubscriber(const LogUpdate& llu, const SubscriberRecord& r
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << identityToString(record.id) << ": already subscribed";
+ out << _instance->communicator()->identityToString(record.id) << ": already subscribed";
}
return;
}
@@ -1116,7 +1116,7 @@ TopicImpl::observerRemoveSubscriber(const LogUpdate& llu, const Ice::IdentitySeq
{
out << ",";
}
- out << identityToString(*id);
+ out << _instance->communicator()->identityToString(*id);
}
out << " llu: " << llu.generation << "/" << llu.iteration;
}
diff --git a/cpp/src/IceStorm/TopicManagerI.cpp b/cpp/src/IceStorm/TopicManagerI.cpp
index 15696d70abc..5c4ad1c6cbc 100644
--- a/cpp/src/IceStorm/TopicManagerI.cpp
+++ b/cpp/src/IceStorm/TopicManagerI.cpp
@@ -421,14 +421,14 @@ TopicManagerImpl::observerInit(const LogUpdate& llu, const TopicContentSeq& cont
out << "init";
for(TopicContentSeq::const_iterator p = content.begin(); p != content.end(); ++p)
{
- out << " topic: " << identityToString(p->id) << " subscribers: ";
+ out << " topic: " << _instance->communicator()->identityToString(p->id) << " subscribers: ";
for(SubscriberRecordSeq::const_iterator q = p->records.begin(); q != p->records.end(); ++q)
{
if(q != p->records.begin())
{
out << ",";
}
- out << identityToString(q->id);
+ out << _instance->communicator()->identityToString(q->id);
if(traceLevels->topicMgr > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(q->obj);
@@ -803,7 +803,7 @@ TopicManagerImpl::installTopic(const string& name, const Ice::Identity& id, bool
if(create)
{
out << "creating new topic \"" << name << "\". id: "
- << identityToString(id)
+ << _instance->communicator()->identityToString(id)
<< " subscribers: ";
for(SubscriberRecordSeq::const_iterator q = subscribers.begin(); q != subscribers.end(); ++q)
{
@@ -813,7 +813,7 @@ TopicManagerImpl::installTopic(const string& name, const Ice::Identity& id, bool
}
if(traceLevels->topicMgr > 1)
{
- out << identityToString(q->id)
+ out << _instance->communicator()->identityToString(q->id)
<< " endpoints: " << IceStormInternal::describeEndpoints(q->obj);
}
}
@@ -821,7 +821,7 @@ TopicManagerImpl::installTopic(const string& name, const Ice::Identity& id, bool
else
{
out << "loading topic \"" << name << "\" from database. id: "
- << identityToString(id)
+ << _instance->communicator()->identityToString(id)
<< " subscribers: ";
for(SubscriberRecordSeq::const_iterator q = subscribers.begin(); q != subscribers.end(); ++q)
{
@@ -831,7 +831,7 @@ TopicManagerImpl::installTopic(const string& name, const Ice::Identity& id, bool
}
if(traceLevels->topicMgr > 1)
{
- out << identityToString(q->id)
+ out << _instance->communicator()->identityToString(q->id)
<< " endpoints: " << IceStormInternal::describeEndpoints(q->obj);
}
}
diff --git a/cpp/src/IceStorm/TransientTopicI.cpp b/cpp/src/IceStorm/TransientTopicI.cpp
index f11688d1a10..062db7014fb 100644
--- a/cpp/src/IceStorm/TransientTopicI.cpp
+++ b/cpp/src/IceStorm/TransientTopicI.cpp
@@ -178,7 +178,7 @@ TransientTopicImpl::subscribe(const QoS& origQoS, const Ice::ObjectPrx& obj, con
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": subscribe: " << identityToString(id);
+ out << _name << ": subscribe: " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
@@ -280,7 +280,7 @@ TransientTopicImpl::subscribeAndGetPublisher(const QoS& qos, const Ice::ObjectPr
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": subscribeAndGetPublisher: " << identityToString(id);
+ out << _name << ": subscribeAndGetPublisher: " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
@@ -338,7 +338,7 @@ TransientTopicImpl::unsubscribe(const Ice::ObjectPrx& subscriber, const Ice::Cur
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": unsubscribe: " << identityToString(id);
+ out << _name << ": unsubscribe: " << _instance->communicator()->identityToString(id);
if(traceLevels->topic > 1)
{
out << " endpoints: " << IceStormInternal::describeEndpoints(subscriber);
@@ -374,7 +374,7 @@ TransientTopicImpl::link(const TopicPrx& topic, Ice::Int cost, const Ice::Curren
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << ": link " << identityToString(topic->ice_getIdentity())
+ out << _name << ": link " << _instance->communicator()->identityToString(topic->ice_getIdentity())
<< " cost " << cost;
}
@@ -434,7 +434,7 @@ TransientTopicImpl::unlink(const TopicPrx& topic, const Ice::Current&)
if(traceLevels->topic > 0)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicCat);
- out << _name << " unlink " << identityToString(id);
+ out << _name << " unlink " << _instance->communicator()->identityToString(id);
}
// Remove the subscriber from the subscribers list. Note
diff --git a/cpp/src/IceStorm/TransientTopicManagerI.cpp b/cpp/src/IceStorm/TransientTopicManagerI.cpp
index 5bd8449fd66..8c45a471f19 100644
--- a/cpp/src/IceStorm/TransientTopicManagerI.cpp
+++ b/cpp/src/IceStorm/TransientTopicManagerI.cpp
@@ -55,7 +55,7 @@ TransientTopicManagerImpl::create(const string& name, const Ice::Current&)
{
Ice::Trace out(traceLevels->logger, traceLevels->topicMgrCat);
out << "creating new topic \"" << name << "\". id: "
- << identityToString(id);
+ << _instance->communicator()->identityToString(id);
}
//
diff --git a/cpp/src/IceUtil/StringUtil.cpp b/cpp/src/IceUtil/StringUtil.cpp
index ec33cf8c587..0e7d9162d6c 100644
--- a/cpp/src/IceUtil/StringUtil.cpp
+++ b/cpp/src/IceUtil/StringUtil.cpp
@@ -35,96 +35,89 @@ toOctalString(unsigned int n)
return string(s, charPos, (32 - charPos));
}
+char
+toHexDigit(Byte b)
+{
+ assert(b < 16);
+ if(b < 10)
+ {
+ return '0' + b;
+ }
+ else
+ {
+ return 'a' - 10 + b;
+ }
+}
+
+
+unsigned int
+addContinuationByte(string::iterator& p, string::iterator end, unsigned int codePoint)
+{
+ if(p == end)
+ {
+ throw IllegalArgumentException(__FILE__, __LINE__, "UTF-8 sequence too short");
+ }
+
+ Byte b = static_cast<Byte>(*p++);
+
+ if((b >> 6) != 2)
+ {
+ throw IllegalArgumentException(__FILE__, __LINE__, "Invalid UTF-8 sequence");
+ }
+ return (codePoint << 6) + (b & 0x3F);
+}
+
//
-// Write the byte b as an escape sequence if it isn't a printable ASCII
-// character and append the escape sequence to s. 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 s.
+// Appends a 2 to 4 bytes UTF-8 sequence as a universal character name
//
void
-encodeChar(string::value_type b, string& s, const string& special)
+appendUniversalName(char c, string::iterator& p, string::iterator end, string& result)
{
- switch(b)
+ unsigned int codePoint;
+
+ Byte b = static_cast<Byte>(c);
+ if((b >> 5) == 0x06)
{
- case '\\':
- {
- s.append("\\\\");
- break;
- }
-
- case '\'':
- {
- s.append("\\'");
- break;
- }
-
- case '"':
- {
- s.append("\\\"");
- break;
- }
-
- case '\b':
- {
- s.append("\\b");
- break;
- }
-
- case '\f':
- {
- s.append("\\f");
- break;
- }
-
- case '\n':
- {
- s.append("\\n");
- break;
- }
-
- case '\r':
- {
- s.append("\\r");
- break;
- }
-
- case '\t':
+ // 2 bytes
+ codePoint = (b & 0x1F);
+ codePoint = addContinuationByte(p, end, codePoint);
+ }
+ else if((b >> 4) == 0x0E)
+ {
+ // 3 bytes
+ codePoint = (b & 0x0F);
+ codePoint = addContinuationByte(p, end, codePoint);
+ codePoint = addContinuationByte(p, end, codePoint);
+ }
+ else if((b >> 3) == 0x1E)
+ {
+ // 4 bytes
+ codePoint = (b & 0x07);
+ codePoint = addContinuationByte(p, end, codePoint);
+ codePoint = addContinuationByte(p, end, codePoint);
+ codePoint = addContinuationByte(p, end, codePoint);
+ }
+ else
+ {
+ ostringstream ostr;
+ ostr << "Invalid first byte 0x" << hex << static_cast<unsigned short>(b) << " in UTF-8 sequence" << endl;
+ throw IllegalArgumentException(__FILE__, __LINE__, ostr.str());
+ }
+
+ if(codePoint > 0xFFFF)
+ {
+ result.append("\\U");
+ for(int j = 7; j >= 0; j--)
{
- s.append("\\t");
- break;
+ result.push_back(toHexDigit(static_cast<Byte>((codePoint >> (j * 4)) & 0x0F)));
}
-
- default:
+ }
+ else
+ {
+ result.append("\\u");
+ for(int j = 3; j >= 0; j--)
{
- unsigned char i = static_cast<unsigned char>(b);
- if(!(i >= 32 && i <= 126))
- {
- s.push_back('\\');
- string octal = toOctalString(i);
- //
- // Add leading zeroes so that we avoid problems during
- // decoding. For example, consider the escaped 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 as a single
- // character with value 11.
- //
- for(string::size_type j = octal.size(); j < 3; j++)
- {
- s.push_back('0');
- }
- s.append(octal);
- }
- else if(special.find(b) != string::npos)
- {
- s.push_back('\\');
- s.push_back(b);
- }
- else
- {
- s.push_back(b);
- }
- break;
+ result.push_back(toHexDigit(static_cast<Byte>((codePoint >> (j * 4)) & 0x0F)));
}
}
}
@@ -132,27 +125,153 @@ encodeChar(string::value_type b, string& s, const string& special)
}
//
-// 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. Any characters that appear in special are prefixed with a backslash in the returned string.
//
string
-IceUtilInternal::escapeString(const string& s, const string& special)
+IceUtilInternal::escapeString(const string& s, const string& special, ToStringMode toStringMode)
{
for(string::size_type i = 0; i < special.size(); ++i)
{
if(static_cast<unsigned char>(special[i]) < 32 || static_cast<unsigned char>(special[i]) > 126)
{
- throw IllegalArgumentException(__FILE__, __LINE__, "special characters must be in ASCII range 32-126");
+ throw IllegalArgumentException(__FILE__, __LINE__, "Special characters must be in ASCII range 32-126");
}
}
-
+
+ //
+ // First convert to UTF-8
+ //
+ string u8s = nativeToUTF8(s, getProcessStringConverter());
+
+ string::iterator p = u8s.begin();
+
string result;
- for(string::size_type i = 0; i < s.size(); ++i)
+
+ while(p != u8s.end())
{
- encodeChar(s[i], result, special);
+ char c = *p++;
+
+ switch(c)
+ {
+ case '\\':
+ {
+ result.append("\\\\");
+ break;
+ }
+
+ case '\'':
+ {
+ result.append("\\'");
+ break;
+ }
+
+ case '"':
+ {
+ result.append("\\\"");
+ break;
+ }
+
+ case '\b':
+ {
+ result.append("\\b");
+ break;
+ }
+
+ case '\f':
+ {
+ result.append("\\f");
+ break;
+ }
+
+ case '\n':
+ {
+ result.append("\\n");
+ break;
+ }
+
+ case '\r':
+ {
+ result.append("\\r");
+ break;
+ }
+
+ case '\t':
+ {
+ result.append("\\t");
+ break;
+ }
+
+ default:
+ {
+ if(special.find(c) != string::npos)
+ {
+ result.push_back('\\');
+ result.push_back(c);
+ }
+ else
+ {
+ unsigned char i = static_cast<unsigned char>(c);
+
+ if(i < 32 || i > 126)
+ {
+ if(toStringMode == ICE_ENUM(ToStringMode, Compat))
+ {
+ // append octal string
+
+ result.push_back('\\');
+ string octal = toOctalString(i);
+ //
+ // Add leading zeroes so that we avoid problems during
+ // decoding. For example, consider the escaped 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 as a single
+ // character with value 11.
+ //
+ for(string::size_type j = octal.size(); j < 3; j++)
+ {
+ result.push_back('0');
+ }
+ result.append(octal);
+ }
+ else if(i < 32 || i == 127)
+ {
+ // append \u00nn
+ result.append("\\u00");
+ result.push_back(toHexDigit(i >> 4));
+ result.push_back(toHexDigit(i & 0x0F));
+ }
+ else if(toStringMode == ICE_ENUM(ToStringMode, ASCII))
+ {
+ // append \unnnn or \Unnnnnnnn after reading more UTF-8 bytes
+ appendUniversalName(c, p, u8s.end(), result);
+ }
+ else
+ {
+ // keep as is
+ result.push_back(c);
+ }
+ }
+ else
+ {
+ // printable ASCII character
+ result.push_back(c);
+ }
+ }
+ break;
+ }
+ }
}
-
+
+ if(toStringMode == ICE_ENUM(ToStringMode, Unicode))
+ {
+ //
+ // Convert back to Native
+ //
+ result = UTF8ToNative(result, getProcessStringConverter());
+ }
+ // else it's a pure ASCII string
+
return result;
}
@@ -163,7 +282,7 @@ char
checkChar(const string& s, string::size_type pos)
{
unsigned char c = static_cast<unsigned char>(s[pos]);
- if(!(c >= 32 && c <= 126))
+ if(c < 32 || c == 127)
{
ostringstream ostr;
if(pos > 0)
@@ -174,29 +293,74 @@ checkChar(const string& s, string::size_type pos)
{
ostr << "first character";
}
- ostr << " is not a printable ASCII character (ordinal " << static_cast<int>(c) << ")";
+ ostr << " has invalid ordinal value " << static_cast<int>(c);
throw IllegalArgumentException(__FILE__, __LINE__, ostr.str());
}
return c;
}
//
-// Decode the character or escape sequence starting at start and return it.
+// Append codePoint as a UTF-8 sequence
+//
+void
+appendUTF8(unsigned int codePoint, bool inBMP, string& result)
+{
+ if(inBMP && codePoint >= 0xD800 && codePoint <= 0xDFFF)
+ {
+ throw IllegalArgumentException(__FILE__, __LINE__,
+ "A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead");
+ }
+
+ if(codePoint <= 0x7F)
+ {
+ // ASCII
+ result.push_back(static_cast<char>(codePoint));
+ }
+ else if(codePoint <= 0x7FF)
+ {
+ // 2 bytes
+ result.push_back(static_cast<char>((codePoint >> 6) | 0xC0));
+ result.push_back(static_cast<char>((codePoint & 0x3F) | 0x80));
+ }
+ else if(codePoint <= 0xFFFF)
+ {
+ // 3 bytes
+ result.push_back(static_cast<char>((codePoint >> 12) | 0xE0));
+ result.push_back(static_cast<char>(((codePoint >> 6) & 0x3F) | 0x80));
+ result.push_back(static_cast<char>((codePoint & 0x3F) | 0x80));
+ }
+ else if(codePoint <= 0x10FFFF)
+ {
+ // 4 bytes
+ result.push_back(static_cast<char>((codePoint >> 18) | 0xF0));
+ result.push_back(static_cast<char>(((codePoint >> 12) & 0x3F) | 0x80));
+ result.push_back(static_cast<char>(((codePoint >> 6) & 0x3F) | 0x80));
+ result.push_back(static_cast<char>((codePoint & 0x3F) | 0x80));
+ }
+ else
+ {
+ throw IllegalArgumentException(__FILE__, __LINE__, "Invalid universal character name");
+ }
+}
+
+//
+// Decode the character or escape sequence starting at start and appends it to result;
// 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.
//
-char
-decodeChar(const string& s, string::size_type start, string::size_type end, string::size_type& nextStart)
+bool
+decodeChar(const string& s, string::size_type start, string::size_type end, string::size_type& nextStart,
+ string& result)
{
assert(start < end);
assert(end <= s.size());
- char c;
+ bool pureASCII = true;
if(s[start] != '\\')
{
- c = checkChar(s, start++);
+ result.push_back(checkChar(s, start++));
}
else
{
@@ -204,43 +368,90 @@ decodeChar(const string& s, string::size_type start, string::size_type end, stri
{
throw IllegalArgumentException(__FILE__, __LINE__, "trailing backslash");
}
- switch(s[++start])
+
+ char c = s[++start];
+
+ switch(c)
{
- case '\\':
- case '\'':
- case '"':
+ case '\\':
+ case '\'':
+ case '"':
+ {
+ ++start;
+ result.push_back(c);
+ break;
+ }
+ case 'b':
{
- c = s[start++];
+ ++start;
+ result.push_back('\b');
break;
}
- case 'b':
+ case 'f':
{
++start;
- c = '\b';
+ result.push_back('\f');
break;
}
- case 'f':
+ case 'n':
{
++start;
- c = '\f';
+ result.push_back('\n');
break;
}
- case 'n':
+ case 'r':
{
++start;
- c = '\n';
+ result.push_back('\r');
break;
}
- case 'r':
+ case 't':
{
++start;
- c = '\r';
+ result.push_back('\t');
break;
}
- case 't':
+ case 'u':
+ case 'U':
{
+ unsigned 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 + static_cast<unsigned int>(charVal);
+ --size;
+ }
+ if(size > 0)
+ {
+ throw IllegalArgumentException(__FILE__, __LINE__,
+ "Invalid universal character name: too few hex digits");
+ }
+
+ appendUTF8(codePoint, inBMP, result);
+ if(codePoint > 127)
+ {
+ pureASCII = false;
+ }
break;
}
case '0':
@@ -269,31 +480,26 @@ decodeChar(const string& s, string::size_type start, string::size_type end, stri
ostr << "octal value \\" << oct << val << dec << " (" << val << ") is out of range";
throw IllegalArgumentException(__FILE__, __LINE__, ostr.str());
}
- c = static_cast<char>(val);
+ result.push_back(static_cast<char>(val));
+ if(val > 127)
+ {
+ pureASCII = false;
+ }
break;
}
default:
{
- c = checkChar(s, start++);
+ if(static_cast<unsigned char>(c) > 127)
+ {
+ pureASCII = false;
+ }
+ result.push_back(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.
-//
-void
-decodeString(const string& s, string::size_type start, string::size_type end, string& sb)
-{
- while(start < end)
- {
- sb.push_back(decodeChar(s, start, end, start));
- }
+ return pureASCII;
}
}
@@ -306,11 +512,61 @@ IceUtilInternal::unescapeString(const string& s, string::size_type start, string
{
assert(start <= end && end <= s.size());
- string result;
- result.reserve(end - start);
- result.clear();
- decodeString(s, start, end, result);
- return result;
+ // Optimization for strings without escapes
+ string::size_type p = s.find('\\', start);
+ if(p == string::npos || p >= end)
+ {
+ p = start;
+ while(p < end)
+ {
+ checkChar(s, p++);
+ }
+ return s.substr(start, end);
+ }
+ else
+ {
+ StringConverterPtr stringConverter = getProcessStringConverter();
+
+ const string* inputStringPtr = &s;
+ string u8s;
+
+ if(stringConverter)
+ {
+ bool inputIsPureASCII = true;
+ string::size_type i = start;
+ while(i < end && inputIsPureASCII)
+ {
+ inputIsPureASCII = static_cast<unsigned char>(s[i++]) <= 127;
+ }
+
+ if(!inputIsPureASCII)
+ {
+ u8s = nativeToUTF8(s.substr(start, end), stringConverter);
+ inputStringPtr = &u8s;
+ start = 0;
+ end = u8s.size();
+ }
+ }
+
+ bool resultIsPureASCII = true;
+ string result;
+ result.reserve(end - start);
+ while(start < end)
+ {
+ if(decodeChar(*inputStringPtr, start, end, start, result))
+ {
+ resultIsPureASCII = false;
+ }
+ }
+
+ if(stringConverter && !resultIsPureASCII)
+ {
+ // Need to convert from UTF-8 to Native
+ result = UTF8ToNative(result, stringConverter);
+ }
+
+ return result;
+ }
}
bool
@@ -328,7 +584,7 @@ IceUtilInternal::splitString(const string& str, const string& delim, vector<stri
quoteChar = str[pos++];
continue; // Skip the quote
}
- else if(quoteChar == '\0' && str[pos] == '\\' && pos + 1 < length &&
+ else if(quoteChar == '\0' && str[pos] == '\\' && pos + 1 < length &&
(str[pos + 1] == '\'' || str[pos + 1] == '"'))
{
++pos;
@@ -356,7 +612,7 @@ IceUtilInternal::splitString(const string& str, const string& delim, vector<stri
continue;
}
}
-
+
if(pos < length)
{
elt += str[pos++];
@@ -437,7 +693,7 @@ IceUtilInternal::checkQuote(const string& s, string::size_type start)
//
// Match `s' against the pattern `pat'. A * in the pattern acts
// as a wildcard: it matches any non-empty sequence of characters.
-// We match by hand here because it's portable across platforms
+// We match by hand here because it's portable across platforms
// (whereas regex() isn't). Only one * per pattern is supported.
//
bool
@@ -500,7 +756,7 @@ IceUtilInternal::errorToString(int error, LPCVOID source)
wstring lpMsgBuf(256, wchar_t());
DWORD stored = 0;
-
+
while(stored == 0)
{
stored = FormatMessageW(
@@ -531,7 +787,7 @@ IceUtilInternal::errorToString(int error, LPCVOID source)
else
{
break;
- }
+ }
}
}
@@ -539,7 +795,7 @@ IceUtilInternal::errorToString(int error, LPCVOID source)
#else
LPWSTR msg = 0;
-
+
DWORD stored = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
@@ -552,7 +808,7 @@ IceUtilInternal::errorToString(int error, LPCVOID source)
0,
NULL);
#endif
-
+
if(stored > 0)
{
assert(msg && wcslen(msg) > 0);
@@ -576,159 +832,159 @@ IceUtilInternal::errorToString(int error, LPCVOID source)
return os.str();
}
}
-
+
switch(error)
{
case WSAEINTR:
return "WSAEINTR";
-
+
case WSAEBADF:
return "WSAEBADF";
-
+
case WSAEACCES:
return "WSAEACCES";
-
+
case WSAEFAULT:
return "WSAEFAULT";
-
+
case WSAEINVAL:
return "WSAEINVAL";
-
+
case WSAEMFILE:
return "WSAEMFILE";
-
+
case WSAEWOULDBLOCK:
return "WSAEWOULDBLOCK";
-
+
case WSAEINPROGRESS:
return "WSAEINPROGRESS";
-
+
case WSAEALREADY:
return "WSAEALREADY";
-
+
case WSAENOTSOCK:
return "WSAENOTSOCK";
-
+
case WSAEDESTADDRREQ:
return "WSAEDESTADDRREQ";
-
+
case WSAEMSGSIZE:
return "WSAEMSGSIZE";
-
+
case WSAEPROTOTYPE:
return "WSAEPROTOTYPE";
-
+
case WSAENOPROTOOPT:
return "WSAENOPROTOOPT";
-
+
case WSAEPROTONOSUPPORT:
return "WSAEPROTONOSUPPORT";
-
+
case WSAESOCKTNOSUPPORT:
return "WSAESOCKTNOSUPPORT";
-
+
case WSAEOPNOTSUPP:
return "WSAEOPNOTSUPP";
-
+
case WSAEPFNOSUPPORT:
return "WSAEPFNOSUPPORT";
-
+
case WSAEAFNOSUPPORT:
return "WSAEAFNOSUPPORT";
-
+
case WSAEADDRINUSE:
return "WSAEADDRINUSE";
-
+
case WSAEADDRNOTAVAIL:
return "WSAEADDRNOTAVAIL";
-
+
case WSAENETDOWN:
return "WSAENETDOWN";
-
+
case WSAENETUNREACH:
return "WSAENETUNREACH";
-
+
case WSAENETRESET:
return "WSAENETRESET";
-
+
case WSAECONNABORTED:
return "WSAECONNABORTED";
-
+
case WSAECONNRESET:
return "WSAECONNRESET";
-
+
case WSAENOBUFS:
return "WSAENOBUFS";
-
+
case WSAEISCONN:
return "WSAEISCONN";
-
+
case WSAENOTCONN:
return "WSAENOTCONN";
-
+
case WSAESHUTDOWN:
return "WSAESHUTDOWN";
-
+
case WSAETOOMANYREFS:
return "WSAETOOMANYREFS";
-
+
case WSAETIMEDOUT:
return "WSAETIMEDOUT";
-
+
case WSAECONNREFUSED:
return "WSAECONNREFUSED";
-
+
case WSAELOOP:
return "WSAELOOP";
-
+
case WSAENAMETOOLONG:
return "WSAENAMETOOLONG";
-
+
case WSAEHOSTDOWN:
return "WSAEHOSTDOWN";
-
+
case WSAEHOSTUNREACH:
return "WSAEHOSTUNREACH";
-
+
case WSAENOTEMPTY:
return "WSAENOTEMPTY";
-
+
case WSAEPROCLIM:
return "WSAEPROCLIM";
-
+
case WSAEUSERS:
return "WSAEUSERS";
-
+
case WSAEDQUOT:
return "WSAEDQUOT";
-
+
case WSAESTALE:
return "WSAESTALE";
-
+
case WSAEREMOTE:
return "WSAEREMOTE";
-
+
case WSAEDISCON:
return "WSAEDISCON";
-
+
case WSASYSNOTREADY:
return "WSASYSNOTREADY";
-
+
case WSAVERNOTSUPPORTED:
return "WSAVERNOTSUPPORTED";
-
+
case WSANOTINITIALISED:
return "WSANOTINITIALISED";
-
+
case WSAHOST_NOT_FOUND:
return "WSAHOST_NOT_FOUND";
-
+
case WSATRY_AGAIN:
return "WSATRY_AGAIN";
-
+
case WSANO_RECOVERY:
return "WSANO_RECOVERY";
-
+
case WSANO_DATA:
return "WSANO_DATA";
diff --git a/cpp/src/Slice/Preprocessor.cpp b/cpp/src/Slice/Preprocessor.cpp
index c8e49029f25..57d5ed5f78f 100644
--- a/cpp/src/Slice/Preprocessor.cpp
+++ b/cpp/src/Slice/Preprocessor.cpp
@@ -83,11 +83,9 @@ Slice::Preprocessor::addQuotes(const string& arg)
{
//
// Add quotes around the given argument to ensure that arguments
- // with spaces will be preserved as a single argument. We also
- // escape the "\" character to ensure that we don't end up with a
- // \" at the end of the string.
+ // with spaces will be preserved as a single argument
//
- return "\"" + IceUtilInternal::escapeString(arg, "\\") + "\"";
+ return "\"" + escapeString(arg, "", IceUtilInternal::Unicode) + "\"";
}
string
diff --git a/cpp/src/icegriddb/IceGridDB.cpp b/cpp/src/icegriddb/IceGridDB.cpp
index 42b61f1ab92..8426d773d63 100644
--- a/cpp/src/icegriddb/IceGridDB.cpp
+++ b/cpp/src/icegriddb/IceGridDB.cpp
@@ -372,7 +372,7 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " NAME = " << identityToString(p->proxy->ice_getIdentity()) << endl;
+ cout << " NAME = " << communicator()->identityToString(p->proxy->ice_getIdentity()) << endl;
}
objs.put(txn, p->proxy->ice_getIdentity(), *p);
}
@@ -390,7 +390,7 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " NAME = " << identityToString(p->proxy->ice_getIdentity()) << endl;
+ cout << " NAME = " << communicator()->identityToString(p->proxy->ice_getIdentity()) << endl;
}
internalObjs.put(txn, p->proxy->ice_getIdentity(), *p);
}
@@ -483,7 +483,7 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " IDENTITY = " << identityToString(id) << endl;
+ cout << " IDENTITY = " << communicator()->identityToString(id) << endl;
}
data.objects.push_back(object);
}
@@ -503,7 +503,7 @@ Client::run(int argc, char* argv[])
{
if(debug)
{
- cout << " IDENTITY = " << identityToString(id) << endl;
+ cout << " IDENTITY = " << communicator()->identityToString(id) << endl;
}
data.internalObjects.push_back(object);
}
diff --git a/cpp/test/Ice/interceptor/AMDInterceptorI.cpp b/cpp/test/Ice/interceptor/AMDInterceptorI.cpp
index f790db8c6a0..7e546344602 100644
--- a/cpp/test/Ice/interceptor/AMDInterceptorI.cpp
+++ b/cpp/test/Ice/interceptor/AMDInterceptorI.cpp
@@ -172,4 +172,4 @@ DispatchInterceptorAsyncCallbackI::exception()
test(false);
return true;
}
-#endif \ No newline at end of file
+#endif
diff --git a/cpp/test/Ice/location/AllTests.cpp b/cpp/test/Ice/location/AllTests.cpp
index 80e10c780db..39ea56f9462 100644
--- a/cpp/test/Ice/location/AllTests.cpp
+++ b/cpp/test/Ice/location/AllTests.cpp
@@ -716,7 +716,7 @@ allTests(const Ice::CommunicatorPtr& communicator, const string& ref)
registry->addObject(adapter->add(ICE_MAKE_SHARED(HelloI), id));
adapter->activate();
- HelloPrxPtr helloPrx = ICE_CHECKED_CAST(HelloPrx, communicator->stringToProxy(identityToString(id)));
+ HelloPrxPtr helloPrx = ICE_CHECKED_CAST(HelloPrx, communicator->stringToProxy(communicator->identityToString(id)));
test(!helloPrx->ice_getConnection());
adapter->deactivate();
diff --git a/cpp/test/Ice/operations/TestI.cpp b/cpp/test/Ice/operations/TestI.cpp
index 91154cf5769..2adfceda6db 100644
--- a/cpp/test/Ice/operations/TestI.cpp
+++ b/cpp/test/Ice/operations/TestI.cpp
@@ -926,4 +926,4 @@ MyDerivedClassI::opMDict2(ICE_IN(Test::StringStringD) p1, Test::StringStringD& p
return p1;
}
-#endif \ No newline at end of file
+#endif
diff --git a/cpp/test/Ice/proxy/AllTests.cpp b/cpp/test/Ice/proxy/AllTests.cpp
index 4fe2207c759..791c6c620a7 100644
--- a/cpp/test/Ice/proxy/AllTests.cpp
+++ b/cpp/test/Ice/proxy/AllTests.cpp
@@ -20,6 +20,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
{
const string endp = getTestEndpoint(communicator, 0);
cout << "testing stringToProxy... " << flush;
+
string ref = "test:" + endp;
Ice::ObjectPrxPtr base = communicator->stringToProxy(ref);
test(base);
@@ -64,6 +65,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const Ice::ProxyParseException&)
{
}
+
b1 = communicator->stringToProxy("test\\040test");
test(b1->ice_getIdentity().name == "test test" && b1->ice_getIdentity().category.empty());
try
@@ -74,10 +76,11 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const Ice::IdentityParseException&)
{
}
+
b1 = communicator->stringToProxy("test\\40test");
test(b1->ice_getIdentity().name == "test test");
- // Test some octal and hex corner cases.
+ // Test some octal corner cases.
b1 = communicator->stringToProxy("test\\4test");
test(b1->ice_getIdentity().name == "test\4test");
b1 = communicator->stringToProxy("test\\04test");
@@ -98,6 +101,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
test(!b1);
b1 = communicator->stringToProxy("\"\"");
test(!b1);
+
try
{
b1 = communicator->stringToProxy("\"\" test"); // Invalid trailing characters.
@@ -106,6 +110,7 @@ allTests(const Ice::CommunicatorPtr& communicator)
catch(const Ice::ProxyParseException&)
{
}
+
try
{
b1 = communicator->stringToProxy("test:"); // Missing endpoint.
@@ -142,8 +147,10 @@ allTests(const Ice::CommunicatorPtr& communicator)
test(b1->ice_getIdentity().name == "test" && b1->ice_getIdentity().category == "category" &&
b1->ice_getAdapterId() == "adapter 1");
b1 = communicator->stringToProxy("\"category \\/test@foo/test\"@adapter");
- test(b1->ice_getIdentity().name == "test" && b1->ice_getIdentity().category == "category /test@foo" &&
- b1->ice_getAdapterId() == "adapter");
+
+ test(b1->ice_getIdentity().name == "test" && b1->ice_getIdentity().category == "category /test@foo"
+ && b1->ice_getAdapterId() == "adapter");
+
b1 = communicator->stringToProxy("\"category \\/test@foo/test\"@\"adapter:tcp\"");
test(b1->ice_getIdentity().name == "test" && b1->ice_getIdentity().category == "category /test@foo" &&
b1->ice_getAdapterId() == "adapter:tcp");
@@ -258,14 +265,85 @@ allTests(const Ice::CommunicatorPtr& communicator)
// Test for bug ICE-5543: escaped escapes in stringToIdentity
//
Ice::Identity id = { "test", ",X2QNUAzSBcJ_e$AV;E\\" };
- Ice::Identity id2 = Ice::stringToIdentity(Ice::identityToString(id));
+ Ice::Identity id2 = Ice::stringToIdentity(communicator->identityToString(id));
test(id == id2);
id.name = "test";
id.category = ",X2QNUAz\\SB\\/cJ_e$AV;E\\\\";
- id2 = Ice::stringToIdentity(Ice::identityToString(id));
+ id2 = Ice::stringToIdentity(communicator->identityToString(id));
+ test(id == id2);
+
+ id.name = "/test";
+ id.category = "cat/";
+ string idStr = communicator->identityToString(id);
+ test(idStr == "cat\\//\\/test");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+
+ try
+ {
+ // Illegal character < 32
+ id = Ice::stringToIdentity("xx\01FooBar");
+ test(false);
+ }
+ catch(const Ice::IdentityParseException&)
+ {
+ }
+
+ try
+ {
+ // Illegal surrogate
+ id = Ice::stringToIdentity("xx\\ud911");
+ test(false);
+ }
+ catch(const Ice::IdentityParseException&)
+ {
+ }
+
+ // Testing bytes 127 (\x7F) and €
+ id.name = "test";
+ id.category = "\x7F\xE2\x82\xAC";
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, Unicode));
+ test(idStr == "\\u007f\xE2\x82\xAC/test");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+ test(Ice::identityToString(id) == idStr);
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, ASCII));
+ test(idStr == "\\u007f\\u20ac/test");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, Compat));
+ test(idStr == "\\177\\342\\202\\254/test");
+ id2 = Ice::stringToIdentity(idStr);
test(id == id2);
+ id2 = Ice::stringToIdentity(communicator->identityToString(id));
+ test(id == id2);
+
+ // More unicode characters
+#ifdef ICE_CPP11_MAPPING
+ id.name = u8"banana \016-\U0001F34C\U000020AC\u00a2\u0024";
+ id.category = u8"greek \U0001016A";
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, Unicode));
+ test(idStr == u8"greek \U0001016A/banana \\u000e-\U0001F34C\U000020AC\u00a2$");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, ASCII));
+ test(idStr == "greek \\U0001016a/banana \\u000e-\\U0001f34c\\u20ac\\u00a2$");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+
+ idStr = identityToString(id, Ice::ICE_ENUM(ToStringMode, Compat));
+ test(idStr == "greek \\360\\220\\205\\252/banana \\016-\\360\\237\\215\\214\\342\\202\\254\\302\\242$");
+ id2 = Ice::stringToIdentity(idStr);
+ test(id == id2);
+#endif
+
cout << "ok" << endl;
cout << "testing propertyToProxy... " << flush;
@@ -445,10 +523,8 @@ allTests(const Ice::CommunicatorPtr& communicator)
cout << "testing proxy methods... " << flush;
-// Deprecated
-// test(communicator->identityToString(base->ice_identity(communicator->stringToIdentity("other"))->ice_getIdentity())
-// == "other");
- test(Ice::identityToString(base->ice_identity(Ice::stringToIdentity("other"))->ice_getIdentity()) == "other");
+ test(communicator->identityToString(base->ice_identity(Ice::stringToIdentity("other"))->ice_getIdentity())
+ == "other");
test(base->ice_facet("facet")->ice_getFacet() == "facet");
test(base->ice_adapterId("id")->ice_getAdapterId() == "id");
test(base->ice_twoway()->ice_isTwoway());
diff --git a/cpp/test/Ice/proxy/run.py b/cpp/test/Ice/proxy/run.py
index 7921ce9e9ff..38e60970744 100755
--- a/cpp/test/Ice/proxy/run.py
+++ b/cpp/test/Ice/proxy/run.py
@@ -23,5 +23,5 @@ import TestUtil
TestUtil.queueClientServerTest()
TestUtil.queueClientServerTest(configName = "amd", localOnly = True, message = "Running test with AMD server.",
server = TestUtil.getTestExecutable("serveramd"))
-TestUtil.queueCollocatedTest()
+TestUtil.queueCollocatedTest(additionalOptions = "--Ice.ToStringMode=Compat")
TestUtil.runQueuedTests()
diff --git a/cpp/test/Ice/stringConverter/Client.cpp b/cpp/test/Ice/stringConverter/Client.cpp
index 4a8e7027aea..f0d7f4df1cd 100644
--- a/cpp/test/Ice/stringConverter/Client.cpp
+++ b/cpp/test/Ice/stringConverter/Client.cpp
@@ -127,6 +127,22 @@ main(int argc, char* argv[])
wstring wmsg = proxy->widen(msg);
test(proxy->narrow(wmsg) == msg);
test(wmsg.size() == msg.size());
+
+ // Test stringToIdentity and identityToString
+
+ string identStr = "cat/" + msg;
+ Ice::Identity ident = Ice::stringToIdentity(identStr);
+ test(ident.name == msg);
+ test(ident.category == "cat");
+ test(identityToString(ident, Ice::ICE_ENUM(ToStringMode, Unicode)) == identStr);
+
+ identStr = identityToString(ident, Ice::ICE_ENUM(ToStringMode, ASCII));
+ test(identStr == "cat/tu me fends le c\\u0153ur!");
+ test(Ice::stringToIdentity(identStr) == ident);
+ identStr = identityToString(ident, Ice::ICE_ENUM(ToStringMode, Compat));
+ test(identStr == "cat/tu me fends le c\\305\\223ur!");
+ test(Ice::stringToIdentity(identStr) == ident);
+
communicator->destroy();
cout << "ok" << endl;
}
@@ -134,7 +150,6 @@ main(int argc, char* argv[])
Ice::setProcessStringConverter(ICE_NULLPTR);
Ice::setProcessWstringConverter(Ice::createUnicodeWstringConverter());
-
string propValue = "Ice:createStringConverter";
if(useIconv && !useLocale)
{
diff --git a/cpp/test/IceGrid/deployer/AllTests.cpp b/cpp/test/IceGrid/deployer/AllTests.cpp
index 222a243ba6c..d4cfa91c6bd 100644
--- a/cpp/test/IceGrid/deployer/AllTests.cpp
+++ b/cpp/test/IceGrid/deployer/AllTests.cpp
@@ -430,16 +430,16 @@ allTests(const Ice::CommunicatorPtr& comm)
test(find_if(objs.begin(), objs.end(), bind2nd(ProxyIdentityEqual(comm),"ReplicatedObject")) != objs.end());
{
- test(identityToString(query->findObjectByType("::TestId1")->ice_getIdentity()) == "cat/name1");
- test(identityToString(query->findObjectByType("::TestId2")->ice_getIdentity()) == "cat1/name1");
- test(identityToString(query->findObjectByType("::TestId3")->ice_getIdentity()) == "cat1/name1-bis");
- test(identityToString(query->findObjectByType("::TestId4")->ice_getIdentity()) == "c2\\/c2/n2\\/n2");
- test(identityToString(query->findObjectByType("::TestId5")->ice_getIdentity()) == "n2\\/n2");
+ test(comm->identityToString(query->findObjectByType("::TestId1")->ice_getIdentity()) == "cat/name1");
+ test(comm->identityToString(query->findObjectByType("::TestId2")->ice_getIdentity()) == "cat1/name1");
+ test(comm->identityToString(query->findObjectByType("::TestId3")->ice_getIdentity()) == "cat1/name1-bis");
+ test(comm->identityToString(query->findObjectByType("::TestId4")->ice_getIdentity()) == "c2\\/c2/n2\\/n2");
+ test(comm->identityToString(query->findObjectByType("::TestId5")->ice_getIdentity()) == "n2\\/n2");
}
{
Ice::ObjectPrx obj = query->findObjectByType("::Test");
- string id = identityToString(obj->ice_getIdentity());
+ string id = comm->identityToString(obj->ice_getIdentity());
test(id == "Server1" || id == "Server2" || id == "SimpleServer" ||
id == "IceBox1-Service1" || id == "IceBox1-Service2" ||
id == "IceBox2-Service1" || id == "IceBox2-Service2" ||
@@ -448,7 +448,7 @@ allTests(const Ice::CommunicatorPtr& comm)
{
Ice::ObjectPrx obj = query->findObjectByTypeOnLeastLoadedNode("::Test", LoadSample5);
- string id = identityToString(obj->ice_getIdentity());
+ string id = comm->identityToString(obj->ice_getIdentity());
test(id == "Server1" || id == "Server2" || id == "SimpleServer" ||
id == "IceBox1-Service1" || id == "IceBox1-Service2" ||
id == "IceBox2-Service1" || id == "IceBox2-Service2" ||
diff --git a/cpp/test/IceGrid/session/AllTests.cpp b/cpp/test/IceGrid/session/AllTests.cpp
index e7f18c31519..dcf1d8414b8 100644
--- a/cpp/test/IceGrid/session/AllTests.cpp
+++ b/cpp/test/IceGrid/session/AllTests.cpp
@@ -269,7 +269,7 @@ public:
Lock sync(*this);
this->objects.erase(id);
updated(updateSerial(0, "object removed `" +
- identityToString(id) + "'"));
+ current.adapter->getCommunicator()->identityToString(id) + "'"));
}
int serial;
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);
}
}
diff --git a/csharp/test/Ice/location/AllTests.cs b/csharp/test/Ice/location/AllTests.cs
index 707520b4e36..129737c3073 100644
--- a/csharp/test/Ice/location/AllTests.cs
+++ b/csharp/test/Ice/location/AllTests.cs
@@ -603,7 +603,7 @@ public class AllTests : TestCommon.TestApp
adapter.activate();
HelloPrx helloPrx = HelloPrxHelper.checkedCast(
- communicator.stringToProxy("\"" + Ice.Util.identityToString(id) + "\""));
+ communicator.stringToProxy("\"" + communicator.identityToString(id) + "\""));
test(helloPrx.ice_getConnection() == null);
adapter.deactivate();
diff --git a/csharp/test/Ice/proxy/AllTests.cs b/csharp/test/Ice/proxy/AllTests.cs
index 1998f785847..bd7d5aacbe9 100644
--- a/csharp/test/Ice/proxy/AllTests.cs
+++ b/csharp/test/Ice/proxy/AllTests.cs
@@ -254,11 +254,77 @@ public class AllTests : TestCommon.TestApp
// Test for bug ICE-5543: escaped escapes in stringToIdentity
//
Ice.Identity id = new Ice.Identity("test", ",X2QNUAzSBcJ_e$AV;E\\");
- Ice.Identity id2 = Ice.Util.stringToIdentity(Ice.Util.identityToString(id));
+ Ice.Identity id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
test(id.Equals(id2));
id = new Ice.Identity("test", ",X2QNUAz\\SB\\/cJ_e$AV;E\\\\");
- id2 = Ice.Util.stringToIdentity(Ice.Util.identityToString(id));
+ id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.Equals(id2));
+
+ id = new Ice.Identity("/test", "cat/");
+ string idStr = communicator.identityToString(id);
+ test(idStr == "cat\\//\\/test");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+
+ try
+ {
+ // Illegal character < 32
+ id = Ice.Util.stringToIdentity("xx\01FooBar");
+ test(false);
+ }
+ catch(Ice.IdentityParseException)
+ {
+ }
+
+ try
+ {
+ // Illegal surrogate
+ id = Ice.Util.stringToIdentity("xx\\ud911");
+ test(false);
+ }
+ catch(Ice.IdentityParseException)
+ {
+ }
+
+ // Testing bytes 127 (\x7F, \177) and €
+ id = new Ice.Identity("test", "\x7f€");
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr == "\\u007f€/test");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+ test(Ice.Util.identityToString(id) == idStr);
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr == "\\u007f\\u20ac/test");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Compat);
+ test(idStr == "\\177\\342\\202\\254/test");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+
+ id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.Equals(id2));
+
+ // More unicode character
+ id = new Ice.Identity("banana \x0E-\ud83c\udf4c\u20ac\u00a2\u0024", "greek \ud800\udd6a");
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr == "greek \ud800\udd6a/banana \\u000e-\ud83c\udf4c\u20ac\u00a2$");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr == "greek \\U0001016a/banana \\u000e-\\U0001f34c\\u20ac\\u00a2$");
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.Equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Compat);
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(idStr == "greek \\360\\220\\205\\252/banana \\016-\\360\\237\\215\\214\\342\\202\\254\\302\\242$");
test(id.Equals(id2));
WriteLine("ok");
@@ -456,8 +522,6 @@ public class AllTests : TestCommon.TestApp
test(communicator.identityToString(
baseProxy.ice_identity(communicator.stringToIdentity("other")).ice_getIdentity()).Equals("other"));
#pragma warning restore 612, 618
- test(Ice.Util.identityToString(
- baseProxy.ice_identity(Ice.Util.stringToIdentity("other")).ice_getIdentity()).Equals("other"));
test(baseProxy.ice_facet("facet").ice_getFacet().Equals("facet"));
test(baseProxy.ice_adapterId("id").ice_getAdapterId().Equals("id"));
test(baseProxy.ice_twoway().ice_isTwoway());
diff --git a/csharp/test/Ice/proxy/run.py b/csharp/test/Ice/proxy/run.py
index d0771952158..88a9c6c01bc 100755
--- a/csharp/test/Ice/proxy/run.py
+++ b/csharp/test/Ice/proxy/run.py
@@ -23,5 +23,5 @@ import TestUtil
TestUtil.queueClientServerTest()
TestUtil.queueClientServerTest(configName = "amd", localOnly = True, message = "Running test with AMD server.",
server="serveramd")
-TestUtil.queueCollocatedTest()
+TestUtil.queueCollocatedTest(additionalOptions = "--Ice.ToStringMode=Compat")
TestUtil.runQueuedTests()
diff --git a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java
index 72d7031cc94..97543a77755 100644
--- a/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java
+++ b/java-compat/src/Glacier2/src/main/java/Glacier2/SessionFactoryHelper.java
@@ -369,7 +369,7 @@ public class SessionFactoryHelper
{
StringBuilder sb = new StringBuilder();
sb.append("\"");
- sb.append(Ice.Util.identityToString(ident));
+ sb.append(Ice.Util.identityToString(ident, Ice.ToStringMode.Unicode));
sb.append("\":");
sb.append(_protocol + " -p ");
sb.append(getPortInternal());
diff --git a/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java
index 5523f7663b4..8ca4682639c 100644
--- a/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java
+++ b/java-compat/src/Ice/src/main/java/Ice/CommunicatorI.java
@@ -78,7 +78,7 @@ public final class CommunicatorI implements Communicator
public String
identityToString(Ice.Identity ident)
{
- return Ice.Util.identityToString(ident);
+ return Ice.Util.identityToString(ident, _instance.toStringMode());
}
@Override
diff --git a/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java
index 1aeef2206fa..53abcf4b4b6 100644
--- a/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java
+++ b/java-compat/src/Ice/src/main/java/Ice/ObjectAdapterI.java
@@ -980,7 +980,8 @@ public final class ObjectAdapterI implements ObjectAdapter
if(_routerInfo.getAdapter() != null)
{
throw new AlreadyRegisteredException("object adapter with router",
- Ice.Util.identityToString(router.ice_getIdentity()));
+ Ice.Util.identityToString(router.ice_getIdentity(),
+ _instance.toStringMode()));
}
//
diff --git a/java-compat/src/Ice/src/main/java/Ice/Util.java b/java-compat/src/Ice/src/main/java/Ice/Util.java
index 3c2b04d8fd4..a758a316e00 100644
--- a/java-compat/src/Ice/src/main/java/Ice/Util.java
+++ b/java-compat/src/Ice/src/main/java/Ice/Util.java
@@ -324,23 +324,37 @@ public final class Util
*
* @param ident The object identity to convert.
*
+ * @param toStringMode Specifies if and how non-printable ASCII characters are escaped in the result.
+ *
* @return The string representation of the object identity.
**/
- public static String
- identityToString(Identity ident)
+ public static String identityToString(Identity ident, ToStringMode toStringMode)
{
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);
}
}
/**
+ * Converts an object identity to a string.
+ *
+ * @param ident The object identity to convert.
+ *
+ * @return The string representation of the object identity using the default mode (Unicode)
+ **/
+ // public static String identityToString(Identity ident)
+ // {
+ // return identityToString(ident, ToStringMode.Unicode);
+ // }
+
+
+ /**
* Compares the object identities of two proxies.
*
* @param lhs A proxy.
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java
index 095948736e3..5b9f377d807 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/CommunicatorObserverI.java
@@ -319,7 +319,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb
public String
getIdentity()
{
- return Ice.Util.identityToString(_current.id);
+ return _current.adapter.getCommunicator().identityToString(_current.id);
}
final private Ice.Current _current;
@@ -428,7 +428,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb
catch(Exception ex)
{
// 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();
@@ -458,7 +458,7 @@ public class CommunicatorObserverI implements Ice.Instrumentation.CommunicatorOb
{
if(_proxy != null)
{
- return Ice.Util.identityToString(_proxy.ice_getIdentity());
+ return _proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity());
}
else
{
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java
index 1e1b4c4dfa8..2723ce7a7b7 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/IncomingBase.java
@@ -236,8 +236,8 @@ class IncomingBase
IceUtilInternal.OutputBase out = new IceUtilInternal.OutputBase(pw);
out.setUseTab(false);
out.print("dispatch exception:");
- out.print("\nidentity: " + Ice.Util.identityToString(_current.id));
- out.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, ""));
+ out.print("\nidentity: " + Ice.Util.identityToString(_current.id, _instance.toStringMode()));
+ out.print("\nfacet: " + IceUtilInternal.StringUtil.escapeString(_current.facet, "", _instance.toStringMode()));
out.print("\noperation: " + _current.operation);
if(_current.con != null)
{
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Instance.java b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java
index 30b78609ca8..997b64313f6 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/Instance.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Instance.java
@@ -393,6 +393,13 @@ public final class Instance implements Ice.ClassResolver
return _batchAutoFlushSize;
}
+ public Ice.ToStringMode
+ toStringMode()
+ {
+ // No mutex lock, immutable
+ return _toStringMode;
+ }
+
public int
cacheMessageBuffers()
{
@@ -1018,6 +1025,24 @@ public final class Instance implements Ice.ClassResolver
}
}
+ String toStringModeStr = _initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode");
+ if(toStringModeStr.equals("Unicode"))
+ {
+ _toStringMode = Ice.ToStringMode.Unicode;
+ }
+ else if(toStringModeStr.equals("ASCII"))
+ {
+ _toStringMode = Ice.ToStringMode.ASCII;
+ }
+ else if(toStringModeStr.equals("Compat"))
+ {
+ _toStringMode = Ice.ToStringMode.Compat;
+ }
+ else
+ {
+ throw new Ice.InitializationException("The value for Ice.ToStringMode must be Unicode, ASCII or Compat");
+ }
+
_implicitContext = Ice.ImplicitContextI.create(_initData.properties.getProperty("Ice.ImplicitContext"));
_routerManager = new RouterManager();
@@ -1820,6 +1845,7 @@ public final class Instance implements Ice.ClassResolver
private final DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy().
private final int _messageSizeMax; // Immutable, not reset by destroy().
private final int _batchAutoFlushSize; // Immutable, not reset by destroy().
+ private final Ice.ToStringMode _toStringMode; // Immutable, not reset by destroy().
private final int _cacheMessageBuffers; // Immutable, not reset by destroy().
private final ACMConfig _clientACM; // Immutable, not reset by destroy().
private final ACMConfig _serverACM; // Immutable, not reset by destroy().
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java
index 82c4dea0e25..65f0c20840c 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/LocatorInfo.java
@@ -466,7 +466,7 @@ public final class LocatorInfo
else
{
s.append("object = ");
- s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append(Ice.Util.identityToString(ref.getIdentity(), ref.getInstance().toStringMode()));
s.append("\n");
}
@@ -518,13 +518,13 @@ public final class LocatorInfo
StringBuilder s = new StringBuilder(128);
s.append("object not found\n");
s.append("object = ");
- 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());
}
Ice.NotRegisteredException e = new Ice.NotRegisteredException();
e.kindOfObject = "object";
- e.id = Ice.Util.identityToString(ref.getIdentity());
+ e.id = Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode());
throw e;
}
catch(Ice.NotRegisteredException ex)
@@ -547,7 +547,7 @@ public final class LocatorInfo
else
{
s.append("object = ");
- s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
s.append("\n");
}
s.append("reason = " + ex);
@@ -591,7 +591,7 @@ public final class LocatorInfo
{
s.append("object\n");
s.append("object = ");
- s.append(Ice.Util.identityToString(ref.getIdentity()));
+ s.append(Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
s.append("\n");
}
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
@@ -630,7 +630,7 @@ public final class LocatorInfo
StringBuilder s = new StringBuilder(128);
s.append("searching for object by id\n");
s.append("object = ");
- 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/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
index 78fca903d04..54e72359604 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/PropertyNames.java
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ./config/PropertyNames.xml, Thu Aug 18 20:28:56 2016
+// Generated by makeprops.py from file PropertyNames.xml, Tue Oct 18 11:39:01 2016
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -165,6 +165,7 @@ public final class PropertyNames
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),
@@ -980,7 +981,7 @@ public final class PropertyNames
new Property("IceSSL\\.DHParams", false, null),
new Property("IceSSL\\.EntropyDaemon", false, null),
new Property("IceSSL\\.FindCert", false, null),
- new Property("IceSSL\\.FindCert\\.[^\\s]+", true, "IceSSL.FindCert"),
+ new Property("IceSSL\\.FindCert\\.[^\\s]+", true, null),
new Property("IceSSL\\.InitOpenSSL", false, null),
new Property("IceSSL\\.KeyFile", true, null),
new Property("IceSSL\\.Keychain", false, null),
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/Reference.java b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java
index b7ea1dd2f32..48ac1b0788a 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/Reference.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/Reference.java
@@ -306,13 +306,18 @@ public abstract class Reference implements Cloneable
//
StringBuilder s = new StringBuilder(128);
+ Ice.ToStringMode toStringMode = _instance.toStringMode();
+ final String separators = " :@";
+
+ String id = Ice.Util.identityToString(_identity, 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);
- if(IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1)
+
+ if(IceUtilInternal.StringUtil.findFirstOf(id, separators) != -1)
{
s.append('"');
s.append(id);
@@ -331,8 +336,8 @@ public abstract class Reference implements Cloneable
// the facet string in quotes.
//
s.append(" -f ");
- String fs = IceUtilInternal.StringUtil.escapeString(_facet, "");
- if(IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1)
+ String fs = IceUtilInternal.StringUtil.escapeString(_facet, "", toStringMode);
+ if(IceUtilInternal.StringUtil.findFirstOf(fs, separators) != -1)
{
s.append('"');
s.append(fs);
@@ -481,16 +486,16 @@ public abstract class Reference implements Cloneable
@Override
public Reference clone()
{
- Reference c = null;
- try
- {
- c = (Reference)super.clone();
- }
- catch(CloneNotSupportedException ex)
- {
- assert false;
- }
- return c;
+ Reference c = null;
+ try
+ {
+ c = (Reference)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
}
protected int _hashValue;
diff --git a/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java
index 688b2ca9935..bdca554000a 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/RoutableReference.java
@@ -353,7 +353,7 @@ public class RoutableReference extends Reference
// 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/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java
index 2789304f276..aa74865221c 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/ServantManager.java
@@ -32,11 +32,11 @@ public final 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;
}
@@ -77,11 +77,11 @@ public final class ServantManager
if(m == null || (obj = m.remove(facet)) == null)
{
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;
}
@@ -120,7 +120,7 @@ public final 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;
}
@@ -218,7 +218,7 @@ public final 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;
}
@@ -236,7 +236,7 @@ public final 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/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java
index 2ff165c475d..d50797350e5 100644
--- a/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java
+++ b/java-compat/src/Ice/src/main/java/IceInternal/TraceUtil.java
@@ -166,15 +166,21 @@ public final class TraceUtil
{
try
{
+ Ice.ToStringMode toStringMode = Ice.ToStringMode.Unicode;
+ if(stream.instance() != null)
+ {
+ toStringMode = stream.instance().toStringMode();
+ }
+
Ice.Identity identity = new Ice.Identity();
identity.__read(stream);
- out.write("\nidentity = " + Ice.Util.identityToString(identity));
+ out.write("\nidentity = " + Ice.Util.identityToString(identity, toStringMode));
String[] facet = stream.readStringSeq();
out.write("\nfacet = ");
if(facet.length > 0)
{
- out.write(IceUtilInternal.StringUtil.escapeString(facet[0], ""));
+ out.write(IceUtilInternal.StringUtil.escapeString(facet[0], "", toStringMode));
}
String operation = stream.readString();
diff --git a/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java
index 953359c5c4b..5c274db2375 100644
--- a/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java
+++ b/java-compat/src/Ice/src/main/java/IceUtilInternal/StringUtil.java
@@ -75,97 +75,119 @@ public final class StringUtil
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)
+ encodeChar(char c, StringBuilder sb, String special, Ice.ToStringMode toStringMode)
{
- switch(b)
+ switch(c)
{
- case (byte)'\\':
+ case '\\':
{
sb.append("\\\\");
break;
}
- case (byte)'\'':
+ case '\'':
{
sb.append("\\'");
break;
}
- case (byte)'"':
+ case '"':
{
sb.append("\\\"");
break;
}
- case (byte)'\b':
+ case '\b':
{
sb.append("\\b");
break;
}
- case (byte)'\f':
+ case '\f':
{
sb.append("\\f");
break;
}
- case (byte)'\n':
+ case '\n':
{
sb.append("\\n");
break;
}
- case (byte)'\r':
+ case '\r':
{
sb.append("\\r");
break;
}
- case (byte)'\t':
+ case '\t':
{
sb.append("\\t");
break;
}
default:
{
- if(!(b >= 32 && b <= 126))
- {
- sb.append('\\');
- String octal = Integer.toOctalString(b < 0 ? b + 256 : b);
- //
- // 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)
+ if(special != null && special.indexOf(c) != -1)
{
sb.append('\\');
- sb.append((char)b);
+ sb.append(c);
}
else
{
- sb.append((char)b);
+ if(c < 32 || c > 126)
+ {
+ if(toStringMode == Ice.ToStringMode.Compat)
+ {
+ //
+ // When ToStringMode=Compat, c is a UTF-8 byte
+ //
+ assert(c < 256);
+
+ sb.append('\\');
+ String octal = Integer.toOctalString(c);
+ //
+ // 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(c < 32 || c == 127 || toStringMode == Ice.ToStringMode.ASCII)
+ {
+ // append \\unnnn
+ sb.append("\\u");
+ String hex = Integer.toHexString(c);
+ 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 backlash in the returned string.
+ // Add escape sequences (like "\n" to the input string)
+ // The second parameter adds characters to escape, and can be empty.
//
public static String
- escapeString(String s, String special)
+ escapeString(String s, String special, Ice.ToStringMode toStringMode)
{
if(special != null)
{
@@ -178,31 +200,72 @@ public final class StringUtil
}
}
- byte[] bytes = null;
- try
+ if(toStringMode == Ice.ToStringMode.Compat)
{
- bytes = s.getBytes("UTF8");
+ // Encode UTF-8 bytes
+
+ byte[] bytes = null;
+ try
+ {
+ bytes = s.getBytes("UTF8");
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ assert(false);
+ return null;
+ }
+
+ StringBuilder result = new StringBuilder(bytes.length);
+ for(int i = 0; i < bytes.length; i++)
+ {
+ encodeChar((char)(bytes[i] & 0xFF), result, special, toStringMode);
+ }
+
+ return result.toString();
}
- catch(java.io.UnsupportedEncodingException ex)
+ else
{
- assert(false);
- return null;
- }
+ StringBuilder result = new StringBuilder(s.length());
- StringBuilder result = new StringBuilder(bytes.length);
- for(int i = 0; i < bytes.length; i++)
- {
- encodeChar(bytes[i], result, special);
- }
+ for(int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+ if(toStringMode == Ice.ToStringMode.Unicode || !Character.isSurrogate(c))
+ {
+ encodeChar(c, result, special, toStringMode);
+ }
+ else
+ {
+ assert(toStringMode == Ice.ToStringMode.ASCII && Character.isSurrogate(c));
+ if(i + 1 == s.length())
+ {
+ throw new IllegalArgumentException("High surrogate without low surrogate");
+ }
+ else
+ {
+ i++;
+ int codePoint = Character.toCodePoint(c, s.charAt(i));
+ // append \Unnnnnnnn
+ result.append("\\U");
+ String hex = Integer.toHexString(codePoint);
+ 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)
{
char c = s.charAt(pos);
- if(!(c >= 32 && c <= 126))
+ if(c < 32 || c == 127)
{
String msg;
if(pos > 0)
@@ -213,28 +276,27 @@ public final class StringUtil
{
msg = "first character";
}
- msg += " is not a printable ASCII character (ordinal " + (int)c + ")";
+ msg += " has invalid ordinal value " + (int)c;
throw new IllegalArgumentException(msg);
}
return c;
}
//
- // Decode the character or escape sequence starting at start and return it.
- // newStart is set to the index of the first character following the decoded character
+ // 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, Ice.Holder<Integer> nextStart)
+ private static int
+ decodeChar(String s, int start, int end, StringBuilder result)
{
assert(start >= 0);
assert(start < end);
assert(end <= s.length());
- char c;
-
if(s.charAt(start) != '\\')
{
- c = checkChar(s, start++);
+ result.append(checkChar(s, start++));
}
else
{
@@ -242,45 +304,98 @@ public final class StringUtil
{
throw new IllegalArgumentException("trailing backslash");
}
- switch(s.charAt(++start))
+
+ char c = s.charAt(++start);
+
+ switch(c)
{
case '\\':
case '\'':
case '"':
{
- c = s.charAt(start++);
+ ++start;
+ result.append(c);
break;
}
case 'b':
{
++start;
- c = '\b';
+ result.append('\b');
break;
}
case 'f':
{
++start;
- c = '\f';
+ result.append('\f');
break;
}
case 'n':
{
++start;
- c = '\n';
+ result.append('\n');
break;
}
case 'r':
{
++start;
- c = '\r';
+ result.append('\r');
break;
}
case 't':
{
++start;
- c = '\t';
+ result.append('\t');
break;
}
+ case 'u':
+ case 'U':
+ {
+ int codePoint = 0;
+ boolean inBMP = (c == 'u');
+ int size = inBMP ? 4 : 8;
+ ++start;
+ while(size > 0 && start < end)
+ {
+ c = s.charAt(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 IllegalArgumentException("Invalid universal character name: too few hex digits");
+ }
+ if(inBMP && Character.isSurrogate((char)codePoint))
+ {
+ throw new IllegalArgumentException("A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead");
+ }
+ if(inBMP || Character.isBmpCodePoint(codePoint))
+ {
+ result.append((char)codePoint);
+ }
+ else
+ {
+ result.append(Character.toChars(codePoint));
+ }
+ break;
+ }
+
case '0':
case '1':
case '2':
@@ -290,49 +405,71 @@ public final class StringUtil
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;
+ boolean done = false;
+ while(!done)
{
- int charVal = s.charAt(start++) - '0';
- if(charVal < 0 || charVal > 7)
+ int val = 0;
+ for(int j = 0; j < 3 && start < end; ++j)
{
- --start;
- break;
+ int charVal = s.charAt(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;
}
- val = val * 8 + charVal;
+
+ if(!done)
+ {
+ if(val > 255)
+ {
+ String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range";
+ throw new IllegalArgumentException(msg);
+ }
+ arr[i++] = (byte)val;
+
+ if((start + 1 < end) && s.charAt(start) == '\\')
+ {
+ start++;
+ // loop, read next octal escape sequence
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ }
+
+ try
+ {
+ result.append(new String(arr, 0, i, "UTF8"));
}
- if(val > 255)
+ catch(java.io.UnsupportedEncodingException ex)
{
- String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range";
- throw new IllegalArgumentException(msg);
+ throw new IllegalArgumentException("unsupported encoding", ex);
}
- c = (char)val;
break;
}
default:
{
- c = checkChar(s, start++);
+ result.append(checkChar(s, start++));
break;
}
}
}
- nextStart.value = 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)
- {
- Ice.Holder<Integer> nextStart = new Ice.Holder<Integer>();
- while(start < end)
- {
- sb.append(decodeChar(s, start, end, nextStart));
- start = nextStart.value;
- }
+ return start;
}
//
@@ -344,26 +481,29 @@ public final class StringUtil
{
assert(start >= 0 && start <= end && end <= s.length());
- StringBuilder sb = new StringBuilder(end - start);
- decodeString(s, start, end, sb);
- String decodedString = sb.toString();
-
- byte[] arr = new byte[decodedString.length()];
- for(int i = 0; i < arr.length; ++i)
- {
- arr[i] = (byte)decodedString.charAt(i);
- }
-
- try
+ // Optimization for strings without escapes
+ int p = s.indexOf('\\', start);
+ if(p == -1 || p >= end)
{
- return new String(arr, 0, arr.length, "UTF8");
+ p = start;
+ while(p < end)
+ {
+ checkChar(s, p++);
+ }
+ return s.substring(start, end);
}
- catch(java.io.UnsupportedEncodingException ex)
+ else
{
- throw new IllegalArgumentException("unsupported encoding", ex);
+ StringBuilder sb = new StringBuilder(end - start);
+ while(start < end)
+ {
+ start = decodeChar(s, start, end, sb);
+ }
+ return sb.toString();
}
}
+
//
// Join a list of strings using the given delimiter.
//
diff --git a/java-compat/src/IceBox/src/main/java/IceBox/Admin.java b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java
index 52e39ee771e..0b363f83c6a 100644
--- a/java-compat/src/IceBox/src/main/java/IceBox/Admin.java
+++ b/java-compat/src/IceBox/src/main/java/IceBox/Admin.java
@@ -84,7 +84,7 @@ public final class Admin
return 1;
}
- managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" :" + managerEndpoints;
+ managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" :" + managerEndpoints;
}
else
{
@@ -95,7 +95,7 @@ public final class Admin
return 1;
}
- managerProxy = "\"" + Ice.Util.identityToString(managerIdentity) + "\" @" + managerAdapterId;
+ managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" @" + managerAdapterId;
}
base = communicator().stringToProxy(managerProxy);
diff --git a/java-compat/test/src/main/java/test/Ice/location/AllTests.java b/java-compat/test/src/main/java/test/Ice/location/AllTests.java
index 33bada684a8..06eae325c60 100644
--- a/java-compat/test/src/main/java/test/Ice/location/AllTests.java
+++ b/java-compat/test/src/main/java/test/Ice/location/AllTests.java
@@ -682,7 +682,7 @@ public class AllTests
// Note the quotes are necessary here due to ":" in the
// java generated UUID.
HelloPrx helloPrx = HelloPrxHelper.checkedCast(
- communicator.stringToProxy("\"" + Ice.Util.identityToString(id) + "\""));
+ communicator.stringToProxy("\"" + communicator.identityToString(id) + "\""));
test(helloPrx.ice_getConnection() == null);
adapter.deactivate();
diff --git a/java-compat/test/src/main/java/test/Ice/proxy/AllTests.java b/java-compat/test/src/main/java/test/Ice/proxy/AllTests.java
index 1b92d902a92..4db1ac8cebc 100644
--- a/java-compat/test/src/main/java/test/Ice/proxy/AllTests.java
+++ b/java-compat/test/src/main/java/test/Ice/proxy/AllTests.java
@@ -270,11 +270,77 @@ public class AllTests
// Test for bug ICE-5543: escaped escapes in stringToIdentity
//
Ice.Identity id = new Ice.Identity("test", ",X2QNUAzSBcJ_e$AV;E\\");
- Ice.Identity id2 = Ice.Util.stringToIdentity(Ice.Util.identityToString(id));
+ Ice.Identity id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
test(id.equals(id2));
id = new Ice.Identity("test", ",X2QNUAz\\SB\\/cJ_e$AV;E\\\\");
- id2 = Ice.Util.stringToIdentity(Ice.Util.identityToString(id));
+ id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.equals(id2));
+
+ id = new Ice.Identity("/test", "cat/");
+ String idStr = communicator.identityToString(id);
+ test(idStr.equals("cat\\//\\/test"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ try
+ {
+ // Illegal character < 32
+ id = Ice.Util.stringToIdentity("xx\01FooBar");
+ test(false);
+ }
+ catch(Ice.IdentityParseException e)
+ {
+ }
+
+ try
+ {
+ // Illegal surrogate
+ id = Ice.Util.stringToIdentity("xx\\ud911");
+ test(false);
+ }
+ catch(Ice.IdentityParseException e)
+ {
+ }
+
+ // Testing bytes 127 (\x7F, \177) and €
+ id = new Ice.Identity("test", "\177€");
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr.equals("\\u007f€/test"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+ // test(Ice.Util.identityToString(id).equals(idStr));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr.equals("\\u007f\\u20ac/test"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Compat);
+ test(idStr.equals("\\177\\342\\202\\254/test"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ id2 = Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.equals(id2));
+
+ // More unicode character
+ id = new Ice.Identity("banana \016-\ud83c\udf4c\u20ac\u00a2\u0024", "greek \ud800\udd6a");
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr.equals("greek \ud800\udd6a/banana \\u000e-\ud83c\udf4c\u20ac\u00a2$"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr.equals("greek \\U0001016a/banana \\u000e-\\U0001f34c\\u20ac\\u00a2$"));
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.Util.identityToString(id, Ice.ToStringMode.Compat);
+ id2 = Ice.Util.stringToIdentity(idStr);
+ test(idStr.equals("greek \\360\\220\\205\\252/banana \\016-\\360\\237\\215\\214\\342\\202\\254\\302\\242$"));
test(id.equals(id2));
out.println("ok");
@@ -461,8 +527,6 @@ public class AllTests
out.print("testing proxy methods... ");
out.flush();
- test(Ice.Util.identityToString(
- base.ice_identity(Ice.Util.stringToIdentity("other")).ice_getIdentity()).equals("other"));
test(base.ice_facet("facet").ice_getFacet().equals("facet"));
test(base.ice_adapterId("id").ice_getAdapterId().equals("id"));
test(base.ice_twoway().ice_isTwoway());
diff --git a/java-compat/test/src/main/java/test/Ice/proxy/run.py b/java-compat/test/src/main/java/test/Ice/proxy/run.py
index 78cfe699505..0d0598cb160 100755
--- a/java-compat/test/src/main/java/test/Ice/proxy/run.py
+++ b/java-compat/test/src/main/java/test/Ice/proxy/run.py
@@ -24,5 +24,5 @@ import TestUtil
TestUtil.queueClientServerTest()
TestUtil.queueClientServerTest(configName = "amd", localOnly = True, message = "Running test with AMD server.",
server="test.Ice.proxy.AMDServer")
-TestUtil.queueCollocatedTest()
+TestUtil.queueCollocatedTest(additionalOptions = "--Ice.ToStringMode=Compat")
TestUtil.runQueuedTests()
diff --git a/java/src/Glacier2/src/main/java/com/zeroc/Glacier2/SessionFactoryHelper.java b/java/src/Glacier2/src/main/java/com/zeroc/Glacier2/SessionFactoryHelper.java
index f7b86f48c09..d7c293bd3c7 100644
--- a/java/src/Glacier2/src/main/java/com/zeroc/Glacier2/SessionFactoryHelper.java
+++ b/java/src/Glacier2/src/main/java/com/zeroc/Glacier2/SessionFactoryHelper.java
@@ -352,7 +352,7 @@ public class SessionFactoryHelper
{
StringBuilder sb = new StringBuilder();
sb.append("\"");
- sb.append(Util.identityToString(ident));
+ sb.append(Util.identityToString(ident, com.zeroc.Ice.ToStringMode.Unicode));
sb.append("\":");
sb.append(_protocol + " -p ");
sb.append(getPortInternal());
diff --git a/java/src/Ice/src/main/java/com/zeroc/Ice/CommunicatorI.java b/java/src/Ice/src/main/java/com/zeroc/Ice/CommunicatorI.java
index 64ff934f6d4..035c6b39f15 100644
--- a/java/src/Ice/src/main/java/com/zeroc/Ice/CommunicatorI.java
+++ b/java/src/Ice/src/main/java/com/zeroc/Ice/CommunicatorI.java
@@ -74,11 +74,11 @@ public final class CommunicatorI implements Communicator
return Util.stringToIdentity(s);
}
- @Override @SuppressWarnings("deprecation")
+ @Override
public String
identityToString(Identity ident)
{
- return Util.identityToString(ident);
+ return Util.identityToString(ident, _instance.toStringMode());
}
@Override
diff --git a/java/src/Ice/src/main/java/com/zeroc/Ice/ObjectAdapterI.java b/java/src/Ice/src/main/java/com/zeroc/Ice/ObjectAdapterI.java
index 61cf6d72537..2ae50796171 100644
--- a/java/src/Ice/src/main/java/com/zeroc/Ice/ObjectAdapterI.java
+++ b/java/src/Ice/src/main/java/com/zeroc/Ice/ObjectAdapterI.java
@@ -981,7 +981,7 @@ public final class ObjectAdapterI implements ObjectAdapter
if(_routerInfo.getAdapter() != null)
{
throw new AlreadyRegisteredException("object adapter with router",
- Util.identityToString(router.ice_getIdentity()));
+ _communicator.identityToString(router.ice_getIdentity()));
}
//
diff --git a/java/src/Ice/src/main/java/com/zeroc/Ice/Util.java b/java/src/Ice/src/main/java/com/zeroc/Ice/Util.java
index 20ec18f99bd..2cb75ec9cd0 100644
--- a/java/src/Ice/src/main/java/com/zeroc/Ice/Util.java
+++ b/java/src/Ice/src/main/java/com/zeroc/Ice/Util.java
@@ -275,21 +275,36 @@ public final class Util
*
* @param ident The object identity to convert.
*
+ * @param toStringMode Specifies if and how non-printable ASCII characters are escaped in the result.
+ *
* @return The string representation of the object identity.
**/
- public static String identityToString(Identity ident)
+ public static String identityToString(Identity ident, ToStringMode toStringMode)
{
if(ident.category == null || ident.category.length() == 0)
{
- return StringUtil.escapeString(ident.name, "/");
+ return StringUtil.escapeString(ident.name, "/", toStringMode);
}
else
{
- return StringUtil.escapeString(ident.category, "/") + '/' + StringUtil.escapeString(ident.name, "/");
+ return StringUtil.escapeString(ident.category, "/", toStringMode) + '/' +
+ StringUtil.escapeString(ident.name, "/", toStringMode);
}
}
/**
+ * Converts an object identity to a string.
+ *
+ * @param ident The object identity to convert.
+ *
+ * @return The string representation of the object identity using the default mode (Unicode)
+ **/
+ public static String identityToString(Identity ident)
+ {
+ return identityToString(ident, ToStringMode.Unicode);
+ }
+
+ /**
* Compares the object identities of two proxies.
*
* @param lhs A proxy.
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/CommunicatorObserverI.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/CommunicatorObserverI.java
index d16ba494470..a3ffebca386 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/CommunicatorObserverI.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/CommunicatorObserverI.java
@@ -320,7 +320,7 @@ public class CommunicatorObserverI implements com.zeroc.Ice.Instrumentation.Comm
public String
getIdentity()
{
- return com.zeroc.Ice.Util.identityToString(_current.id);
+ return _current.adapter.getCommunicator().identityToString(_current.id);
}
final private com.zeroc.Ice.Current _current;
@@ -429,7 +429,7 @@ public class CommunicatorObserverI implements com.zeroc.Ice.Instrumentation.Comm
catch(Exception ex)
{
// Either a fixed proxy or the communicator is destroyed.
- os.append(com.zeroc.Ice.Util.identityToString(_proxy.ice_getIdentity()));
+ os.append(_proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity()));
os.append(" [").append(_operation).append(']');
}
_id = os.toString();
@@ -459,7 +459,7 @@ public class CommunicatorObserverI implements com.zeroc.Ice.Instrumentation.Comm
{
if(_proxy != null)
{
- return com.zeroc.Ice.Util.identityToString(_proxy.ice_getIdentity());
+ return _proxy.ice_getCommunicator().identityToString(_proxy.ice_getIdentity());
}
else
{
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Incoming.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Incoming.java
index 8929771e994..67941f3b1e5 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Incoming.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Incoming.java
@@ -533,8 +533,8 @@ final public class Incoming implements com.zeroc.Ice.Request
com.zeroc.IceUtilInternal.OutputBase out = new com.zeroc.IceUtilInternal.OutputBase(pw);
out.setUseTab(false);
out.print("dispatch exception:");
- out.print("\nidentity: " + Util.identityToString(_current.id));
- out.print("\nfacet: " + com.zeroc.IceUtilInternal.StringUtil.escapeString(_current.facet, ""));
+ out.print("\nidentity: " + Util.identityToString(_current.id, _instance.toStringMode()));
+ out.print("\nfacet: " + com.zeroc.IceUtilInternal.StringUtil.escapeString(_current.facet, "", _instance.toStringMode()));
out.print("\noperation: " + _current.operation);
if(_current.con != null)
{
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Instance.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Instance.java
index d4c3663560f..5bf70b1d2f6 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Instance.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Instance.java
@@ -390,6 +390,13 @@ public final class Instance implements com.zeroc.Ice.ClassResolver
return _batchAutoFlushSize;
}
+ public com.zeroc.Ice.ToStringMode
+ toStringMode()
+ {
+ // No mutex lock, immutable
+ return _toStringMode;
+ }
+
public int
cacheMessageBuffers()
{
@@ -1065,6 +1072,24 @@ public final class Instance implements com.zeroc.Ice.ClassResolver
}
}
+ String toStringModeStr = _initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode");
+ if(toStringModeStr.equals("Unicode"))
+ {
+ _toStringMode = com.zeroc.Ice.ToStringMode.Unicode;
+ }
+ else if(toStringModeStr.equals("ASCII"))
+ {
+ _toStringMode = com.zeroc.Ice.ToStringMode.ASCII;
+ }
+ else if(toStringModeStr.equals("Compat"))
+ {
+ _toStringMode = com.zeroc.Ice.ToStringMode.Compat;
+ }
+ else
+ {
+ throw new com.zeroc.Ice.InitializationException("The value for Ice.ToStringMode must be Unicode, ASCII or Compat");
+ }
+
_implicitContext =
com.zeroc.Ice.ImplicitContextI.create(_initData.properties.getProperty("Ice.ImplicitContext"));
@@ -1875,6 +1900,7 @@ public final class Instance implements com.zeroc.Ice.ClassResolver
private final DefaultsAndOverrides _defaultsAndOverrides; // Immutable, not reset by destroy().
private final int _messageSizeMax; // Immutable, not reset by destroy().
private final int _batchAutoFlushSize; // Immutable, not reset by destroy().
+ private final com.zeroc.Ice.ToStringMode _toStringMode; // Immutable, not reset by destroy().
private final int _cacheMessageBuffers; // Immutable, not reset by destroy().
private final ACMConfig _clientACM; // Immutable, not reset by destroy().
private final ACMConfig _serverACM; // Immutable, not reset by destroy().
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/LocatorInfo.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/LocatorInfo.java
index f363157b13a..8e5cc8974ce 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/LocatorInfo.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/LocatorInfo.java
@@ -462,7 +462,7 @@ public final class LocatorInfo
else
{
s.append("object = ");
- s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity()));
+ s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity(), ref.getInstance().toStringMode()));
s.append("\n");
}
@@ -514,13 +514,13 @@ public final class LocatorInfo
StringBuilder s = new StringBuilder(128);
s.append("object not found\n");
s.append("object = ");
- s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity()));
+ s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
com.zeroc.Ice.NotRegisteredException e = new com.zeroc.Ice.NotRegisteredException();
e.kindOfObject = "object";
- e.id = com.zeroc.Ice.Util.identityToString(ref.getIdentity());
+ e.id = com.zeroc.Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode());
throw e;
}
catch(com.zeroc.Ice.NotRegisteredException ex)
@@ -543,7 +543,7 @@ public final class LocatorInfo
else
{
s.append("object = ");
- s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity()));
+ s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
s.append("\n");
}
s.append("reason = " + ex);
@@ -587,7 +587,7 @@ public final class LocatorInfo
{
s.append("object\n");
s.append("object = ");
- s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity()));
+ s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
s.append("\n");
}
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
@@ -626,7 +626,7 @@ public final class LocatorInfo
StringBuilder s = new StringBuilder(128);
s.append("searching for object by id\n");
s.append("object = ");
- s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity()));
+ s.append(com.zeroc.Ice.Util.identityToString(ref.getIdentity(), instance.toStringMode()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.toString());
}
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
index 45647f08494..46750aa5e7a 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/PropertyNames.java
@@ -6,7 +6,7 @@
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
-// Generated by makeprops.py from file ..\config\PropertyNames.xml, Fri Jul 15 14:02:34 2016
+// Generated by makeprops.py from file PropertyNames.xml, Tue Oct 18 11:38:54 2016
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -165,6 +165,7 @@ public final class PropertyNames
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),
@@ -980,7 +981,7 @@ public final class PropertyNames
new Property("IceSSL\\.DHParams", false, null),
new Property("IceSSL\\.EntropyDaemon", false, null),
new Property("IceSSL\\.FindCert", false, null),
- new Property("IceSSL\\.FindCert\\.[^\\s]+", true, "IceSSL.FindCert"),
+ new Property("IceSSL\\.FindCert\\.[^\\s]+", true, null),
new Property("IceSSL\\.InitOpenSSL", false, null),
new Property("IceSSL\\.KeyFile", true, null),
new Property("IceSSL\\.Keychain", false, null),
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Reference.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Reference.java
index e8420c9c6f7..2b2d2fc12e0 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/Reference.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/Reference.java
@@ -306,13 +306,18 @@ public abstract class Reference implements Cloneable
//
StringBuilder s = new StringBuilder(128);
+ com.zeroc.Ice.ToStringMode toStringMode = _instance.toStringMode();
+ final String separators = " :@";
+
+ String id = com.zeroc.Ice.Util.identityToString(_identity, 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 = com.zeroc.Ice.Util.identityToString(_identity);
- if(com.zeroc.IceUtilInternal.StringUtil.findFirstOf(id, " :@") != -1)
+
+ if(com.zeroc.IceUtilInternal.StringUtil.findFirstOf(id, separators) != -1)
{
s.append('"');
s.append(id);
@@ -331,8 +336,8 @@ public abstract class Reference implements Cloneable
// the facet string in quotes.
//
s.append(" -f ");
- String fs = com.zeroc.IceUtilInternal.StringUtil.escapeString(_facet, "");
- if(com.zeroc.IceUtilInternal.StringUtil.findFirstOf(fs, " :@") != -1)
+ String fs = com.zeroc.IceUtilInternal.StringUtil.escapeString(_facet, "", toStringMode);
+ if(com.zeroc.IceUtilInternal.StringUtil.findFirstOf(fs, separators) != -1)
{
s.append('"');
s.append(fs);
@@ -481,16 +486,16 @@ public abstract class Reference implements Cloneable
@Override
public Reference clone()
{
- Reference c = null;
- try
- {
- c = (Reference)super.clone();
- }
- catch(CloneNotSupportedException ex)
- {
- assert false;
- }
- return c;
+ Reference c = null;
+ try
+ {
+ c = (Reference)super.clone();
+ }
+ catch(CloneNotSupportedException ex)
+ {
+ assert false;
+ }
+ return c;
}
protected int _hashValue;
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/RoutableReference.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/RoutableReference.java
index b383011df95..4600da1e9d3 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/RoutableReference.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/RoutableReference.java
@@ -353,7 +353,8 @@ public class RoutableReference extends Reference
// the reference parser uses as separators, then we enclose
// the adapter id string in quotes.
//
- String a = com.zeroc.IceUtilInternal.StringUtil.escapeString(_adapterId, null);
+
+ String a = com.zeroc.IceUtilInternal.StringUtil.escapeString(_adapterId, null, getInstance().toStringMode());
if(com.zeroc.IceUtilInternal.StringUtil.findFirstOf(a, " :@") != -1)
{
s.append('"');
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/ServantManager.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/ServantManager.java
index d83dfb8e141..badc3786f45 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/ServantManager.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/ServantManager.java
@@ -32,11 +32,12 @@ public final class ServantManager
if(m.containsKey(facet))
{
com.zeroc.Ice.AlreadyRegisteredException ex = new com.zeroc.Ice.AlreadyRegisteredException();
- ex.id = com.zeroc.Ice.Util.identityToString(ident);
+ ex.id = com.zeroc.Ice.Util.identityToString(ident, _instance.toStringMode());
ex.kindOfObject = "servant";
if(facet.length() > 0)
{
- ex.id += " -f " + com.zeroc.IceUtilInternal.StringUtil.escapeString(facet, "");
+ ex.id += " -f " + com.zeroc.IceUtilInternal.StringUtil.escapeString(facet, "",
+ _instance.toStringMode());
}
throw ex;
}
@@ -77,11 +78,12 @@ public final class ServantManager
if(m == null || (obj = m.remove(facet)) == null)
{
com.zeroc.Ice.NotRegisteredException ex = new com.zeroc.Ice.NotRegisteredException();
- ex.id = com.zeroc.Ice.Util.identityToString(ident);
+ ex.id = com.zeroc.Ice.Util.identityToString(ident, _instance.toStringMode());
ex.kindOfObject = "servant";
if(facet.length() > 0)
{
- ex.id += " -f " + com.zeroc.IceUtilInternal.StringUtil.escapeString(facet, "");
+ ex.id += " -f " + com.zeroc.IceUtilInternal.StringUtil.escapeString(facet, "",
+ _instance.toStringMode());
}
throw ex;
}
@@ -120,7 +122,7 @@ public final class ServantManager
if(m == null)
{
com.zeroc.Ice.NotRegisteredException ex = new com.zeroc.Ice.NotRegisteredException();
- ex.id = com.zeroc.Ice.Util.identityToString(ident);
+ ex.id = com.zeroc.Ice.Util.identityToString(ident, _instance.toStringMode());
ex.kindOfObject = "servant";
throw ex;
}
@@ -218,7 +220,8 @@ public final class ServantManager
if(l != null)
{
com.zeroc.Ice.AlreadyRegisteredException ex = new com.zeroc.Ice.AlreadyRegisteredException();
- ex.id = com.zeroc.IceUtilInternal.StringUtil.escapeString(category, "");
+ ex.id = com.zeroc.IceUtilInternal.StringUtil.escapeString(category, "",
+ _instance.toStringMode());
ex.kindOfObject = "servant locator";
throw ex;
}
@@ -236,7 +239,8 @@ public final class ServantManager
if(l == null)
{
com.zeroc.Ice.NotRegisteredException ex = new com.zeroc.Ice.NotRegisteredException();
- ex.id = com.zeroc.IceUtilInternal.StringUtil.escapeString(category, "");
+ ex.id = com.zeroc.IceUtilInternal.StringUtil.escapeString(category, "",
+ _instance.toStringMode());
ex.kindOfObject = "servant locator";
throw ex;
}
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceInternal/TraceUtil.java b/java/src/Ice/src/main/java/com/zeroc/IceInternal/TraceUtil.java
index 4798d1be659..36b60e57168 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceInternal/TraceUtil.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceInternal/TraceUtil.java
@@ -168,14 +168,20 @@ public final class TraceUtil
{
try
{
+ com.zeroc.Ice.ToStringMode toStringMode = com.zeroc.Ice.ToStringMode.Unicode;
+ if(stream.instance() != null)
+ {
+ toStringMode = stream.instance().toStringMode();
+ }
+
com.zeroc.Ice.Identity identity = com.zeroc.Ice.Identity.read(stream, null);
- out.write("\nidentity = " + com.zeroc.Ice.Util.identityToString(identity));
+ out.write("\nidentity = " + com.zeroc.Ice.Util.identityToString(identity, toStringMode));
String[] facet = stream.readStringSeq();
out.write("\nfacet = ");
if(facet.length > 0)
{
- out.write(com.zeroc.IceUtilInternal.StringUtil.escapeString(facet[0], ""));
+ out.write(com.zeroc.IceUtilInternal.StringUtil.escapeString(facet[0], "", toStringMode));
}
String operation = stream.readString();
diff --git a/java/src/Ice/src/main/java/com/zeroc/IceUtilInternal/StringUtil.java b/java/src/Ice/src/main/java/com/zeroc/IceUtilInternal/StringUtil.java
index cf6de757a9c..782c352c218 100644
--- a/java/src/Ice/src/main/java/com/zeroc/IceUtilInternal/StringUtil.java
+++ b/java/src/Ice/src/main/java/com/zeroc/IceUtilInternal/StringUtil.java
@@ -75,97 +75,119 @@ public final class StringUtil
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)
+ encodeChar(char c, StringBuilder sb, String special, com.zeroc.Ice.ToStringMode toStringMode)
{
- switch(b)
+ switch(c)
{
- case (byte)'\\':
+ case '\\':
{
sb.append("\\\\");
break;
}
- case (byte)'\'':
+ case '\'':
{
sb.append("\\'");
break;
}
- case (byte)'"':
+ case '"':
{
sb.append("\\\"");
break;
}
- case (byte)'\b':
+ case '\b':
{
sb.append("\\b");
break;
}
- case (byte)'\f':
+ case '\f':
{
sb.append("\\f");
break;
}
- case (byte)'\n':
+ case '\n':
{
sb.append("\\n");
break;
}
- case (byte)'\r':
+ case '\r':
{
sb.append("\\r");
break;
}
- case (byte)'\t':
+ case '\t':
{
sb.append("\\t");
break;
}
default:
{
- if(!(b >= 32 && b <= 126))
- {
- sb.append('\\');
- String octal = Integer.toOctalString(b < 0 ? b + 256 : b);
- //
- // 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)
+ if(special != null && special.indexOf(c) != -1)
{
sb.append('\\');
- sb.append((char)b);
+ sb.append(c);
}
else
{
- sb.append((char)b);
+ if(c < 32 || c > 126)
+ {
+ if(toStringMode == com.zeroc.Ice.ToStringMode.Compat)
+ {
+ //
+ // When ToStringMode=Compat, c is a UTF-8 byte
+ //
+ assert(c < 256);
+
+ sb.append('\\');
+ String octal = Integer.toOctalString(c);
+ //
+ // 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(c < 32 || c == 127 || toStringMode == com.zeroc.Ice.ToStringMode.ASCII)
+ {
+ // append \\unnnn
+ sb.append("\\u");
+ String hex = Integer.toHexString(c);
+ 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 backlash in the returned string.
+ // Add escape sequences (like "\n" to the input string)
+ // The second parameter adds characters to escape, and can be empty.
//
public static String
- escapeString(String s, String special)
+ escapeString(String s, String special, com.zeroc.Ice.ToStringMode toStringMode)
{
if(special != null)
{
@@ -178,31 +200,72 @@ public final class StringUtil
}
}
- byte[] bytes = null;
- try
+ if(toStringMode == com.zeroc.Ice.ToStringMode.Compat)
{
- bytes = s.getBytes("UTF8");
+ // Encode UTF-8 bytes
+
+ byte[] bytes = null;
+ try
+ {
+ bytes = s.getBytes("UTF8");
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ assert(false);
+ return null;
+ }
+
+ StringBuilder result = new StringBuilder(bytes.length);
+ for(int i = 0; i < bytes.length; i++)
+ {
+ encodeChar((char)(bytes[i] & 0xFF), result, special, toStringMode);
+ }
+
+ return result.toString();
}
- catch(java.io.UnsupportedEncodingException ex)
+ else
{
- assert(false);
- return null;
- }
+ StringBuilder result = new StringBuilder(s.length());
- StringBuilder result = new StringBuilder(bytes.length);
- for(int i = 0; i < bytes.length; i++)
- {
- encodeChar(bytes[i], result, special);
- }
+ for(int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+ if(toStringMode == com.zeroc.Ice.ToStringMode.Unicode || !Character.isSurrogate(c))
+ {
+ encodeChar(c, result, special, toStringMode);
+ }
+ else
+ {
+ assert(toStringMode == com.zeroc.Ice.ToStringMode.ASCII && Character.isSurrogate(c));
+ if(i + 1 == s.length())
+ {
+ throw new IllegalArgumentException("High surrogate without low surrogate");
+ }
+ else
+ {
+ i++;
+ int codePoint = Character.toCodePoint(c, s.charAt(i));
+ // append \Unnnnnnnn
+ result.append("\\U");
+ String hex = Integer.toHexString(codePoint);
+ 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)
{
char c = s.charAt(pos);
- if(!(c >= 32 && c <= 126))
+ if(c < 32 || c == 127)
{
String msg;
if(pos > 0)
@@ -213,42 +276,27 @@ public final class StringUtil
{
msg = "first character";
}
- msg += " is not a printable ASCII character (ordinal " + (int)c + ")";
+ msg += " has invalid ordinal value " + (int)c;
throw new IllegalArgumentException(msg);
}
return c;
}
- static class Holder<T>
- {
- public Holder()
- {
- }
-
- public Holder(T value)
- {
- this.value = value;
- }
-
- public T value;
- }
-
//
- // Decode the character or escape sequence starting at start and return it.
- // newStart is set to the index of the first character following the decoded character
+ // 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, Holder<Integer> nextStart)
+ private static int
+ decodeChar(String s, int start, int end, StringBuilder result)
{
assert(start >= 0);
assert(start < end);
assert(end <= s.length());
- char c;
-
if(s.charAt(start) != '\\')
{
- c = checkChar(s, start++);
+ result.append(checkChar(s, start++));
}
else
{
@@ -256,45 +304,98 @@ public final class StringUtil
{
throw new IllegalArgumentException("trailing backslash");
}
- switch(s.charAt(++start))
+
+ char c = s.charAt(++start);
+
+ switch(c)
{
case '\\':
case '\'':
case '"':
{
- c = s.charAt(start++);
+ ++start;
+ result.append(c);
break;
}
case 'b':
{
++start;
- c = '\b';
+ result.append('\b');
break;
}
case 'f':
{
++start;
- c = '\f';
+ result.append('\f');
break;
}
case 'n':
{
++start;
- c = '\n';
+ result.append('\n');
break;
}
case 'r':
{
++start;
- c = '\r';
+ result.append('\r');
break;
}
case 't':
{
++start;
- c = '\t';
+ result.append('\t');
+ break;
+ }
+ case 'u':
+ case 'U':
+ {
+ int codePoint = 0;
+ boolean inBMP = (c == 'u');
+ int size = inBMP ? 4 : 8;
+ ++start;
+ while(size > 0 && start < end)
+ {
+ c = s.charAt(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 IllegalArgumentException("Invalid universal character name: too few hex digits");
+ }
+ if(inBMP && Character.isSurrogate((char)codePoint))
+ {
+ throw new IllegalArgumentException("A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead");
+ }
+ if(inBMP || Character.isBmpCodePoint(codePoint))
+ {
+ result.append((char)codePoint);
+ }
+ else
+ {
+ result.append(Character.toChars(codePoint));
+ }
break;
}
+
case '0':
case '1':
case '2':
@@ -304,49 +405,71 @@ public final class StringUtil
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;
+ boolean done = false;
+ while(!done)
{
- int charVal = s.charAt(start++) - '0';
- if(charVal < 0 || charVal > 7)
+ int val = 0;
+ for(int j = 0; j < 3 && start < end; ++j)
{
- --start;
- break;
+ int charVal = s.charAt(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 \\" + Integer.toOctalString(val) + " (" + val + ") is out of range";
+ throw new IllegalArgumentException(msg);
+ }
+ arr[i++] = (byte)val;
+
+ if((start + 1 < end) && s.charAt(start) == '\\')
+ {
+ start++;
+ // loop, read next octal escape sequence
+ }
+ else
+ {
+ done = true;
+ }
}
- val = val * 8 + charVal;
}
- if(val > 255)
+
+ try
{
- String msg = "octal value \\" + Integer.toOctalString(val) + " (" + val + ") is out of range";
- throw new IllegalArgumentException(msg);
+ result.append(new String(arr, 0, i, "UTF8"));
+ }
+ catch(java.io.UnsupportedEncodingException ex)
+ {
+ throw new IllegalArgumentException("unsupported encoding", ex);
}
- c = (char)val;
break;
}
default:
{
- c = checkChar(s, start++);
+ result.append(checkChar(s, start++));
break;
}
}
}
- nextStart.value = 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)
- {
- Holder<Integer> nextStart = new Holder<>();
- while(start < end)
- {
- sb.append(decodeChar(s, start, end, nextStart));
- start = nextStart.value;
- }
+ return start;
}
//
@@ -358,23 +481,25 @@ public final class StringUtil
{
assert(start >= 0 && start <= end && end <= s.length());
- StringBuilder sb = new StringBuilder(end - start);
- 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
+ int p = s.indexOf('\\', start);
+ if(p == -1 || p >= end)
{
- arr[i] = (byte)decodedString.charAt(i);
- }
-
- try
- {
- return new String(arr, 0, arr.length, "UTF8");
+ p = start;
+ while(p < end)
+ {
+ checkChar(s, p++);
+ }
+ return s.substring(start, end);
}
- catch(java.io.UnsupportedEncodingException ex)
+ else
{
- throw new IllegalArgumentException("unsupported encoding", ex);
+ StringBuilder sb = new StringBuilder(end - start);
+ while(start < end)
+ {
+ start = decodeChar(s, start, end, sb);
+ }
+ return sb.toString();
}
}
diff --git a/java/src/IceBox/src/main/java/com/zeroc/IceBox/Admin.java b/java/src/IceBox/src/main/java/com/zeroc/IceBox/Admin.java
index ace16b7d0b7..6f1645bb53b 100644
--- a/java/src/IceBox/src/main/java/com/zeroc/IceBox/Admin.java
+++ b/java/src/IceBox/src/main/java/com/zeroc/IceBox/Admin.java
@@ -82,7 +82,7 @@ public final class Admin
return 1;
}
- managerProxy = "\"" + com.zeroc.Ice.Util.identityToString(managerIdentity) + "\" :" +
+ managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" :" +
managerEndpoints;
}
else
@@ -94,7 +94,7 @@ public final class Admin
return 1;
}
- managerProxy = "\"" + com.zeroc.Ice.Util.identityToString(managerIdentity) + "\" @" +
+ managerProxy = "\"" + communicator().identityToString(managerIdentity) + "\" @" +
managerAdapterId;
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/AdapterEditor.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/AdapterEditor.java
index 6b2477854f8..20415fa116f 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/AdapterEditor.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/AdapterEditor.java
@@ -575,9 +575,11 @@ class AdapterEditor extends CommunicatorChildEditor
private java.util.Map<String, String[]> objectDescriptorSeqToMap(java.util.List<ObjectDescriptor> objects)
{
java.util.Map<String, String[]> result = new java.util.TreeMap<>();
+ com.zeroc.Ice.Communicator communicator = getAdapter().getRoot().getCoordinator().getCommunicator();
+
for(ObjectDescriptor p : objects)
{
- String k = com.zeroc.Ice.Util.identityToString(p.id);
+ String k = communicator.identityToString(p.id);
result.put(k, new String[]{p.type, getAdapter().lookupPropertyValue(k),p.proxyOptions});
}
return result;
@@ -587,11 +589,12 @@ class AdapterEditor extends CommunicatorChildEditor
{
String badIdentities = "";
java.util.LinkedList<ObjectDescriptor> result = new java.util.LinkedList<>();
+ com.zeroc.Ice.Communicator communicator = getAdapter().getRoot().getCoordinator().getCommunicator();
for(java.util.Map.Entry<String, String[]> p : map.entrySet())
{
try
{
- com.zeroc.Ice.Identity id = com.zeroc.Ice.Util.stringToIdentity(p.getKey());
+ com.zeroc.Ice.Identity id = communicator.stringToIdentity(p.getKey());
String[] val = p.getValue();
result.add(new ObjectDescriptor(id, val[0], val[2]));
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/PropertiesField.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/PropertiesField.java
index 782c476376e..cb6ad3998f0 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/PropertiesField.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/PropertiesField.java
@@ -111,11 +111,11 @@ public class PropertiesField extends JTable
for(ObjectDescriptor q : p.objects)
{
- hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id));
+ hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id, com.zeroc.Ice.ToStringMode.Unicode));
}
for(ObjectDescriptor q : p.allocatables)
{
- hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id));
+ hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id, com.zeroc.Ice.ToStringMode.Unicode));
}
}
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/ReplicaGroupEditor.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/ReplicaGroupEditor.java
index 4f1642b15e8..c81585473f1 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/ReplicaGroupEditor.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/ReplicaGroupEditor.java
@@ -422,9 +422,10 @@ class ReplicaGroupEditor extends Editor
private java.util.Map<String, String[]> objectDescriptorSeqToMap(java.util.List<ObjectDescriptor> objects)
{
java.util.Map<String, String[]> result = new java.util.TreeMap<>();
+ com.zeroc.Ice.Communicator communicator = _target.getCoordinator().getCommunicator();
for(ObjectDescriptor p : objects)
{
- result.put(com.zeroc.Ice.Util.identityToString(p.id), new String[]{p.type, p.proxyOptions});
+ result.put(communicator.identityToString(p.id), new String[]{p.type, p.proxyOptions});
}
return result;
}
@@ -433,12 +434,13 @@ class ReplicaGroupEditor extends Editor
{
String badIdentities = "";
java.util.LinkedList<ObjectDescriptor> result = new java.util.LinkedList<>();
+ com.zeroc.Ice.Communicator communicator = _target.getCoordinator().getCommunicator();
for(java.util.Map.Entry<String, String[]> p : map.entrySet())
{
try
{
- com.zeroc.Ice.Identity id = com.zeroc.Ice.Util.stringToIdentity(p.getKey());
+ com.zeroc.Ice.Identity id = communicator.stringToIdentity(p.getKey());
String[] val = p.getValue();
result.add(new ObjectDescriptor(id, val[0], val[1]));
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/TreeNode.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/TreeNode.java
index f8276f2dc2c..56dd18e634e 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/TreeNode.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Application/TreeNode.java
@@ -140,11 +140,11 @@ public abstract class TreeNode extends TreeNodeBase
for(ObjectDescriptor q : p.objects)
{
- hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id));
+ hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id, com.zeroc.Ice.ToStringMode.Unicode));
}
for(ObjectDescriptor q : p.allocatables)
{
- hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id));
+ hiddenPropertyValues.add(com.zeroc.Ice.Util.identityToString(q.id, com.zeroc.Ice.ToStringMode.Unicode));
}
}
}
@@ -261,7 +261,7 @@ public abstract class TreeNode extends TreeNodeBase
for(ObjectDescriptor p : objects)
{
java.util.List<String[]> attributes = new java.util.LinkedList<>();
- String strId = com.zeroc.Ice.Util.identityToString(p.id);
+ String strId = com.zeroc.Ice.Util.identityToString(p.id, com.zeroc.Ice.ToStringMode.Unicode);
attributes.add(createAttribute("identity", strId));
if(p.type.length() > 0)
{
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Coordinator.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Coordinator.java
index 8bbd0625ac1..c35d5e3608f 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Coordinator.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/Coordinator.java
@@ -2014,7 +2014,7 @@ public class Coordinator
masterRegistryId.name = "Registry";
cb.setRegistry(RegistryPrx.uncheckedCast(_communicator.stringToProxy(
- "\"" + com.zeroc.Ice.Util.identityToString(masterRegistryId) +
+ "\"" + _communicator.identityToString(masterRegistryId) +
"\"")));
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/Root.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/Root.java
index 277e5c34a56..c0f646fa74f 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/Root.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/Root.java
@@ -600,23 +600,23 @@ public class Root extends ListArrayTreeNode
{
for(ObjectInfo info : objects)
{
- _objects.put(com.zeroc.Ice.Util.identityToString(info.proxy.ice_getIdentity()), info);
+ _objects.put(info.proxy.ice_getCommunicator().identityToString(info.proxy.ice_getIdentity()), info);
}
}
public void objectAdded(ObjectInfo info)
{
- _objects.put(com.zeroc.Ice.Util.identityToString(info.proxy.ice_getIdentity()), info);
+ _objects.put(info.proxy.ice_getCommunicator().identityToString(info.proxy.ice_getIdentity()), info);
}
public void objectUpdated(ObjectInfo info)
{
- _objects.put(com.zeroc.Ice.Util.identityToString(info.proxy.ice_getIdentity()), info);
+ _objects.put(info.proxy.ice_getCommunicator().identityToString(info.proxy.ice_getIdentity()), info);
}
public void objectRemoved(com.zeroc.Ice.Identity id)
{
- _objects.remove(com.zeroc.Ice.Util.identityToString(id));
+ _objects.remove(_coordinator.getCommunicator().identityToString(id));
}
//
@@ -836,7 +836,7 @@ public class Root extends ListArrayTreeNode
JOptionPane.ERROR_MESSAGE);
}
- String strIdentity = com.zeroc.Ice.Util.identityToString(proxy.ice_getIdentity());
+ String strIdentity = _coordinator.getCommunicator().identityToString(proxy.ice_getIdentity());
final String prefix = "Adding well-known object '" + strIdentity + "'...";
final AdminPrx admin = _coordinator.getAdmin();
@@ -887,7 +887,7 @@ public class Root extends ListArrayTreeNode
{
com.zeroc.Ice.ObjectPrx proxy = _coordinator.getCommunicator().stringToProxy(strProxy);
com.zeroc.Ice.Identity identity = proxy.ice_getIdentity();
- final String strIdentity = com.zeroc.Ice.Util.identityToString(identity);
+ final String strIdentity = _coordinator.getCommunicator().identityToString(identity);
final String prefix = "Removing well-known object '" + strIdentity + "'...";
final String errorTitle = "Failed to remove object '" + strIdentity + "'";
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/TableField.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/TableField.java
index 77ac0980e60..8bb4a53393d 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/TableField.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/LiveDeployment/TableField.java
@@ -77,7 +77,7 @@ public class TableField extends JTable
{
com.zeroc.Ice.Identity id =
new com.zeroc.Ice.Identity(resolver.substitute(p.id.name), resolver.substitute(p.id.category));
- map.put(com.zeroc.Ice.Util.identityToString(id), resolver.substitute(p.type));
+ map.put(com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.Unicode), resolver.substitute(p.type));
}
setSortedMap(map);
}
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/ObjectObserverI.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/ObjectObserverI.java
index f68074429f7..7d80cf457fb 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/ObjectObserverI.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/ObjectObserverI.java
@@ -71,7 +71,7 @@ class ObjectObserverI implements ObjectObserver
{
if(_trace)
{
- _coordinator.traceObserver("objectRemoved for object " + com.zeroc.Ice.Util.identityToString(id));
+ _coordinator.traceObserver("objectRemoved for object " + _coordinator.getCommunicator().identityToString(id));
}
SwingUtilities.invokeLater(() -> _coordinator.objectRemoved(id));
diff --git a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java
index 53d4f2a83ca..e6da2e4b8b6 100644
--- a/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java
+++ b/java/src/IceGridGUI/src/main/java/com/zeroc/IceGridGUI/SessionKeeper.java
@@ -1114,7 +1114,7 @@ public class SessionKeeper
{
com.zeroc.Ice.LocatorPrx prx = com.zeroc.Ice.LocatorPrx.uncheckedCast(
communicator.stringToProxy(
- com.zeroc.Ice.Util.identityToString(locator.ice_getIdentity()) +
+ communicator.identityToString(locator.ice_getIdentity()) +
":" + e.toString()));
if(_directDiscoveryEndpointModel.indexOf(prx) == -1)
@@ -2226,7 +2226,7 @@ public class SessionKeeper
id.name = "Locator";
id.category = _directInstanceName.getText();
StringBuilder endpoint = new StringBuilder();
- endpoint.append(com.zeroc.Ice.Util.identityToString(id));
+ endpoint.append(_coordinator.getCommunicator().identityToString(id));
endpoint.append(":");
endpoint.append(_directCustomEndpointValue.getText());
_coordinator.getCommunicator().stringToProxy(endpoint.toString());
@@ -2283,7 +2283,7 @@ public class SessionKeeper
id.name = "router";
id.category = _routedInstanceName.getText();
StringBuilder endpoint = new StringBuilder();
- endpoint.append(com.zeroc.Ice.Util.identityToString(id));
+ endpoint.append(_coordinator.getCommunicator().identityToString(id));
endpoint.append(":");
endpoint.append(_routedCustomEndpointValue.getText());
_coordinator.getCommunicator().stringToProxy(endpoint.toString());
@@ -3125,7 +3125,7 @@ public class SessionKeeper
id.name = "Locator";
id.category = _directInstanceName.getText();
StringBuilder endpoint = new StringBuilder();
- endpoint.append(com.zeroc.Ice.Util.identityToString(id));
+ endpoint.append(_coordinator.getCommunicator().identityToString(id));
endpoint.append(":");
endpoint.append(_directCustomEndpointValue.getText());
return containsSecureEndpoints(endpoint.toString());
@@ -3143,7 +3143,7 @@ public class SessionKeeper
id.name = "router";
id.category = _routedInstanceName.getText();
StringBuilder endpoint = new StringBuilder();
- endpoint.append(com.zeroc.Ice.Util.identityToString(id));
+ endpoint.append(_coordinator.getCommunicator().identityToString(id));
endpoint.append(":");
endpoint.append(_routedCustomEndpointValue.getText());
return containsSecureEndpoints(endpoint.toString());
@@ -3335,7 +3335,7 @@ public class SessionKeeper
id.name = inf.getDirect() ? "Locator" : "router";
id.category = inf.getInstanceName();
StringBuilder endpoint = new StringBuilder();
- endpoint.append(com.zeroc.Ice.Util.identityToString(id));
+ endpoint.append(_coordinator.getCommunicator().identityToString(id));
endpoint.append(":");
endpoint.append(inf.getEndpoint());
ssl = containsSecureEndpoints(endpoint.toString());
diff --git a/java/test/src/main/java/test/Ice/location/AllTests.java b/java/test/src/main/java/test/Ice/location/AllTests.java
index 164408efc27..e3fee0edb51 100644
--- a/java/test/src/main/java/test/Ice/location/AllTests.java
+++ b/java/test/src/main/java/test/Ice/location/AllTests.java
@@ -663,7 +663,7 @@ public class AllTests
// Note the quotes are necessary here due to ":" in the
// java generated UUID.
HelloPrx helloPrx = HelloPrx.checkedCast(
- communicator.stringToProxy("\"" + com.zeroc.Ice.Util.identityToString(id) + "\""));
+ communicator.stringToProxy("\"" + communicator.identityToString(id) + "\""));
test(helloPrx.ice_getConnection() == null);
adapter.deactivate();
diff --git a/java/test/src/main/java/test/Ice/proxy/AllTests.java b/java/test/src/main/java/test/Ice/proxy/AllTests.java
index 633f48bc256..92caa297e39 100644
--- a/java/test/src/main/java/test/Ice/proxy/AllTests.java
+++ b/java/test/src/main/java/test/Ice/proxy/AllTests.java
@@ -91,7 +91,7 @@ public class AllTests
b1 = communicator.stringToProxy("test\\40test");
test(b1.ice_getIdentity().name.equals("test test"));
- // Test some octal and hex corner cases.
+ // Test some octal corner cases.
b1 = communicator.stringToProxy("test\\4test");
test(b1.ice_getIdentity().name.equals("test\4test"));
b1 = communicator.stringToProxy("test\\04test");
@@ -273,11 +273,77 @@ public class AllTests
// Test for bug ICE-5543: escaped escapes in stringToIdentity
//
com.zeroc.Ice.Identity id = new com.zeroc.Ice.Identity("test", ",X2QNUAzSBcJ_e$AV;E\\");
- com.zeroc.Ice.Identity id2 = com.zeroc.Ice.Util.stringToIdentity(com.zeroc.Ice.Util.identityToString(id));
+ com.zeroc.Ice.Identity id2 = com.zeroc.Ice.Util.stringToIdentity(communicator.identityToString(id));
test(id.equals(id2));
id = new com.zeroc.Ice.Identity("test", ",X2QNUAz\\SB\\/cJ_e$AV;E\\\\");
- id2 = com.zeroc.Ice.Util.stringToIdentity(com.zeroc.Ice.Util.identityToString(id));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.equals(id2));
+
+ id = new com.zeroc.Ice.Identity("/test", "cat/");
+ String idStr = communicator.identityToString(id);
+ test(idStr.equals("cat\\//\\/test"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ try
+ {
+ // Illegal character < 32
+ id = com.zeroc.Ice.Util.stringToIdentity("xx\01FooBar");
+ test(false);
+ }
+ catch(com.zeroc.Ice.IdentityParseException e)
+ {
+ }
+
+ try
+ {
+ // Illegal surrogate
+ id = com.zeroc.Ice.Util.stringToIdentity("xx\\ud911");
+ test(false);
+ }
+ catch(com.zeroc.Ice.IdentityParseException e)
+ {
+ }
+
+ // Testing bytes 127 (\x7F, \177) and €
+ id = new com.zeroc.Ice.Identity("test", "\177€");
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.Unicode);
+ test(idStr.equals("\\u007f€/test"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+ test(com.zeroc.Ice.Util.identityToString(id).equals(idStr));
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.ASCII);
+ test(idStr.equals("\\u007f\\u20ac/test"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.Compat);
+ test(idStr.equals("\\177\\342\\202\\254/test"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ id2 = com.zeroc.Ice.Util.stringToIdentity(communicator.identityToString(id));
+ test(id.equals(id2));
+
+ // More unicode character
+ id = new com.zeroc.Ice.Identity("banana \016-\ud83c\udf4c\u20ac\u00a2\u0024", "greek \ud800\udd6a");
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.Unicode);
+ test(idStr.equals("greek \ud800\udd6a/banana \\u000e-\ud83c\udf4c\u20ac\u00a2$"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.ASCII);
+ test(idStr.equals("greek \\U0001016a/banana \\u000e-\\U0001f34c\\u20ac\\u00a2$"));
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = com.zeroc.Ice.Util.identityToString(id, com.zeroc.Ice.ToStringMode.Compat);
+ id2 = com.zeroc.Ice.Util.stringToIdentity(idStr);
+ test(idStr.equals("greek \\360\\220\\205\\252/banana \\016-\\360\\237\\215\\214\\342\\202\\254\\302\\242$"));
test(id.equals(id2));
out.println("ok");
@@ -464,10 +530,6 @@ public class AllTests
out.print("testing proxy methods... ");
out.flush();
- test(com.zeroc.Ice.Util.identityToString(
- base.ice_identity(com.zeroc.Ice.Util.stringToIdentity("other")).ice_getIdentity()).equals("other"));
- test(com.zeroc.Ice.Util.identityToString(
- base.ice_identity(com.zeroc.Ice.Util.stringToIdentity("other")).ice_getIdentity()).equals("other"));
test(base.ice_facet("facet").ice_getFacet().equals("facet"));
test(base.ice_adapterId("id").ice_getAdapterId().equals("id"));
test(base.ice_twoway().ice_isTwoway());
diff --git a/java/test/src/main/java/test/Ice/proxy/run.py b/java/test/src/main/java/test/Ice/proxy/run.py
index 78cfe699505..0d0598cb160 100755
--- a/java/test/src/main/java/test/Ice/proxy/run.py
+++ b/java/test/src/main/java/test/Ice/proxy/run.py
@@ -24,5 +24,5 @@ import TestUtil
TestUtil.queueClientServerTest()
TestUtil.queueClientServerTest(configName = "amd", localOnly = True, message = "Running test with AMD server.",
server="test.Ice.proxy.AMDServer")
-TestUtil.queueCollocatedTest()
+TestUtil.queueCollocatedTest(additionalOptions = "--Ice.ToStringMode=Compat")
TestUtil.runQueuedTests()
diff --git a/js/src/Ice/Communicator.js b/js/src/Ice/Communicator.js
index 4fd7a9d91ab..e4556285275 100644
--- a/js/src/Ice/Communicator.js
+++ b/js/src/Ice/Communicator.js
@@ -83,7 +83,7 @@ class Communicator
identityToString(ident)
{
- return Ice.identityToString(ident);
+ return Ice.identityToString(ident, this._instance.toStringMode());
}
createObjectAdapter(name)
diff --git a/js/src/Ice/IdentityUtil.js b/js/src/Ice/IdentityUtil.js
index 1d5b79a4a51..1cbfbc051d2 100644
--- a/js/src/Ice/IdentityUtil.js
+++ b/js/src/Ice/IdentityUtil.js
@@ -106,17 +106,19 @@ Ice.stringToIdentity = function(s)
*
* @param ident The object identity to convert.
*
+* @param toStringMode Specifies if and how non-printable ASCII characters are escaped in the result.
+*
* @return The string representation of the object identity.
**/
-Ice.identityToString = function(ident)
+Ice.identityToString = function(ident, toStringMode = Ice.ToStringMode.Unicode)
{
if(ident.category === null || ident.category.length === 0)
{
- return StringUtil.escapeString(ident.name, "/");
+ return StringUtil.escapeString(ident.name, "/", toStringMode);
}
else
{
- return StringUtil.escapeString(ident.category, "/") + '/' + StringUtil.escapeString(ident.name, "/");
+ return StringUtil.escapeString(ident.category, "/", toStringMode) + '/' + StringUtil.escapeString(ident.name, "/", toStringMode);
}
};
diff --git a/js/src/Ice/IncomingAsync.js b/js/src/Ice/IncomingAsync.js
index 2ba22566f5d..995b81fd1f3 100644
--- a/js/src/Ice/IncomingAsync.js
+++ b/js/src/Ice/IncomingAsync.js
@@ -123,8 +123,8 @@ class IncomingAsync
const s = [];
s.push("dispatch exception:");
- s.push("\nidentity: " + Ice.identityToString(this._current.id));
- s.push("\nfacet: " + StringUtil.escapeString(this._current.facet, ""));
+ s.push("\nidentity: " + Ice.identityToString(this._current.id, this._instance.toStringMode()));
+ s.push("\nfacet: " + StringUtil.escapeString(this._current.facet, "", this._instance.toStringMode()));
s.push("\noperation: " + this._current.operation);
if(this._connection !== null)
{
diff --git a/js/src/Ice/Instance.js b/js/src/Ice/Instance.js
index df3a67a8947..f521ec74499 100644
--- a/js/src/Ice/Instance.js
+++ b/js/src/Ice/Instance.js
@@ -36,7 +36,8 @@ Ice.__M.require(module,
"../Ice/LocalException",
"../Ice/Exception",
"../Ice/ProcessLogger",
- "../Ice/ACM"
+ "../Ice/ACM",
+ "../Ice/ToStringMode"
]);
const IceSSL = Ice.__M.require(module, ["../Ice/EndpointInfo"]).IceSSL;
@@ -80,6 +81,7 @@ class Instance
this._messageSizeMax = 0;
this._batchAutoFlushSize = 0;
this._clientACM = null;
+ this._toStringMode = Ice.ToStringMode.Unicode;
this._implicitContext = null;
this._routerManager = null;
this._locatorManager = null;
@@ -247,6 +249,12 @@ class Instance
return this._clientACM;
}
+ toStringMode()
+ {
+ // this value is immutable
+ return this._toStringMode;
+ }
+
getImplicitContext()
{
return this._implicitContext;
@@ -347,6 +355,21 @@ class Instance
new ACMConfig(this._initData.properties, this._initData.logger,
"Ice.ACM", new ACMConfig()));
+
+ const toStringModeStr = this._initData.properties.getPropertyWithDefault("Ice.ToStringMode", "Unicode");
+ if(toStringModeStr === "ASCII")
+ {
+ _toStringMode = Ice.ToStringMode.ASCII;
+ }
+ else if(toStringModeStr === "Compat")
+ {
+ _toStringMode = Ice.ToStringMode.Compat;
+ }
+ else if(toStringModeStr !== "Unicode")
+ {
+ throw new Ice.InitializationException("The value for Ice.ToStringMode must be Unicode, ASCII or Compat");
+ }
+
this._implicitContext =
ImplicitContextI.create(this._initData.properties.getProperty("Ice.ImplicitContext"));
diff --git a/js/src/Ice/LocatorInfo.js b/js/src/Ice/LocatorInfo.js
index deeed68660a..8219a62e0b5 100644
--- a/js/src/Ice/LocatorInfo.js
+++ b/js/src/Ice/LocatorInfo.js
@@ -198,7 +198,7 @@ class LocatorInfo
else
{
s.push("object = ");
- s.push(Ice.identityToString(ref.getIdentity()));
+ s.push(Ice.identityToString(ref.getIdentity(), ref.getInstance().toStringMode()));
s.push("\n");
}
@@ -241,13 +241,13 @@ class LocatorInfo
const s = [];
s.push("object not found\n");
s.push("object = ");
- s.push(Ice.identityToString(ref.getIdentity()));
+ s.push(Ice.identityToString(ref.getIdentity(), instance.toStringMode()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
}
const e = new Ice.NotRegisteredException();
e.kindOfObject = "object";
- e.id = Ice.identityToString(ref.getIdentity());
+ e.id = Ice.identityToString(ref.getIdentity(), instance.toStringMode());
throw e;
}
else if(ex instanceof Ice.NotRegisteredException)
@@ -269,7 +269,7 @@ class LocatorInfo
else
{
s.push("object = ");
- s.push(Ice.identityToString(ref.getIdentity()));
+ s.push(Ice.identityToString(ref.getIdentity(), instance.toStringMode()));
s.push("\n");
}
s.push("reason = " + ex.toString());
@@ -313,7 +313,7 @@ class LocatorInfo
{
s.push("object\n");
s.push("object = ");
- s.push(Ice.identityToString(ref.getIdentity()));
+ s.push(Ice.identityToString(ref.getIdentity(), instance.toStringMode()));
s.push("\n");
}
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
@@ -350,7 +350,7 @@ class LocatorInfo
const s = [];
s.push("searching for object by id\n");
s.push("object = ");
- s.push(Ice.identityToString(ref.getIdentity()));
+ s.push(Ice.identityToString(ref.getIdentity(), instance.toStringMode()));
instance.initializationData().logger.trace(instance.traceLevels().locationCat, s.join(""));
}
diff --git a/js/src/Ice/ObjectAdapterI.js b/js/src/Ice/ObjectAdapterI.js
index 4db04bf214a..07bdd31cea3 100644
--- a/js/src/Ice/ObjectAdapterI.js
+++ b/js/src/Ice/ObjectAdapterI.js
@@ -176,7 +176,7 @@ class ObjectAdapterI
{
throw new Ice.AlreadyRegisteredException(
"object adapter with router",
- Ice.identityToString(router.ice_getIdentity()));
+ Ice.identityToString(router.ice_getIdentity(), this._instance.toStringMode()));
}
//
diff --git a/js/src/Ice/Operation.js b/js/src/Ice/Operation.js
index 37e637bd388..85b70ee6fac 100644
--- a/js/src/Ice/Operation.js
+++ b/js/src/Ice/Operation.js
@@ -280,7 +280,7 @@ function __dispatchImpl(servant, op, incomingAsync, current)
const method = servant[op.servantMethod];
if(method === undefined || typeof(method) !== "function")
{
- throw new Ice.UnknownException("servant for identity " + Ice.identityToString(current.id) +
+ throw new Ice.UnknownException("servant for identity " + current.adapter.getCommunicator().identityToString(current.id) +
" does not define operation `" + op.servantMethod + "'");
}
diff --git a/js/src/Ice/PropertyNames.js b/js/src/Ice/PropertyNames.js
index fc1c7b8b9fd..0d1add2f012 100644
--- a/js/src/Ice/PropertyNames.js
+++ b/js/src/Ice/PropertyNames.js
@@ -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 ../config/PropertyNames.xml, Fri Oct 14 20:53:43 2016
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -166,6 +166,7 @@ PropertyNames.IceProps =
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\.ToASCII/", 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/js/src/Ice/Reference.js b/js/src/Ice/Reference.js
index 0bda489e771..21424413d29 100644
--- a/js/src/Ice/Reference.js
+++ b/js/src/Ice/Reference.js
@@ -1267,12 +1267,15 @@ class Reference
//
const s = [];
+ const toStringMode = this._instance.toStringMode();
+
//
// If the encoded identity string contains characters which
// the reference parser uses as separators, then we enclose
// the identity string in quotes.
//
- const id = Ice.identityToString(this._identity);
+
+ const id = Ice.identityToString(this._identity, toStringMode);
if(id.search(/[ :@]/) != -1)
{
s.push('"');
@@ -1292,7 +1295,7 @@ class Reference
// the facet string in quotes.
//
s.push(" -f ");
- const fs = StringUtil.escapeString(this._facet, "");
+ const fs = StringUtil.escapeString(this._facet, "", toStringMode);
if(fs.search(/[ :@]/) != -1)
{
s.push('"');
@@ -1967,7 +1970,7 @@ class RoutableReference extends Reference
// the reference parser uses as separators, then we enclose
// the adapter id string in quotes.
//
- const a = StringUtil.escapeString(this._adapterId, null);
+ const a = StringUtil.escapeString(this._adapterId, null, this._instance.toStringMode());
if(a.search(/[ :@]/) != -1)
{
s.push('"');
diff --git a/js/src/Ice/ServantManager.js b/js/src/Ice/ServantManager.js
index d388b366f40..dd9d7628edc 100644
--- a/js/src/Ice/ServantManager.js
+++ b/js/src/Ice/ServantManager.js
@@ -55,11 +55,11 @@ class ServantManager
if(m.has(facet))
{
const ex = new Ice.AlreadyRegisteredException();
- ex.id = Ice.identityToString(ident);
+ ex.id = Ice.identityToString(ident, this._instance.toStringMode());
ex.kindOfObject = "servant";
if(facet.length > 0)
{
- ex.id += " -f " + StringUtil.escapeString(facet, "");
+ ex.id += " -f " + StringUtil.escapeString(facet, "", this._instance.toStringMode());
}
throw ex;
}
@@ -96,11 +96,11 @@ class ServantManager
if(m === undefined || !m.has(facet))
{
const ex = new Ice.NotRegisteredException();
- ex.id = Ice.identityToString(ident);
+ ex.id = Ice.identityToString(ident, this._instance.toStringMode());
ex.kindOfObject = "servant";
if(facet.length > 0)
{
- ex.id += " -f " + StringUtil.escapeString(facet, "");
+ ex.id += " -f " + StringUtil.escapeString(facet, "", this._instance.toStringMode());
}
throw ex;
}
@@ -141,7 +141,7 @@ class ServantManager
if(m === undefined)
{
const ex = new Ice.NotRegisteredException();
- ex.id = Ice.identityToString(ident);
+ ex.id = Ice.identityToString(ident, this._instance.toStringMode());
ex.kindOfObject = "servant";
throw ex;
}
@@ -234,7 +234,7 @@ class ServantManager
if(this._locatorMap.has(category))
{
const ex = new Ice.AlreadyRegisteredException();
- ex.id = StringUtil.escapeString(category, "");
+ ex.id = StringUtil.escapeString(category, "", this._instance.toStringMode());
ex.kindOfObject = "servant locator";
throw ex;
}
@@ -250,7 +250,7 @@ class ServantManager
if(l === undefined)
{
const ex = new Ice.NotRegisteredException();
- ex.id = StringUtil.escapeString(category, "");
+ ex.id = StringUtil.escapeString(category, "", this._instance.toStringMode());
ex.kindOfObject = "servant locator";
throw ex;
}
diff --git a/js/src/Ice/StringUtil.js b/js/src/Ice/StringUtil.js
index 1673f4d745a..c23273e6ba8 100644
--- a/js/src/Ice/StringUtil.js
+++ b/js/src/Ice/StringUtil.js
@@ -7,7 +7,7 @@
//
// **********************************************************************
-const Ice = require("../Ice/Debug").Ice;
+const Ice = require("../Ice/Debug").Ice;
const Debug = Ice.Debug;
Ice.StringUtil = class
@@ -49,11 +49,9 @@ Ice.StringUtil = class
return -1;
}
//
- // 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 backlash in the returned string.
+ // Add escape sequences (such as "\n", or "\123") to s
//
- static escapeString(s, special)
+ static escapeString(s, special, toStringMode)
{
special = special === undefined ? null : special;
if(special !== null)
@@ -68,26 +66,51 @@ Ice.StringUtil = class
}
let result = [];
- for(let i = 0; i < s.length; ++i)
+
+ if(toStringMode === Ice.ToStringMode.Compat)
{
- const c = s.charCodeAt(i);
- if(c < 128)
- {
- encodeChar(c, result, special);
- }
- else if(c > 127 && c < 2048)
+ // Encode UTF-8 bytes
+ var bytes = unescape(encodeURIComponent(s));
+ for(let i = 0; i < bytes.length; ++i)
{
- encodeChar((c >> 6) | 192, result, special);
- encodeChar((c & 63) | 128, result, special);
+ const c = bytes.charCodeAt(i);
+ encodeChar(c, result, special, toStringMode);
}
- else
+ }
+ else
+ {
+ for(let i = 0; i < s.length; ++i)
{
- encodeChar((c >> 12) | 224, result, special);
- encodeChar(((c >> 6) & 63) | 128, result, special);
- encodeChar((c & 63) | 128, result, special);
+ const c = s.charCodeAt(i);
+ if(toStringMode === Ice.ToStringMode.Unicode || c < 0xD800 || c > 0xDFFF)
+ {
+ encodeChar(c, result, special, toStringMode);
+ }
+ else
+ {
+ Debug.assert(toStringMode === Ice.ToStringMode.ASCII && c >= 0xD800 && c <= 0xDFFF);
+ if(i + 1 === s.length)
+ {
+ throw new Error("High surrogate without low surrogate");
+ }
+ else
+ {
+ const codePoint = s.codePointAt(i);
+ Debug.assert(codePoint > 0xFFFF);
+ i++;
+
+ // append \Unnnnnnnn
+ result.push("\\U");
+ const hex = codePoint.toString(16);
+ for(let j = hex.length; j < 8; j++)
+ {
+ result.push('0');
+ }
+ result.push(hex);
+ }
+ }
}
}
-
return result.join("");
}
//
@@ -101,10 +124,26 @@ Ice.StringUtil = class
Debug.assert(start >= 0 && start <= end && end <= s.length);
- const arr = [];
- decodeString(s, start, end, arr);
-
- return arr.join("");
+ // Optimization for strings without escapes
+ let p = s.indexOf('\\', start);
+ if(p == -1 || p >= end)
+ {
+ p = start;
+ while(p < end)
+ {
+ checkChar(s, p++);
+ }
+ return s.substring(start, end);
+ }
+ else
+ {
+ const arr = [];
+ while(start < end)
+ {
+ start = decodeChar(s, start, end, arr);
+ }
+ return arr.join("");
+ }
}
//
// Split string helper; returns null for unmatched quotes
@@ -217,15 +256,10 @@ Ice.StringUtil = class
};
module.exports.Ice = Ice;
-//
-// 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.
-//
-function encodeChar(b, sb, special)
+
+function encodeChar(c, sb, special, toStringMode)
{
- switch(b)
+ switch(c)
{
case 92: // '\\'
{
@@ -269,44 +303,71 @@ function encodeChar(b, sb, special)
}
default:
{
- if(!(b >= 32 && b <= 126))
+ var s = String.fromCharCode(c);
+
+ if(special !== null && special.indexOf(s) !== -1)
{
sb.push('\\');
- const octal = b.toString(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(let j = octal.length; j < 3; j++)
- {
- sb.push('0');
- }
- sb.push(octal);
+ sb.push(s);
}
else
{
- const c = String.fromCharCode(b);
- if(special !== null && special.indexOf(c) !== -1)
+ if(c < 32 || c > 126)
{
- sb.push('\\');
- sb.push(c);
+ if(toStringMode === Ice.ToStringMode.Compat)
+ {
+ //
+ // When ToStringMode=Compat, c is a UTF-8 byte
+ //
+ Debug.assert(c < 256);
+ sb.push('\\');
+ const octal = c.toString(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(let j = octal.length; j < 3; j++)
+ {
+ sb.push('0');
+ }
+ sb.push(octal);
+ }
+ else if(c < 32 || c == 127 || toStringMode === Ice.ToStringMode.ASCII)
+ {
+ // append \\unnnn
+ sb.push("\\u");
+ const hex = c.toString(16);
+ for(let j = hex.length; j < 4; j++)
+ {
+ sb.push('0');
+ }
+ sb.push(hex);
+ }
+ else
+ {
+ // keep as is
+ sb.push(s);
+ }
}
else
{
- sb.push(c);
+ // printable ASCII character
+ sb.push(s);
}
}
+ break;
}
}
}
+
function checkChar(s, pos)
{
- const n = s.charCodeAt(pos);
- if(!(n >= 32 && n <= 126))
+ const c = s.charCodeAt(pos);
+ if(c < 32 || c === 127)
{
let msg;
if(pos > 0)
@@ -317,32 +378,25 @@ function checkChar(s, pos)
{
msg = "first character";
}
- msg += " is not a printable ASCII character (ordinal " + n + ")";
+ msg += " has invalid ordinal value" + c;
throw new Error(msg);
}
- return n;
+ return s.charAt(pos)
}
-
//
-// Decode the character or escape sequence starting at start and return it.
-// 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.
//
-function decodeChar(s, start, end, nextStart)
+function decodeChar(s, start, end, result)
{
Debug.assert(start >= 0);
+ Debug.assert(start < end);
Debug.assert(end <= s.length);
- if(start >= end)
- {
- throw new Error("EOF while decoding string");
- }
-
- let c;
-
if(s.charAt(start) != '\\')
{
- c = checkChar(s, start++);
+ result.push(checkChar(s, start++));
}
else
{
@@ -350,43 +404,94 @@ function decodeChar(s, start, end, nextStart)
{
throw new Error("trailing backslash");
}
- switch(s.charAt(++start))
+
+ const c = s.charAt(++start);
+
+ switch(c)
{
case '\\':
case '\'':
case '"':
{
- c = s.charCodeAt(start++);
+ ++start;
+ result.push(c);
break;
}
case 'b':
{
++start;
- c = "\b".charCodeAt(0);
+ result.push("\b");
break;
}
case 'f':
{
++start;
- c = "\f".charCodeAt(0);
+ result.push("\f");
break;
}
case 'n':
{
++start;
- c = "\n".charCodeAt(0);
+ result.push("\n");
break;
}
case 'r':
{
++start;
- c = "\r".charCodeAt(0);
+ result.push("\r")
break;
}
case 't':
{
++start;
- c = "\t".charCodeAt(0);
+ result.push("\t")
+ break;
+ }
+ case 'u':
+ case 'U':
+ {
+ let codePoint = 0;
+ const inBMP = (c === 'u');
+ let size = inBMP ? 4 : 8;
+ ++start;
+ while(size > 0 && start < end)
+ {
+ let charVal = s.charCodeAt(start++);
+ if(charVal >= 0x30 && charVal <= 0x39)
+ {
+ charVal -= 0x30;
+ }
+ else if(charVal >= 0x61 && charVal <= 0x66)
+ {
+ charVal += 10 - 0x61;
+ }
+ else if(charVal >= 0x41 && charVal <= 0x46)
+ {
+ charVal += 10 - 0x41;
+ }
+ else
+ {
+ break; // while
+ }
+ codePoint = codePoint * 16 + charVal;
+ --size;
+ }
+ if(size > 0)
+ {
+ throw new Error("Invalid universal character name: too few hex digits");
+ }
+ if(inBMP && codePoint >= 0xD800 && codePoint <= 0xDFFF)
+ {
+ throw new Error("A non-BMP character cannot be encoded with \\unnnn, use \\Unnnnnnnn instead");
+ }
+ if(inBMP || codePoint <= 0xFFFF)
+ {
+ result.push(String.fromCharCode(codePoint));
+ }
+ else
+ {
+ result.push(String.fromCodePoint(codePoint));
+ }
break;
}
case '0':
@@ -398,65 +503,61 @@ function decodeChar(s, start, end, nextStart)
case '6':
case '7':
{
- const octalChars = "01234567";
- let val = 0;
- for(let j = 0; j < 3 && start < end; ++j)
+ // UTF-8 byte sequence encoded with octal escapes
+
+ let arr = [];
+ let done = false;
+ while(!done)
{
- const ch = s.charAt(start++);
- if(octalChars.indexOf(ch) == -1)
+ let val = 0;
+ for(let j = 0; j < 3 && start < end; ++j)
{
- --start;
- break;
+ let charVal = s.charCodeAt(start++) - '0'.charCodeAt(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)
+ {
+ throw new Error("octal value \\" + val.toString(8) + " (" + val + ") is out of range");
+ }
+ arr.push(String.fromCharCode(val));
+
+ if((start + 1 < end) && s.charAt(start) === '\\')
+ {
+ start++;
+ // loop, read next octal escape sequence
+ }
+ else
+ {
+ done = true;
+ }
}
- val = val * 8 + parseInt(ch);
- }
- if(val > 255)
- {
- throw new Error("octal value \\" + val.toString(8) + " (" + val + ") is out of range");
}
- c = val;
+
+ // Decode UTF-8 arr into string
+ result.push(decodeURIComponent(escape(arr.join(""))));
break;
}
default:
{
- c = checkChar(s, start++);
+ result.push(checkChar(s, start++));
break;
}
}
}
- nextStart.value = start;
- return c;
-}
-//
-// Remove escape sequences from s and append the result to sb.
-// Return true if successful, false otherwise.
-//
-function decodeString(s, start, end, arr)
-{
- let nextStart = { 'value': 0 };
- while(start < end)
- {
- const c = decodeChar(s, start, end, nextStart);
- start = nextStart.value;
-
- if(c < 128)
- {
- arr.push(String.fromCharCode(c));
- }
- else if(c > 191 && c < 224)
- {
- const c2 = decodeChar(s, start, end, nextStart);
- start = nextStart.value;
- arr.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63)));
- }
- else
- {
- const c2 = decodeChar(s, start, end, nextStart);
- start = nextStart.value;
- const c3 = decodeChar(s, start, end, nextStart);
- start = nextStart.value;
- arr.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
- }
- }
+ return start;
}
diff --git a/js/src/Ice/ToStringMode.js b/js/src/Ice/ToStringMode.js
new file mode 100644
index 00000000000..ed2112858dd
--- /dev/null
+++ b/js/src/Ice/ToStringMode.js
@@ -0,0 +1,12 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2016 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+const Ice = require("../Ice/EnumBase").Ice;
+Ice.ToStringMode = Ice.Slice.defineEnum([['Unicode', 0], ['ASCII',1], ['Compat',2]]);
+module.exports.Ice = Ice;
diff --git a/js/src/Ice/TraceUtil.js b/js/src/Ice/TraceUtil.js
index 3d8c2c93304..9d52c297d55 100644
--- a/js/src/Ice/TraceUtil.js
+++ b/js/src/Ice/TraceUtil.js
@@ -39,15 +39,21 @@ function traceSlicing(kind, typeId, slicingCat, logger)
function printIdentityFacetOperation(s, stream)
{
+ let toStringMode = Ice.ToStringMode.Unicode;
+ if(stream.instance() !== null)
+ {
+ toStringMode = stream.instance().toStringMode();
+ }
+
const identity = new Identity();
identity.__read(stream);
- s.push("\nidentity = " + Ice.identityToString(identity));
+ s.push("\nidentity = " + Ice.identityToString(identity, toStringMode));
const facet = Ice.StringSeqHelper.read(stream);
s.push("\nfacet = ");
if(facet.length > 0)
{
- s.push(StringUtil.escapeString(facet[0], ""));
+ s.push(StringUtil.escapeString(facet[0], "", toStringMode));
}
const operation = stream.readString();
diff --git a/js/test/Ice/proxy/Client.js b/js/test/Ice/proxy/Client.js
index 61d7fe996cc..b25d8e2e452 100644
--- a/js/test/Ice/proxy/Client.js
+++ b/js/test/Ice/proxy/Client.js
@@ -321,9 +321,11 @@
}
}
+
//
// Test for bug ICE-5543: escaped escapes in stringToIdentity
//
+
var id = new Ice.Identity("test", ",X2QNUAzSBcJ_e$AV;E\\");
var id2 = Ice.stringToIdentity(Ice.identityToString(id));
test(id.equals(id2));
@@ -332,6 +334,80 @@
id2 = Ice.stringToIdentity(Ice.identityToString(id));
test(id.equals(id2));
+ id = new Ice.Identity("/test", "cat/");
+ var idStr = Ice.identityToString(id);
+ test(idStr === "cat\\//\\/test");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ try
+ {
+ // Illegal character < 32
+ id = Ice.stringToIdentity("xx\x01FooBar");
+ test(false);
+ }
+ catch(ex)
+ {
+ if(!(ex instanceof Ice.IdentityParseException))
+ {
+ test(false);
+ }
+ }
+ try
+ {
+ // Illegal surrogate
+ id = Ice.stringToIdentity("xx\\ud911");
+ test(false);
+ }
+ catch(ex)
+ {
+ if(!(ex instanceof Ice.IdentityParseException))
+ {
+ test(false);
+ }
+ }
+
+ // Testing bytes 127 (\x7F) and €
+ id = new Ice.Identity("test", "\x7F€");
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr === "\\u007f€/test");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+ test(Ice.identityToString(id) === idStr);
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr === "\\u007f\\u20ac/test");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.Compat);
+ test(idStr === "\\177\\342\\202\\254/test");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ id2 = Ice.stringToIdentity(communicator.identityToString(id));
+ test(id.equals(id2));
+
+ // More unicode characters
+
+ id = new Ice.Identity("banana \x0e-\ud83c\udf4c\u20ac\u00a2\u0024", "greek \ud800\udd6a");
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.Unicode);
+ test(idStr === "greek \ud800\udd6a/banana \\u000e-\ud83c\udf4c\u20ac\u00a2$");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.ASCII);
+ test(idStr === "greek \\U0001016a/banana \\u000e-\\U0001f34c\\u20ac\\u00a2$");
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
+ idStr = Ice.identityToString(id, Ice.ToStringMode.Compat);
+ test(idStr === "greek \\360\\220\\205\\252/banana \\016-\\360\\237\\215\\214\\342\\202\\254\\302\\242$")
+ id2 = Ice.stringToIdentity(idStr);
+ test(id.equals(id2));
+
out.writeLine("ok");
out.write("testing propertyToProxy... ");
diff --git a/objective-c/include/objc/Ice/Initialize.h b/objective-c/include/objc/Ice/Initialize.h
index 5dcaa28eb79..597e5ce079a 100644
--- a/objective-c/include/objc/Ice/Initialize.h
+++ b/objective-c/include/objc/Ice/Initialize.h
@@ -77,6 +77,7 @@ ICE_API @interface ICEUtil : NSObject
+(NSArray*)argsToStringSeq:(int)argc argv:(char*[])argv;
+(void)stringSeqToArgs:(NSArray*)args argc:(int*)argc argv:(char*[])argv;
+(ICEIdentity*) stringToIdentity:(NSString*)str;
++(NSMutableString*) identityToString:(ICEIdentity*)ident toStringMode:(ICEToStringMode)toStringMode;
+(NSMutableString*) identityToString:(ICEIdentity*)ident;
@end
diff --git a/objective-c/src/Ice/CommunicatorI.mm b/objective-c/src/Ice/CommunicatorI.mm
index 3110c72e47d..39d1e3a929e 100644
--- a/objective-c/src/Ice/CommunicatorI.mm
+++ b/objective-c/src/Ice/CommunicatorI.mm
@@ -242,7 +242,17 @@
-(NSMutableString*) identityToString:(ICEIdentity*)ident
{
- return [ICEUtil identityToString:ident];
+ NSException* nsex = nil;
+ try
+ {
+ return [toNSMutableString(COMMUNICATOR->identityToString([ident identity])) autorelease];
+ }
+ catch(const std::exception& ex)
+ {
+ nsex = toObjCException(ex);
+ }
+ @throw nsex;
+ return nil; // Keep the compiler happy.
}
-(id<ICEObjectAdapter>) createObjectAdapter:(NSString*)name;
diff --git a/objective-c/src/Ice/Initialize.mm b/objective-c/src/Ice/Initialize.mm
index 0e23324738f..40f8ce180e7 100644
--- a/objective-c/src/Ice/Initialize.mm
+++ b/objective-c/src/Ice/Initialize.mm
@@ -554,12 +554,13 @@ private:
return nil; // Keep the compiler happy.
}
-+(NSMutableString*) identityToString:(ICEIdentity*)ident
++(NSMutableString*) identityToString:(ICEIdentity*)ident toStringMode:(ICEToStringMode)toStringMode
{
NSException* nsex = nil;
try
{
- return [toNSMutableString(Ice::identityToString([ident identity])) autorelease];
+ return [toNSMutableString(Ice::identityToString([ident identity],
+ static_cast<Ice::ToStringMode>(toStringMode))) autorelease];
}
catch(const std::exception& ex)
{
@@ -568,6 +569,12 @@ private:
@throw nsex;
return nil; // Keep the compiler happy.
}
+
++(NSMutableString*) identityToString:(ICEIdentity*)ident
+{
+ return [ICEUtil identityToString:ident toStringMode:ICEUnicode];
+}
+
@end
@implementation ICEEncodingVersion(StringConv)
diff --git a/objective-c/src/Ice/Proxy.mm b/objective-c/src/Ice/Proxy.mm
index f269605b385..4c44532c3d8 100644
--- a/objective-c/src/Ice/Proxy.mm
+++ b/objective-c/src/Ice/Proxy.mm
@@ -780,7 +780,7 @@ BOOL _returnsData;
marshal:marshal
returnsData:NO
completed:completed
- response:TRUE
+ response:YES
exception:exception
sent:sent
context:ctx];
@@ -800,7 +800,7 @@ BOOL _returnsData;
mode:mode
format:format
marshal:marshal
- returnsData:TRUE
+ returnsData:YES
completed:completed
response:response
exception:exception
diff --git a/objective-c/test/Ice/binding/AllTests.m b/objective-c/test/Ice/binding/AllTests.m
index 92c61e93000..ee873ed5a65 100644
--- a/objective-c/test/Ice/binding/AllTests.m
+++ b/objective-c/test/Ice/binding/AllTests.m
@@ -137,7 +137,7 @@ createTestIntfPrx(NSArray* adapters)
test = [a getTestIntf];
[endpoints addObjectsFromArray:getEndpoints(test)];
}
- NSString* proxy = [ICEUtil identityToString:[test ice_getIdentity]];
+ NSString* proxy = [[test ice_getCommunicator] identityToString:[test ice_getIdentity]];
for(NSString* e in endpoints)
{
proxy = [proxy stringByAppendingString:@":"];
diff --git a/objective-c/test/Ice/proxy/AllTests.m b/objective-c/test/Ice/proxy/AllTests.m
index 5f595d46687..f7f6cc90acf 100644
--- a/objective-c/test/Ice/proxy/AllTests.m
+++ b/objective-c/test/Ice/proxy/AllTests.m
@@ -413,8 +413,31 @@ proxyAllTests(id<ICECommunicator> communicator)
tprintf("testing proxy methods... ");
test([[communicator identityToString:[[base ice_identity:[communicator stringToIdentity:@"other"]] ice_getIdentity]]
isEqualToString:@"other"]);
- test([[ICEUtil identityToString:[[base ice_identity:[ICEUtil stringToIdentity:@"other"]] ice_getIdentity]]
- isEqualToString:@"other"]);
+
+ //
+ // Verify that ToStringMode is passed correctly
+ //
+ ICEIdentity *ident = [ICEIdentity identity:@"test" category:@"\x7F\xE2\x82\xAC"];
+
+ NSString *idStr = [ICEUtil identityToString:ident toStringMode:ICEUnicode];
+ test([idStr isEqualToString:@"\\u007f\xE2\x82\xAC/test"]);
+ ICEIdentity *id2 = [ICEUtil stringToIdentity:idStr];
+ test([ident isEqual:id2]);
+ test([[ICEUtil identityToString:ident] isEqualToString:idStr]);
+
+ idStr = [ICEUtil identityToString:ident toStringMode:ICEASCII];
+ test([idStr isEqualToString:@"\\u007f\\u20ac/test"]);
+ id2 = [ICEUtil stringToIdentity:idStr];
+ test([ident isEqual:id2]);
+
+ idStr = [ICEUtil identityToString:ident toStringMode:ICECompat];
+ test([idStr isEqualToString:@"\\177\\342\\202\\254/test"]);
+ id2 = [ICEUtil stringToIdentity:idStr];
+ test([ident isEqual:id2]);
+
+ id2 = [ICEUtil stringToIdentity:[communicator identityToString:ident]];
+ test([ident isEqual:id2]);
+
test([[[base ice_facet:@"facet"] ice_getFacet] isEqualToString:@"facet"]);
test([[[base ice_adapterId:@"id"] ice_getAdapterId] isEqualToString:@"id"]);
test([[base ice_twoway] ice_isTwoway]);
diff --git a/php/lib/Ice.php b/php/lib/Ice.php
index fa996209da6..402f94de032 100644
--- a/php/lib/Ice.php
+++ b/php/lib/Ice.php
@@ -187,6 +187,7 @@ require_once 'Ice/Version.php';
require_once 'Ice/Instrumentation.php';
require_once 'Ice/Metrics.php';
require_once 'Ice/RemoteLogger.php';
+require_once 'Ice/Communicator.php';
$Ice_Protocol_1_0 = new Ice_ProtocolVersion(1, 0);
$Ice_Encoding_1_0 = new Ice_EncodingVersion(1, 0);
diff --git a/php/lib/Ice_ns.php b/php/lib/Ice_ns.php
index 95bcf7d55d5..b21357c833f 100644
--- a/php/lib/Ice_ns.php
+++ b/php/lib/Ice_ns.php
@@ -195,6 +195,7 @@ require_once 'Ice/Version.php';
require_once 'Ice/Instrumentation.php';
require_once 'Ice/Metrics.php';
require_once 'Ice/RemoteLogger.php';
+require_once 'Ice/Communicator.php';
$Ice_Protocol_1_0 = new Ice\ProtocolVersion(1, 0);
$Ice_Encoding_1_0 = new Ice\EncodingVersion(1, 0);
diff --git a/php/src/php5/Communicator.cpp b/php/src/php5/Communicator.cpp
index 8b03d75a694..d1a53a18e32 100644
--- a/php/src/php5/Communicator.cpp
+++ b/php/src/php5/Communicator.cpp
@@ -1365,7 +1365,9 @@ ZEND_FUNCTION(Ice_identityToString)
assert(identityClass);
zval* zv;
- if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O"), &zv, identityClass) != SUCCESS)
+ long mode = 0;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O|l"), &zv, identityClass, &mode TSRMLS_CC) != SUCCESS)
{
RETURN_NULL();
}
@@ -1377,7 +1379,7 @@ ZEND_FUNCTION(Ice_identityToString)
try
{
- string str = Ice::identityToString(id);
+ string str = identityToString(id, static_cast<Ice::ToStringMode>(mode));
RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1);
}
catch(const IceUtil::Exception& ex)
diff --git a/php/src/php7/Communicator.cpp b/php/src/php7/Communicator.cpp
index b7943d07907..4f8ffabd945 100644
--- a/php/src/php7/Communicator.cpp
+++ b/php/src/php7/Communicator.cpp
@@ -1368,7 +1368,9 @@ ZEND_FUNCTION(Ice_identityToString)
assert(identityClass);
zval* zv;
- if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, identityClass) != SUCCESS)
+ long mode = 0;
+
+ if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O|l"), &zv, identityClass, &mode) != SUCCESS)
{
RETURN_NULL();
}
@@ -1380,7 +1382,7 @@ ZEND_FUNCTION(Ice_identityToString)
try
{
- string str = Ice::identityToString(id);
+ string str = Ice::identityToString(id, static_cast<Ice::ToStringMode>(mode));
RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()));
}
catch(const IceUtil::Exception& ex)
diff --git a/php/test/Ice/proxy/Client.php b/php/test/Ice/proxy/Client.php
index a80838fb44f..987a8c792a6 100644
--- a/php/test/Ice/proxy/Client.php
+++ b/php/test/Ice/proxy/Client.php
@@ -42,6 +42,18 @@ function allTests($communicator)
$identityToString = $NS ? "Ice\\identityToString" : "Ice_identityToString";
$stringToIdentity = $NS ? "Ice\\stringToIdentity" : "Ice_stringToIdentity";
+ $modeUnicode = $NS ? constant("Ice\\ToStringMode::Unicode") : constant("Ice_ToStringMode::Unicode");
+ $modeASCII = $NS ? constant("Ice\\ToStringMode::ASCII") : constant("Ice_ToStringMode::ASCII");
+ $modeCompat = $NS ? constant("Ice\\ToStringMode::Compat") : constant("Ice_ToStringMode::Compat");
+
+ if($NS)
+ {
+ echo "namespace ON\n";
+ }
+ else
+ {
+ echo "namespace OFF\n";
+ }
echo "testing stringToProxy... ";
flush();
@@ -439,7 +451,31 @@ function allTests($communicator)
echo "testing proxy methods... ";
flush();
test($communicator->identityToString($base->ice_identity($communicator->stringToIdentity("other"))->ice_getIdentity()) == "other");
- test($identityToString($base->ice_identity($stringToIdentity("other"))->ice_getIdentity()) == "other");
+
+ //
+ // Verify that ToStringMode is passed correctly
+ //
+ $ident = new Ice_Identity("test", "\x7F\xE2\x82\xAC");
+
+ $idStr = $identityToString($ident, $modeUnicode);
+ test($idStr == "\\u007f\xE2\x82\xAC/test");
+ $ident2 = $stringToIdentity($idStr);
+ test($ident == $ident2);
+ test($identityToString($ident) == $idStr);
+
+ $idStr = $identityToString($ident, $modeASCII);
+ test($idStr == "\\u007f\\u20ac/test");
+ $ident2 = $stringToIdentity($idStr);
+ test($ident == $ident2);
+
+ $idStr = $identityToString($ident, $modeCompat);
+ test($idStr == "\\177\\342\\202\\254/test");
+ $ident2 = $stringToIdentity($idStr);
+ test($ident == $ident2);
+
+ $ident2 = $stringToIdentity($communicator->identityToString($ident));
+ test($ident == $ident2);
+
test($base->ice_facet("facet")->ice_getFacet() == "facet");
test($base->ice_adapterId("id")->ice_getAdapterId() == "id");
test($base->ice_twoway()->ice_isTwoway());
diff --git a/python/modules/IcePy/Communicator.cpp b/python/modules/IcePy/Communicator.cpp
index 1549cd1043c..eb223c85853 100644
--- a/python/modules/IcePy/Communicator.cpp
+++ b/python/modules/IcePy/Communicator.cpp
@@ -1740,19 +1740,34 @@ IcePy::getCommunicatorWrapper(const Ice::CommunicatorPtr& communicator)
extern "C"
PyObject*
-IcePy_identityToString(PyObject* /*self*/, PyObject* obj)
+IcePy_identityToString(PyObject* /*self*/, PyObject* args)
{
+ PyObject* identityType = lookupType("Ice.Identity");
+ PyObject* obj;
+ PyObject* mode = 0;
+ if(!PyArg_ParseTuple(args, STRCAST("O!O"), identityType, &obj, &mode))
+ {
+ return 0;
+ }
+
Ice::Identity id;
if(!getIdentity(obj, id))
{
return 0;
}
-
+
+ Ice::ToStringMode toStringMode = Ice::Unicode;
+ if(mode != Py_None && PyObject_HasAttrString(mode, STRCAST("value")))
+ {
+ PyObjectHandle modeValue = PyObject_GetAttrString(mode, STRCAST("value"));
+ toStringMode = static_cast<Ice::ToStringMode>(PyLong_AsLong(modeValue.get()));
+ }
+
string str;
try
{
- str = Ice::identityToString(id);
+ str = identityToString(id, toStringMode);
}
catch(const Ice::Exception& ex)
{
diff --git a/python/modules/IcePy/Init.cpp b/python/modules/IcePy/Init.cpp
index 88205ebc571..581e4f649c5 100644
--- a/python/modules/IcePy/Init.cpp
+++ b/python/modules/IcePy/Init.cpp
@@ -60,8 +60,8 @@ static PyMethodDef methods[] =
PyDoc_STR(STRCAST("createProperties([args]) -> Ice.Properties")) },
{ STRCAST("stringToIdentity"), reinterpret_cast<PyCFunction>(IcePy_stringToIdentity), METH_O,
PyDoc_STR(STRCAST("stringToIdentity(string) -> Ice.Identity")) },
- { STRCAST("identityToString"), reinterpret_cast<PyCFunction>(IcePy_identityToString), METH_O,
- PyDoc_STR(STRCAST("identityToString(Ice.Identity) -> string")) },
+ { STRCAST("identityToString"), reinterpret_cast<PyCFunction>(IcePy_identityToString), METH_VARARGS,
+ PyDoc_STR(STRCAST("identityToString(Ice.Identity, Ice.ToStringMode) -> string")) },
{ STRCAST("getProcessLogger"), reinterpret_cast<PyCFunction>(IcePy_getProcessLogger), METH_NOARGS,
PyDoc_STR(STRCAST("getProcessLogger() -> Ice.Logger")) },
{ STRCAST("setProcessLogger"), reinterpret_cast<PyCFunction>(IcePy_setProcessLogger), METH_VARARGS,
diff --git a/python/modules/IcePy/Operation.cpp b/python/modules/IcePy/Operation.cpp
index 3b59074a8e5..c8dad9a0c96 100644
--- a/python/modules/IcePy/Operation.cpp
+++ b/python/modules/IcePy/Operation.cpp
@@ -3349,7 +3349,7 @@ IcePy::TypedUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*, con
if(!method.get())
{
ostringstream ostr;
- ostr << "servant for identity " << identityToString(current.id)
+ ostr << "servant for identity " << _communicator->identityToString(current.id)
<< " does not define operation `" << _op->dispatchName << "'";
string str = ostr.str();
PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()));
@@ -3712,7 +3712,7 @@ IcePy::BlobjectUpcall::dispatch(PyObject* servant, const pair<const Ice::Byte*,
if(!method.get())
{
ostringstream ostr;
- ostr << "servant for identity " << identityToString(current.id)
+ ostr << "servant for identity " << communicator->identityToString(current.id)
<< " does not define operation `" << dispatchName << "'";
string str = ostr.str();
PyErr_Warn(PyExc_RuntimeWarning, const_cast<char*>(str.c_str()));
diff --git a/python/python/Ice.py b/python/python/Ice.py
index 162f626682d..7c06a1fec77 100644
--- a/python/python/Ice.py
+++ b/python/python/Ice.py
@@ -716,8 +716,8 @@ the list that were recognized by the Ice run time.
#
# Ice.identityToString
#
-def identityToString(id):
- return IcePy.identityToString(id)
+def identityToString(id, toStringMode=None):
+ return IcePy.identityToString(id, toStringMode)
#
# Ice.stringToIdentity
diff --git a/python/test/Ice/location/AllTests.py b/python/test/Ice/location/AllTests.py
index bf0a378b85f..91519152101 100644
--- a/python/test/Ice/location/AllTests.py
+++ b/python/test/Ice/location/AllTests.py
@@ -248,7 +248,7 @@ def allTests(communicator, ref):
registry.addObject(adapter.add(HelloI(), id));
adapter.activate();
- helloPrx = Test.HelloPrx.checkedCast(communicator.stringToProxy(Ice.identityToString(id)));
+ helloPrx = Test.HelloPrx.checkedCast(communicator.stringToProxy(communicator.identityToString(id)));
test(not helloPrx.ice_getConnection());
adapter.deactivate();
diff --git a/python/test/Ice/proxy/AllTests.py b/python/test/Ice/proxy/AllTests.py
index bd889945639..6e04cc674fa 100644
--- a/python/test/Ice/proxy/AllTests.py
+++ b/python/test/Ice/proxy/AllTests.py
@@ -358,10 +358,35 @@ def allTests(communicator, collocated):
sys.stdout.write("testing proxy methods... ")
sys.stdout.flush()
+
+
test(communicator.identityToString(base.ice_identity(communicator.stringToIdentity("other")).ice_getIdentity()) \
== "other")
- test(Ice.identityToString(base.ice_identity(Ice.stringToIdentity("other")).ice_getIdentity()) == "other")
-
+
+ #
+ # Verify that ToStringMode is passed correctly
+ #
+ ident = Ice.Identity("test", "\x7F\xE2\x82\xAC")
+
+ idStr = Ice.identityToString(ident, Ice.ToStringMode.Unicode)
+ test(idStr == "\\u007f\xE2\x82\xAC/test")
+ ident2 = Ice.stringToIdentity(idStr)
+ test(ident == ident2)
+ test(Ice.identityToString(ident) == idStr)
+
+ idStr = Ice.identityToString(ident, Ice.ToStringMode.ASCII)
+ test(idStr == "\\u007f\\u20ac/test")
+ ident2 = Ice.stringToIdentity(idStr)
+ test(ident == ident2)
+
+ idStr = Ice.identityToString(ident, Ice.ToStringMode.Compat)
+ test(idStr == "\\177\\342\\202\\254/test")
+ ident2 = Ice.stringToIdentity(idStr)
+ test(ident == ident2)
+
+ ident2 = Ice.stringToIdentity(communicator.identityToString(ident))
+ test(ident == ident2)
+
test(base.ice_facet("facet").ice_getFacet() == "facet")
test(base.ice_adapterId("id").ice_getAdapterId() == "id")
test(base.ice_twoway().ice_isTwoway())
diff --git a/ruby/ruby/Ice.rb b/ruby/ruby/Ice.rb
index 88e1b9a744f..41d14b2ad7d 100644
--- a/ruby/ruby/Ice.rb
+++ b/ruby/ruby/Ice.rb
@@ -213,6 +213,7 @@ end
#
require 'Ice/BuiltinSequences.rb'
require 'Ice/Current.rb'
+require 'Ice/Communicator.rb'
require 'Ice/EndpointTypes.rb'
require 'Ice/LocalException.rb'
require 'Ice/Locator.rb'
diff --git a/ruby/src/IceRuby/Communicator.cpp b/ruby/src/IceRuby/Communicator.cpp
index 3d90f420464..73fd483f8be 100644
--- a/ruby/src/IceRuby/Communicator.cpp
+++ b/ruby/src/IceRuby/Communicator.cpp
@@ -239,12 +239,27 @@ IceRuby_stringToIdentity(VALUE self, VALUE str)
extern "C"
VALUE
-IceRuby_identityToString(VALUE self, VALUE id)
+IceRuby_identityToString(int argc, VALUE* argv, VALUE self)
{
ICE_RUBY_TRY
{
- Ice::Identity ident = getIdentity(id);
- string str = Ice::identityToString(ident);
+ if(argc < 1 || argc > 2)
+ {
+ throw RubyException(rb_eArgError, "wrong number of arguments");
+ }
+
+ Ice::Identity ident = getIdentity(argv[0]);
+
+
+ Ice::ToStringMode toStringMode = Ice::Unicode;
+ if(argc == 2)
+ {
+ volatile VALUE modeValue = callRuby(rb_funcall, argv[1], rb_intern("to_i"), 0);
+ assert(TYPE(modeValue) == T_FIXNUM);
+ toStringMode = static_cast<Ice::ToStringMode>(FIX2LONG(modeValue));
+ }
+
+ string str = Ice::identityToString(ident, toStringMode);
return createString(str);
}
ICE_RUBY_CATCH
@@ -602,7 +617,7 @@ void
IceRuby::initCommunicator(VALUE iceModule)
{
rb_define_module_function(iceModule, "initialize", CAST_METHOD(IceRuby_initialize), -1);
- rb_define_module_function(iceModule, "identityToString", CAST_METHOD(IceRuby_identityToString), 1);
+ rb_define_module_function(iceModule, "identityToString", CAST_METHOD(IceRuby_identityToString), -1);
rb_define_module_function(iceModule, "stringToIdentity", CAST_METHOD(IceRuby_stringToIdentity), 1);
_communicatorClass = rb_define_class_under(iceModule, "CommunicatorI", rb_cObject);
diff --git a/ruby/src/IceRuby/Util.cpp b/ruby/src/IceRuby/Util.cpp
index ef076d04bd8..7fa1222fb06 100644
--- a/ruby/src/IceRuby/Util.cpp
+++ b/ruby/src/IceRuby/Util.cpp
@@ -442,8 +442,8 @@ IceRuby::contextToHash(const Ice::Context& ctx)
volatile VALUE result = callRuby(rb_hash_new);
for(Ice::Context::const_iterator p = ctx.begin(); p != ctx.end(); ++p)
{
- volatile VALUE key = callRuby(rb_str_new, p->first.c_str(), static_cast<long>(p->first.size()));
- volatile VALUE value = callRuby(rb_str_new, p->second.c_str(), static_cast<long>(p->second.size()));
+ volatile VALUE key = createString(p->first);
+ volatile VALUE value = createString(p->second);
callRuby(rb_hash_aset, result, key, value);
}
return result;
@@ -522,8 +522,8 @@ IceRuby::createIdentity(const Ice::Identity& id)
assert(!NIL_P(cls));
volatile VALUE result = callRuby(rb_class_new_instance, 0, reinterpret_cast<VALUE*>(0), cls);
- volatile VALUE name = callRuby(rb_str_new, id.name.c_str(), static_cast<long>(id.name.size()));
- volatile VALUE category = callRuby(rb_str_new, id.category.c_str(), static_cast<long>(id.category.size()));
+ volatile VALUE name = createString(id.name);
+ volatile VALUE category = createString(id.category);
callRuby(rb_iv_set, result, "@name", name);
callRuby(rb_iv_set, result, "@category", category);
return result;
diff --git a/ruby/test/Ice/proxy/AllTests.rb b/ruby/test/Ice/proxy/AllTests.rb
index cc15619ccc5..cecc44c2b7d 100644
--- a/ruby/test/Ice/proxy/AllTests.rb
+++ b/ruby/test/Ice/proxy/AllTests.rb
@@ -355,7 +355,31 @@ def allTests(communicator)
print "testing proxy methods... "
STDOUT.flush
test(communicator.identityToString(base.ice_identity(communicator.stringToIdentity("other")).ice_getIdentity()) == "other")
- test(Ice::identityToString(base.ice_identity(Ice::stringToIdentity("other")).ice_getIdentity()) == "other")
+
+ #
+ # Verify that ToStringMode is passed correctly
+ #
+ ident = Ice::Identity.new("test", "\x7F\xE2\x82\xAC")
+
+ idStr = Ice::identityToString(ident, Ice::ToStringMode::Unicode)
+ test(idStr == "\\u007f\xE2\x82\xAC/test")
+ ident2 = Ice::stringToIdentity(idStr)
+ test(ident == ident2)
+ test(Ice::identityToString(ident) == idStr)
+
+ idStr = Ice::identityToString(ident, Ice::ToStringMode::ASCII)
+ test(idStr == "\\u007f\\u20ac/test")
+ ident2 = Ice::stringToIdentity(idStr)
+ test(ident == ident2)
+
+ idStr = Ice::identityToString(ident, Ice::ToStringMode::Compat)
+ test(idStr == "\\177\\342\\202\\254/test")
+ ident2 = Ice::stringToIdentity(idStr)
+ test(ident == ident2)
+
+ ident2 = Ice::stringToIdentity(communicator.identityToString(ident))
+ test(ident == ident2)
+
test(base.ice_facet("facet").ice_getFacet() == "facet")
test(base.ice_adapterId("id").ice_getAdapterId() == "id")
test(base.ice_twoway().ice_isTwoway())
diff --git a/slice/Ice/Communicator.ice b/slice/Ice/Communicator.ice
index 8914cf37a1a..3940e93691c 100644
--- a/slice/Ice/Communicator.ice
+++ b/slice/Ice/Communicator.ice
@@ -216,7 +216,7 @@ local interface Communicator
* @see #stringToIdentity
*
**/
- ["cpp:const", "deprecate:identityToString() is deprecated, use the static identityToString() method instead."]
+ ["cpp:const"]
string identityToString(Identity ident);
/**
@@ -583,4 +583,34 @@ local interface Communicator
FacetMap findAllAdminFacets();
};
+
+/**
+ * The output mode for xxxToString method such as identityToString and proxyToString.
+ * The actual encoding format for the string is the same for all modes: you
+ * don't need to specify an encoding format or mode when reading such a string.
+ *
+ **/
+local enum ToStringMode
+{
+ /**
+ * Characters > 127 are kept as-is in the resulting string. Non-printable ASCII
+ * characters <= 127 are encoded as \\t, \\n (etc.) or \\unnnn.
+ **/
+ Unicode,
+
+ /**
+ * Characters > 127 are encoded as universal character names in the resulting string:
+ * \\unnnn for BMP characters and \\Unnnnnnnn for non-BMP characters. Non-printable ASCII
+ * characters <= 127 are encoded as \\t, \\n (etc.) or \\unnnn.
+ **/
+ ASCII,
+
+ /**
+ * Characters > 127 are encoded as a sequence of UTF-8 bytes using octal escapes.
+ * characters <= 127 are encoded as \\t, \\n (etc.) or an octal escape. Use this mode
+ * to generate strings compatible with Ice 3.6 and earlier.
+ **/
+ Compat
+};
+
};