diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:21 +0000 |
commit | 3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (patch) | |
tree | 197c810e5f5bce17b1233a7cb8d7b50c0bcd25e2 /TAO/tao/Codeset | |
parent | 6b846cf03c0bcbd8c276cb0af61a181e5f98eaae (diff) | |
download | ATCD-3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c.tar.gz |
Repo restructuring
Diffstat (limited to 'TAO/tao/Codeset')
21 files changed, 2665 insertions, 0 deletions
diff --git a/TAO/tao/Codeset/Codeset.cpp b/TAO/tao/Codeset/Codeset.cpp new file mode 100644 index 00000000000..c946ad4c3b5 --- /dev/null +++ b/TAO/tao/Codeset/Codeset.cpp @@ -0,0 +1,48 @@ +// -*- C++ -*- + +// ================================================================= +/** + * @file Codeset.cpp + * + * $Id$ + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +// ================================================================= + +#include "tao/Codeset/Codeset.h" +#include "tao/Codeset/Codeset_Manager_Factory.h" +#include "tao/Codeset/UTF8_Latin1_Factory.h" +#include "tao/Codeset/UTF16_BOM_Factory.h" + +#include "ace/Dynamic_Service.h" + + +ACE_RCSID (Codeset, Codeset, "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +int +TAO_Codeset_Initializer::init (void) +{ + int result = 0; + + result += ACE_Service_Config::process_directive + (ace_svc_desc_TAO_UTF8_Latin1_Factory); + + result += ACE_Service_Config::process_directive + (ace_svc_desc_TAO_UTF16_BOM_Factory); + + TAO_Codeset_Manager_Factory *cmf = ACE_Dynamic_Service<TAO_Codeset_Manager_Factory>::instance("TAO_Codeset"); + + if (cmf != 0) + { + return result; + } + + result += ACE_Service_Config::process_directive + (ace_svc_desc_TAO_Codeset_Manager_Factory,1); // force replacement + return result; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/Codeset.h b/TAO/tao/Codeset/Codeset.h new file mode 100644 index 00000000000..73dc459283d --- /dev/null +++ b/TAO/tao/Codeset/Codeset.h @@ -0,0 +1,43 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Codeset.h + * + * $Id$ + * + * @author Carlos O'Ryan <coryan@uci.edu> + */ +//============================================================================= + + +#ifndef TAO_CODESET_H +#define TAO_CODESET_H + +#include /**/ "ace/pre.h" + +#include "tao/Codeset/codeset_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Versioned_Namespace.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Codeset_Export TAO_Codeset_Initializer +{ +public: + /// Used to force the initialization of the ORB code. + static int init (void); +}; + +static int +TAO_Requires_Codeset_Initializer = TAO_Codeset_Initializer::init (); + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_CODESET_H */ diff --git a/TAO/tao/Codeset/Codeset_Descriptor.cpp b/TAO/tao/Codeset/Codeset_Descriptor.cpp new file mode 100644 index 00000000000..cede07a2aa3 --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Descriptor.cpp @@ -0,0 +1,135 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO/tao/Codeset +// +// = FILENAME +// Codeset_Translator_Factory.cpp +// +// = DESCRIPTION +// The base for all the translator factories. Translator factories are +// responsible for supplying the proper translator on demand. +// +// = AUTHORS +// Phil Mesnier <mesnier_p@ociweb.com> +// +// ============================================================================ + +#include "tao/Codeset/Codeset_Descriptor.h" +#include "tao/Codeset/Codeset_Translator_Factory.h" + +#include "ace/Codeset_Registry.h" +#include "ace/Log_Msg.h" +#include "tao/debug.h" + +ACE_RCSID (Codeset, + Codeset_Manager_i, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Codeset_Descriptor::TAO_Codeset_Descriptor () + :ncs_ (0), + max_bytes_ (1), + num_translators_ (0), + trans_base_(0) +{ +} + +TAO_Codeset_Descriptor::~TAO_Codeset_Descriptor () +{ + Translator_Node *temp = trans_base_; + while (temp) + { + temp = trans_base_->next_; + // don't need to delete the associated translator factory, it is + // owned by the service registry + ACE_OS::free (trans_base_->name_); + delete trans_base_; + trans_base_ = temp; + } +} + +void +TAO_Codeset_Descriptor::ncs (const ACE_TCHAR *name) +{ + ACE_CDR::ULong n = 0; + if (ACE_Codeset_Registry::locale_to_registry + (ACE_TEXT_ALWAYS_CHAR(name), n) == 0) + { + char **endPtr = 0; + n = static_cast<ACE_CDR::ULong> ( + ACE_OS::strtoul(ACE_TEXT_ALWAYS_CHAR(name), endPtr, 0)); + } + this->ncs(n); +} + +void +TAO_Codeset_Descriptor::ncs (ACE_CDR::ULong n) +{ + this->ncs_ = n; + // Validate the CodesetId + this->max_bytes_ = ACE_Codeset_Registry::get_max_bytes(n); + if (this->max_bytes_ == 0) + { + if (TAO_debug_level > 0) + ACE_ERROR((LM_ERROR, + ACE_TEXT("(%P|%t) TAO_Codeset_Descriptor::ncs, ") + ACE_TEXT("unknown codeset id 0x%x\n"), + n)); + this->ncs_ = 0; + } +} + +ACE_CDR::ULong +TAO_Codeset_Descriptor::ncs (void) const +{ + return this->ncs_; +} + +int +TAO_Codeset_Descriptor::num_translators (void) const +{ + return this->num_translators_; +} + +int +TAO_Codeset_Descriptor::max_bytes (void) const +{ + return this->max_bytes_; +} + +void +TAO_Codeset_Descriptor::add_translator (const ACE_TCHAR *name) +{ + Translator_Node *temp = trans_base_; + if (this->trans_base_ == 0) + { + ACE_NEW (this->trans_base_, Translator_Node); + temp = trans_base_; + } + else + { + while (temp->next_ != 0) + temp = temp->next_; + ACE_NEW (temp->next_, Translator_Node); + temp = temp->next_; + } + if (temp) + { + this->num_translators_ ++; + temp->name_ = ACE_OS::strdup (name); + temp->translator_factory_ = 0; + temp->next_ = 0; + } +} + +TAO_Codeset_Descriptor::Translator_Node * +TAO_Codeset_Descriptor::translators (void) +{ + return this->trans_base_; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/Codeset_Descriptor.h b/TAO/tao/Codeset/Codeset_Descriptor.h new file mode 100644 index 00000000000..a0a8b89363c --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Descriptor.h @@ -0,0 +1,65 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Codeset_Descriptor.h + * + * $Id$ + * + * @author Phil Mesnier + */ +//============================================================================= + +#ifndef TAO_CODESET_DESCRIPTOR_H +#define TAO_CODESET_DESCRIPTOR_H + +#include /**/ "ace/pre.h" + +#include "tao/Codeset/codeset_export.h" +#include "ace/CDR_Base.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/Codeset_Descriptor_Base.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Codeset_Translator_Factory; + +class TAO_Codeset_Export TAO_Codeset_Descriptor + : public TAO_Codeset_Descriptor_Base +{ +public: + TAO_Codeset_Descriptor (); + virtual ~TAO_Codeset_Descriptor (); + + struct Translator_Node + { + ACE_TCHAR *name_; + TAO_Codeset_Translator_Factory *translator_factory_; + Translator_Node *next_; + }; + + void ncs (ACE_CDR::ULong ncs); + void ncs (const ACE_TCHAR *name); + ACE_CDR::ULong ncs (void) const; + int max_bytes (void) const; + int num_translators (void) const; + + void add_translator (const ACE_TCHAR *name); + Translator_Node *translators (void); + +private: + ACE_CDR::ULong ncs_; + int max_bytes_; + int num_translators_; + Translator_Node *trans_base_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_CODESET_DESCRIPTOR_H */ diff --git a/TAO/tao/Codeset/Codeset_Manager_Factory.cpp b/TAO/tao/Codeset/Codeset_Manager_Factory.cpp new file mode 100644 index 00000000000..7f89626dc47 --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Manager_Factory.cpp @@ -0,0 +1,50 @@ +/* -*- C++ -*- */ + +// ================================================================= +/** + * @file Codeset_Manager_Factory.cpp + * + * $Id$ + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + * + */ +// ================================================================= + +#include "tao/Codeset/Codeset_Manager_Factory.h" +#include "ace/Service_Config.h" +#include "tao/Codeset/Codeset_Manager_i.h" + +ACE_RCSID (Codeset, Codeset_Manager_Factory, "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Codeset_Manager_Factory::~TAO_Codeset_Manager_Factory () +{ +} + +bool +TAO_Codeset_Manager_Factory::is_default() const +{ + return false; +} + + +TAO_Codeset_Manager * +TAO_Codeset_Manager_Factory::create () +{ + TAO_Codeset_Manager_i *csm = 0; + ACE_NEW_RETURN (csm, TAO_Codeset_Manager_i, 0); + + return csm; +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +ACE_FACTORY_DEFINE (TAO_Codeset, TAO_Codeset_Manager_Factory) +ACE_STATIC_SVC_DEFINE (TAO_Codeset_Manager_Factory, + ACE_TEXT ("TAO_Codeset"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_Codeset_Manager_Factory), + ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, + 0) diff --git a/TAO/tao/Codeset/Codeset_Manager_Factory.h b/TAO/tao/Codeset/Codeset_Manager_Factory.h new file mode 100644 index 00000000000..44ed6f20d8c --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Manager_Factory.h @@ -0,0 +1,59 @@ +/* -*- C++ -*- */ + + +//============================================================================= +/** + * @file Codeset_Manager_Factory.h + * + * $Id$ + * + * @author Carlos O'Ryan <coryan@uci.edu> + */ +//============================================================================= + + +#ifndef TAO_CODESET_MANAGER_FACTORY_H +#define TAO_CODESET_MANAGER_FACTORY_H + +#include /**/ "ace/pre.h" + +#include "tao/Codeset/codeset_export.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Service_Config.h" +#include "tao/Codeset_Manager_Factory_Base.h" + + +// **************************************************************** + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_Codeset_Manager_Factory + * + * @brief Class loader for initializing a codeset manager + */ + +class TAO_Codeset_Export TAO_Codeset_Manager_Factory : + public TAO_Codeset_Manager_Factory_Base +{ +public: + virtual ~TAO_Codeset_Manager_Factory (); + virtual TAO_Codeset_Manager *create(void); + virtual bool is_default(void) const; + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +ACE_STATIC_SVC_DECLARE (TAO_Codeset_Manager_Factory) +ACE_FACTORY_DECLARE (TAO_Codeset, TAO_Codeset_Manager_Factory) + + + +#include /**/ "ace/post.h" + +#endif /* TAO_CODESET_MANAGER_FACTORY_H */ diff --git a/TAO/tao/Codeset/Codeset_Manager_i.cpp b/TAO/tao/Codeset/Codeset_Manager_i.cpp new file mode 100644 index 00000000000..98664b6f60e --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Manager_i.cpp @@ -0,0 +1,510 @@ +// $Id$ + +#include "tao/TAO_Server_Request.h" +#include "tao/operation_details.h" +#include "tao/Transport.h" +#include "tao/Profile.h" +#include "tao/SystemException.h" +#include "tao/debug.h" +#include "tao/CDR.h" +#include "tao/ORB_Core.h" + +#include "tao/Codeset/Codeset_Descriptor.h" +#include "tao/Codeset/Codeset_Manager_i.h" +#include "tao/Codeset/Codeset_Translator_Factory.h" +#include "tao/Codeset/Codeset.h" + +#include "ace/Dynamic_Service.h" +#include "ace/Codeset_Registry.h" +#include "ace/OS_NS_string.h" +#include "ace/Service_Config.h" + + +ACE_RCSID (Codeset, + Codeset_Manager_i, + "$Id$") + + +// These numbers are assigned by the OpenGroup, a database is +// available at +// +// ftp://ftp.opengroup.org/pub/code_set_registry/ +// +#define TAO_CODESET_ID_ISO8859_1 0x00010001U +#define TAO_CODESET_ID_UNICODE 0x00010109U +#define TAO_CODESET_ID_XOPEN_UTF_8 0x05010001U + +// These are the default codesets that TAO declares, of course they +// will be different on each platform, once the complete support for +// character sets is implemented + +#if (defined TAO_DEFAULT_CHAR_CODESET_ID) +# undef TAO_DEFAULT_CHAR_CODESET_ID +#endif /* defined TAO_DEFAULT_CHAR_CODESET_ID */ + +#if (defined TAO_DEFAULT_WCHAR_CODESET_ID) +# undef TAO_DEFAULT_WCHAR_CODESET_ID +#endif /* defined TAO_DEFAULT_WCHAR_CODESET_ID */ + +//#define TAO_DEFAULT_CHAR_CODESET_ID TAO_CODESET_ID_XOPEN_UTF_8 +#define TAO_DEFAULT_CHAR_CODESET_ID TAO_CODESET_ID_ISO8859_1 +#define TAO_DEFAULT_WCHAR_CODESET_ID TAO_CODESET_ID_UNICODE + +// **************************************************************** + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// NCS for char is defaulted to ISO 8859-1:1987; Latin Alphabet No. 1 +CONV_FRAME::CodeSetId +TAO_Codeset_Manager_i::default_char_codeset = TAO_DEFAULT_CHAR_CODESET_ID; +/// NCS for wchar is not defaulted by the CORBA specification, but a default +/// may be set here if desired +CONV_FRAME::CodeSetId +TAO_Codeset_Manager_i::default_wchar_codeset = TAO_DEFAULT_WCHAR_CODESET_ID; + +TAO_Codeset_Manager_i::TAO_Codeset_Manager_i (void) + : codeset_info_ (), + char_descriptor_ (), + wchar_descriptor_ () +{ + char_descriptor_.ncs(TAO_Codeset_Manager_i::default_char_codeset); + char_descriptor_.add_translator (ACE_TEXT ("UTF8_Latin1_Factory")); + + wchar_descriptor_.ncs(TAO_Codeset_Manager_i::default_wchar_codeset); + wchar_descriptor_.add_translator (ACE_TEXT ("UTF16_BOM_Factory")); + +} + +TAO_Codeset_Manager_i::~TAO_Codeset_Manager_i (void) +{ +} + +TAO_Codeset_Descriptor_Base * +TAO_Codeset_Manager_i::char_codeset_descriptor (void) +{ + return &this->char_descriptor_; +} + +TAO_Codeset_Descriptor_Base * +TAO_Codeset_Manager_i::wchar_codeset_descriptor (void) +{ + return &this->wchar_descriptor_; +} + +void +TAO_Codeset_Manager_i::set_codeset (TAO_Tagged_Components& tc) const +{ + tc.set_code_sets (this->codeset_info_); +} + +void +TAO_Codeset_Manager_i::set_tcs (TAO_Profile &theProfile, + TAO_Transport &trans) +{ + /// If tcs is already set on the transport then do not process, + /// use existing transport as CDR have translators set. + TAO_Tagged_Components& theTaggedComp = theProfile.tagged_components (); + + CONV_FRAME::CodeSetComponentInfo remote; + + /// Get the codeset component + if (theTaggedComp.get_code_sets(remote) == 0 ) + { + if (trans.is_tcs_set ()) + { + if(TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::set_tcs, ") + ACE_TEXT ("transport already set\n"))); + return; + } + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::set_tcs, ") + ACE_TEXT ("No codeset component in profile\n"))); + + // These are the "fallback" codeset ids for use if no context is + // available + remote.ForCharData.native_code_set = + TAO_CODESET_ID_XOPEN_UTF_8; + remote.ForWcharData.native_code_set = + TAO_CODESET_ID_UNICODE; + + trans.char_translator + (this->get_char_trans + (TAO_Codeset_Manager_i::default_char_codeset)); + trans.wchar_translator + (this->get_wchar_trans + (TAO_Codeset_Manager_i::default_wchar_codeset)); + } + else + { + CONV_FRAME::CodeSetId tcs = + computeTCS (remote.ForCharData, + this->codeset_info_.ForCharData); + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO (%P|%t) - Codeset_Manager_i::set_tcs, ") + ACE_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_TEXT("TAO (%P|%t) - Codeset_Manager_i::set_tcs, ") + ACE_TEXT("setting wchar translator (%08x)\n"), + tcs)); + trans.wchar_translator(this->get_wchar_trans (tcs)); + } +} + +void +TAO_Codeset_Manager_i::process_service_context (TAO_ServerRequest &request) +{ + // Get the service Context from an object of TAO_ServerRequest + // and set the TCS values on the Transport + TAO_Service_Context &service_cntx = request.request_service_context (); + IOP::ServiceContext context; + context.context_id = IOP::CodeSets; + + // These are the "fallback" codeset ids for use if no other codeset + // can be computed based on our local set and those in the context + CONV_FRAME::CodeSetId tcs_c = TAO_CODESET_ID_XOPEN_UTF_8; + CONV_FRAME::CodeSetId tcs_w = TAO_CODESET_ID_UNICODE; + + if (service_cntx.get_context(context)) + { + // Convert the Service Context to Codeset Context + const char *buffer = + reinterpret_cast<const char*> (context.context_data.get_buffer ()); + + TAO_InputCDR cdr (buffer,context.context_data.length ()); + CORBA::Boolean byte_order; + + if (cdr >> TAO_InputCDR::to_boolean (byte_order)) + { + cdr.reset_byte_order (static_cast<int> (byte_order)); + cdr >> tcs_c; + cdr >> tcs_w; + } + } + else + { + if (request.transport()->is_tcs_set()) + return; + if (TAO_debug_level > 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO (%P|%t) - ") + ACE_TEXT("Codeset_Manager_i::process_service_context ") + ACE_TEXT("no codeset context in request, using defaults\n") + )); + tcs_c = TAO_Codeset_Manager_i::default_char_codeset; + tcs_w = TAO_Codeset_Manager_i::default_wchar_codeset; + } + if (TAO_debug_level > 2) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("process_service_context, ") + ACE_TEXT ("using tcsc = %08x, tcsw = %08x\n"), + tcs_c,tcs_w)); + } + + request.transport()->char_translator(this->get_char_trans (tcs_c)); + request.transport()->wchar_translator(this->get_wchar_trans (tcs_w)); +} + +void +TAO_Codeset_Manager_i::generate_service_context (TAO_Operation_Details &opd, + TAO_Transport &trans) +{ + TAO_Service_Context &service_cntx = opd.request_service_context (); + CONV_FRAME::CodeSetContext codeset_cntx; + + // Generating codeset context + // Assuming the TCS values from Transport will be defaulted + TAO_Codeset_Translator_Factory *tf = + dynamic_cast<TAO_Codeset_Translator_Factory*>(trans.char_translator()); + + codeset_cntx.char_data = + tf ? tf->tcs () : this->codeset_info_.ForCharData.native_code_set; + + tf = + dynamic_cast<TAO_Codeset_Translator_Factory*>(trans.wchar_translator()); + + codeset_cntx.wchar_data = + tf ? tf->tcs () : this->codeset_info_.ForWcharData.native_code_set; + + if (TAO_debug_level > 2) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("generate_service_context, ") + ACE_TEXT ("using tcs_c = %08x, tcs_w = %08x\n"), + codeset_cntx.char_data, + codeset_cntx.wchar_data)); + } + + TAO_OutputCDR codeset_cdr; + codeset_cdr << TAO_OutputCDR::from_boolean (TAO_ENCAP_BYTE_ORDER); + codeset_cdr << codeset_cntx; + + service_cntx.set_context (IOP::CodeSets,codeset_cdr); +} + +/// Checks whether the NCS is a part of CCS +int +TAO_Codeset_Manager_i::isElementOf (CONV_FRAME::CodeSetId id, + CONV_FRAME::CodeSetComponent &cs_comp) +{ + for (CORBA::ULong i = 0L; + i < cs_comp.conversion_code_sets.length (); + ++i ) + { + if (id == cs_comp.conversion_code_sets[i]) + return 1; + } + + return 0; +} + +/// Find the Intersection of Client and Server CCS's +CONV_FRAME::CodeSetId +TAO_Codeset_Manager_i::intersectionOf (CONV_FRAME::CodeSetComponent &cs_comp1, + CONV_FRAME::CodeSetComponent &cs_comp2) +{ + for(CORBA::ULong index = 0L; + index < cs_comp1.conversion_code_sets.length(); + ++index ) + { + if (this->isElementOf(cs_comp1.conversion_code_sets[index], cs_comp2)) + { + return cs_comp1.conversion_code_sets[index]; + } + } + + return 0; +} + +int +TAO_Codeset_Manager_i::isCompatible(CONV_FRAME::CodeSetId cs1, + CONV_FRAME::CodeSetId cs2 ) +{ + // Call the is_compatible method of ACE_Codeset_Registry + return ACE_Codeset_Registry::is_compatible(cs1,cs2); +} + +/// returns the TCS for Char / Wchar +CONV_FRAME::CodeSetId +TAO_Codeset_Manager_i::computeTCS (CONV_FRAME::CodeSetComponent &remote, + CONV_FRAME::CodeSetComponent &local ) +{ + if (remote.native_code_set == local.native_code_set) + { + return local.native_code_set; + } + + if (this->isElementOf (remote.native_code_set, local)) + { + return remote.native_code_set; + } + + if (this->isElementOf (local.native_code_set, remote)) + { + return local.native_code_set; + } + + CONV_FRAME::CodeSetId tcs; + + if ((tcs = this->intersectionOf (remote, local)) == 0) + { + if (isCompatible (local.native_code_set, remote.native_code_set)) + { + return remote.native_code_set; + } + else + { + ACE_DECLARE_NEW_CORBA_ENV; + ACE_THROW_RETURN(CORBA::CODESET_INCOMPATIBLE (), 0); + } + } + + return tcs; +} + +void +TAO_Codeset_Manager_i::open(void) +{ +#if 0 + // These translators help comply with the CORBA 3.0.2 specifcation + TAO_Codeset_Translator_Factory *fact = + ACE_Dynamic_Service<TAO_Codeset_Translator_Factory>:: + instance ("UTF8_Latin1_Factory"); + if (fact == 0) + ACE_Service_Config::process_directive + (ACE_DYNAMIC_SERVICE_DIRECTIVE ("UTF8_Latin1_Factory", + "TAO_Codeset", + "_make_TAO_UTF8_Latin1_Factory", + "")); + else + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO (%P|%t) - Codeset_Manager_i::open skipping ") + ACE_TEXT("redundant load of UTF8_Latin1_Factory\n") + )); + } + + fact = ACE_Dynamic_Service<TAO_Codeset_Translator_Factory>:: + instance ("UTF16_BOM_Factory"); + if (fact == 0) + ACE_Service_Config::process_directive + (ACE_DYNAMIC_SERVICE_DIRECTIVE ("UTF16_BOM_Factory", + "TAO_Codeset", + "_make_TAO_UTF16_BOM_Factory", + "")); + else + { + if (TAO_debug_level > 2) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO (%P|%t) - Codeset_Manager_i::open skipping ") + ACE_TEXT("redundant load of UTF16_BOM_Factory\n") + )); + } +#endif + + // add in from the service configurator + this->codeset_info_.ForCharData.native_code_set = + this->char_descriptor_.ncs(); + this->codeset_info_.ForWcharData.native_code_set = + this->wchar_descriptor_.ncs(); + ACE_OutputCDR::wchar_maxbytes(this->wchar_descriptor_.max_bytes()); + + if (init_ccs (this->char_descriptor_, + this->codeset_info_.ForCharData) == -1) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("configure_codeset_factories, failed to init ") + ACE_TEXT ("char codeset factories\n"))); + } + + if (init_ccs (this->wchar_descriptor_, + this->codeset_info_.ForWcharData) == -1) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("configure_codeset_factories, failed to init ") + ACE_TEXT ("wchar codeset factories\n"))); + } +} + +// Initialise the specific type codeset factories +int +TAO_Codeset_Manager_i::init_ccs (TAO_Codeset_Descriptor& cd, + CONV_FRAME::CodeSetComponent& cs_comp) +{ + cs_comp.conversion_code_sets.length + (static_cast<CORBA::ULong> (cd.num_translators())); + + CORBA::ULong index; + TAO_Codeset_Descriptor::Translator_Node *tlist = cd.translators(); + + for (index = 0; tlist; tlist = tlist->next_) + { + tlist->translator_factory_ = + ACE_Dynamic_Service<TAO_Codeset_Translator_Factory>::instance + (ACE_TEXT_ALWAYS_CHAR (tlist->name_)); + + if (tlist->translator_factory_ == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("init_ccs, Unable to load ") + ACE_TEXT ("code set translator <%s>, %m\n"), + tlist->name_)); + continue; + } + + if (tlist->translator_factory_->ncs() != cs_comp.native_code_set) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("init_ccs, codeset translator <%s> ") + ACE_TEXT ("has wrong ncs (%d), %m\n"), + tlist->name_, + tlist->translator_factory_->ncs())); + tlist->translator_factory_ = 0; + continue; + } + + // this is a special case for the utf16 bom translator. + if (tlist->translator_factory_->tcs() == cs_comp.native_code_set) + continue; + + cs_comp.conversion_code_sets[index++] = + tlist->translator_factory_->tcs(); + if (TAO_debug_level > 2) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - Codeset_Manager_i::") + ACE_TEXT ("init_ccs, Loaded Codeset translator ") + ACE_TEXT ("<%s>, ncs = %08x tcs = %08x\n"), + tlist->name_, + tlist->translator_factory_->ncs(), + tlist->translator_factory_->tcs() + )); + } + } + + cs_comp.conversion_code_sets.length(index); + return 0; +} + +TAO_Codeset_Translator_Base * +TAO_Codeset_Manager_i::get_char_trans (CONV_FRAME::CodeSetId tcs) +{ + if (this->codeset_info_.ForCharData.native_code_set == tcs) + return 0; + return this->get_translator_i (this->char_descriptor_,tcs); +} + +TAO_Codeset_Translator_Base * +TAO_Codeset_Manager_i::get_wchar_trans (CONV_FRAME::CodeSetId tcs) +{ + if (tcs == this->codeset_info_.ForWcharData.native_code_set && + tcs != ACE_CODESET_ID_ISO_UTF_16) + return 0; + return this->get_translator_i (this->wchar_descriptor_,tcs); +} + +TAO_Codeset_Translator_Base * +TAO_Codeset_Manager_i::get_translator_i (TAO_Codeset_Descriptor& cd, + CONV_FRAME::CodeSetId tcs) +{ + for (TAO_Codeset_Descriptor::Translator_Node *tlist = cd.translators(); + tlist; tlist = tlist->next_) + { + TAO_Codeset_Translator_Factory *fact = tlist->translator_factory_; + if (fact && tcs == fact->tcs ()) + return fact; + } + return 0; +} + +void +TAO_Codeset_Manager_i::get_ncs (CONV_FRAME::CodeSetId &ncsc, + CONV_FRAME::CodeSetId &ncsw) +{ + ncsc = this->char_descriptor_.ncs(); + ncsw = this->wchar_descriptor_.ncs(); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/Codeset_Manager_i.h b/TAO/tao/Codeset/Codeset_Manager_i.h new file mode 100644 index 00000000000..a9167804b1c --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Manager_i.h @@ -0,0 +1,150 @@ +// This may look like C, but it's really -*- C++ -*- + +//====================================================================== +/* + * @file Codeset_Manager_i.h + * + * $Id$ + * + * Interface for the TAO CodeSet Manager. + * + * @author Phil Mesnier + */ +//====================================================================== + +#ifndef TAO_CODESET_MANAGER_I_H +#define TAO_CODESET_MANAGER_I_H + +#include /**/ "ace/pre.h" + +#include "tao/CONV_FRAMEC.h" +#include "tao/Codeset_Manager.h" +#include "tao/Codeset/codeset_export.h" +#include "tao/Codeset/Codeset_Descriptor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Unbounded_Set.h" +#include "ace/Dynamic_Service_Dependency.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Profile; +class TAO_Transport; +class TAO_Operation_Details; + +class TAO_ServerRequest; +class TAO_Tagged_Components; +class TAO_Codeset_Descriptor; + +// **************************************************************** + +/** + * @class TAO_Codeset_Manager + * + * @brief The encapsulation of logic for codeset negotiation + * + * The Codeset Manager is owned by the ORB_Core, initialized through Resource + * Factory configuration options. The codeset manager participates in profile + * creation by servers and connection establishment by clients. The involvement + * is necessary to supply a codeset component to the profile including for both + * chars and wide chars the native code set and any conversion code sets for + * which translators are available. The codeset manager is also responsible for + * determining the transmission codesets based an the local and remote codeset + * information. The transmission codesets are communicated via a service + * context attached to the first request sent on the new connection. + * + */ + +class TAO_Codeset_Export TAO_Codeset_Manager_i : + public TAO_Codeset_Manager +{ + +public: + /// NCS for char is defaulted to ISO 8859-1:1987; Latin Alphabet + /// No. 1 + static CONV_FRAME::CodeSetId default_char_codeset; + /// NCS for wchar is defaulted to 0 (not used), but people wishing + /// to provide a non-compliant default wchar codeset may do so. + static CONV_FRAME::CodeSetId default_wchar_codeset; + + TAO_Codeset_Manager_i (void); + ~TAO_Codeset_Manager_i (void); + + /// Called by an object of TAO_Acceptor to set NCS and CCS values + /// for Char/Wchar in to the Object Reference. + void set_codeset (TAO_Tagged_Components& ) const; + /// + /// Called from an object of "TAO_GIOP_Invocation" to set TCS on the + /// Transport + void set_tcs (TAO_Profile &theProfile, TAO_Transport &); + + /// Called from an Object of TAO_Messaging for every request at + /// server side to process service context and set TCS for + /// Char/WChar + void process_service_context (TAO_ServerRequest &); + + /// Called by a client object to generate service context + /// at this time Transport has the TCS for Char and WChar + void generate_service_context (TAO_Operation_Details&, TAO_Transport & ); + + /// Called by the resource factory to signify the end of + /// initialization. This will traverse the list of named codeset + /// translator factories and add any of those that have a native + /// codeset id matching the manager's native codeset id. + void open(void); + + virtual TAO_Codeset_Descriptor_Base *char_codeset_descriptor (void); + virtual TAO_Codeset_Descriptor_Base *wchar_codeset_descriptor (void); + +private: + // Compute the TCS for Char/WChar asper the CORBA Specification + CONV_FRAME::CodeSetId computeTCS (CONV_FRAME::CodeSetComponent &, + CONV_FRAME::CodeSetComponent &); + + // Find CodesetId in the codeset component + int isElementOf (CONV_FRAME::CodeSetId, + CONV_FRAME::CodeSetComponent & ); + + // find the intersection of CodesetIds between Client and Server CCS + CONV_FRAME::CodeSetId intersectionOf (CONV_FRAME::CodeSetComponent &, + CONV_FRAME::CodeSetComponent &); + + // determine compatibility between two codesets via the codeset + // registry + int isCompatible (CONV_FRAME::CodeSetId, CONV_FRAME::CodeSetId); + + // traverse the list of codeset factories, populating the list of + // conversion codeset values with the translated codeset id from + // each factory that has a matching native codeset. Those factories + // that do not have a matching codeset are not retained in the list. + int init_ccs (TAO_Codeset_Descriptor&, + CONV_FRAME::CodeSetComponent&); + + // get the translator between our ncs_c and the supplied tcs_c + TAO_Codeset_Translator_Base * get_char_trans (CONV_FRAME::CodeSetId); + + // get the translator between our ncs_w and the supplied tcs_w + TAO_Codeset_Translator_Base * get_wchar_trans (CONV_FRAME::CodeSetId); + + TAO_Codeset_Translator_Base * get_translator_i (TAO_Codeset_Descriptor&, + CONV_FRAME::CodeSetId); + + void get_ncs (CONV_FRAME::CodeSetId &ncsc, CONV_FRAME::CodeSetId& ncsw); + + // The CodeSetComponentInfo struct contains all of the information + // regarding the code sets this application recognizes. This is + // where the native code set for both char and wchar are stored. + CONV_FRAME::CodeSetComponentInfo codeset_info_; + + TAO_Codeset_Descriptor char_descriptor_; + TAO_Codeset_Descriptor wchar_descriptor_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" + +#endif /* TAO_CODESET_MANAGER_I_H */ diff --git a/TAO/tao/Codeset/Codeset_Translator_Factory.cpp b/TAO/tao/Codeset/Codeset_Translator_Factory.cpp new file mode 100644 index 00000000000..bd3a915c51d --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Translator_Factory.cpp @@ -0,0 +1,81 @@ +// -*- C++ -*- + +// ============================================================================ +// +// = LIBRARY +// TAO/tao/Codeset +// +// = FILENAME +// Codeset_Translator_Factory.cpp +// +// = DESCRIPTION +// The base for all the translator factories. Translator factories are +// responsible for supplying the proper translator on demand. +// +// = AUTHORS +// Phil Mesnier <mesnier_p@ociweb.com> +// +// ============================================================================ + +#include "tao/Codeset/Codeset_Translator_Factory.h" +#include "tao/CDR.h" + +ACE_RCSID (Codeset, + Codeset_Translator_Factory, + "$Id$") + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_Codeset_Translator_Factory::TAO_Codeset_Translator_Factory () +{ + +} + +TAO_Codeset_Translator_Factory::~TAO_Codeset_Translator_Factory () +{ + +} + +int +TAO_Codeset_Translator_Factory::init (int , ACE_TCHAR **) +{ + return 0; +} + +void +TAO_Codeset_Translator_Factory::assign_i ( + TAO_InputCDR *cdr, + ACE_Char_Codeset_Translator *trans + ) const +{ + cdr->char_translator(trans); +} + +void +TAO_Codeset_Translator_Factory::assign_i ( + TAO_OutputCDR *cdr, + ACE_Char_Codeset_Translator *trans + ) const +{ + cdr->char_translator(trans); +} + +void +TAO_Codeset_Translator_Factory::assign_i ( + TAO_InputCDR *cdr, + ACE_WChar_Codeset_Translator *trans + ) const +{ + cdr->wchar_translator(trans); +} + +void +TAO_Codeset_Translator_Factory::assign_i ( + TAO_OutputCDR *cdr, + ACE_WChar_Codeset_Translator *trans + ) const +{ + cdr->wchar_translator(trans); +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/Codeset_Translator_Factory.h b/TAO/tao/Codeset/Codeset_Translator_Factory.h new file mode 100644 index 00000000000..518a168de63 --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Translator_Factory.h @@ -0,0 +1,92 @@ +// -*- C++ -*- + +// =================================================================== +/** + * @file Codeset_Translator_Factory.h + * + * $Id$ + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +// =================================================================== + +#ifndef TAO_CODESET_TRANSLATOR_FACTORY_H +#define TAO_CODESET_TRANSLATOR_FACTORY_H + +#include /**/ "ace/pre.h" +#include "ace/Service_Object.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/CONV_FRAMEC.h" +#include "tao/Codeset_Translator_Base.h" +#include "tao/Codeset/codeset_export.h" + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL +class ACE_Char_Codeset_Translator; +class ACE_WChar_Codeset_Translator; +ACE_END_VERSIONED_NAMESPACE_DECL + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_InputCDR; +class TAO_OutputCDR; + +// **************************************************************** + +/** + * @class TAO_Codeset_Translator_Factory + * + * @brief Abstract base class for factories providing codeset translators + * + * The codeset translator factory is a loadable service object. It is used to + * supply the actual translator used in converting between two codesets. The + * intent of using a factory is to avoid requiring codeset translators to be + * multiply inherited both from the translator base class and the service + * object base. The translator factory is also responsible for assigning + * translators to CDR streams. Since there is no common base class between + * input and output CDRs, the assingment code must be duplicated. + */ + +class TAO_Codeset_Export TAO_Codeset_Translator_Factory : + public TAO_Codeset_Translator_Base, + public ACE_Service_Object +{ +public: + TAO_Codeset_Translator_Factory (); + virtual ~TAO_Codeset_Translator_Factory (); + virtual int init (int argc, ACE_TCHAR *argv[]); + +protected: + /// Assign the translator to the supplied input CDR. The template instance + /// will have a translator that is based on either the Char or Wchar + /// translator, so the compiler will select the appropriate call from + /// assign(). + void assign_i (TAO_InputCDR *, ACE_Char_Codeset_Translator* ) const; + /// Assign the translator to the supplied input CDR. The template instance + /// will have a translator that is based on either the Char or Wchar + /// translator, so the compiler will select the appropriate call from + /// assign(). + void assign_i (TAO_InputCDR *, ACE_WChar_Codeset_Translator* ) const; + /// Assign the translator to the supplied output CDR. The template instance + /// will have a translator that is based on either the Char or Wchar + /// translator, so the compiler will select the appropriate call from + /// assign(). + void assign_i (TAO_OutputCDR *, ACE_Char_Codeset_Translator* ) const; + /// Assign the translator to the supplied output CDR. The template instance + /// will have a translator that is based on either the Char or Wchar + /// translator, so the compiler will select the appropriate call from + /// assign(). + void assign_i (TAO_OutputCDR *, ACE_WChar_Codeset_Translator* ) const; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +// Get the template includes last +#include "tao/Codeset/Codeset_Translator_Factory_T.h" + +#include /**/ "ace/post.h" +#endif /* TAO_Codeset_Translator_Factory */ diff --git a/TAO/tao/Codeset/Codeset_Translator_Factory_T.cpp b/TAO/tao/Codeset/Codeset_Translator_Factory_T.cpp new file mode 100644 index 00000000000..734417e9934 --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Translator_Factory_T.cpp @@ -0,0 +1,92 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// TAO/tao +// +// = FILENAME +// Codeset_Translator_Factory_T.cpp +// +// = DESCRIPTION +// The template for creating a particular instance of a codeset translator +// +// = AUTHORS +// Phil Mesnier <mesnier_p@ociweb.com> +// +// ============================================================================ +#ifndef TAO_CODESET_TRANSLATOR_FACTORY_T_CPP +#define TAO_CODESET_TRANSLATOR_FACTORY_T_CPP + +#include "tao/Codeset/Codeset_Translator_Factory_T.h" +#include "tao/debug.h" +#include "tao/CDR.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +template<class NCS_TO_TCS> +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::TAO_Codeset_Translator_Factory_T () : + translator_(0) +{ +} + +template<class NCS_TO_TCS> +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::~TAO_Codeset_Translator_Factory_T () +{ + delete translator_; +} + +template<class NCS_TO_TCS> +int +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::init (int argc, ACE_TCHAR* argv[]) +{ + this->TAO_Codeset_Translator_Factory::init (argc,argv); + ACE_NEW_RETURN (translator_,NCS_TO_TCS,-1); + if( TAO_debug_level > 0 ) + ACE_DEBUG((LM_DEBUG, "TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::init() entered\n")); + return 0; +} + +// ncs & tcs values set at compile time as a result of instantiating the +// template. +template<class NCS_TO_TCS> +CONV_FRAME::CodeSetId +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::ncs () const +{ + return this->translator_->ncs(); +} + +template<class NCS_TO_TCS> +CONV_FRAME::CodeSetId +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::tcs () const +{ + return this->translator_->tcs(); +} + +// Assign either a reference to teh existing translator or a new translator +// for input CDR streams +template<class NCS_TO_TCS> +void +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::assign (TAO_InputCDR *cdr) const +{ + if (cdr) + { + this->assign_i(cdr,this->translator_); + } +} + +// Assign either a reference to teh existing translator or a new translator +// for input CDR streams +template<class NCS_TO_TCS> +void +TAO_Codeset_Translator_Factory_T<NCS_TO_TCS>::assign (TAO_OutputCDR *cdr) const +{ + if (cdr) + { + this->assign_i(cdr,this->translator_); + } +} + +TAO_END_VERSIONED_NAMESPACE_DECL + +#endif /* TAO_CODESET_TRANSLATOR_FACTORY_T_CPP */ diff --git a/TAO/tao/Codeset/Codeset_Translator_Factory_T.h b/TAO/tao/Codeset/Codeset_Translator_Factory_T.h new file mode 100644 index 00000000000..ce5a902c7fe --- /dev/null +++ b/TAO/tao/Codeset/Codeset_Translator_Factory_T.h @@ -0,0 +1,85 @@ +// -*- C++ -*- + +// =================================================================== +/** + * @file Codeset_Translator_Factory_T.h + * + * $Id$ + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +// =================================================================== + +#ifndef TAO_CODESET_TRANSLATOR_FACTORY_T_H +#define TAO_CODESET_TRANSLATOR_FACTORY_T_H + +#include /**/ "ace/pre.h" + +#include "tao/Codeset/Codeset_Translator_Factory.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_Codeset_Translator_Factory_T + * + * @brief Template for translator factory classes. + * + * The template argument is the actual translator class. The factory creates an + * instance of the translator during initialization. Other than that, the + * template returns the actual values for the native and translated codeset + * ids, and performs the translator assignment to the CDR objects as needed. + */ + +template<class NCS_TO_TCS> +class TAO_Codeset_Translator_Factory_T +: public TAO_Codeset_Translator_Factory +{ +public: + + TAO_Codeset_Translator_Factory_T (); + virtual ~TAO_Codeset_Translator_Factory_T (); + + /// initialize the factory service object. Instantiates the translator. + int init( int argc, ACE_TCHAR* argv[]); + + /// ncs returns the translator's native codeset ID. + CONV_FRAME::CodeSetId ncs () const; + /// tcs returns the translator's transmission codeset ID. + CONV_FRAME::CodeSetId tcs () const; + + /// Assign the translator to the input CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null input CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_InputCDR *) const; + /// Assign the translator to the output CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null output CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_OutputCDR *) const; + +private: + NCS_TO_TCS *translator_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "tao/Codeset/Codeset_Translator_Factory_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Codeset_Translator_Factory_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#include /**/ "ace/post.h" +#endif /* TAO_Codeset_Translator_Factory_T */ diff --git a/TAO/tao/Codeset/UTF16_BOM_Factory.cpp b/TAO/tao/Codeset/UTF16_BOM_Factory.cpp new file mode 100644 index 00000000000..1140d84a6bb --- /dev/null +++ b/TAO/tao/Codeset/UTF16_BOM_Factory.cpp @@ -0,0 +1,142 @@ +// -*- 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 "tao/debug.h" +#include "tao/Codeset/UTF16_BOM_Factory.h" +#include "ace/OS_NS_strings.h" +#include "ace/Dynamic_Service.h" +#include "ace/Log_Msg.h" + +ACE_STATIC_SVC_DEFINE (TAO_UTF16_BOM_Factory, + ACE_TEXT ("UTF16_BOM_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_UTF16_BOM_Factory), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) +ACE_FACTORY_DEFINE (TAO_Codeset, TAO_UTF16_BOM_Factory) + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_UTF16_BOM_Factory::TAO_UTF16_BOM_Factory () + : translator_ (0) + , forceBE_ (false) +{ +} + +TAO_UTF16_BOM_Factory::~TAO_UTF16_BOM_Factory () +{ + delete this->translator_; +} + +int +TAO_UTF16_BOM_Factory::init (int argc, ACE_TCHAR *argv[]) +{ + TAO_Codeset_Translator_Factory::init (argc, argv); + + for (int narg = 0; narg < argc;) + { + int consumed = parse_one_arg (argc - narg, &argv[narg]); + if (consumed > 0) + { + narg += consumed; + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t)TAO_UTF16_BOM_Factory parameter error: %s\n") + ACE_TEXT ("Usage: TAO_UTF16_BOM_Factory \"-forceBE\"\n") + , argv[narg] + )); + return -1; + } + } + return 0; +} + +int +TAO_UTF16_BOM_Factory::parse_one_arg (int argc, ACE_TCHAR *argv[]) +{ + int consumed = 0; + if ((argc > 0) && (ACE_OS::strcasecmp (argv[0], ACE_TEXT("-forcebe")) == 0)) + { + this->forceBE_ = true; + consumed = 1; + } + return consumed; +} + +CONV_FRAME::CodeSetId +TAO_UTF16_BOM_Factory::ncs () const +{ + create_translator(); + return this->translator_->ncs(); +} + +CONV_FRAME::CodeSetId +TAO_UTF16_BOM_Factory::tcs () const +{ + create_translator(); + return this->translator_->tcs(); +} + +// Assign either a reference to the existing translator or a new translator +// for input CDR streams +void +TAO_UTF16_BOM_Factory::assign (TAO_InputCDR *cdr) const +{ + if (cdr) + { + create_translator (); + this->assign_i (cdr, this->translator_); + } +} + +// Assign either a reference to the existing translator or a new translator +// for output CDR streams +void +TAO_UTF16_BOM_Factory::assign (TAO_OutputCDR *cdr) const +{ + if (cdr) + { + create_translator (); + this->assign_i (cdr, this->translator_); + } +} + +void +TAO_UTF16_BOM_Factory::create_translator () const +{ + if (this->translator_ == 0) + { + TAO_UTF16_BOM_Factory * pthis = const_cast<TAO_UTF16_BOM_Factory *> (this); + ACE_NEW (pthis->translator_, TAO_UTF16_BOM_Translator (this->forceBE_)); + if (this->translator_ == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO (%P|%t) - UTF16_BOM_Factory: ") + ACE_TEXT ("Cannot create translator\n") + )); + } + } +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/UTF16_BOM_Factory.h b/TAO/tao/Codeset/UTF16_BOM_Factory.h new file mode 100644 index 00000000000..a72652a7458 --- /dev/null +++ b/TAO/tao/Codeset/UTF16_BOM_Factory.h @@ -0,0 +1,71 @@ +// -*- 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/Codeset_Translator_Factory.h" + +#include "tao/Codeset/UTF16_BOM_Translator.h" +#include "tao/Codeset/codeset_export.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Codeset_Export TAO_UTF16_BOM_Factory + : public TAO_Codeset_Translator_Factory +{ +public: + TAO_UTF16_BOM_Factory (); + virtual ~TAO_UTF16_BOM_Factory (); + virtual int init (int argc, ACE_TCHAR *argv[]); + + /// ncs returns the translator's native codeset ID. + CONV_FRAME::CodeSetId ncs () const; + /// tcs returns the translator's transmission codeset ID. + CONV_FRAME::CodeSetId tcs () const; + + /// Assign the translator to the input CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null input CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_InputCDR *) const; + /// Assign the translator to the output CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null output CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_OutputCDR *) const; + +private: + void create_translator () const; + int parse_one_arg (int argc, ACE_TCHAR *argv[]); + +private: + TAO_UTF16_BOM_Translator *translator_; + bool forceBE_; // force big endian wchar, warray, & wstring +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Codeset, TAO_UTF16_BOM_Factory) +ACE_FACTORY_DECLARE (TAO_Codeset, TAO_UTF16_BOM_Factory) + +#include /**/ "ace/post.h" +#endif /* UTF16_BOM_FACTORY_H */ diff --git a/TAO/tao/Codeset/UTF16_BOM_Translator.cpp b/TAO/tao/Codeset/UTF16_BOM_Translator.cpp new file mode 100644 index 00000000000..0feaca04783 --- /dev/null +++ b/TAO/tao/Codeset/UTF16_BOM_Translator.cpp @@ -0,0 +1,444 @@ +// $Id$ + +// ============================================================================ +// 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 "tao/Codeset/UTF16_BOM_Translator.h" +#include "ace/OS_Memory.h" +#include "tao/debug.h" +#include "ace/Log_Msg.h" + +ACE_RCSID (Codeset, + TAO_UTF16_BOM_Translator, + "$Id$") + + + // **************************************************************** + + +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; + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +///////////////////////////// +// TAO_UTF16_BOM_Translator implementation + +TAO_UTF16_BOM_Translator::TAO_UTF16_BOM_Translator (bool forceBE) + : forceBE_(forceBE) +{ + if (TAO_debug_level > 1) + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("TAO (%P|%t) - UTF16_BOM_Translator: ") + ACE_TEXT("forceBE %d\n"), this->forceBE_ ? 1:0 )); +} + +TAO_UTF16_BOM_Translator::~TAO_UTF16_BOM_Translator (void) +{ +} + +// = Documented in $ACE_ROOT/ace/CDR_Stream.h +ACE_CDR::Boolean +TAO_UTF16_BOM_Translator::read_wchar (ACE_InputCDR &cdr, ACE_CDR::WChar &x) +{ + if (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 && + 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, + reinterpret_cast<char *> (&sx), 1,1,2)) + return 0; + +#if defined (ACE_LITTLE_ENDIAN) + ACE_CDR::Short ux; + ACE_CDR::swap_2 (reinterpret_cast<const char*> (&sx), + reinterpret_cast<char *> (&ux)); + x = static_cast<ACE_CDR::WChar> (ux); +#else + x = static_cast<ACE_CDR::WChar> (sx); +#endif // ACE_LITTLE_ENDIAN + return 1; + } + + ACE_UTF16_T buf[2]; + if (len != 4 || !this->read_array (cdr, + 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 (reinterpret_cast<const char*> (&buf[1]), + reinterpret_cast<char *> (&ux)); + x = static_cast<ACE_CDR::WChar> (ux); + } + else + x = 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 = static_cast<ACE_CDR::WChar> (sx); + return 1; + } + return 0; +} + +ACE_CDR::Boolean +TAO_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 (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 + && 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 +TAO_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; + static const 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 = 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] = static_cast<ACE_CDR::WChar> (sb[i]); +#else + if (!must_swap) + { + x[i] = static_cast<ACE_CDR::WChar> (sb[i]); + } + else + { + ACE_CDR::UShort sx; + ACE_CDR::swap_2 (&buf[i*2], reinterpret_cast<char *> (&sx)); + x[i] = 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 +TAO_UTF16_BOM_Translator::read_wchar_array (ACE_InputCDR & cdr, + ACE_CDR::WChar *x, + ACE_CDR::ULong length) +{ + if (length == 0) + return 1; + + if (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 + && 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 +TAO_UTF16_BOM_Translator::write_wchar (ACE_OutputCDR &cdr, + ACE_CDR::WChar x) +{ + return this->write_wchar_i (cdr, x, true); +} + +ACE_CDR::Boolean +TAO_UTF16_BOM_Translator::write_wchar_i (ACE_OutputCDR &cdr, + ACE_CDR::WChar x, + bool allow_BOM) +{ + if (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 + && static_cast<ACE_CDR::Short> (this->minor_version (cdr)) > 1) + { + int len = 0; + ACE_CDR::UShort buffer[2]; + + if( allow_BOM && cdr.byte_order()) + { + len = 2; +#if defined (ACE_LITTLE_ENDIAN) + if (this->forceBE_) + { + // force both the byte order mark and the data to Big Endian order + buffer[0] = ACE_UNICODE_BOM_SWAPPED; + ACE_CDR::swap_2 (reinterpret_cast<const char *> (&x), + reinterpret_cast<char *> (&buffer[1])); + } + else +#endif + { + // store both the byte order mark and the data in native order + buffer[0] = ACE_UNICODE_BOM_CORRECT; + buffer[1] = static_cast<ACE_CDR::Short> (x); + } + } + else + { + // not using a byte order mark + // force it to be big endian w/o BOM + len = 1; + if (cdr.byte_order ()) + ACE_CDR::swap_2 (reinterpret_cast<const char *> (&x), + reinterpret_cast<char *> (buffer)); + else + buffer[0] = static_cast<ACE_CDR::Short> (x); + } + + unsigned char tcsize = + 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 (static_cast<ACE_CDR::Short> (this->minor_version (cdr)) != 0) + { + // GIOP 1.1 simple support + ACE_UTF16_T sx = 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 +TAO_UTF16_BOM_Translator::write_wstring (ACE_OutputCDR & cdr, + ACE_CDR::ULong len, + const ACE_CDR::WChar *x) +{ + // we'll accept a null pointer but only for an empty string + ACE_ASSERT (x != 0 || len == 0); + if (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 + && static_cast<ACE_CDR::Short> (this->minor_version (cdr)) > 1) + { + if (len == 0) // for zero length strings, only write a length of + // zero. The BOM is not needed in this case. + return this->write_4(cdr, &len); + + if (this->forceBE_ && cdr.byte_order()) + { + ACE_CDR::ULong l = (len+1) * + static_cast<ACE_CDR::ULong> ( + ACE_UTF16_CODEPOINT_SIZE); + if (this->write_4 (cdr, &l) && + this->write_2 (cdr, &ACE_UNICODE_BOM_SWAPPED) && + x != 0) + return this->write_swapped_wchar_array_i (cdr, x, len); + } + else + { + ACE_CDR::ULong l = (len+1) * + static_cast<ACE_CDR::ULong> ( + 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 + { + // pre GIOP 1.2: include null terminator in length + 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 +TAO_UTF16_BOM_Translator::write_wchar_array (ACE_OutputCDR & cdr, + const ACE_CDR::WChar *x, + ACE_CDR::ULong length) +{ + if (static_cast<ACE_CDR::Short> (this->major_version (cdr)) == 1 + && 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], false) == 0) + return 0; + + return 1; + } + + return this->write_wchar_array_i (cdr, x, length); +} + +ACE_CDR::Boolean +TAO_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; + static const size_t align = ACE_CDR::SHORT_ALIGN; + if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * length, align, buf) + != 0) + { + return 0; + } + + ACE_UTF16_T *sb = reinterpret_cast<ACE_UTF16_T *> (buf); + + for (size_t i = 0; i < length; ++i) + { + sb[i] = static_cast<ACE_UTF16_T> (x[i]); + } + return 1; + +} + +ACE_CDR::Boolean +TAO_UTF16_BOM_Translator::write_swapped_wchar_array_i (ACE_OutputCDR & cdr, + const ACE_CDR::WChar *x, + ACE_CDR::ULong length) +{ + if (length == 0) + return 1; + char* buf; + static const size_t align = ACE_CDR::SHORT_ALIGN; + if (cdr.adjust (ACE_UTF16_CODEPOINT_SIZE * length, align, buf) + != 0) + { + return 0; + } + + ACE_UTF16_T *sb = reinterpret_cast<ACE_UTF16_T *> (buf); + + for (size_t i = 0; i < length; ++i) + { + ACE_CDR::swap_2 (reinterpret_cast<const char*> (&x[i]), + reinterpret_cast<char *> (&sb[i])); + } + return 1; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/UTF16_BOM_Translator.h b/TAO/tao/Codeset/UTF16_BOM_Translator.h new file mode 100644 index 00000000000..6dbe046621d --- /dev/null +++ b/TAO/tao/Codeset/UTF16_BOM_Translator.h @@ -0,0 +1,101 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file UTF16_BOM_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 "tao/Codeset/codeset_export.h" +#include "tao/Versioned_Namespace.h" +#include "ace/CDR_Stream.h" + + +// **************************************************************** + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class TAO_UTF16_BOM_Translator + * + * @brief Codeset translation specialization - Manages Byte Order Marker + * + * This class performs the codeset translation: + * - Native: UTF16 (i.e. Unicode) + * - Stream: UTF16 with Byte Order Marker + */ +class TAO_Codeset_Export TAO_UTF16_BOM_Translator + : public ACE_WChar_Codeset_Translator +{ +public: + /// constructor + /// @param forceBE: true forces all wchar, warray, and wstrings to big-endian byte order + TAO_UTF16_BOM_Translator (bool forceBE); + + /// Virtual destruction + virtual ~TAO_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_swapped_wchar_array_i (ACE_OutputCDR & cdr, + const ACE_CDR::WChar *x, + ACE_CDR::ULong length); + + + ACE_CDR::Boolean write_wchar_i (ACE_OutputCDR &, + ACE_CDR::WChar , + bool allow_BOM); + +private: + /// if this flag is true, force wchar's to big endian order + bool forceBE_; + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* UTF16_BOM_TRANSLATOR_H */ diff --git a/TAO/tao/Codeset/UTF8_Latin1_Factory.cpp b/TAO/tao/Codeset/UTF8_Latin1_Factory.cpp new file mode 100644 index 00000000000..2298e093c7d --- /dev/null +++ b/TAO/tao/Codeset/UTF8_Latin1_Factory.cpp @@ -0,0 +1,91 @@ +// $Id$ +#include "tao/debug.h" +#include "ace/Dynamic_Service.h" +#include "ace/Log_Msg.h" +#include "tao/Codeset/UTF8_Latin1_Factory.h" + +ACE_STATIC_SVC_DEFINE (TAO_UTF8_Latin1_Factory, + ACE_TEXT ("UTF8_Latin1_Factory"), + ACE_SVC_OBJ_T, + &ACE_SVC_NAME (TAO_UTF8_Latin1_Factory), + ACE_Service_Type::DELETE_THIS + | ACE_Service_Type::DELETE_OBJ, + 0) +ACE_FACTORY_DEFINE (TAO_Codeset, TAO_UTF8_Latin1_Factory) + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +TAO_UTF8_Latin1_Factory::TAO_UTF8_Latin1_Factory() + : translator_ (0) +{ +} + +TAO_UTF8_Latin1_Factory::~TAO_UTF8_Latin1_Factory () +{ + delete this->translator_; +} +int +TAO_UTF8_Latin1_Factory::init (int argc, ACE_TCHAR *argv[]) +{ + TAO_Codeset_Translator_Factory::init (argc, argv); + return 0; +} + +CONV_FRAME::CodeSetId +TAO_UTF8_Latin1_Factory::ncs () const +{ + create_translator(); + return this->translator_->ncs(); +} + +CONV_FRAME::CodeSetId +TAO_UTF8_Latin1_Factory::tcs () const +{ + create_translator(); + return this->translator_->tcs(); +} + +// Assign either a reference to the existing translator or a new translator +// for input CDR streams +void +TAO_UTF8_Latin1_Factory::assign (TAO_InputCDR *cdr) const +{ + if (cdr) + { + create_translator(); + this->assign_i(cdr,this->translator_); + } +} + +// Assign either a reference to the existing translator or a new translator +// for output CDR streams +void +TAO_UTF8_Latin1_Factory::assign (TAO_OutputCDR *cdr) const +{ + if (cdr) + { + create_translator(); + this->assign_i(cdr,this->translator_); + } +} + +void +TAO_UTF8_Latin1_Factory::create_translator () const +{ + if (this->translator_ == 0) + { + TAO_UTF8_Latin1_Factory * pthis = + const_cast <TAO_UTF8_Latin1_Factory *>(this); + ACE_NEW (pthis->translator_, TAO_UTF8_Latin1_Translator); + if (this->translator_ == 0) + { + if (TAO_debug_level) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P|%t) TAO_UTF8_Latin1_Factory cannot ") + ACE_TEXT("create TAO_UTF8_Latin1_Translator\n") + )); + } + } +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/UTF8_Latin1_Factory.h b/TAO/tao/Codeset/UTF8_Latin1_Factory.h new file mode 100644 index 00000000000..292333ad7e0 --- /dev/null +++ b/TAO/tao/Codeset/UTF8_Latin1_Factory.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +// $Id$ + +#ifndef UTF8_LATIN1_FACTORY_H +#define UTF8_LATIN1_FACTORY_H + +#include /**/ "ace/pre.h" +#include "tao/Codeset/codeset_export.h" +#include "ace/Service_Config.h" +#include "tao/Codeset/Codeset_Translator_Factory.h" + +#include "tao/Codeset/UTF8_Latin1_Translator.h" + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +class TAO_Codeset_Export TAO_UTF8_Latin1_Factory + : public TAO_Codeset_Translator_Factory +{ +public: + TAO_UTF8_Latin1_Factory (); + virtual ~TAO_UTF8_Latin1_Factory (); + virtual int init (int argc, ACE_TCHAR *argv[]); + + /// ncs returns the translator's native codeset ID. + CONV_FRAME::CodeSetId ncs () const; + /// tcs returns the translator's transmission codeset ID. + CONV_FRAME::CodeSetId tcs () const; + + /// Assign the translator to the input CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null input CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_InputCDR *) const; + /// Assign the translator to the output CDR. The inherited assign_i is used + /// to assign either a char or wchar translator, depending on the base type + /// of NCS_TO_TCS. A null output CDR is permitted, in which case assign is a + /// no-op. + virtual void assign (TAO_OutputCDR *) const; + +private: + void create_translator () const; + +private: + TAO_UTF8_Latin1_Translator *translator_; +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +ACE_STATIC_SVC_DECLARE_EXPORT (TAO_Codeset, TAO_UTF8_Latin1_Factory) +ACE_FACTORY_DECLARE (TAO_Codeset, TAO_UTF8_Latin1_Factory) + +#include /**/ "ace/post.h" +#endif /* UTF8_LATIN1_FACTORY_H */ diff --git a/TAO/tao/Codeset/UTF8_Latin1_Translator.cpp b/TAO/tao/Codeset/UTF8_Latin1_Translator.cpp new file mode 100644 index 00000000000..204a1dc0bd6 --- /dev/null +++ b/TAO/tao/Codeset/UTF8_Latin1_Translator.cpp @@ -0,0 +1,224 @@ +// -*- C++ -*- +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// UTF8_Latin1_Translator.cpp +// +// = DESCRIPTION +// Defines the methods required to convert UTF-8 based unicode strings +// to the Latin-1 codeset. +// +// = AUTHOR +// Phil Mesnier <mesnier_p@ociweb.com> +// +// ============================================================================ +#include "tao/Codeset/UTF8_Latin1_Translator.h" +#include "tao/debug.h" +#include "ace/OS_Memory.h" + +// **************************************************************** + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +///////////////////////////// +// UTF8_Latin1_Translator implementation + +TAO_UTF8_Latin1_Translator::TAO_UTF8_Latin1_Translator () +{ +} + +TAO_UTF8_Latin1_Translator::~TAO_UTF8_Latin1_Translator (void) +{ +} + +// = Documented in $ACE_ROOT/ace/CDR_Stream.h +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::read_char (ACE_InputCDR &cdr, ACE_CDR::Char &x) +{ + // We cannot have a codepoint > 0xBF at this point, since we are expecting + // only one single char. + ACE_CDR::Octet ox; + if (this->read_1 (cdr, &ox)) + { + if (ox < 0xC0) + { + x = ox; + return 1; + } + } + return 0; +} + +ACE_CDR::ULong +TAO_UTF8_Latin1_Translator::read_char_i (ACE_InputCDR &cdr, ACE_CDR::Char &x) +{ + // This will read up to 2 octets and combine them into one char if possible + ACE_CDR::Octet upper; + if (this->read_1 (cdr, &upper)) + { + if ( upper >= 0xC4) // Anything with a leading char > 110001xx converts + // to a codepoint value > 0x00FF, thus won't fit in + // a single char. + return 0; + if ( upper < 0xC0 ) + { + x = static_cast<ACE_CDR::Char>(upper); + return 1; + } + ACE_CDR::Octet lower; + if (this->read_1 (cdr, &lower)) + { + ACE_CDR::Octet final = ((upper & 0xBF) << 6) + (lower & 0xC0); + x = static_cast<ACE_CDR::Char>(final); + return 2; + }; + } + return 0; +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::read_string (ACE_InputCDR &cdr, + ACE_CDR::Char *&x) +{ + ACE_CDR::ULong len; + if (!cdr.read_ulong (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()) + { + ACE_NEW_RETURN (x, + ACE_CDR::Char [len], + 0); + // pos keeps track of the character position, it will never be + // greater than len + size_t pos = 0; + ACE_CDR::ULong incr = 1; + for (ACE_CDR::ULong i = 0; incr > 0 && i < len; i += incr) + { + incr = this->read_char_i(cdr,x[pos++]); + } + if (incr > 0) + 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::Char[1], + 0); + x[0] = '\x00'; + return 1; + } + x = 0; + return 0; +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::read_char_array (ACE_InputCDR & cdr, + ACE_CDR::Char *x, + ACE_CDR::ULong length) +{ + if (length == 0) + return 1; + + for (size_t i = 0; i < length; ++i) + if (!this->read_char(cdr,x[i])) + return 0; + + return 1; +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::write_char (ACE_OutputCDR &cdr, + ACE_CDR::Char x) +{ + ACE_CDR::Octet ox = x; + if (ox < 0xC0) + return this->write_1 (cdr,&ox); + else + { // character cannot be represented in a single octet + errno = EINVAL; + return 0; + } +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::write_char_i (ACE_OutputCDR &cdr, + ACE_CDR::Char x) +{ + // @@@ Strictly speaking, we should test for 7F < x < C0 and do + // something else in that case, but for now we will just let it + // pass. + + ACE_CDR::Octet ox = x; + if (ox < 0xC0) + return this->write_1 (cdr,&ox); + else + { // character cannot be represented in a single octet + // Since the source will never be > 0xFF, we don't have to worry about + // using a third octet. + ACE_CDR::Octet upper = 0xC0 + (ox >> 6); + ACE_CDR::Octet lower = 0x80 + (ox & 0x3F); + if (this->write_1(cdr, &upper)) + return this->write_1(cdr, &lower); + } + return 0; +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::write_string (ACE_OutputCDR & cdr, + ACE_CDR::ULong len, + const ACE_CDR::Char *x) +{ + // we'll accept a null pointer but only for an empty string + if (x == 0 && len != 0) + return 0; + + ACE_CDR::ULong l = len; + // Compute the real buffer size by adding in multi-byte codepoints. + for (ACE_CDR::ULong i = 0; i < len; i++) + if (static_cast<ACE_CDR::Octet>(x[i]) > 0xbf) l++; + + // Always add one for the nul + l++; + if (cdr.write_ulong (l)) + { + for (ACE_CDR::ULong i = 0; i < len; ++i) + { + if (this->write_char_i (cdr,x[i]) == 0) + return 0; + } + ACE_CDR::Octet s = 0; + return this->write_1 (cdr, &s); + } + return 0; +} + +ACE_CDR::Boolean +TAO_UTF8_Latin1_Translator::write_char_array (ACE_OutputCDR & cdr, + const ACE_CDR::Char *x, + ACE_CDR::ULong length) +{ + if (length == 0) + return 1; + + for (size_t i = 0; i < length; ++i) + // We still have to write each char individually, as any translated + // value may fail to fit in a single octet. + if (this->write_char (cdr, x[i]) == 0) + return 0; + + return 1; +} + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Codeset/UTF8_Latin1_Translator.h b/TAO/tao/Codeset/UTF8_Latin1_Translator.h new file mode 100644 index 00000000000..791ea994d43 --- /dev/null +++ b/TAO/tao/Codeset/UTF8_Latin1_Translator.h @@ -0,0 +1,89 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file UTF8_Latin1_Translator.h + * + * $Id$ + * + * + * + * @author Phil Mesnier <mesnier_p@ociweb.com> + */ +//============================================================================= + +#ifndef UTF8_LATIN1_TRANSLATOR_H +#define UTF8_LATIN1_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 "tao/Codeset/codeset_export.h" +#include "tao/Versioned_Namespace.h" +#include "ace/CDR_Stream.h" + +// **************************************************************** + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class UTF8_Latin1_Translator + * + * @brief Codeset translation specialization - Manages Byte Order Marker + * + * This class performs the codeset translation: + * - Native: ISO-8859-1 (i.e. Latin 1) + * - Stream: UTF-8 (8 bit unicode mapping) + * + * When writing chars, it is possible to raise a DATA_CONVERSION exception + * because some valid Latin codepoints map to 2-byte utf-8 codepoints. + * + * When reading strings, it is possible to raise a DATA_CONVERSION exception + * because the string may include utf-8 unicode codepoints > 0x00FF. + */ +class TAO_Codeset_Export TAO_UTF8_Latin1_Translator + : public ACE_Char_Codeset_Translator +{ +public: + /// constructor + TAO_UTF8_Latin1_Translator (); + + /// Virtual destruction + virtual ~TAO_UTF8_Latin1_Translator (void); + + // = Documented in $ACE_ROOT/ace/CDR_Stream.h + virtual ACE_CDR::Boolean read_char (ACE_InputCDR &, + ACE_CDR::Char &); + virtual ACE_CDR::Boolean read_string (ACE_InputCDR &, + ACE_CDR::Char *&); + virtual ACE_CDR::Boolean read_char_array (ACE_InputCDR &, + ACE_CDR::Char *, + ACE_CDR::ULong); + virtual ACE_CDR::Boolean write_char (ACE_OutputCDR &, + ACE_CDR::Char); + virtual ACE_CDR::Boolean write_string (ACE_OutputCDR &, + ACE_CDR::ULong, + const ACE_CDR::Char *); + virtual ACE_CDR::Boolean write_char_array (ACE_OutputCDR &, + const ACE_CDR::Char *, + ACE_CDR::ULong); + virtual ACE_CDR::ULong ncs () {return 0x00010001U;} + virtual ACE_CDR::ULong tcs () {return 0x05010001U;} + +private: + ACE_CDR::ULong read_char_i (ACE_InputCDR &, + ACE_CDR::Char &); + + ACE_CDR::Boolean write_char_i (ACE_OutputCDR &, + ACE_CDR::Char); + +}; + +TAO_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* UTF8_LATIN1_TRANSLATOR_H */ diff --git a/TAO/tao/Codeset/codeset_export.h b/TAO/tao/Codeset/codeset_export.h new file mode 100644 index 00000000000..0c7a2863484 --- /dev/null +++ b/TAO/tao/Codeset/codeset_export.h @@ -0,0 +1,40 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl +// ------------------------------ +#ifndef TAO_CODESET_EXPORT_H +#define TAO_CODESET_EXPORT_H + +#include "ace/config-all.h" + +#if defined (TAO_AS_STATIC_LIBS) +# if !defined (TAO_CODESET_HAS_DLL) +# define TAO_CODESET_HAS_DLL 0 +# endif /* ! TAO_CODESET_HAS_DLL */ +#else +# if !defined (TAO_CODESET_HAS_DLL) +# define TAO_CODESET_HAS_DLL 1 +# endif /* ! TAO_CODESET_HAS_DLL */ +#endif + +#if defined (TAO_CODESET_HAS_DLL) && (TAO_CODESET_HAS_DLL == 1) +# if defined (TAO_CODESET_BUILD_DLL) +# define TAO_Codeset_Export ACE_Proper_Export_Flag +# define TAO_CODESET_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define TAO_CODESET_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* TAO_CODESET_BUILD_DLL */ +# define TAO_Codeset_Export ACE_Proper_Import_Flag +# define TAO_CODESET_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define TAO_CODESET_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* TAO_CODESET_BUILD_DLL */ +#else /* TAO_CODESET_HAS_DLL == 1 */ +# define TAO_Codeset_Export +# define TAO_CODESET_SINGLETON_DECLARATION(T) +# define TAO_CODESET_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* TAO_CODESET_HAS_DLL == 1 */ + +#endif /* TAO_CODESET_EXPORT_H */ + +// End of auto generated file. |