summaryrefslogtreecommitdiff
path: root/TAO
diff options
context:
space:
mode:
authorPhil Mesnier <mesnier_p@ociweb.com>2004-05-21 03:01:27 +0000
committerPhil Mesnier <mesnier_p@ociweb.com>2004-05-21 03:01:27 +0000
commit74fa743a42c15559c7460a876e4d7927cff1498e (patch)
treef0783923f6a7d47e5e296354b76dc4832012b8d3 /TAO
parent2f4ac18e616081eaa860d3e6c579c5d9cc52d734 (diff)
downloadATCD-74fa743a42c15559c7460a876e4d7927cff1498e.tar.gz
Thu May 20 21:28:41 2004 Phil Mesnier <mesnier_p@ociweb.com>
Diffstat (limited to 'TAO')
-rw-r--r--TAO/interop-tests/wchar/Client.java207
-rw-r--r--TAO/interop-tests/wchar/README32
-rw-r--r--TAO/interop-tests/wchar/Server.java75
-rw-r--r--TAO/interop-tests/wchar/WCharReference.java97
-rw-r--r--TAO/interop-tests/wchar/WChar_PasserImpl.java137
-rw-r--r--TAO/interop-tests/wchar/build.xml42
-rw-r--r--TAO/interop-tests/wchar/client.cpp269
-rw-r--r--TAO/interop-tests/wchar/interop_wchar.idl62
-rw-r--r--TAO/interop-tests/wchar/interop_wchar.mpc15
-rw-r--r--TAO/interop-tests/wchar/interop_wchar_i.cpp225
-rw-r--r--TAO/interop-tests/wchar/interop_wchar_i.h109
-rwxr-xr-xTAO/interop-tests/wchar/run_test.pl42
-rw-r--r--TAO/interop-tests/wchar/server.cpp111
-rw-r--r--TAO/interop-tests/wchar/wchar_reference.cpp131
-rw-r--r--TAO/interop-tests/wchar/wchar_reference.h57
-rw-r--r--TAO/tao/Codeset_Manager.cpp80
-rw-r--r--TAO/tao/Codeset_Manager.h9
-rw-r--r--TAO/tao/UTF16_BOM_Factory.cpp39
-rw-r--r--TAO/tao/UTF16_BOM_Factory.h35
-rw-r--r--TAO/tao/UTF16_BOM_Translator.cpp369
-rw-r--r--TAO/tao/UTF16_BOM_Translator.h85
-rw-r--r--TAO/tao/tao.mpc2
-rw-r--r--TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.cpp528
-rw-r--r--TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.h43
24 files changed, 2659 insertions, 142 deletions
diff --git a/TAO/interop-tests/wchar/Client.java b/TAO/interop-tests/wchar/Client.java
new file mode 100644
index 00000000000..821582b167e
--- /dev/null
+++ b/TAO/interop-tests/wchar/Client.java
@@ -0,0 +1,207 @@
+package interop.wchar;
+
+import org.omg.CORBA.*;
+import java.io.*;
+import interop.*;
+
+/**
+ * Client.java
+ *
+ * Java implemention of the interoperability tests for wchars.
+ *
+ * @author Phil Mesnier
+ * @version $Id$
+ */
+
+public class Client
+{
+
+ private static WCharReference ref = new WCharReference();
+ private static org.omg.CORBA.ORB orb;
+
+ private static int WCHAR_TO_SERVER = 0x0001;
+ private static int WSTRING_TO_SERVER = 0x0002;
+ private static int WARRAY_TO_SERVER = 0x0004;
+ private static int ANY_WCHAR_TO_SERVER = 0x0008;
+ private static int WSTRING_EXCEPTION = 0x0010;
+ private static int WCHAR_FROM_SERVER = 0x0020;
+ private static int WSTRING_FROM_SERVER = 0x0040;
+ private static int WARRAY_FROM_SERVER = 0x0080;
+ private static int ANY_WCHAR_FROM_SERVER = 0x0100;
+ private static int TBD_6 = 0x0200;
+ private static int TBD_5 = 0x0400;
+ private static int TBD_4 = 0x0800;
+ private static int TBD_3 = 0x1000;
+ private static int TBD_2 = 0x2000;
+ private static int TBD_1 = 0x4000;
+ private static int TBD_0 = 0x8000;
+ private static int ALL_TESTS = 0xFFFF;
+
+ private static String test_name[] =
+ {
+ "wchar_to_server", "wstring_to_server", "warray_to_server",
+ "any(wchar)_to_server", "wstring_exception", "wchar_from_server",
+ "wstring_from_server", "warray_from_server", "any(wchar)_from_server"
+ };
+
+ private static int tests_to_run = 0;
+ private static short data_set = 0;
+ private static boolean verbose = false;
+
+ private static boolean runOneTest (WChar_Passer server, int test_num)
+ {
+ switch (test_num)
+ {
+ case 0x0001: //WCHAR_TO_SERVER:
+ return server.wchar_to_server (Client.
+ ref.get_wchar(data_set),
+ data_set);
+ case 0x0002: //WSTRING_TO_SERVER:
+ return server.wstring_to_server (Client.
+ ref.get_wstring(data_set),
+ data_set);
+ case 0x0004: //WARRAY_TO_SERVER:
+ return server.warray_to_server (Client.
+ ref.get_warray(data_set),
+ data_set);
+ case 0x0008: //ANY_WCHAR_TO_SERVER:
+ {
+ Any a = orb.create_any();
+ a.insert_wchar (ref.get_wchar(data_set));
+ return server.any_to_server (a,data_set);
+ }
+ case 0x0010: //WSTRING_EXCEPTION:
+ {
+ try {
+ server.exception_test(data_set);
+ } catch (interop.WChar_PasserPackage.WStringException ex) {
+ return Client.ref.match_except (data_set,ex.why);
+ }
+ break;
+ }
+ case 0x0020: // WCHAR_FROM_SERVER:
+ {
+ char wc = server.wchar_from_server (data_set);
+ return Client.ref.match_wchar (data_set,wc);
+ }
+ case 0x0040: //WSTRING_FROM_SERVER:
+ {
+ String ws = server.wstring_from_server (data_set);
+ return Client.ref.match_wstring (data_set,ws);
+ }
+ case 0x0080: //WARRAY_FROM_SERVER:
+ {
+ char wa[] = server.warray_from_server (data_set);
+ return Client.ref.match_warray (data_set,wa);
+ }
+ case 0x0100: // ANY_WCHAR_FROM_SERVER:
+ {
+ if (verbose)
+ System.out.println ("test any(wchar) from server not yet implemented");
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+ }
+
+ public static boolean runTests (WChar_Passer server)
+ {
+ int successes = 0;
+ int numtests = 0;
+ ref.set_verbose (verbose);
+ int t = 1;
+ for (int i = 0; i < test_name.length; i++, t <<= 1)
+ if ((tests_to_run & t) == t)
+ {
+ boolean result = runOneTest (server,t);
+ ++numtests;
+ if (result) ++successes;
+ if (verbose)
+ System.out.println (test_name[i] +
+ "[" + data_set + "] " +
+ (result ? "passed" : "failed"));
+ }
+ if (verbose)
+ System.out.println ("Total of " + successes +
+ "successes out of " + numtests + " tests");
+ return successes == numtests;
+ }
+
+ public static void main( String[] args )
+ throws Exception
+ {
+ String iorfile = "IOR";
+ boolean kill_server = false;
+
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].equals ("-i"))
+ iorfile = args[++i];
+ else if (args[i].equals ("-v"))
+ verbose = true;
+ else if (args[i].equals ("-x"))
+ kill_server = true;
+ else if (args[i].equals ("-t"))
+ {
+ int tnum = Integer.decode(args[++i]).intValue();
+ if (tnum >= 0 && tnum < test_name.length)
+ tests_to_run |= (1 << tnum);
+ }
+ else
+ {
+ System.out.println( "Usage: jaco interop.wchar.Client " +
+ "-i <ior_file> " +
+ "-t <0 <= num < " + test_name.length + "> " +
+ "-v " +
+ "-x ");
+ System.out.println ("Available tests:");
+ for (int j = 0; i < test_name.length; i++)
+ System.out.println (j + " - " + test_name[i]);
+ System.exit( 1 );
+ }
+ }
+ if (tests_to_run == 0)
+ tests_to_run = ALL_TESTS;
+
+ File f = new File(iorfile);
+
+ //check if file exists
+ if( ! f.exists() )
+ {
+ System.out.println("File " + iorfile +
+ " does not exist.");
+ System.exit( -1 );
+ }
+
+ //check if args[0] points to a directory
+ if( f.isDirectory() )
+ {
+ System.out.println("File " + iorfile +
+ " is a directory.");
+ System.exit( -1 );
+ }
+
+ // initialize the ORB.
+ orb = org.omg.CORBA.ORB.init( args, null );
+
+ BufferedReader br =
+ new BufferedReader( new FileReader( f ));
+
+ // get object reference from command-line argument file
+ org.omg.CORBA.Object obj =
+ orb.string_to_object( br.readLine() );
+
+ br.close();
+
+ WChar_Passer wp = WChar_PasserHelper.narrow( obj );
+
+ boolean result = Client.runTests (wp);
+ System.out.println ("wchar_interop test (Jacorb client, " +
+ wp.orb_name() + " server) " +
+ (result ? "passed" : "failed"));
+ if (kill_server)
+ wp.shutdown();
+ }
+}// Client
diff --git a/TAO/interop-tests/wchar/README b/TAO/interop-tests/wchar/README
new file mode 100644
index 00000000000..99335123e81
--- /dev/null
+++ b/TAO/interop-tests/wchar/README
@@ -0,0 +1,32 @@
+Test for passing wchar data between TAO and JacORB processes.
+This test may also be run for tao-tao on different platforms.
+
+To build this test for JacORB requires a JacORB 2.0 installation, and the
+ant build tool. The Java classpath must include $JACORB_HOME/lib/jacorb.jar
+and $TAO_ROOT/interop-tests/classes.
+
+To build the tao test client and server, first run mwc.pl in the ordinary
+way to generate makefiles or project files. Then to build the JacORB client
+and server, use "ant" which assumes $JACORB_HOME is set to the JacORB home
+directory.
+
+The TAO server command line is:
+ ./server [-o iorfile] [-v]
+The default ior file for the server is "./IOR"
+The -v option causes the server to output some details of its operation.
+
+The TAO client command line is:
+ ./client [-k ior] [[-t 0 < n <= 8]...] [-v] [-x]
+The default ior is "file://IOR". Note that it is an IOR, not a filename.
+The -t option selects individual tests, no selection implies all tests,
+ the -t option may be repeated to select a number of tests
+The -v option make the test more verbose, not adding it only outputs final
+ pass/fail message.
+The -x option makes the client send a shutdown request to the server.
+Anything else, such as -?, will yield a list of options and test descriptions.
+
+To run the JacORB client or server, use the "jaco" utility,
+
+jaco interop.wchar.Server [-o iorfile] [-v]
+jaco interop.wchar.Client [-i iorfile] [-t 0..8] [-v] [-x]
+Note that Client takes -i iorfile, not -k ior.
diff --git a/TAO/interop-tests/wchar/Server.java b/TAO/interop-tests/wchar/Server.java
new file mode 100644
index 00000000000..710f1ee775b
--- /dev/null
+++ b/TAO/interop-tests/wchar/Server.java
@@ -0,0 +1,75 @@
+package interop.wchar;
+
+import java.io.*;
+
+import org.omg.CORBA.*;
+import org.omg.PortableServer.*;
+import interop.*;
+
+/**
+ * Server.java
+ *
+ * Java implemention of the interoperability tests for wchars.
+ *
+ * @author Phil Mesnier
+ * @version $Id$
+ */
+
+public class Server
+{
+ public static void main(String[] args)
+ {
+ String iorfile = "IOR";
+ boolean verbose = false;
+ for (int i = 0; i < args.length; i++)
+ {
+ if (args[i].equals ("-o"))
+ iorfile = args[++i];
+ else if (args[i].equals ("-v"))
+ verbose = true;
+ else
+ {
+ System.out.println( "Usage: jaco interop.wchar.Server " +
+ "-o <ior_file> " +
+ "-v ");
+ System.exit( 1 );
+ }
+ }
+
+ try
+ {
+ //init ORB
+ ORB orb = ORB.init( args, null );
+
+ //init POA
+ POA poa =
+ POAHelper.narrow( orb.resolve_initial_references( "RootPOA" ));
+
+ poa.the_POAManager().activate();
+
+ // create a GoodDay object
+ WChar_PasserImpl servant = new WChar_PasserImpl(orb, verbose);
+
+ // create the object reference
+ org.omg.CORBA.Object obj =
+ poa.servant_to_reference( servant );
+
+ PrintWriter pw =
+ new PrintWriter( new FileWriter( args[ 0 ] ));
+
+ // print stringified object reference to file
+ pw.println( orb.object_to_string( obj ));
+
+ pw.flush();
+ pw.close();
+
+ // wait for requests
+ orb.run();
+ }
+ catch( Exception e )
+ {
+ System.out.println( e );
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/TAO/interop-tests/wchar/WCharReference.java b/TAO/interop-tests/wchar/WCharReference.java
new file mode 100644
index 00000000000..ae62392afcf
--- /dev/null
+++ b/TAO/interop-tests/wchar/WCharReference.java
@@ -0,0 +1,97 @@
+package interop.wchar;
+
+
+/**
+ * Client.java
+ *
+ * Java implemention of the reference wchar data supplied to both
+ * clients and servers. This is independently maintained in parallel
+ * with the c++ version, wchar_reference.cpp
+ *
+ * @author Phil Mesnier
+ * @version $Id$
+ */
+
+public class WCharReference
+{
+ private char ref_wchar[] = {1234};
+ private String ref_wstring[] = {"have a nice day"};
+ private char ref_warray[][] =
+ { {'a','A','!','1','4','[','?','%','X','E'} };
+ private String ref_except[] = {"TEST EXCEPTION"};
+
+ private boolean verbose = false;
+
+ public WCharReference ()
+ {
+ }
+
+ public WCharReference (boolean v)
+ {
+ verbose = v;
+ }
+
+ public void set_verbose (boolean v)
+ {
+ verbose = v;
+ }
+
+ public char get_wchar (int key) {
+ return ref_wchar[key];
+ }
+
+ public String get_wstring (int key) {
+ return ref_wstring[key];
+ }
+
+ public char[] get_warray (int key) {
+ return ref_warray[key];
+ }
+
+ public String get_except (int key) {
+ return ref_except[key];
+ }
+
+ public boolean match_wchar (short key, char test)
+ {
+ if (verbose)
+ System.out.println ("match_wchar: expecting " +
+ ref_wchar[key] + " got " +
+ test + " for key " + key);
+ return ref_wchar[key] == test;
+ }
+
+ public boolean match_wstring (short key, String test)
+ {
+ if (verbose)
+ System.out.println ("match_wstring: expecting " +
+ ref_wstring[key] + " got " +
+ test + " for key " + key);
+ return test.equals(ref_wstring[key]);
+ }
+
+ public boolean match_warray (short key, char test[])
+ {
+ if (verbose)
+ System.out.println ("match_warray: key " + key);
+ for (int i = 0; i < test.length; i++)
+ {
+ if (verbose)
+ System.out.println (" expecting[" + i + "] " +
+ ref_warray[key][i] + ", got " +
+ test[i]);
+ if (ref_warray[key][i] != test[i])
+ return false;
+ }
+ return true;
+ }
+
+ public boolean match_except (short key, String test)
+ {
+ if (verbose)
+ System.out.println ("match_except: expecting " +
+ ref_except[key] + " got " +
+ test + " for key " + key);
+ return test.equals(ref_except[key]);
+ }
+}
diff --git a/TAO/interop-tests/wchar/WChar_PasserImpl.java b/TAO/interop-tests/wchar/WChar_PasserImpl.java
new file mode 100644
index 00000000000..575ba37fbe2
--- /dev/null
+++ b/TAO/interop-tests/wchar/WChar_PasserImpl.java
@@ -0,0 +1,137 @@
+package interop.wchar;
+
+import org.omg.CORBA.*;
+import interop.*;
+
+/**
+ * WChar_PasserImpl.java
+ *
+ * Java implemention of the interoperability tests for wchars.
+ *
+ * @author Phil Mesnier
+ * @version $Id$
+ */
+
+public class WChar_PasserImpl
+ extends WChar_PasserPOA
+{
+ private ORB orb;
+ private WCharReference ref;
+
+ public WChar_PasserImpl( ORB o, boolean v )
+ {
+ this.orb = o;
+ this.ref = new WCharReference(v);
+ }
+
+ public String orb_name ()
+ {
+ return "JacORB";
+ }
+
+ public boolean wchar_to_server (char test, short key)
+ {
+ System.out.println ("wchar_to_server called, test = " + (int)test
+ + " key = " + key);
+ if (key != 0)
+ return false;
+ return ref.match_wchar(key,test);
+ }
+
+ public char wchar_from_server (short key)
+ {
+ return ref.get_wchar(key);
+ }
+
+ public boolean wstring_to_server (String test, short key)
+ {
+ return ref.match_wstring (key,test);
+ }
+
+ public String wstring_from_server (short key)
+ {
+ return ref.get_wstring (key);
+ }
+
+ public boolean warray_to_server (char test[], short key)
+ {
+ return ref.match_warray (key,test);
+ }
+
+ public char[] warray_from_server (short key)
+ {
+ return ref.get_warray (key);
+ }
+
+ public boolean wstruct_to_server (wstruct test, short key)
+ {
+ return false;
+ }
+
+ public wstruct wstruct_from_server (short key)
+ {
+ return new wstruct();
+ }
+
+ public boolean wunion_to_server (wunion test, short key)
+ {
+ return false;
+ }
+
+ public wunion wunion_from_server (short key, wchar_types type)
+ {
+ return new wunion();
+ }
+
+ public boolean any_to_server (Any test, short key)
+ {
+ int kind = test.type().kind().value();
+ switch( kind )
+ {
+ case TCKind._tk_wchar:
+ return wchar_to_server(test.extract_wchar(),key);
+ case TCKind._tk_wstring:
+ return wstring_to_server(test.extract_wstring(),key);
+ default:
+ System.out.println ("WChar_PasserImpl.any_to_server " +
+ kind + " is not an implemented kind");
+ }
+ return false;
+ }
+
+ public Any any_from_server (short key, wchar_types type)
+ {
+ Any a = orb.create_any();
+ switch (type.value()) {
+ case interop.wchar_types._is_wchar:
+ a.insert_wchar(ref.get_wchar(key));
+ break;
+ case interop.wchar_types._is_wstring:
+ a.insert_wstring(ref.get_wstring(key));
+ break;
+ case interop.wchar_types._is_warray:
+ break;
+ }
+ return a;
+ }
+
+ public Any any_echo (Any test)
+ {
+ return test;
+ }
+
+ public void exception_test(short key)
+ throws interop.WChar_PasserPackage.WStringException
+ {
+ throw new interop.
+ WChar_PasserPackage.
+ WStringException(ref.get_except(key),ref.get_wchar(key));
+ }
+
+ public void shutdown ()
+ {
+ orb.shutdown(false);
+ }
+
+
+}
diff --git a/TAO/interop-tests/wchar/build.xml b/TAO/interop-tests/wchar/build.xml
new file mode 100644
index 00000000000..f948d0a5939
--- /dev/null
+++ b/TAO/interop-tests/wchar/build.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/*
+ *
+ */
+-->
+
+<project name="wc_test" default="compile" basedir=".">
+ <target name="init" >
+ <property environment="env" />
+ <property name="jacorb.home" value="${env.JACORB_HOME}" />
+ <property name="debug" value="on" />
+
+ <!-- generated source -->
+ <mkdir dir="gensrc" />
+ <!-- compiled java -->
+ <mkdir dir="../classes" />
+ <taskdef name="jacidl" classname="org.jacorb.idl.JacIDL">
+ <classpath>
+ <fileset dir="${jacorb.home}/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </classpath>
+ </taskdef>
+ </target>
+
+ <target name="compile" depends="init">
+ <jacidl srcdir="." destdir="gensrc" />
+ <javac debug="${debug}"
+ debuglevel="${debuglevel}"
+ srcdir="."
+ destdir="../classes" >
+ <classpath>
+ <fileset dir="${jacorb.home}/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </classpath>
+ </javac>
+ </target>
+
+</project>
diff --git a/TAO/interop-tests/wchar/client.cpp b/TAO/interop-tests/wchar/client.cpp
new file mode 100644
index 00000000000..c3d05e8bb67
--- /dev/null
+++ b/TAO/interop-tests/wchar/client.cpp
@@ -0,0 +1,269 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// interop_test/wchar
+//
+// = FILENAME
+// client.cpp
+//
+// = DESCRIPTION
+// C++ client side for testing interoperability with wchar data.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+
+#include "interop_wcharC.h"
+#include "wchar_reference.h"
+
+#include <ace/streams.h>
+#include <ace/Get_Opt.h>
+
+const int WCHAR_TO_SERVER = 0x0001;
+const int WSTRING_TO_SERVER = 0x0002;
+const int WARRAY_TO_SERVER = 0x0004;
+const int ANY_WCHAR_TO_SERVER = 0x0008;
+const int WSTRING_EXCEPTION = 0x0010;
+const int WCHAR_FROM_SERVER = 0x0020;
+const int WSTRING_FROM_SERVER = 0x0040;
+const int WARRAY_FROM_SERVER = 0x0080;
+const int ANY_WCHAR_FROM_SERVER = 0x0100;
+const int ANY_WSTRING_TO_SERVER = 0x0200;
+const int ANY_WSTRING_FROM_SERVER = 0x0400;
+const int ANY_WSTRING_ECHO = 0x0800;
+const int TBD_3 = 0x1000;
+const int TBD_2 = 0x2000;
+const int TBD_1 = 0x4000;
+const int TBD_0 = 0x8000;
+const int ALL_TESTS = 0xFFFF;
+
+const char * test_name[] =
+ {
+ "wchar_to_server", "wstring_to_server", "warray_to_server",
+ "any(wchar)_to_server", "wstring_exception", "wchar_from_server",
+ "wstring_from_server", "warray_from_server", "any(wchar)_from_server",
+ "any(wstring)_to_server", "any(wstring)_from_server", "any(wstring)_echo"
+ };
+
+const int LAST_TEST = sizeof (test_name) / sizeof (test_name[0]);
+const char *ior = "file://IOR";
+int tests_to_run = 0;
+int verbose = 0;
+int kill_server = 0;
+int data_set = 0;
+
+#if defined (ACE_HAS_WCHAR) || defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+
+wchar_reference ref;
+
+CORBA::Boolean
+run_one_test (interop::WChar_Passer_ptr server,
+ int test_num)
+{
+ switch (test_num)
+ {
+ case WCHAR_TO_SERVER:
+ return server->wchar_to_server (ref.get_wchar(data_set),data_set);
+ case WSTRING_TO_SERVER:
+ return server->wstring_to_server (ref.get_wstring(data_set),data_set);
+ case WARRAY_TO_SERVER:
+ return server->warray_to_server (ref.get_warray(data_set),data_set);
+ case ANY_WCHAR_TO_SERVER:
+ {
+ CORBA::Any a;
+ a <<= CORBA::Any::from_wchar(ref.get_wchar(data_set));
+ return server->any_to_server (a,data_set);
+ }
+ case WSTRING_EXCEPTION:
+ {
+ try {
+ server->exception_test(data_set);
+ } catch (interop::WChar_Passer::WStringException &e) {
+ return ref.match_except (data_set,e.why.in());
+ }
+ break;
+ }
+ case WCHAR_FROM_SERVER:
+ {
+ CORBA::WChar wc = server->wchar_from_server (data_set);
+ return ref.match_wchar (data_set,wc);
+ }
+ case WSTRING_FROM_SERVER:
+ {
+ CORBA::WString_var ws = server->wstring_from_server (data_set);
+ return ref.match_wstring (data_set,ws.in());
+ }
+ case WARRAY_FROM_SERVER:
+ {
+ interop::warray_var wa = server->warray_from_server (data_set);
+ return ref.match_warray (data_set,wa.in());
+ }
+ case ANY_WCHAR_FROM_SERVER:
+ {
+ CORBA::WChar wc;
+ CORBA::Any_var test = server->any_from_server (data_set,
+ interop::is_wchar);
+ if (test >>= CORBA::Any::to_wchar(wc))
+ {
+ return ref.match_wchar (data_set,wc);
+ }
+ return 0;
+ }
+ case ANY_WSTRING_TO_SERVER:
+ {
+ CORBA::Any a;
+ a <<= ref.get_wstring(data_set);
+ return server->any_to_server (a,data_set);
+ }
+ case ANY_WSTRING_FROM_SERVER:
+ {
+ const CORBA::WChar *ws;
+ CORBA::Any_var test = server->any_from_server (data_set,
+ interop::is_wstring);
+ if (test >>= ws)
+ {
+ return ref.match_wstring (data_set,ws);
+ }
+ return 0;
+ }
+ case ANY_WSTRING_ECHO:
+ {
+ CORBA::Any a;
+ a <<= ref.get_wstring(data_set);
+ const CORBA::WChar *ws;
+ CORBA::Any_var test = server->any_echo (a);
+ if (test >>= ws)
+ {
+ return ref.match_wstring (data_set,ws);
+ }
+ return 0;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+short
+run_tests (interop::WChar_Passer_ptr server)
+{
+ short successes = 0;
+ short numtests = 0;
+ ref.set_verbose (verbose);
+ int t = 1;
+ for (int i = 0; i < LAST_TEST; i++, t <<= 1)
+ if ((tests_to_run & t) == t)
+ {
+ CORBA::Boolean result = run_one_test (server,t);
+ ++numtests;
+ if (result) ++successes;
+ if (verbose)
+ ACE_DEBUG ((LM_DEBUG, "%s[%d] %s\n",
+ test_name[i],data_set,
+ (result ? "passed" : "failed")));
+ }
+ if (verbose)
+ ACE_DEBUG ((LM_DEBUG, "Total of %d successes out of %d tests\n",
+ successes, numtests));
+ return successes == numtests;
+}
+#endif // ACE_HAS_WCHAR || ACE_HAS_XPG4_MULTIBYTE_CHAR
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "k:t:vx");
+ int c;
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'k':
+ ior = get_opts.opt_arg ();
+ break;
+ case 't':
+ {
+ int tnum = atoi(get_opts.opt_arg());
+ if (tnum >= 0 && tnum < LAST_TEST)
+ tests_to_run |= (1 << tnum);
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,"test %d is out of range\n",tnum),-1);
+ break;
+ }
+ case 'v':
+ verbose = 1;
+ break;
+ case 'x':
+ kill_server = 1;
+ break;
+ case '?':
+ default:
+ {
+ ACE_ERROR ((LM_ERROR,
+ "usage: %s "
+ "-k <ior> "
+ "[-t <0 <= test_num < %d>][ -t ...] "
+ "[-v] "
+ "[-x] "
+ "\n",
+ argv [0], LAST_TEST));
+ ACE_ERROR ((LM_ERROR, "Available tests:\n"));
+ for (int i = 0; i < LAST_TEST; i++)
+ ACE_ERROR ((LM_ERROR, " %d - %s\n",i, test_name[i]));
+ return -1;
+ }
+ }
+
+ if (tests_to_run == 0)
+ tests_to_run = ALL_TESTS;
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+main( int argc, char *argv[] )
+{
+#if (!defined ACE_HAS_WCHAR) && (!defined ACE_HAS_XPG4_MULTIBYTE_CHAR)
+ ACE_ERROR_RETURN ((LM_ERROR,"This test requires wchar support\n"),-1);
+#else
+ try {
+ // Initialize orb
+ CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
+ if (parse_args(argc, argv) == -1)
+ return 0;
+
+ // Destringify ior
+ CORBA::Object_var obj = orb->string_to_object( ior );
+ if( CORBA::is_nil( obj.in() ) )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "arg is not a valid ior sting"),
+ -1);
+
+ // Narrow
+ interop::WChar_Passer_var server =
+ interop::WChar_Passer::_narrow( obj.in() );
+
+ if( CORBA::is_nil( server.in() ))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "arg is not a interop::WChar_Passer reference\n"),
+ -1);
+
+ short result = run_tests (server.in());
+ CORBA::String_var server_orb = server->orb_name();
+ ACE_ERROR ((LM_ERROR,
+ "wchar_interop test (TAO client, %s server) %s \n",
+ server_orb.in(),
+ (result ? "passed" : "failed")));
+ if (kill_server)
+ server->shutdown();
+ }
+ catch( const CORBA::Exception &ex ) {
+ ACE_PRINT_EXCEPTION(ex, "Uncaught CORBA exception: ");
+ return 1;
+ }
+ return 0;
+#endif
+}
diff --git a/TAO/interop-tests/wchar/interop_wchar.idl b/TAO/interop-tests/wchar/interop_wchar.idl
new file mode 100644
index 00000000000..bb15e237584
--- /dev/null
+++ b/TAO/interop-tests/wchar/interop_wchar.idl
@@ -0,0 +1,62 @@
+// $Id$
+
+// Tests for interoperability between TAO and JacORB for sending wchar data
+// The CDR defines separate serialization functions for reading and writing
+// wchar, wchar[] and wstring data. Encapsulated wchar data is also tested.
+
+module interop {
+ typedef wchar warray[10];
+
+ struct wstruct {
+ wchar st_char;
+ wstring st_string;
+ warray st_array;
+ any st_any;
+ };
+
+ enum wchar_types {is_wchar, is_wstring, is_warray};
+
+ union wunion switch (wchar_types) {
+ case is_wchar: wchar u_char;
+ case is_wstring: wstring u_string;
+ case is_warray: warray u_array;
+ };
+
+ interface WChar_Passer {
+ // The server and client for this test should both use a well known test
+ // data to allow individual string comparisons against reference strings.
+ // The separate test key value allows the tester to devise several strings,
+ // arrays, or wchar values that may be tested separately.
+
+ readonly attribute string orb_name;
+
+ boolean wchar_to_server (in wchar test, in short key);
+ wchar wchar_from_server (in short key);
+
+ boolean wstring_to_server (in wstring test, in short key);
+ wstring wstring_from_server (in short key);
+
+ boolean warray_to_server (in warray test, in short key);
+ warray warray_from_server (in short key);
+
+ boolean wstruct_to_server (in wstruct test, in short key);
+ wstruct wstruct_from_server (in short key);
+
+ boolean wunion_to_server (in wunion test, in short key);
+ wunion wunion_from_server (in short key, in wchar_types type);
+
+ boolean any_to_server (in any test, in short key);
+ any any_from_server (in short key, in wchar_types type);
+
+ any any_echo (in any test);
+
+ exception WStringException { wstring why; wchar whynot;};
+ void exception_test(in short key) raises (WStringException);
+
+ /// A method to shutdown the ORB
+ /**
+ * This method is used to simplify the test shutdown process
+ */
+ oneway void shutdown ();
+ };
+};
diff --git a/TAO/interop-tests/wchar/interop_wchar.mpc b/TAO/interop-tests/wchar/interop_wchar.mpc
new file mode 100644
index 00000000000..0eca7aaab0b
--- /dev/null
+++ b/TAO/interop-tests/wchar/interop_wchar.mpc
@@ -0,0 +1,15 @@
+project(*Server): taoexe, portableserver {
+ Source_Files {
+ interop_wchar_i.cpp
+ wchar_reference.cpp
+ server.cpp
+ }
+}
+
+project(*Client): taoexe {
+ Source_Files {
+ interop_wcharC.cpp
+ wchar_reference.cpp
+ client.cpp
+ }
+}
diff --git a/TAO/interop-tests/wchar/interop_wchar_i.cpp b/TAO/interop-tests/wchar/interop_wchar_i.cpp
new file mode 100644
index 00000000000..b395b419880
--- /dev/null
+++ b/TAO/interop-tests/wchar/interop_wchar_i.cpp
@@ -0,0 +1,225 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// **** Code generated by the The ACE ORB (TAO) IDL Compiler ****
+// TAO and the TAO IDL Compiler have been developed by:
+// Center for Distributed Object Computing
+// Washington University
+// St. Louis, MO
+// USA
+// http://www.cs.wustl.edu/~schmidt/doc-center.html
+// and
+// Distributed Object Computing Laboratory
+// University of California at Irvine
+// Irvine, CA
+// USA
+// http://doc.ece.uci.edu/
+//
+// Information about TAO is available at:
+// http://www.cs.wustl.edu/~schmidt/TAO.html
+
+// TAO_IDL - Generated from
+// be/be_codegen.cpp:986
+
+#include "interop_wchar_i.h"
+
+// Implementation skeleton constructor
+interop_WChar_Passer_i::interop_WChar_Passer_i (CORBA::ORB_ptr o,
+ int verbose)
+ : orb_(CORBA::ORB::_duplicate (o)),
+ ref_ (verbose)
+{
+}
+
+// Implementation skeleton destructor
+interop_WChar_Passer_i::~interop_WChar_Passer_i (void)
+{
+}
+
+char *
+interop_WChar_Passer_i::orb_name (void)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return CORBA::string_dup ("TAO");
+}
+
+CORBA::Boolean
+interop_WChar_Passer_i::wchar_to_server (CORBA::WChar test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return ref_.match_wchar (key,test);
+}
+
+CORBA::WChar
+interop_WChar_Passer_i::wchar_from_server (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return ref_.get_wchar (key);
+}
+
+CORBA::Boolean
+interop_WChar_Passer_i::wstring_to_server (const CORBA::WChar * test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return ref_.match_wstring(key,test);
+}
+
+CORBA::WChar *
+interop_WChar_Passer_i::wstring_from_server (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return CORBA::wstring_dup (ref_.get_wstring(key));
+}
+
+CORBA::Boolean
+interop_WChar_Passer_i::warray_to_server (const interop::warray test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return ref_.match_warray(key,test);
+}
+
+interop::warray_slice *
+interop_WChar_Passer_i::warray_from_server (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return interop::warray_dup (ref_.get_warray(key));
+}
+
+CORBA::Boolean
+interop_WChar_Passer_i::wstruct_to_server (const interop::wstruct & test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return
+ ref_.match_wchar (key,test.st_char) &&
+ ref_.match_wstring (key,test.st_string) &&
+ ref_.match_warray (key,test.st_array) &&
+ this->any_to_server (test.st_any,key);
+}
+
+interop::wstruct *
+interop_WChar_Passer_i::wstruct_from_server (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ interop::wstruct *ws = new interop::wstruct ();
+ ws->st_char = this->wchar_from_server(key);
+ ws->st_string = this->wstring_from_server(key);
+ ref_.assign_warray (key, ws->st_array);
+ ws->st_any <<= ref_.get_wstring(key);
+ return ws;
+}
+
+CORBA::Boolean
+interop_WChar_Passer_i::wunion_to_server (const interop::wunion & test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ switch (test._d()) {
+ case interop::is_wchar :
+ return this->wchar_to_server (test.u_char(),key);
+ case interop::is_wstring :
+ return this->wstring_to_server (test.u_string(),key);
+ case interop::is_warray :
+ return this->warray_to_server (test.u_array(),key);
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+interop::wunion *
+interop_WChar_Passer_i::wunion_from_server (CORBA::Short key,
+ interop::wchar_types type)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ interop::wunion *wu = new interop::wunion ();
+ switch (type) {
+ case interop::is_wchar :
+ wu->u_char (ref_.get_wchar(key));
+ break;
+ case interop::is_wstring :
+ wu->u_string (ref_.get_wstring(key));
+ break;
+ case interop::is_warray :
+ wu->u_array (ref_.get_warray(key));
+ break;
+ }
+ return wu;
+}
+
+
+CORBA::Boolean
+interop_WChar_Passer_i::any_to_server (const CORBA::Any &test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ CORBA::WChar wc;
+ const CORBA::WChar *ws;
+ CORBA::WString_var wstr;
+ interop::warray_forany forany;
+
+ if (test >>= CORBA::Any::to_wchar(wc))
+ {
+ return this->wchar_to_server(wc,key);
+ }
+ else if (test >>= ws)
+ {
+ return this->wstring_to_server (ws,key);
+ }
+ else if (test >>= forany)
+ {
+ return this->warray_to_server (forany.in(),key);
+ }
+ return 0;
+}
+
+CORBA::Any*
+interop_WChar_Passer_i::any_from_server (CORBA::Short key,
+ interop::wchar_types type)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ CORBA::Any *any = new CORBA::Any;
+ switch (type) {
+ case interop::is_wchar :
+ (*any) <<= CORBA::Any::from_wchar(ref_.get_wchar(key));
+ break;
+ case interop::is_wstring :
+ (*any) <<= ref_.get_wstring(key);
+ break;
+ case interop::is_warray :
+ {
+ interop::warray_forany forany(ref_.get_warray(key));
+ (*any) <<= forany.in();
+ break;
+ }
+ }
+ return any;
+}
+
+CORBA::Any *
+interop_WChar_Passer_i::any_echo (const CORBA::Any &test)
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ return new CORBA::Any (test);
+}
+
+void
+interop_WChar_Passer_i::exception_test ( CORBA::Short key )
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ interop::WChar_Passer::WStringException))
+{
+ interop::WChar_Passer::WStringException ex(ref_.get_except(key),
+ this->wchar_from_server(key));
+ throw ex;
+}
+
+void
+interop_WChar_Passer_i::shutdown ( )
+ ACE_THROW_SPEC (( CORBA::SystemException ))
+{
+ this->orb_->shutdown(0);
+}
diff --git a/TAO/interop-tests/wchar/interop_wchar_i.h b/TAO/interop-tests/wchar/interop_wchar_i.h
new file mode 100644
index 00000000000..ae8aecbade5
--- /dev/null
+++ b/TAO/interop-tests/wchar/interop_wchar_i.h
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+//
+// $Id$
+
+// **** Code generated by the The ACE ORB (TAO) IDL Compiler ****
+// TAO and the TAO IDL Compiler have been developed by:
+// Center for Distributed Object Computing
+// Washington University
+// St. Louis, MO
+// USA
+// http://www.cs.wustl.edu/~schmidt/doc-center.html
+// and
+// Distributed Object Computing Laboratory
+// University of California at Irvine
+// Irvine, CA
+// USA
+// http://doc.ece.uci.edu/
+//
+// Information about TAO is available at:
+// http://www.cs.wustl.edu/~schmidt/TAO.html
+
+// TAO_IDL - Generated from
+// be/be_codegen.cpp:923
+
+#ifndef INTEROP_WCHAR_I_H_
+#define INTEROP_WCHAR_I_H_
+
+#include "interop_wcharS.h"
+#include "wchar_reference.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+//Class interop_WChar_Passer_i
+class interop_WChar_Passer_i : public virtual POA_interop::WChar_Passer
+{
+public:
+ //Constructor
+ interop_WChar_Passer_i (CORBA::ORB_ptr o, int verbose);
+
+ //Destructor
+ virtual ~interop_WChar_Passer_i (void);
+
+ virtual char * orb_name (void)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean wchar_to_server ( CORBA::WChar test,
+ CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::WChar wchar_from_server ( CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean wstring_to_server ( const CORBA::WChar * test,
+ CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::WChar * wstring_from_server ( CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean warray_to_server (const interop::warray test,
+ CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual interop::warray_slice * warray_from_server ( CORBA::Short key )
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean wstruct_to_server (const interop::wstruct & test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual interop::wstruct * wstruct_from_server (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean wunion_to_server (const interop::wunion & test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual interop::wunion * wunion_from_server (CORBA::Short key,
+ interop::wchar_types type)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Boolean any_to_server (const CORBA::Any &test,
+ CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Any* any_from_server (CORBA::Short key,
+ interop::wchar_types type)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+ virtual CORBA::Any* any_echo (const CORBA::Any &test)
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+virtual void exception_test (CORBA::Short key)
+ ACE_THROW_SPEC (( CORBA::SystemException,
+ interop::WChar_Passer::WStringException ));
+
+virtual void shutdown ()
+ ACE_THROW_SPEC (( CORBA::SystemException ));
+
+private:
+ CORBA::ORB_var orb_;
+ wchar_reference ref_;
+
+};
+
+
+#endif /* INTEROP_WCHAR_I_H_ */
diff --git a/TAO/interop-tests/wchar/run_test.pl b/TAO/interop-tests/wchar/run_test.pl
new file mode 100755
index 00000000000..99cd6ccf720
--- /dev/null
+++ b/TAO/interop-tests/wchar/run_test.pl
@@ -0,0 +1,42 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../bin';
+use PerlACE::Run_Test;
+
+$iorfile = PerlACE::LocalFile ("server.ior");
+unlink $iorfile;
+$status = 0;
+
+$SV = new PerlACE::Process ("server", "-o $iorfile");
+$CL = new PerlACE::Process ("client", "-k file://$iorfile");
+
+$SV->Spawn ();
+
+if (PerlACE::waitforfile_timed ($iorfile, 5) == -1) {
+ print STDERR "ERROR: cannot find file <$iorfile>\n";
+ $SV->Kill (); $SV->TimedWait (1);
+ exit 1;
+}
+
+$client = $CL->SpawnWaitKill (300);
+
+if ($client != 0) {
+ print STDERR "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+$server = $SV->WaitKill (10);
+
+if ($server != 0) {
+ print STDERR "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/TAO/interop-tests/wchar/server.cpp b/TAO/interop-tests/wchar/server.cpp
new file mode 100644
index 00000000000..b89d797c497
--- /dev/null
+++ b/TAO/interop-tests/wchar/server.cpp
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// interop_test/wchar
+//
+// = FILENAME
+// server.cpp
+//
+// = DESCRIPTION
+// C++ server side for testing interoperability with wchar data.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+
+#include "interop_wchar_i.h"
+#include <ace/streams.h>
+#include <ace/Get_Opt.h>
+
+const char *ior_output_file = "IOR";
+int verbose = 0;
+
+int
+parse_args (int argc, char *argv[])
+{
+ ACE_Get_Opt get_opts (argc, argv, "o:v");
+ int c;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'o':
+ ior_output_file = get_opts.opt_arg ();
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case '?':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s "
+ "-o <iorfile> "
+ "-v "
+ "\n",
+ argv [0]),
+ -1);
+ }
+ // Indicates sucessful parsing of the command line
+ return 0;
+}
+
+int
+main( int argc, char *argv[] )
+{
+ if (parse_args(argc, argv))
+ ACE_ERROR_RETURN ((LM_ERROR, "failed to parse args\n"), 1);
+ try
+ {
+ // Initialize orb
+ CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
+
+ //Get reference to Root POA
+ CORBA::Object_var obj = orb->resolve_initial_references( "RootPOA" );
+ PortableServer::POA_var poa = PortableServer::POA::_narrow( obj.in() );
+
+ PortableServer::POAManager_var mgr = poa->the_POAManager();
+
+ // Activate POA Manager
+ mgr->activate();
+
+ // Create an object
+ interop_WChar_Passer_i servant(orb.in(), verbose);
+
+ // Register the servant with the RootPOA, obtain its object
+ // reference, stringify it, and write it to a file.
+ obj = poa->servant_to_reference( &servant );
+
+ CORBA::String_var str = orb->object_to_string( obj.in() );
+
+ if (parse_args(argc, argv))
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "failed to parse args"),
+ 1);
+ }
+
+ FILE *output_file= ACE_OS::fopen (ior_output_file, "w");
+ if (output_file == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open output file for writing IOR: %s",
+ ior_output_file),
+ 1);
+ ACE_OS::fprintf (output_file, "%s", str.in ());
+ ACE_OS::fclose (output_file);
+
+ // Accept requests
+ orb->run();
+ orb->destroy();
+ }
+
+ catch( const CORBA::Exception &ex ) {
+ ACE_PRINT_EXCEPTION(ex, "uncaught exception");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/TAO/interop-tests/wchar/wchar_reference.cpp b/TAO/interop-tests/wchar/wchar_reference.cpp
new file mode 100644
index 00000000000..5103b9e1526
--- /dev/null
+++ b/TAO/interop-tests/wchar/wchar_reference.cpp
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// interop_test/wchar
+//
+// = FILENAME
+// wchar_reference.cpp
+//
+// = DESCRIPTION
+// C++ reference data for testing interoperability with wchars. This is
+// linked into both clients and servers so that both sides have common
+// values for testing what is received or sent.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+#include "wchar_reference.h"
+#include <ace/Log_Msg.h>
+
+#if (defined ACE_HAS_WCHAR) || defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+
+ACE_OS::WChar
+wchar_reference::ref_wchar[NUM_KEYS] =
+ {1234};
+
+const ACE_OS::WChar *
+wchar_reference::ref_wstring[NUM_KEYS] =
+ {L"have a nice day"};
+
+ACE_OS::WChar
+wchar_reference::ref_warray[NUM_KEYS][10] =
+ { {L'a',L'A',L'!',L'1',L'4',L'[',L'?',L'%',L'X',L'E'} };
+
+const ACE_OS::WChar *
+wchar_reference::ref_except[NUM_KEYS] =
+ {L"TEST EXCEPTION"};
+
+wchar_reference::wchar_reference(int v)
+ : verbose_ (v)
+{
+}
+
+void
+wchar_reference::set_verbose(int v)
+{
+ this->verbose_ = v;
+}
+
+ACE_OS::WChar
+wchar_reference::get_wchar (short key)
+{
+ return wchar_reference::ref_wchar[key];
+}
+
+const ACE_OS::WChar *
+wchar_reference::get_wstring (short key)
+{
+ return wchar_reference::ref_wstring[key];
+}
+
+ACE_OS::WChar *
+wchar_reference::get_warray (short key)
+{
+ return wchar_reference::ref_warray[key];
+}
+
+void
+wchar_reference::assign_warray (short key,
+ ACE_OS::WChar *warray)
+{
+ ACE_OS::memcpy(warray,
+ wchar_reference::ref_warray[key],
+ 10*(sizeof(ACE_OS::WChar))
+ );
+}
+
+const ACE_OS::WChar *
+wchar_reference::get_except (short key)
+{
+ return wchar_reference::ref_except[key];
+}
+
+int
+wchar_reference::match_wchar (short key, ACE_OS::WChar test)
+{
+ if (verbose_)
+ ACE_DEBUG ((LM_DEBUG,"match_wchar, expecting %x, got %x for key %d\n",
+ wchar_reference::ref_wchar[key],test,key));
+ return wchar_reference::ref_wchar[key] == test;
+}
+
+int
+wchar_reference::match_wstring (short key, const ACE_OS::WChar *test)
+{
+ if (verbose_)
+ ACE_DEBUG ((LM_DEBUG,"match_wstring: expecting %W, got %W for key %d\n",
+ wchar_reference::ref_wstring[key],test,key));
+ return ACE_OS::strcmp(wchar_reference::ref_wstring[key],test) == 0;
+}
+
+int
+wchar_reference::match_warray (short key, const ACE_OS::WChar *test)
+{
+ if (verbose_)
+ ACE_DEBUG ((LM_DEBUG, "match_warray: key %d\n",key));
+ for (int i = 0; i < 10; i++)
+ {
+ if (verbose_)
+ ACE_DEBUG ((LM_DEBUG," expecting[%d] %x, got %x\n",
+ i, wchar_reference::ref_warray[key][i],
+ test[i]));
+ if (wchar_reference::ref_warray[key][i] != test[i])
+ return 0;
+ }
+ return 1;
+}
+
+int
+wchar_reference::match_except(short key, const ACE_OS::WChar *test)
+{
+ if (verbose_)
+ ACE_DEBUG ((LM_DEBUG,"match_except: expecting %W, got %W for key %d\n",
+ wchar_reference::ref_except[key],test,key));
+ return ACE_OS::strcmp(wchar_reference::ref_except[key],test) == 0;
+}
+
+#endif // ACE_HAS_WCHAR
diff --git a/TAO/interop-tests/wchar/wchar_reference.h b/TAO/interop-tests/wchar/wchar_reference.h
new file mode 100644
index 00000000000..289b25305c4
--- /dev/null
+++ b/TAO/interop-tests/wchar/wchar_reference.h
@@ -0,0 +1,57 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// interop_test/wchar
+//
+// = FILENAME
+// wchar_reference.cpp
+//
+// = DESCRIPTION
+// C++ reference data for testing interoperability with wchars. This is
+// linked into both clients and servers so that both sides have common
+// values for testing what is received or sent.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+#ifndef WCHAR_REFERENCE_H
+#define WCHAR_REFERENCE_H
+
+#include <ace/OS.h>
+
+#if (defined ACE_HAS_WCHAR) || defined (ACE_HAS_XPG4_MULTIBYTE_CHAR)
+
+#define NUM_KEYS 1
+
+class wchar_reference
+{
+ public:
+ wchar_reference (int v = 0);
+ void set_verbose (int v);
+ ACE_OS::WChar get_wchar (short key);
+ const ACE_OS::WChar *get_wstring (short key);
+ ACE_OS::WChar *get_warray (short key);
+ void assign_warray (short key, ACE_OS::WChar *warray);
+
+ const ACE_OS::WChar *get_except (short key);
+
+ int match_wchar (short key, ACE_OS::WChar test);
+ int match_wstring (short key, const ACE_OS::WChar* test);
+ int match_warray (short key, const ACE_OS::WChar *test);
+ int match_except (short key, const ACE_OS::WChar *test);
+
+ private:
+ static ACE_OS::WChar ref_wchar[NUM_KEYS];
+ static const ACE_OS::WChar *ref_wstring[NUM_KEYS];
+ static ACE_OS::WChar ref_warray[NUM_KEYS][10];
+ static const ACE_OS::WChar *ref_except[NUM_KEYS];
+
+ int verbose_;
+};
+
+#endif // ACE_HAS_WCHAR
+#endif // WCHAR_REFERENCE_H
diff --git a/TAO/tao/Codeset_Manager.cpp b/TAO/tao/Codeset_Manager.cpp
index fc100a7c326..5d1f4419aaf 100644
--- a/TAO/tao/Codeset_Manager.cpp
+++ b/TAO/tao/Codeset_Manager.cpp
@@ -11,7 +11,7 @@
#include "ace/Dynamic_Service.h"
#include "ace/Codeset_Registry.h"
#include "ace/OS_NS_string.h"
-
+#include "tao/UTF16_BOM_Factory.h"
ACE_RCSID (tao,
Codeset_Manager,
@@ -45,7 +45,8 @@ TAO_Codeset_Manager::default_wchar_codeset = TAO_DEFAULT_WCHAR_CODESET_ID;
TAO_Codeset_Manager::TAO_Codeset_Manager ()
: codeset_info_ (),
char_factories_ (),
- wchar_factories_ ()
+ wchar_factories_ (),
+ utf16_bom_translator_ (0)
{
this->codeset_info_.ForCharData.native_code_set =
TAO_Codeset_Manager::default_char_codeset;
@@ -76,6 +77,8 @@ TAO_Codeset_Manager::~TAO_Codeset_Manager ()
}
this->wchar_factories_.reset ();
+
+ delete this->utf16_bom_translator_;
}
void
@@ -113,7 +116,7 @@ TAO_Codeset_Manager::set_tcs (TAO_Profile &theProfile,
{
ACE_DEBUG ((LM_DEBUG,
ACE_LIB_TEXT ("TAO (%P|%t) - Codeset_Manager::set_tcs, ")
- ACE_LIB_TEXT ("No codeset componnet in profile\n")));
+ ACE_LIB_TEXT ("No codeset component in profile\n")));
}
remote.ForCharData.native_code_set =
@@ -121,31 +124,28 @@ TAO_Codeset_Manager::set_tcs (TAO_Profile &theProfile,
remote.ForWcharData.native_code_set =
TAO_Codeset_Manager::default_wchar_codeset;
}
-
- CONV_FRAME::CodeSetId tcs = computeTCS (remote.ForCharData,
- this->codeset_info_.ForCharData);
- if (TAO_debug_level > 2)
- {
- ACE_DEBUG ((LM_DEBUG,
- ACE_LIB_TEXT ("TAO (%P|%t) - Codeset_Manager::set_tcs, ")
- ACE_LIB_TEXT ("setting char translator(%08x)\n"),
- tcs));
- }
-
- trans.char_translator (this->get_char_trans (tcs));
-
- tcs = computeTCS (remote.ForWcharData,
- this->codeset_info_.ForWcharData);
-
- if (TAO_debug_level > 2)
- {
- ACE_DEBUG ((LM_DEBUG,
- ACE_LIB_TEXT ("TAO (%P|%t) - Codeset_Manager::set_tcs, ")
- ACE_LIB_TEXT ("setting wchar translator (%08x)\n"),
- tcs));
- }
-
- trans.wchar_translator (this->get_wchar_trans (tcs));
+ else
+ {
+ CONV_FRAME::CodeSetId tcs =
+ computeTCS (remote.ForCharData,
+ this->codeset_info_.ForCharData);
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT("TAO (%P|%t) - Codeset_Manager::set_tcs ")
+ ACE_LIB_TEXT("setting char translator(%08x)\n"),
+ tcs));
+ trans.char_translator(this->get_char_trans (tcs));
+
+ tcs = computeTCS (remote.ForWcharData,
+ this->codeset_info_.ForWcharData);
+
+ if (TAO_debug_level > 2)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT("TAO (%P|%t) - Codeset_Manager::set_tcs ")
+ ACE_LIB_TEXT("setting wchar translator (%08x)\n"),
+ tcs));
+ trans.wchar_translator(this->get_wchar_trans (tcs));
+ }
}
void
@@ -161,9 +161,9 @@ TAO_Codeset_Manager::process_service_context (TAO_ServerRequest &request)
TAO_Service_Context &service_cntx = request.request_service_context ();
IOP::ServiceContext context;
context.context_id = IOP::CodeSets;
+
CONV_FRAME::CodeSetId tcs_c = TAO_Codeset_Manager::default_char_codeset;
CONV_FRAME::CodeSetId tcs_w = TAO_Codeset_Manager::default_wchar_codeset;
-
if (service_cntx.get_context(context))
{
// Convert the Service Context to Codeset Context
@@ -180,7 +180,13 @@ TAO_Codeset_Manager::process_service_context (TAO_ServerRequest &request)
cdr >> tcs_w;
}
}
-
+ else
+ {
+ if (TAO_debug_level > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT("TAO (%P|%t) - Codeset_Manager::process_service_context ")
+ ACE_LIB_TEXT("no codeset context in request, inferring TAO backwards compatibility\n")));
+ }
if (TAO_debug_level > 2)
{
ACE_DEBUG ((LM_DEBUG,
@@ -447,7 +453,19 @@ TAO_Codeset_Manager::get_char_trans (CONV_FRAME::CodeSetId tcs)
{
if (this->codeset_info_.ForCharData.native_code_set == tcs)
{
- return 0;
+ if (tcs != ACE_CODESET_ID_ISO_UTF_16)
+ return 0;
+ else
+ {
+ if (this->utf16_bom_translator_ == 0)
+ {
+ ACE_NEW_RETURN (this->utf16_bom_translator_,
+ UTF16_BOM_Factory,
+ 0);
+ this->utf16_bom_translator_->init(0,0);
+ }
+ return this->utf16_bom_translator_;
+ }
}
return this->get_translator_i (this->char_factories_,tcs);
diff --git a/TAO/tao/Codeset_Manager.h b/TAO/tao/Codeset_Manager.h
index 479e707a75a..24da96db154 100644
--- a/TAO/tao/Codeset_Manager.h
+++ b/TAO/tao/Codeset_Manager.h
@@ -25,6 +25,8 @@
#include "ace/Unbounded_Set.h"
+class ACE_WChar_Codeset_Translator;
+
class TAO_Profile;
class TAO_Transport;
class TAO_Operation_Details;
@@ -205,6 +207,13 @@ private:
// The lists of available translators for both chars and wchars.
TAO_CodesetFactorySet char_factories_;
TAO_CodesetFactorySet wchar_factories_;
+
+ // The UTF16 BOM (Byte Order Marker) translator is unique in that it is
+ // required when UTF16 is used as both the native and transmitted codeset.
+ // It exists to insert or extract the BOM preceeding Wchar data in the
+ // stream.
+ TAO_Codeset_Translator_Factory *utf16_bom_translator_;
+
};
#include /**/ "ace/post.h"
diff --git a/TAO/tao/UTF16_BOM_Factory.cpp b/TAO/tao/UTF16_BOM_Factory.cpp
new file mode 100644
index 00000000000..3330fcfaeac
--- /dev/null
+++ b/TAO/tao/UTF16_BOM_Factory.cpp
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tao
+//
+// = FILENAME
+// UTF16_BOM_Factory.cpp
+//
+// = DESCRIPTION
+// Loader for an instance of the UTF16_BOM_Translator.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+
+#include "UTF16_BOM_Factory.h"
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class TAO_Codeset_Translator_Factory_T<UTF16_BOM_Translator>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate TAO_Codeset_Translator_Factory_T<UTF16_BOM_Translator>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
+
+ACE_STATIC_SVC_DEFINE (UTF16_BOM_Factory,
+ ACE_TEXT ("UTF16_BOM_Factory"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (UTF16_BOM_Factory),
+ ACE_Service_Type::DELETE_THIS
+ | ACE_Service_Type::DELETE_OBJ,
+ 0)
+ACE_FACTORY_DEFINE (TAO, UTF16_BOM_Factory)
diff --git a/TAO/tao/UTF16_BOM_Factory.h b/TAO/tao/UTF16_BOM_Factory.h
new file mode 100644
index 00000000000..5e8fad0e10f
--- /dev/null
+++ b/TAO/tao/UTF16_BOM_Factory.h
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO
+//
+// = FILENAME
+// UTF16_BOM_Factory.h
+//
+// = DESCRIPTION
+// Loader for an instance of the UTF16_BOM_Translator.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+
+#ifndef UTF16_BOM_FACTORY_H
+#define UTF16_BOM_FACTORY_H
+
+#include <ace/pre.h>
+#include <ace/Service_Config.h>
+#include <tao/Codeset_Translator_Factory.h>
+
+#include "UTF16_BOM_Translator.h"
+
+typedef TAO_Export TAO_Codeset_Translator_Factory_T<UTF16_BOM_Translator> UTF16_BOM_Factory;
+
+ACE_STATIC_SVC_DECLARE_EXPORT (TAO, UTF16_BOM_Factory)
+ACE_FACTORY_DECLARE (TAO, UTF16_BOM_Factory)
+
+#include <ace/post.h>
+#endif /* UTF16_BOM_FACTORY_H */
diff --git a/TAO/tao/UTF16_BOM_Translator.cpp b/TAO/tao/UTF16_BOM_Translator.cpp
new file mode 100644
index 00000000000..12a5ef44ac3
--- /dev/null
+++ b/TAO/tao/UTF16_BOM_Translator.cpp
@@ -0,0 +1,369 @@
+// -*- C++ -*-
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tao
+//
+// = FILENAME
+// UTF16_BOM_Translator.cpp
+//
+// = DESCRIPTION
+// Manages the transformation between native and transmitted UTF-16. It is
+// Required because transmitted UTF-16 may carry a byte order marker (BOM)
+// that is not part of the data contents. If no BOM is present, then the
+// serialized UTF-16 data is big-endian, regardless of the byte order of
+// the containing encapsulation.
+//
+// = AUTHOR
+// Phil Mesnier <mesnier_p@ociweb.com>
+//
+// ============================================================================
+
+#include "UTF16_BOM_Translator.h"
+#include "ace/OS_Memory.h"
+
+// ****************************************************************
+
+
+typedef ACE_CDR::UShort ACE_UTF16_T;
+static const size_t ACE_UTF16_CODEPOINT_SIZE = sizeof(ACE_UTF16_T);
+static const unsigned short ACE_UNICODE_BOM_CORRECT = 0xFEFFU;
+static const unsigned short ACE_UNICODE_BOM_SWAPPED = 0xFFFEU;
+
+/////////////////////////////
+// UTF16_BOM_Translator implementation
+
+UTF16_BOM_Translator::UTF16_BOM_Translator (void)
+{
+
+}
+
+UTF16_BOM_Translator::~UTF16_BOM_Translator (void)
+{
+
+}
+
+// = Documented in $ACE_ROOT/ace/CDR_Stream.h
+ACE_CDR::Boolean
+UTF16_BOM_Translator::read_wchar (ACE_InputCDR &cdr, ACE_CDR::WChar &x)
+{
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1 &&
+ ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 2)
+ {
+ ACE_CDR::Octet len;
+ if (! this->read_1 (cdr, &len))
+ return 0;
+
+ if (len == 2) // no BOM present
+ {
+ ACE_CDR::Short sx;
+
+ if (!this->read_array (cdr,
+ ACE_reinterpret_cast (char *,&sx),1,1,2))
+ return 0;
+
+#if defined (ACE_LITTLE_ENDIAN)
+ ACE_CDR::Short ux;
+ ACE_CDR::swap_2 (ACE_reinterpret_cast (const char*,&sx),
+ ACE_reinterpret_cast(char *,&ux));
+ x = ACE_static_cast (ACE_CDR::WChar, ux);
+#else
+ x = ACE_static_cast(ACE_CDR::WChar, sx);
+#endif // ACE_LITTLE_ENDIAN
+ return 1;
+ }
+
+ ACE_UTF16_T buf[2];
+ if (len != 4 || !this->read_array (cdr,
+ ACE_reinterpret_cast(char *,buf),
+ 1,1,4)) // get BO & payload
+ return 0;
+ // Check for byte order mark, if found, consume and honor it.
+ if (buf[0] == ACE_UNICODE_BOM_CORRECT ||
+ buf[0] == ACE_UNICODE_BOM_SWAPPED)
+ {
+ // if we found it, but it came in in the wrong order
+ // invert the byte order flag for the duration of this method
+ if (buf[0] == ACE_UNICODE_BOM_SWAPPED)
+ {
+ ACE_CDR::Short ux;
+ ACE_CDR::swap_2 (ACE_reinterpret_cast (const char*,&buf[1]),
+ ACE_reinterpret_cast(char *,&ux));
+ x = ACE_static_cast (ACE_CDR::WChar, ux);
+ }
+ else
+ x = ACE_static_cast(ACE_CDR::WChar, buf[1]);
+ return 1;
+ }
+ // What do we do here? The length is > 2 but the first word
+ // is not a BOM. Just return an error I suppose
+ return 0;
+ }
+
+ ACE_UTF16_T sx;
+ if (this->read_2 (cdr, &sx))
+ {
+ x = ACE_static_cast(ACE_CDR::WChar, sx);
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::read_wstring (ACE_InputCDR &cdr,
+ ACE_CDR::WChar *&x)
+{
+ ACE_CDR::ULong len;
+ if (!this->read_4 (cdr, &len))
+ return 0;
+
+ // A check for the length being too great is done later in the
+ // call to read_char_array but we want to have it done before
+ // the memory is allocated.
+ if (len > 0 && len <= cdr.length())
+ {
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
+ {
+ len /= ACE_UTF16_CODEPOINT_SIZE;
+
+ //allocating one extra for the null character needed by applications
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len + 1],
+ 0);
+
+ x[len] = L'\x00';
+ if (this->read_wchar_array_i (cdr, x, len,1))
+ {
+ // Since reading the array may have adjusted the length,
+ // we simply rewrite the null terminator
+ x[len] = L'\x00';
+ return 1;
+ }
+ }
+ else
+ {
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar [len],
+ 0);
+ if (this->read_wchar_array (cdr, x, len))
+ return 1;
+ }
+ delete [] x;
+ }
+ else if (len == 0)
+ {
+ // Convert any null strings to empty strings since empty
+ // strings can cause crashes. (See bug 58.)
+ ACE_NEW_RETURN (x,
+ ACE_CDR::WChar[1],
+ 0);
+ x[0] = '\x00';
+ return 1;
+ }
+ x = 0;
+ return 0;
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::read_wchar_array_i (ACE_InputCDR & cdr,
+ ACE_CDR::WChar *x,
+ ACE_CDR::ULong &length,
+ int adjust_len)
+{
+ int has_bom = 0;
+ int must_swap = 0;
+ char* buf;
+ size_t align = ACE_CDR::SHORT_ALIGN;
+ if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * length, align, buf) == 0)
+ {
+ // check for byte order mark. If found, honor it then discard it
+ ACE_UTF16_T *sb = ACE_reinterpret_cast(ACE_UTF16_T *, buf);
+ if (*sb == ACE_UNICODE_BOM_CORRECT || *sb == ACE_UNICODE_BOM_SWAPPED)
+ {
+ must_swap = (*sb == ACE_UNICODE_BOM_SWAPPED);
+ has_bom = 1;
+ }
+ else
+ {
+#if defined (ACE_LITTLE_ENDIAN)
+ must_swap = 1;
+#endif // ACE_LITTLE_ENDIAN
+ }
+
+ if (has_bom)
+ {
+ buf += ACE_UTF16_CODEPOINT_SIZE;
+ sb++;
+ if (adjust_len)
+ length -= 1;
+ }
+
+ for (size_t i = 0; i < length; i++)
+#if defined (ACE_DISABLE_SWAP_ON_READ)
+ x[i] = ACE_static_cast (ACE_CDR::WChar, sb[i]);
+#else
+ if (!must_swap)
+ {
+ x[i] = ACE_static_cast (ACE_CDR::WChar, sb[i]);
+ }
+ else
+ {
+ ACE_CDR::UShort sx;
+ ACE_CDR::swap_2 (&buf[i*2], ACE_reinterpret_cast(char *,&sx));
+ x[i] = ACE_static_cast (ACE_CDR::WChar,sx);
+ }
+#endif /* ACE_DISABLE_SWAP_ON_READ */
+
+ if (has_bom && !adjust_len)
+ {
+ cdr.adjust (ACE_UTF16_CODEPOINT_SIZE, align, buf);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::read_wchar_array (ACE_InputCDR & cdr,
+ ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return 1;
+
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
+ {
+ for (size_t i = 0; i < length; i++)
+ if (!this->read_wchar(cdr,x[i]))
+ return 0;
+ return 1;
+ }
+ else
+ return this->read_wchar_array_i(cdr,x,length);
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::write_wchar (ACE_OutputCDR &cdr,
+ ACE_CDR::WChar x)
+{
+ return this->write_wchar_i (cdr,x,1);
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::write_wchar_i (ACE_OutputCDR &cdr,
+ ACE_CDR::WChar x,
+ int use_BOM)
+{
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
+ {
+ int len = 0;
+ ACE_CDR::UShort buffer[2];
+ if (use_BOM)
+ {
+ len = 2;
+ buffer[0] = ACE_UNICODE_BOM_CORRECT;
+ buffer[1] = ACE_static_cast(ACE_CDR::Short,x);
+ }
+ else
+ {
+ len = 1;
+ if (cdr.byte_order())
+ ACE_CDR::swap_2 (ACE_reinterpret_cast (const char *,&x),
+ ACE_reinterpret_cast (char *,buffer));
+ else
+ buffer[0] = ACE_static_cast(ACE_CDR::Short,x);
+ }
+ unsigned char tcsize = ACE_static_cast (unsigned char,
+ len * ACE_UTF16_CODEPOINT_SIZE);
+ if (this->write_1 (cdr, &tcsize))
+ return this->write_array(cdr, &buffer, tcsize, 1, 1);
+ else
+ return 0;
+ }
+ else if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) != 0)
+ {
+ // GIOP 1.1 simple support
+ ACE_UTF16_T sx = ACE_static_cast (ACE_UTF16_T, x);
+ return this->write_2 (cdr, &sx);
+ }
+ else
+ { // wchar is not allowed with GIOP 1.0.
+ errno = EINVAL;
+ return 0;
+ }
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::write_wstring (ACE_OutputCDR & cdr,
+ ACE_CDR::ULong len,
+ const ACE_CDR::WChar *x)
+{
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
+ {
+ ACE_CDR::ULong l = (len+1) * ACE_UTF16_CODEPOINT_SIZE;
+ if (this->write_4 (cdr, &l) &&
+ this->write_2 (cdr, &ACE_UNICODE_BOM_CORRECT) &&
+ x != 0)
+ return this->write_wchar_array_i (cdr, x, len);
+ }
+ else
+ {
+ ACE_CDR::ULong l = len + 1;
+ if (this->write_4 (cdr, &l))
+ if (x != 0)
+ return this->write_wchar_array_i (cdr, x, len + 1);
+ else
+ {
+ ACE_UTF16_T s = 0;
+ return this->write_2 (cdr,&s);
+ }
+ }
+ return 0;
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::write_wchar_array (ACE_OutputCDR & cdr,
+ const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
+{
+ if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
+ {
+ for (size_t i = 0; i < length; i++)
+ if (this->write_wchar_i (cdr,x[i]) == 0)
+ return 0;
+ return 1;
+ }
+ return this->write_wchar_array_i (cdr, x, length);
+}
+
+ACE_CDR::Boolean
+UTF16_BOM_Translator::write_wchar_array_i (ACE_OutputCDR & cdr,
+ const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
+{
+ if (length == 0)
+ return 1;
+ char* buf;
+ size_t align = ACE_CDR::SHORT_ALIGN;
+ if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * length, align, buf)
+ != 0)
+ {
+ return 0;
+ }
+
+ ACE_UTF16_T *sb = ACE_reinterpret_cast(ACE_UTF16_T *, buf);
+
+ for (size_t i = 0; i < length; i++)
+ {
+ sb[i] = ACE_static_cast (ACE_UTF16_T,x[i]);
+ }
+ return 1;
+
+}
diff --git a/TAO/tao/UTF16_BOM_Translator.h b/TAO/tao/UTF16_BOM_Translator.h
new file mode 100644
index 00000000000..1be88977e07
--- /dev/null
+++ b/TAO/tao/UTF16_BOM_Translator.h
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Wchar_UCS4_UTC16_Translator.h
+ *
+ * $Id$
+ *
+ *
+ *
+ * @author Phil Mesnier <mesnier_p@ociweb.com>
+ */
+//=============================================================================
+
+#ifndef UTF16_BOM_TRANSLATOR_H
+#define UTF16_BOM_TRANSLATOR_H
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/CDR_Stream.h"
+#include "TAO_Export.h"
+
+// ****************************************************************
+
+/**
+ * @class UTF16_BOM_Translator
+ *
+ * @brief Codeset translation specialization.
+ *
+ * This class performs the codeset translation:
+ * - Native: UTF16 (i.e. Unicode)
+ * - Stream: UTF16 with Byte Order Marker
+ */
+class TAO_Export UTF16_BOM_Translator : public ACE_WChar_Codeset_Translator
+{
+public:
+ /// A do nothing constructor.
+ UTF16_BOM_Translator (void);
+
+ /// Virtual destruction
+ virtual ~UTF16_BOM_Translator (void);
+
+ // = Documented in $ACE_ROOT/ace/CDR_Stream.h
+ virtual ACE_CDR::Boolean read_wchar (ACE_InputCDR &,
+ ACE_CDR::WChar &);
+ virtual ACE_CDR::Boolean read_wstring (ACE_InputCDR &,
+ ACE_CDR::WChar *&);
+ virtual ACE_CDR::Boolean read_wchar_array (ACE_InputCDR &,
+ ACE_CDR::WChar *,
+ ACE_CDR::ULong);
+ virtual ACE_CDR::Boolean write_wchar (ACE_OutputCDR &,
+ ACE_CDR::WChar);
+ virtual ACE_CDR::Boolean write_wstring (ACE_OutputCDR &,
+ ACE_CDR::ULong,
+ const ACE_CDR::WChar *);
+ virtual ACE_CDR::Boolean write_wchar_array (ACE_OutputCDR &,
+ const ACE_CDR::WChar *,
+ ACE_CDR::ULong);
+ virtual ACE_CDR::ULong ncs () {return 0x00010109;}
+ virtual ACE_CDR::ULong tcs () {return 0x00010109;}
+
+private:
+ ACE_CDR::Boolean read_wchar_array_i (ACE_InputCDR &,
+ ACE_CDR::WChar *,
+ ACE_CDR::ULong&,
+ int adjust_len = 0);
+
+ ACE_CDR::Boolean write_wchar_array_i (ACE_OutputCDR &,
+ const ACE_CDR::WChar *,
+ ACE_CDR::ULong);
+
+ ACE_CDR::Boolean write_wchar_i (ACE_OutputCDR &,
+ ACE_CDR::WChar ,
+ int use_BOM = 0);
+
+
+};
+
+#include "ace/post.h"
+#endif /* UTF16_BOM_TRANSLATOR_H */
diff --git a/TAO/tao/tao.mpc b/TAO/tao/tao.mpc
index b01056aeeeb..5a78cb71a06 100644
--- a/TAO/tao/tao.mpc
+++ b/TAO/tao/tao.mpc
@@ -151,6 +151,8 @@ project(TAO) : acelib, taoversion, core, tao_output, taodefaults, extra_core {
UShortSeqC.cpp
Codeset_Manager.cpp
Codeset_Translator_Factory.cpp
+ UTF16_BOM_Translator.cpp
+ UTF16_BOM_Factory.cpp
ORB_Core.cpp
ORB_Core_Auto_Ptr.cpp
Collocation_Resolver.cpp
diff --git a/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.cpp b/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.cpp
index 2508e98eb6b..9e34dac66e6 100644
--- a/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.cpp
+++ b/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.cpp
@@ -10,17 +10,8 @@
// WUCS4_UTF16.cpp
//
// = DESCRIPTION
-// Defines the actions required to convert between UCS-4, a 4 byte wide char
-// codeset as the native wchar codeset, and UCS-16, aka unicode, a 2-byte
-// codeset for the transport wchar codeset.
-//
-// This translator does not alter any codepoint values, but it does
-// illustrate how to deal with the unicode byte order marker (BOM) and how
-// to deal with codepoint size differences.
-//
-// Note that the BOM is an optional value. The write_*() methods do not
-// encode this value. When BOM is not encoded, the byte order of the
-// encapsulation is used.
+// Defines the arrays required to convert between UCS-4 a 4 byte wide char
+// codeset, and UCS-16, aka unicode, a 2-byte codeset.
//
// = AUTHOR
// Phil Mesnier <mesnier_p@ociweb.com>
@@ -28,14 +19,202 @@
// ============================================================================
#include "WUCS4_UTF16.h"
-#include "ace/OS_Memory.h"
ACE_RCSID(UCS4_UTF16, WUCS4_UTF16, "$Id$")
// ****************************************************************
+
+// @@ TODO: Find a better home for these definition
+// Note: unlike the UNICODE standard we define these as
+// half-closed ranges i.e.
+// *BEGIN is the first value in the range
+// *END is the first value beyond the range (END is not included
+// in the range)
+// Note the use of unsigned short for UTF-16 codepoints. wchar_t may
+// by four bytes
+typedef ACE_CDR::UShort ACE_UTF16_T;
+static const size_t ACE_UTF16_CODEPOINT_SIZE = sizeof(ACE_UTF16_T);
+
+// surrogate high 1101.10HH.HHHH.HHHH
+// surrogate low 1101.11LL.LLLL.LLLL
+// 4 byte result: 0000.0000.0000.HHHH.HHHH.HHLL.LLLL.LLLL
+// add offset 0000.0000.0000.0000.0001.0000.0000.0000
+
+// range of surrogate values for high-order bits
+static const unsigned short ACE_UTF16_SURROGATE_HIGH_BEGIN = 0xD800U;
+static const unsigned short ACE_UTF16_SURROGATE_HIGH_END = 0xDC00U;
+
+static const unsigned short ACE_UTF16_SURROGATE_LOW_BEGIN = 0xDC00U;
+static const unsigned short ACE_UTF16_SURROGATE_LOW_END = 0xE000U;
+
+// offset to UTF16 values encoded with surrogates start at 2^16
+static const unsigned long ACE_UTF16_SURROGATE_OFFSET = 0x000010000UL;
+
+// shift high order bits from surrogate into correct postion
+static const int ACE_UTF16_SURROGATE_HIGH_SHIFT = 10;
+static const unsigned short ACE_UTF16_SURROGATE_LOW_MASK = 0x3FF;
+
+// largest value that can be represented in UTF16 without using surrogates + 1
+static const unsigned long ACE_UTF16_RAW_END = 0x00010000LU;
+
+// largest value that can be represented in UTF16 + 1
+static const unsigned long ACE_UTF16_END = 0x00110000LU;
+
+// largest value that can be represented in UTF-32 + 1
+static const unsigned long ACE_UTF32_END = 0x80000000LU;
+
+static const unsigned short ACE_UNICODE_SUBSTITUTE_CHARACTER = 0xFFFDU;
+static const unsigned short ACE_UNICODE_BOM_CORRECT = 0xFEFFU;
+static const unsigned short ACE_UNICODE_BOM_SWAPPED = 0xFFFEU;
+
+/////////////////////////////////////////////////////
+// Static inline routines to simplify conversion code
+// @@ should be in anonymous namespace when ACE allows it
+// or better yet, there should be a UTF-16 support thingie(technical term)
+// that provides these methods.
+// Performance: depends on compiler inlining + optimization for performance
+
+/// load next two bytes from buffer into a short. Byte swapping as necessary
+static
+ACE_INLINE
+ACE_UTF16_T
+load_raw_wchar (const char * buffer, size_t & pos, int do_byte_swap)
+{
+ // need a two byte object to load the UTF16 2 byte codepoint
+ ACE_UTF16_T utf16_char = * ACE_reinterpret_cast (ACE_UTF16_T const *,
+ &buffer[pos*ACE_UTF16_CODEPOINT_SIZE]);
+#if ! defined (ACE_DISABLE_SWAP_ON_READ)
+ if (do_byte_swap)
+ {
+ ACE_CDR::swap_2 (
+ &buffer[pos*ACE_UTF16_CODEPOINT_SIZE],
+ ACE_reinterpret_cast(char *,&utf16_char));
+ }
+#endif
+ pos ++;
+ return utf16_char;
+}
+
+/// convert UTF-16 surrogate pair to wchar_t
+static
+ACE_INLINE
+ACE_CDR::WChar
+convert_surrogate_pair (ACE_UTF16_T high, ACE_UTF16_T low)
+{
+ return ACE_static_cast (ACE_CDR::WChar,
+ ((high - ACE_UTF16_SURROGATE_HIGH_BEGIN) << ACE_UTF16_SURROGATE_HIGH_SHIFT)
+ + (low - ACE_UTF16_SURROGATE_LOW_BEGIN)
+ + ACE_UTF16_SURROGATE_OFFSET
+ );
+}
+
+/// load wchar from utf16 buffer
+/// converts surrogate pairs
+/// substitutes SUBSTITUTE_CHAR for bad encoding
+static
+ACE_INLINE
+ACE_CDR::WChar
+load_wchar (const char * buffer, size_t & pos, size_t length, int do_byte_swap)
+{
+ ACE_CDR::WChar rc = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ if (pos < length)
+ {
+ rc = ACE_static_cast (ACE_CDR::WChar, load_raw_wchar (buffer, pos, do_byte_swap));
+ // Is this a UTF16 surrogate?
+ // note assumpton that SURROGATE_HIGH_END == SURROGATE_LOW_BEGIN
+ if (rc >= ACE_UTF16_SURROGATE_HIGH_BEGIN && rc < ACE_UTF16_SURROGATE_LOW_END)
+ {
+ // if we still have two bytes available
+ if (pos < length)
+ {
+ // expecting high surrogate
+ if (rc < ACE_UTF16_SURROGATE_HIGH_END)
+ {
+ ACE_UTF16_T low = load_raw_wchar (buffer, pos, do_byte_swap);
+ if (low >= ACE_UTF16_SURROGATE_LOW_BEGIN
+ && low < ACE_UTF16_SURROGATE_LOW_END)
+ {
+ rc = convert_surrogate_pair (
+ ACE_static_cast (ACE_UTF16_T, rc), low);
+ }
+ else
+ {
+ rc = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ }
+ }
+ else
+ {
+ rc = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ }
+ }
+ else
+ {
+ rc = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ }
+ }
+ }
+ return rc;
+}
+
+static
+ACE_INLINE
+size_t encode_utf16 (ACE_UTF16_T * buffer, ACE_CDR::WChar value)
+{
+ buffer[0] = ACE_static_cast (ACE_UTF16_T, value);
+ size_t length = 1;
+ if (value >= ACE_UTF16_SURROGATE_HIGH_BEGIN)
+ {
+ if (value < ACE_UTF16_SURROGATE_LOW_END)
+ {
+ buffer[0] = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ }
+ else if ((unsigned long)value >= ACE_UTF16_RAW_END)
+ {
+ if ((unsigned long)value >= ACE_UTF16_END)
+ {
+ buffer[0] = ACE_UNICODE_SUBSTITUTE_CHARACTER;
+ }
+ else
+ {
+ ACE_CDR::WChar offset = ACE_static_cast (ACE_CDR::WChar,
+ value - ACE_UTF16_SURROGATE_OFFSET);
+ buffer[0] = (offset >> ACE_UTF16_SURROGATE_HIGH_SHIFT)
+ + ACE_UTF16_SURROGATE_HIGH_BEGIN;
+ buffer[1] = (offset & ACE_UTF16_SURROGATE_LOW_MASK)
+ + ACE_UTF16_SURROGATE_LOW_BEGIN;
+ length = 2;
+ }
+ }
+ }
+ return length;
+}
+
+/// count number of characters in native WString that will be converted
+/// to UTF-16 surrogate pairs
+static
+size_t count_potential_surrogates (
+ const ACE_CDR::WChar *buffer,
+ ACE_CDR::ULong len)
+{
+ size_t count = 0;
+ for (size_t i = 0; i < len; ++i)
+ {
+ ACE_CDR::WChar value = buffer[i];
+ if ((unsigned long)value >= ACE_UTF16_RAW_END &&
+ (unsigned long)value < ACE_UTF16_END)
+ {
+ count += 1;
+ }
+ }
+ return count;
+}
+
+
+/////////////////////////////
+// WUCS4_UTF16 implementation
+
WUCS4_UTF16::WUCS4_UTF16 (void)
- : tcs_size_ (2)
{
}
@@ -49,31 +228,75 @@ WUCS4_UTF16::~WUCS4_UTF16 (void)
ACE_CDR::Boolean
WUCS4_UTF16::read_wchar (ACE_InputCDR &cdr, ACE_CDR::WChar &x)
{
- ACE_CDR::UShort sx = 0;
if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
- && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 2)
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
{
ACE_CDR::Octet len;
- if (!this->read_1 (cdr, &len))
- return 0;
+ if (! this->read_1 (cdr, &len))
+ {
+ return 0;
+ }
+
+ int old_bo = cdr.byte_order();
+
+ ACE_UTF16_T sx = 0;
if (! this->read_2 (cdr,&sx))
- return 0;
- // We need to consume the optional byte-order-marker
- if (sx == 0xFEFE || sx == 0xFFFE)
{
- int old_bo = cdr.byte_order();
- cdr.reset_byte_order (sx == 0xFFFE);
+ return 0;
+ }
+
+ // Check for byte order mark, if found, consume and honor it.
+ if (sx == ACE_UNICODE_BOM_CORRECT || sx == ACE_UNICODE_BOM_SWAPPED)
+ {
+ // if we found it, but it came in in the wrong order
+ // invert the byte order flag for the duration of this method
+ if (sx == ACE_UNICODE_BOM_SWAPPED)
+ {
+ cdr.reset_byte_order (! old_bo);
+ }
this->read_2 (cdr,&sx);
- cdr.reset_byte_order (old_bo);
- return 1;
}
+
+ // check for UTF-16 surrogate pair, and if found interpret it
+ if (sx >= ACE_UTF16_SURROGATE_HIGH_BEGIN
+ && sx < ACE_UTF16_SURROGATE_LOW_END)
+ {
+ if (sx >= ACE_UTF16_SURROGATE_HIGH_END)
+ {
+ cdr.reset_byte_order (old_bo);
+ return 0;
+ }
+
+ ACE_UTF16_T low;
+ if (! this->read_2 (cdr, &low))
+ {
+ cdr.reset_byte_order (old_bo);
+ return 0;;
+ }
+ if (low < ACE_UTF16_SURROGATE_LOW_BEGIN
+ || low >= ACE_UTF16_SURROGATE_LOW_END)
+ {
+ cdr.reset_byte_order (old_bo);
+ return 0;
+ }
+ x = convert_surrogate_pair (sx, low);
+ }
+ else
+ {
+ x = ACE_static_cast(ACE_CDR::WChar, sx);
+ }
+
+ cdr.reset_byte_order (old_bo);
}
else
{
+ ACE_UTF16_T sx = 0;
if (!this->read_2 (cdr, &sx))
- return 0;
+ {
+ return 0;
+ }
+ x = ACE_static_cast(ACE_CDR::WChar, sx);
}
- x = ACE_static_cast(ACE_CDR::WChar, sx);
return 1;
}
@@ -91,20 +314,20 @@ WUCS4_UTF16::read_wstring (ACE_InputCDR &cdr,
if (len > 0 && len <= cdr.length())
{
if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
- && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 2)
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
{
- len /= this->tcs_size_;
+ len /= ACE_UTF16_CODEPOINT_SIZE;
//allocating one extra for the null character needed by applications
ACE_NEW_RETURN (x,
ACE_CDR::WChar [len + 1],
0);
- if (this->read_wchar_array (cdr, x, len))
+ x[len] = L'\x00';
+ if (this->read_wchar_array_i (cdr, x, len,1))
{
- //Null character used by applications to find the end of
- //the wstring
- //Is this okay with the GIOP 1.2 spec??
- x[len] = '\x00';
+ // Since reading the array may have adjusted the length,
+ // we simply rewrite the null terminator
+ x[len] = L'\x00';
return 1;
}
}
@@ -133,118 +356,235 @@ WUCS4_UTF16::read_wstring (ACE_InputCDR &cdr,
}
ACE_CDR::Boolean
-WUCS4_UTF16::read_wchar_array (ACE_InputCDR & cdr,
- ACE_CDR::WChar *x,
- ACE_CDR::ULong length)
+WUCS4_UTF16::read_wchar_array_i (ACE_InputCDR & cdr,
+ ACE_CDR::WChar *x,
+ ACE_CDR::ULong &length,
+ int adjust_len)
{
if (length == 0)
return 1;
char* buf;
size_t align = ACE_CDR::SHORT_ALIGN;
- if (cdr.adjust (this->tcs_size_ * length, align, buf) == 0)
+ if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * length, align, buf) == 0)
{
- ACE_CDR::UShort *sb = ACE_reinterpret_cast(ACE_CDR::UShort *, buf);
- int old_bo = cdr.byte_order();
- if (*sb == 0xFEFE || *sb == 0xFFFE)
+ int byte_swap = cdr.do_byte_swap();
+ size_t pos = 0;
+
+ // check for byte order mark. If found, honor it then discard it
+ ACE_UTF16_T bom = load_raw_wchar (buf, pos, byte_swap);
+ if (bom == ACE_UNICODE_BOM_CORRECT || bom == ACE_UNICODE_BOM_SWAPPED)
{
- cdr.reset_byte_order (*sb == 0xFFFE);
- sb ++;
- length --;
+ if (bom == ACE_UNICODE_BOM_SWAPPED)
+ {
+ byte_swap = !byte_swap;
+ }
+ buf += ACE_UTF16_CODEPOINT_SIZE;
+ if (adjust_len)
+ length -= 1;
}
- for (size_t i = 0; i < length; i++)
-#if defined (ACE_DISABLE_SWAP_ON_READ)
- x[i] = ACE_static_cast (ACE_CDR::WChar, sb[i]);
-#else
- if (!cdr.do_byte_swap ())
- x[i] = ACE_static_cast (ACE_CDR::WChar, sb[i]);
- else
+ size_t bpos = 0;
+ for (size_t xpos = 0; xpos < length; ++xpos)
{
- ACE_CDR::UShort sx;
- ACE_CDR::swap_2 (&buf[i*2], ACE_reinterpret_cast(char *,&sx));
- x[i] = ACE_static_cast (ACE_CDR::WChar,sx);
+ x[xpos] = load_wchar (buf, bpos, length, byte_swap);
}
-#endif /* ACE_DISABLE_SWAP_ON_READ */
- cdr.reset_byte_order (old_bo);
return 1;
}
return 0;
+
}
+
ACE_CDR::Boolean
-WUCS4_UTF16::write_wchar (ACE_OutputCDR &cdr,
- ACE_CDR::WChar x)
+WUCS4_UTF16::read_wchar_array (ACE_InputCDR & cdr,
+ ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
{
- ACE_CDR::UShort sx = ACE_static_cast(ACE_CDR::Short,x);
+ if (length == 0)
+ return 1;
+
if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
- && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 2)
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
{
- if (this->write_1 (cdr, &this->tcs_size_))
- return this->write_array(cdr, &sx, this->tcs_size_, ACE_CDR::SHORT_ALIGN, 1);
- else
- return 0;
+ for (size_t i = 0; i < length; i++)
+ if (!this->read_wchar(cdr,x[i]))
+ return 0;
+ return 1;
}
- else if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 0)
- { // wchar is not allowed with GIOP 1.0.
+ else
+ return this->read_wchar_array_i(cdr,x,length);
+}
+
+ACE_CDR::Boolean
+WUCS4_UTF16::write_wchar (ACE_OutputCDR &cdr,
+ ACE_CDR::WChar x)
+{
+ int encode_len = 1;
+ if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 0)
+ { // wchar is not allowed with GIOP 1.0
errno = EINVAL;
return 0;
}
- return this->write_2 (cdr, &sx);
+ else if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 1)
+ encode_len = 0;
+
+ return write_wchar_i(cdr,x,1,encode_len);
+}
+
+ACE_CDR::Boolean
+WUCS4_UTF16::write_wchar_i (ACE_OutputCDR &cdr,
+ ACE_CDR::WChar x,
+ int use_BOM,
+ int encode_len)
+{
+ // If the desired char cannot be translated into a single unicode char,
+ // we must raise a marshal exception.
+ if ((unsigned long)x >= ACE_UTF16_RAW_END &&
+ (unsigned long)x < ACE_UTF16_END)
+ return 0;
+
+ int len = 0;
+ ACE_CDR::UShort buffer[2];
+ if (use_BOM)
+ {
+ len = 2;
+ buffer[0] = ACE_UNICODE_BOM_CORRECT;
+ buffer[1] = ACE_static_cast(ACE_CDR::Short,x);
+ }
+ else
+ {
+ len = 1;
+ if (cdr.byte_order())
+ ACE_CDR::swap_2 (ACE_reinterpret_cast (const char *,&x),
+ ACE_reinterpret_cast (char *,buffer));
+ else
+ buffer[0] = ACE_static_cast(ACE_CDR::Short,x);
+ }
+
+ if (encode_len)
+ {
+ unsigned char tcsize = ACE_static_cast (unsigned char,
+ len * ACE_UTF16_CODEPOINT_SIZE);
+ if (this->write_1 (cdr, &tcsize))
+ return this->write_array(cdr, &buffer, tcsize, 1, 1);
+ else
+ return 0;
+ }
+ if (this->write_2 (cdr, buffer) == 0)
+ return 0;
+ if (len == 2)
+ return this->write_2 (cdr,buffer+1);
+ return 1;
}
ACE_CDR::Boolean
WUCS4_UTF16::write_wstring (ACE_OutputCDR & cdr,
- ACE_CDR::ULong len,
- const ACE_CDR::WChar *x)
+ ACE_CDR::ULong len,
+ const ACE_CDR::WChar *x)
{
- ACE_CDR::ULong l = 0;
if (ACE_static_cast (ACE_CDR::Short, this->major_version(cdr)) == 1
- && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 2)
+ && ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) > 1)
{
- l = len * this->tcs_size_;
+ // count characters that will require surrogates to
+ // determine transmission length
+ len++; // make room for BOM
+ ACE_UTF16_T bom = ACE_UNICODE_BOM_CORRECT;
+ ACE_CDR::ULong length = len + count_potential_surrogates (x, len);
+ ACE_CDR::ULong l = length * ACE_UTF16_CODEPOINT_SIZE;
if (this->write_4 (cdr, &l) && x != 0)
- return this->write_wchar_array (cdr, x, len);
+ {
+ this->write_2 (cdr,&bom);
+ return this->write_measured_wchar_array (cdr, x, len, length);
+ }
}
else
{
- l = len + 1;
+ ACE_CDR::ULong l = len + 1;
if (this->write_4 (cdr, &l))
if (x != 0)
return this->write_wchar_array (cdr, x, len + 1);
- else
- {
- ACE_CDR::UShort s = 0;
- return this->write_2 (cdr,&s);
- }
+ else
+ {
+ ACE_UTF16_T s = 0;
+ return this->write_2 (cdr,&s);
+ }
}
return 0;
}
ACE_CDR::Boolean
WUCS4_UTF16::write_wchar_array (ACE_OutputCDR & cdr,
- const ACE_CDR::WChar *x,
- ACE_CDR::ULong length)
+ const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length)
+{
+#if 0
+ // I do not believe this is correct, because this could yield an array
+ // with an incorrect number of elements for the space allotted.
+ return this->write_measured_wchar_array (
+ cdr,
+ x,
+ length,
+ length + count_potential_surrogates (x, length));
+#endif
+
+ int encode_len = 1;
+ if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 0)
+ { // wchar is not allowed with GIOP 1.0
+ errno = EINVAL;
+ return 0;
+ }
+ else if (ACE_static_cast (ACE_CDR::Short, this->minor_version(cdr)) == 1)
+ encode_len = 0;
+
+ for (size_t i = 0; i < length; i++)
+ if (this->write_wchar_i (cdr,x[i],0,encode_len) == 0)
+ return 0;
+ return 1;
+}
+
+ACE_CDR::Boolean
+WUCS4_UTF16::write_measured_wchar_array (ACE_OutputCDR & cdr,
+ const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length,
+ ACE_CDR::ULong transmission_length)
{
if (length == 0)
return 1;
char* buf;
size_t align = ACE_CDR::SHORT_ALIGN;
- if (cdr.adjust (this->tcs_size_ * length, align, buf) == 0)
+ if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * transmission_length, align, buf)
+ != 0)
{
- ACE_CDR::UShort *sb = ACE_reinterpret_cast(ACE_CDR::UShort *, buf);
- for (size_t i = 0; i < length; i++)
-#if !defined (ACE_ENABLE_SWAP_ON_WRITE)
- sb[i] = ACE_static_cast (ACE_CDR::UShort, x[i]);
-#else
- if (!cdr.do_byte_swap())
- sb[i] = ACE_static_cast (ACE_CDR::UShort, x[i]);;
- else
+ return 0;
+ }
+
+ ACE_UTF16_T *sb = ACE_reinterpret_cast(ACE_UTF16_T *, buf);
+ size_t sbpos = 0;
+
+ for (size_t i = 0; i < length; i++)
+ {
+ sbpos += encode_utf16 (& sb[sbpos], x[i]);
+ }
+#if defined (ACE_ENABLE_SWAP_ON_WRITE)
+ // NOTE this will rarely be enabled. See the comments in ace/OS.h
+ if (cdr.do_byte_swap())
+ {
+ // note can't use swap_2_array because in-place swaps are not safe :-<
+ // and we don't want to allocate a new array
+ for (size_t i = 0; i < sbpos; i++)
{
- ACE_CDR::UShort sx = ACE_static_cast (ACE_CDR::UShort, x[i]);
- ACE_CDR::swap_2 (ACE_reinterpret_cast(char *,&sx),&buf[i*2]);
+ char * pchar = ACE_static_cast (char *, &sb[i]);
+ // ACE_CDR::swap_2 (pchar, pchar);
+ // can't use swap_2 because inplace swaps are not safe
+ // and work-arounds like copying to another buffer lose
+ // any performance improvement from
+ // that fancy asm code, so we might as well just:
+ char temp = pchar[0];
+ pchar[0] = pchar[1];
+ pchar[1] = temp;
+ //@@TODO write swap_2(char * inplace_buffer);
}
-#endif /* ACE_DISABLE_SWAP_ON_READ */
- return 1;
}
- return 0;
+#endif /* ACE_ENABLE_SWAP_ON_WRITE */
+ return 1;
}
diff --git a/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.h b/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.h
index e7feca60d8d..a71fea1e927 100644
--- a/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.h
+++ b/TAO/tests/CodeSets/libs/UCS4_UTF16/WUCS4_UTF16.h
@@ -2,7 +2,7 @@
//=============================================================================
/**
- * @file WUCS4_UTF16.h
+ * @file Wchar_UCS4_UTC16_Translator.h
*
* $Id$
*
@@ -14,7 +14,7 @@
#ifndef WUCS4_UTF16_H
#define WUCS4_UTF16_H
-#include /**/ "ace/pre.h"
+#include "ace/pre.h"
#include "ace/config-all.h"
@@ -33,19 +33,8 @@
* @brief Codeset translation specialization.
*
* This class performs the codeset translation:
- * - Native: UCS4 (4-byte codepoints, lower 16 match Unicode)
- * - Stream: UTF16 (i.e. Unicode)
- * Defines the actions required to convert between UCS-4, a 4 byte wide char
- * codeset as the native wchar codeset, and UCS-16, aka unicode, a 2-byte
- * codeset for the transport wchar codeset.
- *
- * This translator does not alter any codepoint values, but it does
- * illustrate how to deal with the unicode byte order marker (BOM) and how
- * to deal with codepoint size differences.
- *
- * Note that the BOM is an optional value. The write_*() methods do not
- * encode this value. When BOM is not encoded, the byte order of the
- * encapsulation is used.
+ * - Native: IBM_1047 (i.e. EBCDIC)
+ * - Stream: ISO-8859 (i.e. Latin/1)
*/
class UCS4_UTF16_Export WUCS4_UTF16 : public ACE_WChar_Codeset_Translator
{
@@ -76,8 +65,28 @@ public:
virtual ACE_CDR::ULong tcs () {return 0x00010109;}
private:
- ACE_CDR::Octet tcs_size_;
+ ACE_CDR::Boolean read_wchar_array_i (ACE_InputCDR &,
+ ACE_CDR::WChar *,
+ ACE_CDR::ULong&,
+ int adjust_len = 0);
+
+ ACE_CDR::Boolean write_wchar_i (ACE_OutputCDR &,
+ ACE_CDR::WChar ,
+ int use_BOM,
+ int encode_len);
+
+ /**
+ Due to surrogate pair substution the transmitted length of a wstring can
+ differ from the logical strength length. This version of write_wchar_array
+ accepts both lengths and uses them as necessary.
+ */
+ ACE_CDR::Boolean write_measured_wchar_array (
+ ACE_OutputCDR & cdr,
+ const ACE_CDR::WChar *x,
+ ACE_CDR::ULong length,
+ ACE_CDR::ULong transmission_length);
+
};
-#include /**/ "ace/post.h"
+#include "ace/post.h"
#endif /* WCHAR_UCS4_UTF16_TRANSLATOR */