[Mobies-commit] [commit] r4127 - in UDM/trunk: Projects/Win32/VC10/src/UdmDom Projects/Win32/VC10/tests/test_generic src/UdmDom src/UdmGme tests/test_generic

ksmyth at redhat1.isis.vanderbilt.edu ksmyth at redhat1.isis.vanderbilt.edu
Thu Oct 11 10:10:36 CDT 2012


Author: ksmyth
Date: Thu Oct 11 10:10:36 2012
New Revision: 4127

Log:
Use UTF8 in std::strings on Windows

Modified:
   UDM/trunk/Projects/Win32/VC10/src/UdmDom/UdmDom.vcxproj
   UDM/trunk/Projects/Win32/VC10/tests/test_generic/test_generic.vcxproj
   UDM/trunk/src/UdmDom/UdmDom.cpp
   UDM/trunk/src/UdmGme/UdmGme.cpp
   UDM/trunk/tests/test_generic/genericTest.cpp

Modified: UDM/trunk/Projects/Win32/VC10/src/UdmDom/UdmDom.vcxproj
==============================================================================
--- UDM/trunk/Projects/Win32/VC10/src/UdmDom/UdmDom.vcxproj	Fri Oct  5 10:08:04 2012	(r4126)
+++ UDM/trunk/Projects/Win32/VC10/src/UdmDom/UdmDom.vcxproj	Thu Oct 11 10:10:36 2012	(r4127)
@@ -208,20 +208,6 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\..\..\src\UdmDom\UdmDom.cpp">
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
-      <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
   </ItemGroup>
   <ItemGroup>

Modified: UDM/trunk/Projects/Win32/VC10/tests/test_generic/test_generic.vcxproj
==============================================================================
--- UDM/trunk/Projects/Win32/VC10/tests/test_generic/test_generic.vcxproj	Fri Oct  5 10:08:04 2012	(r4126)
+++ UDM/trunk/Projects/Win32/VC10/tests/test_generic/test_generic.vcxproj	Thu Oct 11 10:10:36 2012	(r4127)
@@ -308,32 +308,24 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="..\..\..\..\..\tests\test_generic\genericTest.cpp">
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
       <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
     </ClCompile>
     <ClCompile Include="..\..\..\..\..\tests\test_generic\test_generic.cpp">
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Disabled</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
       <BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">EnableFastChecks</BasicRuntimeChecks>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MaxSpeed</Optimization>
-      <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>

Modified: UDM/trunk/src/UdmDom/UdmDom.cpp
==============================================================================
--- UDM/trunk/src/UdmDom/UdmDom.cpp	Fri Oct  5 10:08:04 2012	(r4126)
+++ UDM/trunk/src/UdmDom/UdmDom.cpp	Thu Oct 11 10:10:36 2012	(r4127)
@@ -335,6 +335,78 @@
 };
 
 
