summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/include/Ice/BasicStream.h139
-rw-r--r--cpp/include/Ice/Initialize.h3
-rw-r--r--cpp/src/Ice/BasicStream.cpp118
-rw-r--r--cpp/test/Ice/custom/Client.cpp6
-rw-r--r--cpp/test/Ice/custom/Collocated.cpp11
-rw-r--r--cpp/test/Ice/custom/Makefile12
-rw-r--r--cpp/test/Ice/custom/Server.cpp11
-rw-r--r--cpp/test/Ice/custom/ServerAMD.cpp11
-rw-r--r--cpp/test/Ice/custom/StringConverterI.cpp102
-rw-r--r--cpp/test/Ice/custom/StringConverterI.h43
10 files changed, 419 insertions, 37 deletions
diff --git a/cpp/include/Ice/BasicStream.h b/cpp/include/Ice/BasicStream.h
index e87d85b0082..fbcb0d467bb 100644
--- a/cpp/include/Ice/BasicStream.h
+++ b/cpp/include/Ice/BasicStream.h
@@ -16,6 +16,7 @@
#include <Ice/ObjectFactoryF.h>
#include <Ice/Buffer.h>
#include <Ice/Protocol.h>
+#include <Ice/StringConverter.h>
#include <IceUtil/AutoArray.h>
#include <IceUtil/Unicode.h>
@@ -33,6 +34,47 @@ class ICE_API BasicStream : public Buffer
{
public:
+ class UTF8BufferI : public Ice::UTF8Buffer
+ {
+ public:
+
+ UTF8BufferI(BasicStream& stream) :
+ _stream(stream)
+ {
+ }
+
+ Ice::Byte*
+ getMoreBytes(size_t howMany, Ice::Byte* firstUnused)
+ {
+ assert(howMany > 0);
+
+ if(firstUnused != 0)
+ {
+ //
+ // Return unused bytes
+ //
+ _stream.b.resize(firstUnused - _stream.b.begin());
+ }
+
+ //
+ // Index of first unused byte
+ //
+ Container::size_type pos = _stream.b.size();
+
+ //
+ // Since resize may reallocate the buffer, when firstUnused != 0, the
+ // return value can be != firstUnused
+ //
+ _stream.resize(pos + howMany);
+
+ return &_stream.b[pos];
+ }
+
+ private:
+
+ BasicStream& _stream;
+ };
+
typedef void (*PatchFunc)(void*, Ice::ObjectPtr&);
BasicStream(Instance*);
@@ -241,6 +283,31 @@ public:
write(static_cast<Ice::Byte>(v));
}
}
+ void rewriteSize(Ice::Int v, Container::iterator dest)
+ {
+ assert(v >= 0);
+ if(v > 254)
+ {
+ *dest++ = Ice::Byte(255);
+#ifdef ICE_BIG_ENDIAN
+ const Ice::Byte* src = reinterpret_cast<const Ice::Byte*>(&v) + sizeof(Ice::Int) - 1;
+ *dest++ = *src--;
+ *dest++ = *src--;
+ *dest++ = *src--;
+ *dest = *src;
+#else
+ const Ice::Byte* src = reinterpret_cast<const Ice::Byte*>(&v);
+ *dest++ = *src++;
+ *dest++ = *src++;
+ *dest++ = *src++;
+ *dest = *src;
+#endif
+ }
+ else
+ {
+ *dest = static_cast<Ice::Byte>(v);
+ }
+ }
void readSize(Ice::Int& v) // Inlined for performance reasons.
{
Ice::Byte byte;
@@ -405,16 +472,24 @@ public:
//
void write(const char*);
+ void writeConverted(const std::string& v);
void write(const std::string& v)
{
Ice::Int sz = static_cast<Ice::Int>(v.size());
- writeSize(sz);
- if(sz > 0)
- {
- Container::size_type pos = b.size();
- resize(pos + sz);
- memcpy(&b[pos], v.c_str(), sz);
- }
+ if(sz > 0 && _stringConverter)
+ {
+ writeConverted(v);
+ }
+ else
+ {
+ writeSize(sz);
+ if(sz > 0)
+ {
+ Container::size_type pos = b.size();
+ resize(pos + sz);
+ memcpy(&b[pos], v.data(), sz);
+ }
+ }
}
void write(const std::string*, const std::string*);
void read(std::string& v)
@@ -427,8 +502,15 @@ public:
{
throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
}
- std::string(reinterpret_cast<const char*>(&*i), reinterpret_cast<const char*>(&*i) + sz).swap(v);
-// v.assign(reinterpret_cast<const char*>(&(*i)), sz);
+ if(_stringConverter)
+ {
+ _stringConverter->fromUTF8(i, i + sz, v);
+ }
+ else
+ {
+ std::string(reinterpret_cast<const char*>(&*i), reinterpret_cast<const char*>(&*i) + sz).swap(v);
+// v.assign(reinterpret_cast<const char*>(&(*i)), sz);
+ }
i += sz;
}
else
@@ -438,17 +520,25 @@ public:
}
void read(std::vector<std::string>&);
+ void writeConverted(const std::wstring& v);
void write(const std::wstring& v)
{
- std::string s = IceUtil::wstringToString(v);
- Ice::Int sz = static_cast<Ice::Int>(s.size());
- writeSize(sz);
- if(sz > 0)
- {
- Container::size_type pos = b.size();
- resize(pos + sz);
- memcpy(&b[pos], s.c_str(), sz);
- }
+ if(v.size() > 0 && _wstringConverter)
+ {
+ writeConverted(v);
+ }
+ else
+ {
+ std::string s = IceUtil::wstringToString(v);
+ Ice::Int sz = static_cast<Ice::Int>(s.size());
+ writeSize(sz);
+ if(sz > 0)
+ {
+ Container::size_type pos = b.size();
+ resize(pos + sz);
+ memcpy(&b[pos], s.data(), sz);
+ }
+ }
}
void write(const std::wstring*, const std::wstring*);
void read(std::wstring& v)
@@ -461,8 +551,15 @@ public:
{
throwUnmarshalOutOfBoundsException(__FILE__, __LINE__);
}
- std::string s(reinterpret_cast<const char*>(&*i), reinterpret_cast<const char*>(&*i) + sz);
- IceUtil::stringToWstring(s).swap(v);
+ if(_wstringConverter)
+ {
+ _wstringConverter->fromUTF8(i, i + sz, v);
+ }
+ else
+ {
+ std::string s(reinterpret_cast<const char*>(&*i), reinterpret_cast<const char*>(&*i) + sz);
+ IceUtil::stringToWstring(s).swap(v);
+ }
i += sz;
}
else
@@ -625,6 +722,8 @@ private:
bool _sliceObjects;
const Container::size_type _messageSizeMax;
+ const Ice::StringConverterPtr _stringConverter;
+ const Ice::WstringConverterPtr _wstringConverter;
struct SeqData
{
diff --git a/cpp/include/Ice/Initialize.h b/cpp/include/Ice/Initialize.h
index f76eadb8fce..824d3f5f985 100644
--- a/cpp/include/Ice/Initialize.h
+++ b/cpp/include/Ice/Initialize.h
@@ -16,6 +16,7 @@
#include <Ice/LoggerF.h>
#include <Ice/StreamF.h>
#include <Ice/StatsF.h>
+#include <Ice/StringConverter.h>
#include <Ice/BuiltinSequences.h>
namespace Ice
@@ -42,6 +43,8 @@ struct InitializationData
LoggerPtr logger;
StatsPtr stats;
Context defaultContext;
+ StringConverterPtr stringConverter;
+ WstringConverterPtr wstringConverter;
};
ICE_API CommunicatorPtr initialize(int&, char*[], InitializationData = InitializationData(),
diff --git a/cpp/src/Ice/BasicStream.cpp b/cpp/src/Ice/BasicStream.cpp
index bcef19cc5ee..77a48fe5eac 100644
--- a/cpp/src/Ice/BasicStream.cpp
+++ b/cpp/src/Ice/BasicStream.cpp
@@ -29,6 +29,8 @@ using namespace IceInternal;
IceInternal::BasicStream::BasicStream(Instance* instance) :
_instance(instance),
+ _stringConverter(instance->initializationData().stringConverter),
+ _wstringConverter(instance->initializationData().wstringConverter),
_currentReadEncaps(0),
_currentWriteEncaps(0),
_traceSlicing(-1),
@@ -1318,6 +1320,64 @@ IceInternal::BasicStream::write(const char*)
*/
void
+IceInternal::BasicStream::writeConverted(const string& v)
+{
+ //
+ // What is the size of the resulting UTF-8 encoded string?
+ // Impossible to tell, so we guess. If we don't guess correctly,
+ // we'll have to fix the mistake afterwards
+ //
+
+ Int guessedSize = static_cast<Int>(v.size());
+ writeSize(guessedSize); // writeSize() only writes the size; it does not reserve any buffer space.
+
+ size_t firstIndex = b.size();
+ UTF8BufferI buffer(*this);
+
+ Byte* lastByte = _stringConverter->toUTF8(v.data(), v.data() + v.size(), buffer);
+ if(lastByte != b.end())
+ {
+ b.resize(lastByte - b.begin());
+ }
+ size_t lastIndex = b.size();
+
+ Int actualSize = static_cast<Int>(lastIndex - firstIndex);
+
+ //
+ // Check against the guess
+ //
+ if(guessedSize != actualSize)
+ {
+ if(guessedSize <= 254 && actualSize > 254)
+ {
+ //
+ // Move the UTF-8 sequence 4 bytes further
+ // Use memmove instead of memcpy since the source and destination typically overlap.
+ //
+ resize(b.size() + 4);
+ std::memmove(b.begin() + firstIndex + 4, b.begin() + firstIndex, actualSize);
+ }
+ else if(guessedSize > 254 && actualSize <= 254)
+ {
+ //
+ // Move the UTF-8 sequence 4 bytes back
+ //
+ std::memmove(b.begin() + firstIndex - 4, b.begin() + firstIndex, actualSize);
+ resize(b.size() - 4);
+ }
+
+ if(guessedSize <= 254)
+ {
+ rewriteSize(actualSize, b.begin() + firstIndex - 1);
+ }
+ else
+ {
+ rewriteSize(actualSize, b.begin() + firstIndex - 1 - 4);
+ }
+ }
+}
+
+void
IceInternal::BasicStream::write(const string* begin, const string* end)
{
Int sz = static_cast<Int>(end - begin);
@@ -1355,6 +1415,64 @@ IceInternal::BasicStream::read(vector<string>& v)
}
void
+IceInternal::BasicStream::writeConverted(const wstring& v)
+{
+ //
+ // What is the size of the resulting UTF-8 encoded string?
+ // Impossible to tell, so we guess. If we don't guess correctly,
+ // we'll have to fix the mistake afterwards
+ //
+
+ Int guessedSize = static_cast<Int>(v.size());
+ writeSize(guessedSize); // writeSize() only writes the size; it does not reserve any buffer space.
+
+ size_t firstIndex = b.size();
+ UTF8BufferI buffer(*this);
+
+ Byte* lastByte = _wstringConverter->toUTF8(v.data(), v.data() + v.size(), buffer);
+ if(lastByte != b.end())
+ {
+ b.resize(lastByte - b.begin());
+ }
+ size_t lastIndex = b.size();
+
+ Int actualSize = static_cast<Int>(lastIndex - firstIndex);
+
+ //
+ // Check against the guess
+ //
+ if(guessedSize != actualSize)
+ {
+ if(guessedSize <= 254 && actualSize > 254)
+ {
+ //
+ // Move the UTF-8 sequence 4 bytes further
+ // Use memmove instead of memcpy since the source and destination typically overlap.
+ //
+ resize(b.size() + 4);
+ std::memmove(b.begin() + firstIndex + 4, b.begin() + firstIndex, actualSize);
+ }
+ else if(guessedSize > 254 && actualSize <= 254)
+ {
+ //
+ // Move the UTF-8 sequence 4 bytes back
+ //
+ std::memmove(b.begin() + firstIndex - 4, b.begin() + firstIndex, actualSize);
+ resize(b.size() - 4);
+ }
+
+ if(guessedSize <= 254)
+ {
+ rewriteSize(actualSize, b.begin() + firstIndex - 1);
+ }
+ else
+ {
+ rewriteSize(actualSize, b.begin() + firstIndex - 1 - 4);
+ }
+ }
+}
+
+void
IceInternal::BasicStream::write(const wstring* begin, const wstring* end)
{
Int sz = static_cast<Int>(end - begin);
diff --git a/cpp/test/Ice/custom/Client.cpp b/cpp/test/Ice/custom/Client.cpp
index 510eaa37d10..6bd9210dc90 100644
--- a/cpp/test/Ice/custom/Client.cpp
+++ b/cpp/test/Ice/custom/Client.cpp
@@ -10,6 +10,7 @@
#include <Ice/Ice.h>
#include <TestCommon.h>
#include <Test.h>
+#include <StringConverterI.h>
using namespace std;
@@ -31,7 +32,10 @@ main(int argc, char** argv)
try
{
- communicator = Ice::initialize(argc, argv);
+ Ice::InitializationData initData;
+ initData.stringConverter = new Test::StringConverterI();
+ initData.wstringConverter = new Test::WstringConverterI();
+ communicator = Ice::initialize(argc, argv, initData);
status = run(argc, argv, communicator);
}
catch(const Ice::Exception& ex)
diff --git a/cpp/test/Ice/custom/Collocated.cpp b/cpp/test/Ice/custom/Collocated.cpp
index fc60bbaeae7..084a7999ec6 100644
--- a/cpp/test/Ice/custom/Collocated.cpp
+++ b/cpp/test/Ice/custom/Collocated.cpp
@@ -11,6 +11,7 @@
#include <TestCommon.h>
#include <TestI.h>
#include <WstringI.h>
+#include <StringConverterI.h>
using namespace std;
@@ -37,10 +38,12 @@ main(int argc, char** argv)
try
{
- Ice::PropertiesPtr properties = Ice::getDefaultProperties(argc, argv);
- properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
-
- communicator = Ice::initialize(argc, argv);
+ Ice::InitializationData initData;
+ initData.properties = Ice::getDefaultProperties(argc, argv);
+ initData.properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
+ initData.stringConverter = new Test::StringConverterI();
+ initData.wstringConverter = new Test::WstringConverterI();
+ communicator = Ice::initialize(argc, argv, initData);
status = run(argc, argv, communicator);
}
catch(const Ice::Exception& ex)
diff --git a/cpp/test/Ice/custom/Makefile b/cpp/test/Ice/custom/Makefile
index 72e5202de8e..dada88e4294 100644
--- a/cpp/test/Ice/custom/Makefile
+++ b/cpp/test/Ice/custom/Makefile
@@ -20,21 +20,24 @@ COBJS = Test.o \
Wstring.o \
Client.o \
AllTests.o \
- MyByteSeq.o
+ MyByteSeq.o \
+ StringConverterI.o
SOBJS = Test.o \
Wstring.o \
TestI.o \
WstringI.o \
Server.o \
- MyByteSeq.o
+ MyByteSeq.o \
+ StringConverterI.o
SAMDOBJS = TestAMD.o \
TestAMDI.o \
WstringAMD.o \
WstringAMDI.o \
ServerAMD.o \
- MyByteSeq.o
+ MyByteSeq.o \
+ StringConverterI.o
COLOBJS = Test.o \
Wstring.o \
@@ -42,7 +45,8 @@ COLOBJS = Test.o \
WstringI.o \
Collocated.o \
AllTests.o \
- MyByteSeq.o
+ MyByteSeq.o \
+ StringConverterI.o
SRCS = $(COBJS:.o=.cpp) \
$(SOBJS:.o=.cpp) \
diff --git a/cpp/test/Ice/custom/Server.cpp b/cpp/test/Ice/custom/Server.cpp
index 5bb712444b6..92188346034 100644
--- a/cpp/test/Ice/custom/Server.cpp
+++ b/cpp/test/Ice/custom/Server.cpp
@@ -11,6 +11,7 @@
#include <TestCommon.h>
#include <TestI.h>
#include <WstringI.h>
+#include <StringConverterI.h>
using namespace std;
@@ -36,10 +37,12 @@ main(int argc, char** argv)
try
{
- Ice::PropertiesPtr properties = Ice::getDefaultProperties(argc, argv);
- properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
-
- communicator = Ice::initialize(argc, argv);
+ Ice::InitializationData initData;
+ initData.properties = Ice::getDefaultProperties(argc, argv);
+ initData.properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
+ initData.stringConverter = new Test::StringConverterI();
+ initData.wstringConverter = new Test::WstringConverterI();
+ communicator = Ice::initialize(argc, argv, initData);
status = run(argc, argv, communicator);
}
catch(const Ice::Exception& ex)
diff --git a/cpp/test/Ice/custom/ServerAMD.cpp b/cpp/test/Ice/custom/ServerAMD.cpp
index 21608202898..b3561cf14aa 100644
--- a/cpp/test/Ice/custom/ServerAMD.cpp
+++ b/cpp/test/Ice/custom/ServerAMD.cpp
@@ -11,6 +11,7 @@
#include <TestCommon.h>
#include <TestAMDI.h>
#include <WstringAMDI.h>
+#include <StringConverterI.h>
using namespace std;
@@ -36,10 +37,12 @@ main(int argc, char** argv)
try
{
- Ice::PropertiesPtr properties = Ice::getDefaultProperties(argc, argv);
- properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
-
- communicator = Ice::initialize(argc, argv);
+ Ice::InitializationData initData;
+ initData.properties = Ice::getDefaultProperties(argc, argv);
+ initData.properties->setProperty("TestAdapter.Endpoints", "default -p 12010 -t 10000");
+ initData.stringConverter = new Test::StringConverterI();
+ initData.wstringConverter = new Test::WstringConverterI();
+ communicator = Ice::initialize(argc, argv, initData);
status = run(argc, argv, communicator);
}
catch(const Ice::Exception& ex)
diff --git a/cpp/test/Ice/custom/StringConverterI.cpp b/cpp/test/Ice/custom/StringConverterI.cpp
new file mode 100644
index 00000000000..7187194249b
--- /dev/null
+++ b/cpp/test/Ice/custom/StringConverterI.cpp
@@ -0,0 +1,102 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2006 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.
+//
+// **********************************************************************
+
+#include <StringConverterI.h>
+#include <IceUtil/Unicode.h>
+
+Ice::Byte*
+Test::StringConverterI::toUTF8(const char* sourceStart, const char* sourceEnd, Ice::UTF8Buffer& buffer) const
+{
+ size_t size = static_cast<size_t>(sourceEnd - sourceStart);
+ Ice::Byte* targetStart = buffer.getMoreBytes(size, 0);
+ Ice::Byte* targetEnd = targetStart + size;
+
+ char* p = const_cast<char*>(sourceEnd);
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ targetStart[i] = *(--p);
+ }
+ return targetEnd;
+}
+
+void
+Test::StringConverterI::fromUTF8(const Ice::Byte* sourceStart, const Ice::Byte* sourceEnd,
+ const char*& targetStart, const char*& targetEnd) const
+{
+ size_t size = static_cast<size_t>(sourceEnd - sourceStart);
+ char* buf = new char[size];
+
+ Ice::Byte* p = const_cast<Ice::Byte*>(sourceEnd);
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ buf[i] = *(--p);
+ }
+
+ targetStart = buf;
+ targetEnd = targetStart + size;
+}
+
+void
+Test::StringConverterI::freeTarget(const char* target) const
+{
+ delete[] target;
+}
+
+Ice::Byte*
+Test::WstringConverterI::toUTF8(const wchar_t* sourceStart, const wchar_t* sourceEnd, Ice::UTF8Buffer& buffer) const
+{
+ std::wstring ws(sourceStart, sourceEnd);
+ std::string s = IceUtil::wstringToString(ws);
+
+ size_t size = s.size();
+ Ice::Byte* targetStart = buffer.getMoreBytes(size, 0);
+ Ice::Byte* targetEnd = targetStart + size;
+
+ char* p = const_cast<char*>(s.c_str() + size);
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ targetStart[i] = static_cast<Ice::Byte>(*(--p));
+ }
+ return targetEnd;
+}
+
+void
+Test::WstringConverterI::fromUTF8(const Ice::Byte* sourceStart, const Ice::Byte* sourceEnd,
+ const wchar_t*& targetStart, const wchar_t*& targetEnd) const
+{
+ size_t size = static_cast<size_t>(sourceEnd - sourceStart);
+ std::string s(sourceStart, sourceEnd);
+
+ Ice::Byte* p = const_cast<Ice::Byte*>(sourceEnd);
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ s[i] = *(--p);
+ }
+
+ std::wstring ws = IceUtil::stringToWstring(s);
+ size = ws.size();
+ wchar_t* buf = new wchar_t[size];
+ for(unsigned int i = 0; i < size; ++i)
+ {
+ buf[i] = ws[i];
+ }
+
+ targetStart = buf;
+ targetEnd = targetStart + size;
+}
+
+void
+Test::WstringConverterI::freeTarget(const wchar_t* target) const
+{
+#if defined(_MSC_VER) && _MSC_VER < 1300
+ delete[] const_cast<wchar_t*>(target);
+#else
+ delete[] target;
+#endif
+}
diff --git a/cpp/test/Ice/custom/StringConverterI.h b/cpp/test/Ice/custom/StringConverterI.h
new file mode 100644
index 00000000000..48eae68b3be
--- /dev/null
+++ b/cpp/test/Ice/custom/StringConverterI.h
@@ -0,0 +1,43 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2006 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 STRING_CONVERTER_I_H
+#define STRING_CONVERTER_I_H
+
+#include <Ice/StringConverter.h>
+
+//
+// Simple contrived string converters which simply reverse the order of the
+// characters being sent.
+//
+
+namespace Test
+{
+
+class StringConverterI : public Ice::StringConverter
+{
+public:
+
+ virtual Ice::Byte* toUTF8(const char*, const char*, Ice::UTF8Buffer&) const;
+ virtual void fromUTF8(const Ice::Byte*, const Ice::Byte*, const char*&, const char*&) const;
+ virtual void freeTarget(const char*) const;
+};
+
+class WstringConverterI : public Ice::WstringConverter
+{
+public:
+
+ virtual Ice::Byte* toUTF8(const wchar_t*, const wchar_t*, Ice::UTF8Buffer&) const;
+ virtual void fromUTF8(const Ice::Byte*, const Ice::Byte*, const wchar_t*&, const wchar_t*&) const;
+ virtual void freeTarget(const wchar_t*) const;
+};
+
+}
+
+#endif