// // The developer of the original code and/or files is Tripwire, Inc. // Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire, // Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights // reserved. // // This program is free software. The contents of this file are subject // to the terms of the GNU General Public License as published by the // Free Software Foundation; either version 2 of the License, or (at your // option) any later version. You may redistribute it and/or modify it // only in compliance with the GNU General Public License. // // This program is distributed in the hope that it will be useful. // However, this program is distributed AS-IS WITHOUT ANY // WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS // FOR A PARTICULAR PURPOSE. Please see the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, // USA. // // Nothing in the GNU General Public License or any other license to use // the code or files shall permit you to use Tripwire's trademarks, // service marks, or other intellectual property without Tripwire's // prior written consent. // // If you have any questions, please contact Tripwire, Inc. at either // info@tripwire.org or www.tripwire.org. // // // Name....: resources.h // Date....: 05/06/99 // Creator.: Robert DiFalco (rdifalco) // // Abstraction for a keyed collection of resources including a // specialization for dealing with message resources. // #ifndef __RESOURCES_H #define __RESOURCES_H //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Dependencies //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #include // for: Resource Table Implementation #include "debug.h" // for: ASSERT and Trace #include "error.h" // for: eInternal //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Classes Declared in this module //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template< class KEY, class RSC > class cResources_; template< class KEY, class CHR > class cMessages_; //============================================================================= // cResources_ -- Keyed collection of resources //----------------------------------------------------------------------------- // SYNOPSIS: // Used to maintain a table of resources that are indexed by KEY // type values. The type can be any valid type that is // assignable. // // CONSTRAINTS: // must be a valid key type for the std::map concept // must be a valid value type for the std::map concept. // // INVARIANTS: // // template< class KeyT, class RscT > class cResources_ { //--Type Definitions private: typedef std::map< KeyT, RscT > Table; // Storage Rep public: // Type definitions typedef KeyT Key; // The resource id typedef KeyT& KeyRef; typedef const KeyT& ConstKeyRef; typedef RscT Value; // The managed resource typedef Value& ValueRef; typedef const Value& ConstValueRef; typedef typename Table::value_type Pair; //--Interface. public: // Observers ConstValueRef Get( ConstKeyRef ) const; // Modifiers void Put( const Pair*, const Pair* ); void Put( ConstKeyRef, Value ); //--Implementation. protected: static ConstValueRef DefaultValueRef(); // NOTE: private: Table m_table; }; //============================================================================= // cMessages_ -- Specialization of Resources_ for message strings //----------------------------------------------------------------------------- // SYNOPSIS: // Specialization of cResources_ to store message strings // instead of generalized resource objects. In the future this can // be refactored to use message objects so that they can come from // a dynamic source (i.e., not a string-literal) such as persistant // storage or some algorithm based on the concatenation of elements. // The cMessages_ abstraction allows a program to be // character type independent so that it may use ANSI, MBCS, or // UNICODE within the same application instance. This is achieved by // not allowing the client to expect a specific character sequence // representation, such as the near ubiquitous const char*. For // example: // // const char* psz = messages.GetAnsi( IDS_SOMESTRING ); // // The above call requires the caller to be responsible for memory // resources in the case of a conversion. However, there is no // clear way to know up front how many bytes will be required. // Another equally unsatisfactory solution is to allocate the // memory within cMessages and require the caller to release the // the resources when they are done with the message. If we instead // require calls in the following form: // // std::string str = messages.GetAnsi( IDS_SOMESTRING ); // // We can allows assume proper resource use regardless of whether // a simple character pointer is returned or newly allocated // resources used to convert the stored message. // // // CONSTRAINTS: // As with all classes which manipulate character sequences, CHAR // must be a valid character type as defined by the STDCPP standard. // // template< class KeyT, class CharT > class cMessages_ : public cResources_< KeyT, const CharT* > { //--Type definitions protected: typedef cResources_ Resources; public: typedef std::basic_string String; typedef const KeyT& ConstKeyRef; //--Interface. public: String Get ( ConstKeyRef ) const; std::string GetAnsi( ConstKeyRef ) const; #if SUPPORTS_WCHART std::wstring GetWide( ConstKeyRef ) const; #endif//SUPPORTS_WCHART }; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // IMPLEMENTATION: cResources_ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // NOTE: Macros to ease any changes in template arguments #define Resource_Template template< class KeyT, class RscT > #define Resource_Class cResources_< KeyT, RscT > Resource_Template void Resource_Class::Put( const Pair* beg, const Pair* end ) { for ( const Pair* at = beg; at != end; ++at ) { if ( !m_table.insert( *at ).second ) { ASSERTMSG( 0, "Resource key already exists!" ); // throw eInternal( "Resource key already exists!" ); } } } // By value allows the user to Resource_table.Put( 6, "Literal" ); Resource_Template inline void Resource_Class::Put( ConstKeyRef id, Value sResource ) { if ( m_table.insert( Pair( id, sResource ) ).second == false ) { ASSERTMSG( 0, "Resource key already exists!" ); // throw eInternal( "Resource key already exists!" ); } } Resource_Template typename Resource_Class::ConstValueRef Resource_Class::Get( ConstKeyRef id ) const { typename Table::const_iterator at = m_table.find( id ); if ( at == m_table.end() ) { #if IS_UNIX #ifdef _DEBUG std::cerr << "*** Error Resource_Class::Get() [" __FILE__ ":" << __LINE__ << "]: Resource not found\n"; #endif #else ASSERTMSG( 0, "Resource does not exist!" ); #endif // TSS_Raise( eInternal, "Resource does not exist!" ); return DefaultValueRef(); } else { return (*at).second; } } Resource_Template typename Resource_Class::ConstValueRef Resource_Class::DefaultValueRef() { static Value _default; return _default; } #undef Resource_Template //template< class KeyT, class RscT > #undef Resource_Class //Resources_ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // IMPLEMENTATION: cMessages_ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // NOTE: Macros to ease any changes in template arguments #define Message_Template template< class KeyT, class CharT > #define Message_Class cMessages_< KeyT, CharT > Message_Template inline typename Message_Class::String Message_Class::Get( ConstKeyRef id ) const { typename Message_Class::Value msg = Resources::Get( id ); return ( msg == this->DefaultValueRef() ) ? String() : String( msg ); } /// NOTE: Can't have anonymous NS in Headers namespace tss { namespace rsc { /* WARNING:RAD -- Cannot use StringUtil or CodeConvert since these use ErrorMessages and String Resources! */ inline void ToNTMBS( std::string& nbs, const std::string& src ) { nbs.assign( src ); } #if SUPPORTS_WCHART inline void ToNTMBS( std::string& nbs, const std::wstring& wcs ) { nbs.resize( MB_CUR_MAX * wcs.size() ); size_t nWrote = ::wcstombs( const_cast< char * >( nbs.c_str() ), wcs.c_str(), nbs.size() + 1 ); if ( nWrote == (size_t)-1 ) { ASSERTMSG( false, "Conversion error in cMessages_!" ); // throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); } nbs.resize( nWrote ); } inline void ToNTWCS( std::wstring& dst, const std::wstring& src ) { dst.assign( src ); } inline void ToNTWCS( std::wstring& wcs, const std::string& nbs ) { wcs.resize( nbs.size() ); size_t nWrote = ::mbstowcs( const_cast< wchar_t * >( wcs.c_str() ), nbs.c_str(), wcs.size() + 1 ); if ( nWrote == (size_t)-1 ) { ASSERTMSG( false, "Conversion error in cMessages_!" ); // throw eCharacterEncoding( TSS_GetString( cCore, core::STR_ERR_BADCHAR ) ); } wcs.resize( nWrote ); } #endif//SUPPORTS_WCHART }//rsc:: }//tss:: Message_Template inline std::string Message_Class::GetAnsi( ConstKeyRef id ) const { typename Message_Class::Value msg = Resources::Get( id ); if ( msg == this->DefaultValueRef() ) { return std::string(); } else { std::string nbs; tss::rsc::ToNTMBS( nbs, String( msg ) ); return nbs; } } #if SUPPORTS_WCHART Message_Template inline std::wstring Message_Class::GetWide( ConstKeyRef id ) const { Value msg = Resources::Get( id ); if ( msg == DefaultValueRef() ) { return std::string(); } else { std::wstring wcs; tss::rsc::ToNTWCS( wcs, String( msg ) ); return wcs; } } #endif//SUPPORTS_WCHART #undef Message_Template #undef Message_Class #endif//__RESOURCES_H //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE * OLD CODE //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #ifdef RAD_OLDCODE //============================================================================= // cMessages_ -- Specializations //----------------------------------------------------------------------------- // SYNOPSIS: // MSVC does not yet support specializations. As a compromise, we fully // specialize on TCHR but assume a key type of "const int". // // for SUNPro enums are ints, not const ints #if IS_SUNPRO #define ENUM_TYPE int #else #define ENUM_TYPE const int #endif template<> class cMessages_ : public cResources_< ENUM_TYPE, const char* > { protected: typedef cResources_< ENUM_TYPE, const char* > Resources; public: typedef std::string String; typedef int ConstKeyRef; // Better than String Get( ConstKeyRef id ) const { Value msg = Resources::Get( id ); return ( msg != DefaultValueRef() ) ? String( msg ) : String(); } String GetAnsi( ConstKeyRef id ) const { return Get( id ); } #if SUPPORTS_WCHART std::wstring GetWide( ConstKeyRef id ) const { Value msg = Resources::Get( id ); if ( msg == DefaultValueRef() ) { return std::wstring(); } else { String::size_type N = String::traits_type::length( msg ); std::wstring dst( N, 0x00 ); std::ctype< wchar_t >().widen( msg, msg + N, dst.begin() ); return dst; } } #endif//SUPPORTS_WCHART }; #if SUPPORTS_WCHART template<> class cMessages_ : public cResources_< const int, const wchar_t* > { protected: typedef cResources_ Resources; public: typedef std::wstring String; typedef int ConstKeyRef; // Better than String Get( ConstKeyRef id ) const { Value msg = Resources::Get( id ); if( msg != DefaultValueRef() ) return String( msg ); else return String(); } std::string GetAnsi( ConstKeyRef id ) const { Value msg = Resources::Get( id ); if ( msg == DefaultValueRef() ) { return std::string(); } else { String::size_type N = String::traits_type::length( msg ); std::string dst( N, 0x00 ); std::ctype().narrow( msg, msg + N, '?', dst.begin() ); return dst; } } String GetWide( ConstKeyRef id ) const { return Get( id ); } }; #endif//SUPPORTS_WCHART #endif//RAD_OLDCODE