+#ifdef _WIN32
+char* transcode(const XMLCh* const toTranscode)
+{
+	MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager;
+    if (!toTranscode)
+        return 0;
+
+    char* retVal = 0;
+    if (*toTranscode)
+    {
+        // Calc the needed size
+        const unsigned int neededLen = ::WideCharToMultiByte(CP_UTF8, 0, toTranscode, -1, NULL, 0, NULL, NULL);
+
+        // Allocate a buffer of that size plus one for the null and transcode
+        retVal = (char*) manager->allocate((neededLen + 1) * sizeof(char)); //new char[neededLen + 1];
+        ::WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)toTranscode, -1, retVal, neededLen+1, NULL, NULL);
+
+        // And cap it off anyway just to make sure
+        retVal[neededLen] = 0;
+    }
+     else
+    {
+        retVal = (char*) manager->allocate(sizeof(char)); //new char[1];
+        retVal[0] = 0;
+    }
+    return retVal;
+}
+
+
+XMLCh* transcode(const std::string& toTranscode)
+{
+	MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager;
+    XMLCh* retVal = 0;
+	if (!toTranscode.length())
+	{
+        retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));
+        retVal[0] = 0;
+		return retVal;
+	}
+
+    // Calculate the buffer size required
+    const unsigned int neededLen = ::MultiByteToWideChar(CP_UTF8, 0, toTranscode.c_str(), toTranscode.length(), NULL, 0);
+    if (neededLen == 0)
+    {
+        retVal = (XMLCh*) manager->allocate(sizeof(XMLCh));
+        retVal[0] = 0;
+        return retVal;
+    }
+
+    // Allocate a buffer of that size plus one for the null and transcode
+    retVal = (XMLCh*) manager->allocate((neededLen + 1) * sizeof(XMLCh));
+    ::MultiByteToWideChar(CP_UTF8, 0, toTranscode.c_str(), toTranscode.length(), (LPWSTR)retVal, neededLen + 1);
+
+	retVal[neededLen] = 0;
+    return retVal;
+}
+
+#else
+
+char* transcode(const XMLCh* const toTranscode)
+{
+	return XMLString::transcode(toTranscode);
+}
+
+XMLCh* transcode(const std::string& toTranscode)
+{
+	return XMLString::transcode(toTranscode.c_str());
+}
+
+#endif
+
+
 namespace UdmDom
 {	
 	/*
@@ -386,7 +458,7 @@
 		StrX(const XMLCh* const toTranscode)
 		{
 			// Call the private transcoding method
-			fLocalForm = XMLString::transcode(toTranscode);
+			fLocalForm = transcode(toTranscode);
 		}
 
 		~StrX()
@@ -405,14 +477,9 @@
 		XMLCh* fUnicodeForm;
 	
 	public :
-		XStr(const char* const toTranscode)
-		{
-			fUnicodeForm = XMLString::transcode(toTranscode);
-		}
-
-		XStr(const string &toTranscode)
+		XStr(const std::string& toTranscode)
 		{
-			fUnicodeForm = XMLString::transcode(toTranscode.c_str());
+			fUnicodeForm = transcode(toTranscode);
 		}
 
 		~XStr()
@@ -527,8 +594,8 @@
 
 	static inline void setAttrValue(DOMElement &element, const string &name, const string &value)
 	{
-		XMLCh *name_buf = XMLString::transcode(name.c_str());
-		XMLCh *value_buf = XMLString::transcode(value.c_str());
+		XMLCh *name_buf = transcode(name);
+		XMLCh *value_buf = transcode(value);
 		element.setAttribute(name_buf, value_buf);
 		XMLString::release(&name_buf);
 		XMLString::release(&value_buf);
@@ -536,14 +603,14 @@
 
 	static inline void setAttrValue(DOMElement &element, const XMLCh *name, const string &value)
 	{
-		XMLCh *value_buf = XMLString::transcode(value.c_str());
+		XMLCh *value_buf = transcode(value);
 		element.setAttribute(name, value_buf);
 		XMLString::release(&value_buf);
 	}
 
 	static inline const XMLCh *getAttrValue(DOMElement &element, const string &name)
 	{
-		XMLCh *name_buf = XMLString::transcode(name.c_str());
+		XMLCh *name_buf = transcode(name);
 		const XMLCh *value = element.getAttribute(name_buf);
 		XMLString::release(&name_buf);
 
@@ -553,7 +620,7 @@
 	void setTextValue(DOMElement &parent_element, const string &value)
 	{
 		
-		XMLCh *value_buf = XMLString::transcode(value.c_str());
+		XMLCh *value_buf = transcode(value);
 		DOMText *tn = parent_element.getOwnerDocument()->createTextNode(value_buf);
 		parent_element.appendChild(tn);
 		tn->setNodeValue(value_buf);
@@ -578,7 +645,7 @@
 			if ( (n->getNodeType() == DOMNode::TEXT_NODE))
 			{
 				DOMText *tn = (DOMText*)n;
-				char *a = XMLString::transcode(tn->getNodeValue());
+				char *a = transcode(tn->getNodeValue());
         
 				values.push_back(a);
 
@@ -596,7 +663,7 @@
 			if ( (n->getNodeType() == DOMNode::TEXT_NODE))
 			{
 				DOMText *tn = (DOMText*)n;
-				char *a = XMLString::transcode(tn->getNodeValue());
+				char *a = transcode(tn->getNodeValue());
 				retval = a;
 				XMLString::release(&a);
 				break;
@@ -711,7 +778,7 @@
 				key += ns_path + ":";
 			}
 
-			char *cl_name = XMLString::transcode(element.getLocalName());	//class name
+			char *cl_name = transcode(element.getLocalName());	//class name
 			key += cl_name;
 			XMLString::release(&cl_name);
 
@@ -734,7 +801,7 @@
 		static int DSFind(const XMLCh *where, const string &what) {
 			if(where == NULL) return -1;
 			
-			XMLCh *what_buf = XMLString::transcode(what.c_str());
+			XMLCh *what_buf = transcode(what);
 			int index = XMLString::patternMatch(where, what_buf);
 
 			XMLString::release(&what_buf);
@@ -758,7 +825,7 @@
 			XMLString::copyString(retval, src);
 			XMLString::catString(retval, gXML_space);
 
-			XMLCh *data_buf = XMLString::transcode(data.c_str());
+			XMLCh *data_buf = transcode(data);
 			XMLString::catString(retval, data_buf);
 
 			XMLString::release(&data_buf);
@@ -911,7 +978,7 @@
 			
 			//DOMString pa = dom_element.getAttribute(DOMString("desynched_atts"));
 			const XMLCh *pa = dom_element->getAttribute(gXML__desynched_atts);
-			XMLCh *myname_buf = XMLString::transcode(myname.c_str());
+			XMLCh *myname_buf = transcode(myname);
 			if(EmptyVal(pa)) 
 			{
 				//dom_element.setAttribute( DOMString("desynched_atts"), DOMString(myname.c_str()));
@@ -1017,11 +1084,11 @@
 			}	
 			else
 			{
-				XMLCh *name_buf = XMLString::transcode( ((string) meta.name()).c_str() );
+				XMLCh *name_buf = transcode( ((string) meta.name()) );
 				DOMAttr *as = dom_element->getAttributeNode(name_buf);
 				if(as != NULL && as->getSpecified()) 
 				{
-					char *a_buf = XMLString::transcode(as->getValue());
+					char *a_buf = transcode(as->getValue());
 					a = a_buf;
 					XMLString::release(&a_buf);
 				}
@@ -1397,12 +1464,12 @@
 		void removeAssociation(const string &tname, const string &oname, 
 								const string &myid) 
 		{
-			XMLCh *tname_buf = XMLString::transcode(tname.c_str());
+			XMLCh *tname_buf = transcode(tname);
 			XMLCh *origattr = XMLString::replicate( dom_element->getAttribute(tname_buf) );
 			dom_element->removeAttribute(tname_buf);
 			XMLString::release(&tname_buf);
 
-			XMLCh *oname_buf = XMLString::transcode(oname.c_str());
+			XMLCh *oname_buf = transcode(oname);
 			XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = dom_element->getOwnerDocument();
 
 			const BaseRefVectorOf<XMLCh> *v = XMLString::tokenizeString(origattr);
@@ -1691,7 +1758,7 @@
 
 					// we only get here, if multiple roles match, so they have to be recorded
 					string ncomp = GetANameFor(comp);
-					XMLCh *ncomp_buf = XMLString::transcode(ncomp.c_str());
+					XMLCh *ncomp_buf = transcode(ncomp);
 					if(!EmptyVal(chas)) 
 					{
 						if(DSFind(chas,ncomp) < 0) 
@@ -1803,7 +1870,7 @@
 								return;												// do not delete child if multiroles were in effect
 							}
 
-							XMLCh *ncomp_buf = XMLString::transcode(ncomp.c_str());
+							XMLCh *ncomp_buf = transcode(ncomp);
 							UDM_ASSERT( XMLString::compareString(chas, ncomp_buf) == 0);
 							XMLString::release(&ncomp_buf);
 						}
@@ -2651,8 +2718,8 @@
 			else if(mode == Udm::TARGETFROMCLASS) 
 				tname += "_end_";
 			
-			XMLCh *oname_buf = XMLString::transcode(oname.c_str());
-			XMLCh *tname_buf = XMLString::transcode(tname.c_str());
+			XMLCh *oname_buf = transcode(oname);
+			XMLCh *tname_buf = transcode(tname);
 			XMLCh *origattr = XMLString::replicate( dom_element->getAttribute(tname_buf) );
 
 			XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc = dom_element->getOwnerDocument();

Modified: UDM/trunk/src/UdmGme/UdmGme.cpp
==============================================================================
--- UDM/trunk/src/UdmGme/UdmGme.cpp	Fri Oct  5 10:08:04 2012	(r4126)
+++ UDM/trunk/src/UdmGme/UdmGme.cpp	Thu Oct 11 10:10:36 2012	(r4127)
@@ -252,6 +252,70 @@
 #undef INTERFACE_VERSION
 
 
+static _bstr_t BSTRFromUTF8(const std::string & utf8)
+{
+    if (utf8.empty())
+        return _bstr_t();
+
+    // Fail if an invalid input character is encountered
+    const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
+
+    const int utf16Length = ::MultiByteToWideChar(CP_UTF8, conversionFlags, utf8.data(), utf8.length(), NULL, 0);
+    if (utf16Length == 0)
+    {
+        DWORD error = ::GetLastError();
+
+        throw udm_exception(
+            (error == ERROR_NO_UNICODE_TRANSLATION) ? 
+                "Invalid UTF-8 sequence found in input string." :
+                "Can't get length of UTF-16 string (MultiByteToWideChar failed).");
+	}
+
+	BSTR utf16 = SysAllocStringByteLen(NULL, utf16Length*2);
+	if (utf16 == NULL)
+		throw std::bad_alloc();
+
+	if (!::MultiByteToWideChar(CP_UTF8, 0, utf8.data(), utf8.length(), utf16, utf16Length))
+    {
+        DWORD error = ::GetLastError();
+		SysFreeString(utf16);
+        throw udm_exception("Can't convert string from UTF-8 to UTF-16 (MultiByteToWideChar failed).");
+    }
+
+    return _bstr_t(utf16, false);
+}
+
+static std::string UTF8FromBSTR(BSTR utf16)
+{
+    if (utf16 == NULL || *utf16 == L'\0')
+        return std::string();
+
+
+    // const int utf16Length = static_cast<int>(wcslen(utf16));
+	const int utf16Length = SysStringLen(utf16);
+
+    // Get length (in chars) of resulting UTF-8 string
+    const int utf8Length = ::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16Length, NULL, 0, NULL, NULL);
+
+	if (utf8Length == 0)
+    {
+        DWORD error = ::GetLastError();
+        throw udm_exception("Can't get length of UTF-8 string (WideCharToMultiByte failed).");
+    }
+
+    std::string utf8;
+    utf8.resize(utf8Length);
+
+	if (!::WideCharToMultiByte(CP_UTF8, 0, utf16, utf16Length, &utf8[0], utf8.length(), NULL, NULL))
+    {
+        DWORD error = ::GetLastError();
+        throw udm_exception("Can't convert string from UTF-16 to UTF-8 (WideCharToMultiByte failed).");
+    }
+
+    return utf8;
+}
+
+
 
 namespace UdmGme 
 {
@@ -2403,7 +2467,7 @@
 				COMTHROW(self->get_RegistryNode(reg_node_name, &reg_node));
 				
 			val = reg_node->Value;
-			return val.length()? (char*)val : "";
+			return val.length()? UTF8FromBSTR(val) : "";
 
 
 		}
@@ -2443,10 +2507,10 @@
 				}
 			}
 			else
-				return("");
+				return "";
 		}
 		else val = testself->StrAttrByName[SmartBSTR(rname.c_str())];
-		return (char *)val;
+		return UTF8FromBSTR(val);
 	}
 
 	typedef pair<const long, const long> pos_in_aspect;
@@ -2497,22 +2561,22 @@
 		{
 			//to be written as a registry value
 			IMgaRegNodePtr reg_node;
-			BSTR reg_node_name = SmartBSTR(rname.c_str());
+			_bstr_t reg_node_name = BSTRFromUTF8(rname);
 		
 			if (folderself)
 				COMTHROW(folderself->get_RegistryNode(reg_node_name, &reg_node));
 			else
 				COMTHROW(self->get_RegistryNode(reg_node_name, &reg_node));
 
-			COMTHROW(reg_node->put_Value(SmartBSTR(a.c_str())));
+			COMTHROW(reg_node->put_Value(BSTRFromUTF8(a)));
 
 
 		}
 		else if(rname == "name")
 		{
-			objself->Name = SmartBSTR(a.c_str()); 
+			objself->Name = BSTRFromUTF8(a); 
 			if (folderself && folderself->Project->RootFolder == folderself) {
-				folderself->Project->Name = SmartBSTR(a.c_str());
+				folderself->Project->Name = BSTRFromUTF8(a);
 			}
 #ifdef _DEBUG
 			name = a; 
@@ -2554,7 +2618,7 @@
 			}
 
 		}
-		else testself->StrAttrByName[SmartBSTR(rname.c_str())] = SmartBSTR(a.c_str());
+		else testself->StrAttrByName[BSTRFromUTF8(rname)] = BSTRFromUTF8(a);
 	};
 
 	bool GmeObject::getBooleanAttr(const ::Uml::Attribute &meta) const	

Modified: UDM/trunk/tests/test_generic/genericTest.cpp
==============================================================================
--- UDM/trunk/tests/test_generic/genericTest.cpp	Fri Oct  5 10:08:04 2012	(r4126)
+++ UDM/trunk/tests/test_generic/genericTest.cpp	Thu Oct 11 10:10:36 2012	(r4127)
@@ -4,10 +4,12 @@
 #include <UdmBase.h>
 #include <UdmUtil.h>
 #include <cint_string.h>
+#include <string.h>
+#include <iostream>
 #include "genericTest.h"
 #include "LampDiagram.h"
 
-#ifdef WIN32
+#ifdef _WIN32
 #include <io.h>
 #include <stdio.h>
 #else	//WIN32
@@ -32,11 +34,31 @@
 UDM_USE_MGA
 #endif
 
+const char* utf8_test_strings[] = {
+// Árvíztűrő tükörfúrógép
+"\xc3\x81\x72\x76\xc3\xad\x7a\x74\xc5\xb1\x72\xc5\x91\x20\x74\xc3\xbc\x6b\xc3\xb6\x72\x66\xc3\xba\x72\xc3\xb3\x67\xc3\xa9\x70",
+// Γαζέες καὶ μυρτιὲς δὲν θὰ βρῶ πιὰ στὸ χρυσαφὶ ξέφωτο
+"\xce\x93\xce\xb1\xce\xb6\xce\xad\xce\xb5\xcf\x82\x20\xce\xba\xce\xb1\xe1\xbd\xb6\x20\xce\xbc\xcf\x85\xcf\x81\xcf\x84\xce\xb9\xe1\xbd\xb2\xcf\x82\x20\xce\xb4\xe1\xbd\xb2\xce\xbd\x20\xce\xb8\xe1\xbd\xb0\x20\xce\xb2\xcf\x81\xe1\xbf\xb6\x20\xcf\x80\xce\xb9\xe1\xbd\xb0\x20\xcf\x83\xcf\x84\xe1\xbd\xb8\x20\xcf\x87\xcf\x81\xcf\x85\xcf\x83\xce\xb1\xcf\x86\xe1\xbd\xb6\x20\xce\xbe\xce\xad\xcf\x86\xcf\x89\xcf\x84\xce\xbf",
+// いろはにほへとちりぬるを
+"\xe3\x81\x84\xe3\x82\x8d\xe3\x81\xaf\xe3\x81\xab\xe3\x81\xbb\xe3\x81\xb8\xe3\x81\xa8\xe3\x81\xa1\xe3\x82\x8a\xe3\x81\xac\xe3\x82\x8b\xe3\x82\x92",
+// ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン
+"\xe3\x82\xa6\xe3\x83\xb0\xe3\x83\x8e\xe3\x82\xaa\xe3\x82\xaf\xe3\x83\xa4\xe3\x83\x9e\x20\xe3\x82\xb1\xe3\x83\x95\xe3\x82\xb3\xe3\x82\xa8\xe3\x83\x86\x20\xe3\x82\xa2\xe3\x82\xb5\xe3\x82\xad\xe3\x83\xa6\xe3\x83\xa1\xe3\x83\x9f\xe3\x82\xb7\x20\xe3\x83\xb1\xe3\x83\x92\xe3\x83\xa2\xe3\x82\xbb\xe3\x82\xb9\xe3\x83\xb3",
+// דג סקרן שט בים מאוכזב ולפתע מצא לו חברה איך הקליט
+"\xd7\x93\xd7\x92\x20\xd7\xa1\xd7\xa7\xd7\xa8\xd7\x9f\x20\xd7\xa9\xd7\x98\x20\xd7\x91\xd7\x99\xd7\x9d\x20\xd7\x9e\xd7\x90\xd7\x95\xd7\x9b\xd7\x96\xd7\x91\x20\xd7\x95\xd7\x9c\xd7\xa4\xd7\xaa\xd7\xa2\x20\xd7\x9e\xd7\xa6\xd7\x90\x20\xd7\x9c\xd7\x95\x20\xd7\x97\xd7\x91\xd7\xa8\xd7\x94\x20\xd7\x90\xd7\x99\xd7\x9a\x20\xd7\x94\xd7\xa7\xd7\x9c\xd7\x99\xd7\x98",
+// Съешь же ещё этих мягких французских булок да выпей чаю
+"\xd0\xa1\xd1\x8a\xd0\xb5\xd1\x88\xd1\x8c\x20\xd0\xb6\xd0\xb5\x20\xd0\xb5\xd1\x89\xd1\x91\x20\xd1\x8d\xd1\x82\xd0\xb8\xd1\x85\x20\xd0\xbc\xd1\x8f\xd0\xb3\xd0\xba\xd0\xb8\xd1\x85\x20\xd1\x84\xd1\x80\xd0\xb0\xd0\xbd\xd1\x86\xd1\x83\xd0\xb7\xd1\x81\xd0\xba\xd0\xb8\xd1\x85\x20\xd0\xb1\xd1\x83\xd0\xbb\xd0\xbe\xd0\xba\x20\xd0\xb4\xd0\xb0\x20\xd0\xb2\xd1\x8b\xd0\xbf\xd0\xb5\xd0\xb9\x20\xd1\x87\xd0\xb0\xd1\x8e",
+// ๏ เป็นมนุษย์สุดประเสริฐเลิศคุณค่า  กว่าบรรดาฝูงสัตว์เดรัจฉาน
+"\xe0\xb9\x8f\x20\xe0\xb9\x80\xe0\xb8\x9b\xe0\xb9\x87\xe0\xb8\x99\xe0\xb8\xa1\xe0\xb8\x99\xe0\xb8\xb8\xe0\xb8\xa9\xe0\xb8\xa2\xe0\xb9\x8c\xe0\xb8\xaa\xe0\xb8\xb8\xe0\xb8\x94\xe0\xb8\x9b\xe0\xb8\xa3\xe0\xb8\xb0\xe0\xb9\x80\xe0\xb8\xaa\xe0\xb8\xa3\xe0\xb8\xb4\xe0\xb8\x90\xe0\xb9\x80\xe0\xb8\xa5\xe0\xb8\xb4\xe0\xb8\xa8\xe0\xb8\x84\xe0\xb8\xb8\xe0\xb8\x93\xe0\xb8\x84\xe0\xb9\x88\xe0\xb8\xb2\x20\x20\xe0\xb8\x81\xe0\xb8\xa7\xe0\xb9\x88\xe0\xb8\xb2\xe0\xb8\x9a\xe0\xb8\xa3\xe0\xb8\xa3\xe0\xb8\x94\xe0\xb8\xb2\xe0\xb8\x9d\xe0\xb8\xb9\xe0\xb8\x87\xe0\xb8\xaa\xe0\xb8\xb1\xe0\xb8\x95\xe0\xb8\xa7\xe0\xb9\x8c\xe0\xb9\x80\xe0\xb8\x94\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x88\xe0\xb8\x89\xe0\xb8\xb2\xe0\xb8\x99",
+// ಠ_ಠ
+"\xe0\xb2\xa0\x5f\xe0\xb2\xa0",
+};
+
+
 using namespace LampDiagram;
 
 char * UdmTests::genericTest::getRndFileName()
 {
-#ifdef WIN32
+#ifdef _WIN32
 		char * def_tmp_dir = "c:\\";
 #else
 		char * def_tmp_dir = "/tmp/";
@@ -52,7 +74,7 @@
 		//create a temporary folder and set the path
 		//char t_dir_name[L_tmpnam +1];
 		char * t_dir_name;
-#ifdef WIN32
+#ifdef _WIN32
 		t_dir_name = _tempnam(tmp_dir, "UDM");
 #else	//WIN32
 		t_dir_name = tempnam(tmp_dir, "UDM");
@@ -63,7 +85,7 @@
 
 void UdmTests::genericTest::removeFile(const string &pathname)
 {
-#ifdef WIN32
+#ifdef _WIN32
 	_unlink(pathname.c_str());
 #else
 	unlink(pathname.c_str());
@@ -179,6 +201,7 @@
 				d.push_back("triple back\\\\\\slash");
 				d.push_back("triple semi-coloback\\;\\;\\;slash-1");
 				d.push_back("triple semi-coloback\\\\\\;;;slash-2");
+				d.push_back("xxabcd\xc3\xa9");
 				doubleBulbLamp.ArrayStr() = d;
 				
 				CPPUNIT_ASSERT((string)doubleBulbLamp.ArrayStr()[0] == "apple");
@@ -192,7 +215,7 @@
 				CPPUNIT_ASSERT((string)doubleBulbLamp.ArrayStr()[8] == "triple semi-coloback\\;\\;\\;slash-1");
 				CPPUNIT_ASSERT((string)doubleBulbLamp.ArrayStr()[9] == "triple semi-coloback\\\\\\;;;slash-2");
 				CPPUNIT_ASSERT((string)doubleBulbLamp.ArrayStr()[10] == "triplesemi;;;colon");
-				
+				CPPUNIT_ASSERT((string)doubleBulbLamp.ArrayStr()[11] == "xxabcd\xc3\xa9");
 
 							
 				//testing non-persistent array attributes
@@ -210,7 +233,7 @@
 				CPPUNIT_ASSERT(d[8] == "triple semi-coloback\\;\\;\\;slash-1");
 				CPPUNIT_ASSERT(d[9] == "triple semi-coloback\\\\\\;;;slash-2");
 				CPPUNIT_ASSERT(d[10] == "triplesemi;;;colon");
-				
+				CPPUNIT_ASSERT(d[11] == "xxabcd\xc3\xa9");
 
 
 
@@ -628,6 +651,15 @@
 			CPPUNIT_ASSERT(ed_s.size() == 8); //all the devices: 3 Bulb, 3 switch, 1 plug, 1 lamp
 			
 
+			for (int i = 0; i < sizeof(utf8_test_strings) / sizeof(utf8_test_strings[0]); i++)
+			{
+				doubleBulbLamp.RegAttr() = utf8_test_strings[i];
+				CPPUNIT_ASSERT(utf8_test_strings[i] == std::string(doubleBulbLamp.RegAttr()));
+				CPPUNIT_ASSERT_EQUAL(strlen(utf8_test_strings[i]), std::string(doubleBulbLamp.RegAttr()).length());
+				doubleBulbLamp.ModelName() = utf8_test_strings[i];
+				CPPUNIT_ASSERT(utf8_test_strings[i] == std::string(doubleBulbLamp.ModelName()));
+			}
+
 			//testing assignment
 						
 			Udm::SmartDataNetwork snw(LampDiagram::diagram);
@@ -645,6 +677,22 @@
 	return false;
 };
 
+
+static void testLastUTF8StringInXML(const std::string& filename)
+{
+	std::string encoding = "encoding=\"UTF-8\"";
+	std::string test_string = utf8_test_strings[sizeof(utf8_test_strings)/sizeof(utf8_test_strings[0])-1];
+	std::string test1 = std::string("ModelName=\"") + test_string + "\"";
+	std::string test2 = std::string("RegAttr=\"") + test_string + "\"";
+	std::ifstream stream(filename.c_str(), ios::in | ios::binary);
+	CPPUNIT_ASSERT(stream.good());
+	char data[2048];
+	stream.read(data, sizeof(data));
+	CPPUNIT_ASSERT(std::string(data).find(encoding) != std::string::npos);
+	CPPUNIT_ASSERT(std::string(data).find(test1) != std::string::npos);
+	CPPUNIT_ASSERT(std::string(data).find(test2) != std::string::npos);
+}
+
 #ifdef _WIN32
 void UdmTests::genericTest::testDOMMGA()
 {
@@ -653,6 +701,7 @@
 	std::string fname_std = std::string(fname) + ".xml";
 	std::string fname_std_1 = std::string(fname) + ".mga";
 	generictest(fname_std.c_str(),fname_std_1.c_str());
+	testLastUTF8StringInXML(fname_std);
 	removeFile(fname_std);
 	removeFile(fname_std_1);
 	free(fname);
@@ -689,6 +738,7 @@
 	std::string fname_std = std::string(fname) + ".mga";
 	std::string fname_std_1 = std::string(fname) + ".xml";
 	generictest(fname_std.c_str(),fname_std_1.c_str());
+	testLastUTF8StringInXML(fname_std_1);
 	removeFile(fname_std);
 	removeFile(fname_std_1);
 	free(fname);
@@ -714,6 +764,8 @@
 	std::string fname_std = std::string(fname) + ".xml";
 	std::string fname_std_1 = std::string(fname) + "1.xml";
 	generictest(fname_std.c_str(),fname_std_1.c_str());
+	testLastUTF8StringInXML(fname_std);
+	testLastUTF8StringInXML(fname_std_1);
 	removeFile(fname_std);
 	removeFile(fname_std_1);
 	free(fname);
@@ -726,6 +778,7 @@
 	std::string fname_std = std::string(fname) + ".xml";
 	std::string fname_std_1 = std::string(fname) + ".mem";
 	generictest(fname_std.c_str(),fname_std_1.c_str());
+	testLastUTF8StringInXML(fname_std);
 	removeFile(fname_std);
 	removeFile(fname_std_1);
 	free(fname);
@@ -750,6 +803,7 @@
 	std::string fname_std = std::string(fname) + ".mem";
 	std::string fname_std_1 = std::string(fname) + ".xml";
 	generictest(fname_std.c_str(),fname_std_1.c_str());
+	testLastUTF8StringInXML(fname_std_1);
 	removeFile(fname_std);
 	removeFile(fname_std_1);
 	free(fname);


More information about the Mobies-commit mailing list