summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rwxr-xr-xcpp/allTests.py4
-rw-r--r--cpp/include/Ice/Ice.h4
-rw-r--r--cpp/include/Ice/IconvStringConverter.h2
-rwxr-xr-xcpp/include/Ice/StringConverter.h29
-rwxr-xr-xcpp/src/Ice/StringConverter.cpp126
-rw-r--r--cpp/test/Ice/Makefile.mak2
-rw-r--r--cpp/test/Ice/stringConverter/Client.cpp27
-rwxr-xr-xcpp/test/Ice/stringConverter/Makefile.mak8
8 files changed, 185 insertions, 17 deletions
diff --git a/cpp/allTests.py b/cpp/allTests.py
index b19e4510ddb..1394e3039af 100755
--- a/cpp/allTests.py
+++ b/cpp/allTests.py
@@ -94,6 +94,7 @@ tests = [ \
"Ice/servantLocator", \
"Ice/threads", \
"Ice/interceptor", \
+ "Ice/stringConverter", \
"IceSSL/configuration", \
"Freeze/dbmap", \
"Freeze/complex", \
@@ -129,9 +130,6 @@ if isCygwin() == 0:
tests += [ \
]
-if not isWin32() or os.getenv("ICONV_HOME") != None:
- tests.insert(0, "Ice/stringConverter")
-
if isWin32():
tests.insert(0, "IceUtil/condvar")
diff --git a/cpp/include/Ice/Ice.h b/cpp/include/Ice/Ice.h
index 4d8f53a8703..85de61f222e 100644
--- a/cpp/include/Ice/Ice.h
+++ b/cpp/include/Ice/Ice.h
@@ -34,4 +34,8 @@
#include <Ice/Router.h>
#include <Ice/DispatchInterceptor.h>
+#ifndef _WIN32
+#include <Ice/IconvStringConverter.h>
+#endif
+
#endif
diff --git a/cpp/include/Ice/IconvStringConverter.h b/cpp/include/Ice/IconvStringConverter.h
index 185a2bb4b8e..8b532c8739e 100644
--- a/cpp/include/Ice/IconvStringConverter.h
+++ b/cpp/include/Ice/IconvStringConverter.h
@@ -10,7 +10,7 @@
#ifndef ICE_ICONV_STRING_CONVERTER
#define ICE_ICONV_STRING_CONVERTER
-#include <Ice/Ice.h>
+#include <Ice/StringConverter.h>
#include <algorithm>
#include <iconv.h>
diff --git a/cpp/include/Ice/StringConverter.h b/cpp/include/Ice/StringConverter.h
index d2aa1dffa7a..2b59c622e8b 100755
--- a/cpp/include/Ice/StringConverter.h
+++ b/cpp/include/Ice/StringConverter.h
@@ -70,11 +70,32 @@ class ICE_API UnicodeWstringConverter : public WstringConverter
{
public:
- virtual Byte* toUTF8(const wchar_t* sourceStart, const wchar_t* sourceEnd,
- UTF8Buffer&) const;
+ virtual Byte* toUTF8(const wchar_t*, const wchar_t*, UTF8Buffer&) const;
- virtual void fromUTF8(const Byte* sourceStart, const Byte* sourceEnd,
- std::wstring& target) const;
+ virtual void fromUTF8(const Byte*, const Byte*, std::wstring&) const;
};
+
+#ifdef _WIN32
+
+//
+// Converts to/from UTF-8 using MultiByteToWideChar and WideCharToMultiByte
+//
+
+class ICE_API WindowsStringConverter : public StringConverter
+{
+public:
+
+ explicit WindowsStringConverter(unsigned int);
+
+ virtual Byte* toUTF8(const char*, const char*, UTF8Buffer&) const;
+
+ virtual void fromUTF8(const Byte*, const Byte*, std::string& target) const;
+
+private:
+ unsigned int _cp;
+ UnicodeWstringConverter _unicodeWstringConverter;
+};
+#endif
+
}
#endif
diff --git a/cpp/src/Ice/StringConverter.cpp b/cpp/src/Ice/StringConverter.cpp
index 985111f9aa9..1d426877379 100755
--- a/cpp/src/Ice/StringConverter.cpp
+++ b/cpp/src/Ice/StringConverter.cpp
@@ -8,12 +8,49 @@
// **********************************************************************
#include <Ice/StringConverter.h>
-#include <IceUtil/Unicode.h>
+#include <IceUtil/IceUtil.h>
#include <Ice/LocalException.h>
using namespace IceUtil;
using namespace std;
+
+#ifdef _WIN32
+namespace
+{
+//
+// Helper function
+//
+
+string getMessageForLastError()
+{
+ LPVOID lpMsgBuf = 0;
+ DWORD ok = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR)&lpMsgBuf,
+ 0,
+ NULL);
+
+ string msg;
+ if(ok)
+ {
+ msg = (LPCTSTR)lpMsgBuf;
+ LocalFree(lpMsgBuf);
+ }
+ else
+ {
+ msg = "Unknown Windows error";
+ }
+ return msg;
+}
+}
+#endif
+
+
namespace Ice
{
@@ -64,6 +101,12 @@ void
UnicodeWstringConverter::fromUTF8(const Byte* sourceStart, const Byte* sourceEnd,
wstring& target) const
{
+ if(sourceStart == sourceEnd)
+ {
+ target = L"";
+ return;
+ }
+
ConversionResult result =
convertUTF8ToUTFWstring(sourceStart, sourceEnd, target, lenientConversion);
@@ -82,4 +125,85 @@ UnicodeWstringConverter::fromUTF8(const Byte* sourceStart, const Byte* sourceEnd
}
}
}
+
+#ifdef _WIN32
+WindowsStringConverter::WindowsStringConverter(unsigned int cp) :
+ _cp(cp)
+{
+}
+
+Byte*
+WindowsStringConverter::toUTF8(const char* sourceStart,
+ const char* sourceEnd,
+ UTF8Buffer& buffer) const
+{
+ //
+ // First convert to UTF-16
+ //
+ int sourceSize = sourceEnd - sourceStart;
+ assert(sourceSize > 0);
+
+ size_t size = 0;
+ int writtenWchar = 0;
+ IceUtil::ScopedArray<wchar_t> wbuffer;
+ do
+ {
+ size = size == 0 ? static_cast<size_t>(sourceSize) + 2 : 2 * size;
+ wbuffer.reset(new wchar_t[size]);
+
+ writtenWchar = MultiByteToWideChar(_cp, MB_ERR_INVALID_CHARS, sourceStart,
+ sourceSize, wbuffer.get(), size);
+ } while(writtenWchar == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+ if(writtenWchar == 0)
+ {
+ throw StringConversionException(__FILE__, __LINE__, getMessageForLastError());
+ }
+
+ //
+ // Then convert this UTF-16 wbuffer into UTF-8
+ //
+ return _unicodeWstringConverter.toUTF8(wbuffer.get(), wbuffer.get() + writtenWchar, buffer);
+}
+
+void
+WindowsStringConverter::fromUTF8(const Byte* sourceStart, const Byte* sourceEnd,
+ string& target) const
+{
+ if(sourceStart == sourceEnd)
+ {
+ target = "";
+ return;
+ }
+
+ //
+ // First convert to wstring (UTF-16)
+ //
+ wstring wtarget;
+ _unicodeWstringConverter.fromUTF8(sourceStart, sourceEnd, wtarget);
+
+ //
+ // And then to a multi-byte narrow string
+ //
+ size_t size = 0;
+ int writtenChar = 0;
+ IceUtil::ScopedArray<char> buffer;
+ do
+ {
+ size = size == 0 ? static_cast<size_t>(sourceEnd - sourceStart) + 2 : 2 * size;
+ buffer.reset(new char[size]);
+ writtenChar = WideCharToMultiByte(_cp, 0, wtarget.data(), wtarget.size(),
+ buffer.get(), size, 0, 0);
+ } while(writtenChar == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+ if(writtenChar == 0)
+ {
+ throw StringConversionException(__FILE__, __LINE__, getMessageForLastError());
+ }
+
+ target.assign(buffer.get(), writtenChar);
+}
+
+#endif
+
}
diff --git a/cpp/test/Ice/Makefile.mak b/cpp/test/Ice/Makefile.mak
index 77888312c28..dfe04be6621 100644
--- a/cpp/test/Ice/Makefile.mak
+++ b/cpp/test/Ice/Makefile.mak
@@ -32,9 +32,7 @@ SUBDIRS = proxy \
servantLocator \
threads \
interceptor \
-!if "$(ICONV_HOME)" != ""
stringConverter
-!endif
$(EVERYTHING)::
@for %i in ( $(SUBDIRS) ) do \
diff --git a/cpp/test/Ice/stringConverter/Client.cpp b/cpp/test/Ice/stringConverter/Client.cpp
index 795535d6ece..8186e64151e 100644
--- a/cpp/test/Ice/stringConverter/Client.cpp
+++ b/cpp/test/Ice/stringConverter/Client.cpp
@@ -10,7 +10,14 @@
#include <Ice/Ice.h>
#include <TestCommon.h>
#include <Test.h>
+
+#if defined(ICONV_ON_WINDOWS)
+//
+// On Windows, Ice/IcongStringConverter.h is not included by Ice/Ice.h
+//
#include <Ice/IconvStringConverter.h>
+#endif
+
#include <iostream>
#include <locale.h>
@@ -49,26 +56,34 @@ public:
};
static bool useLocale = false;
+static bool useIconv = true;
int
main(int argc, char* argv[])
{
Client app;
+#ifndef _WIN32
//
// Switch to French locale
// (we just used the codeset for as default internal code for
// initData.stringConverter below)
//
-
-#ifndef _WIN32
+
useLocale = (setlocale(LC_ALL, "fr_FR.ISO8859-15") != 0
|| setlocale(LC_ALL, "fr_FR.iso885915@euro") != 0);
#endif
Ice::InitializationData initData;
-#if defined(__hpux)
+#if defined(_WIN32) && !defined(ICONV_ON_WINDOWS)
+ //
+ // 28605 == ISO 8859-15 codepage
+ //
+ initData.stringConverter = new Ice::WindowsStringConverter(28605);
+ useIconv = false;
+
+#elif defined(__hpux)
if(useLocale)
{
initData.stringConverter = new Ice::IconvStringConverter<char>;
@@ -132,11 +147,15 @@ Client::run(int, char*[])
char oe = char(0xBD); // A single character in ISO Latin 9
string msg = string("tu me fends le c") + oe + "ur!";
- cout << "testing iconv string converter";
+ cout << "testing string converter";
if(useLocale)
{
cout << " (using locale)";
}
+ if(useIconv)
+ {
+ cout << " (using iconv)";
+ }
cout << "..." << flush;
wstring wmsg = clientPrx->widen(msg);
test(clientPrx->narrow(wmsg) == msg);
diff --git a/cpp/test/Ice/stringConverter/Makefile.mak b/cpp/test/Ice/stringConverter/Makefile.mak
index adf6d97b850..5b266e2c656 100755
--- a/cpp/test/Ice/stringConverter/Makefile.mak
+++ b/cpp/test/Ice/stringConverter/Makefile.mak
@@ -19,14 +19,18 @@ SRCS = $(OBJS:.obj=.cpp)
!include $(top_srcdir)/config/Make.rules.mak
-CPPFLAGS = -I. -I../../include -I$(ICONV_HOME)/include $(CPPFLAGS) -DICE_NO_ERRNO -DWIN32_LEAN_AND_MEAN
+CPPFLAGS = -I. -I../../include $(CPPFLAGS) -DWIN32_LEAN_AND_MEAN
+!if "$(ICONV_HOME)" != ""
+CPPFLAGS = $(CPPFLAGS) -I$(ICONV_HOME)\include -DICONV_ON_WINDOWS -DICE_NO_ERRNO
+LIBS = $(LIBS) -LIBPATH:$(ICONV_HOME)\lib $(ICONV_LIB)
+!endif
!if "$(CPP_COMPILER)" != "BCC2006" && "$(OPTIMIZE)" != "yes"
PDBFLAGS = /pdb:$(CLIENT:.exe=.pdb)
!endif
$(CLIENT): $(OBJS)
- $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(LIBNAME) $(LIBS) /LIBPATH:$(ICONV_HOME)\lib $(ICONV_LIB)
+ $(LINK) $(LD_EXEFLAGS) $(PDBFLAGS) $(SETARGV) $(OBJS) $(PREOUT)$@ $(PRELIBS)$(LIBNAME) $(LIBS)
@if exist $@.manifest echo ^ ^ ^ Embedding manifest using $(MT) && \
$(MT) -nologo -manifest $@.manifest -outputresource:$@;#1 && del /q $@.manifest