549 lines
15 KiB
C++
549 lines
15 KiB
C++
//
|
|
// 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 <map> // 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_<KEY,REZ> -- Keyed collection of resources
|
|
//-----------------------------------------------------------------------------
|
|
// SYNOPSIS:
|
|
// Used to maintain a table of resources that are indexed by KEY
|
|
// type values. The <REZ> type can be any valid type that is
|
|
// assignable.
|
|
//
|
|
// CONSTRAINTS:
|
|
// <KEY> must be a valid key type for the std::map concept
|
|
// <REZ> 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_<KEY,CHAR> -- Specialization of Resources_ for message strings
|
|
//-----------------------------------------------------------------------------
|
|
// SYNOPSIS:
|
|
// Specialization of cResources_<KEY,REZ> 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_<KEY,CHAR> 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_<KeyT, const CharT* >
|
|
Resources;
|
|
|
|
public:
|
|
|
|
typedef std::basic_string<CharT> 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_<KEY_TYPE, RESOURCE_TYPE>
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// 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_<KeyT,RscT>
|
|
|
|
|
|
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// IMPLEMENTATION: cMessages_<KEY_TYPE, RESOURCE_TYPE>
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
// 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_<char & wchar_t> -- 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_<ENUM_TYPE, char> :
|
|
public cResources_< ENUM_TYPE, const char* >
|
|
{
|
|
protected:
|
|
|
|
typedef
|
|
cResources_< ENUM_TYPE, const char* >
|
|
Resources;
|
|
|
|
public:
|
|
|
|
typedef std::string String;
|
|
typedef int ConstKeyRef; // Better than <const int&>
|
|
|
|
|
|
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_<const int, wchar_t> :
|
|
public cResources_< const int, const wchar_t* >
|
|
{
|
|
protected:
|
|
|
|
typedef
|
|
cResources_<const int, const wchar_t* >
|
|
Resources;
|
|
|
|
public:
|
|
|
|
typedef std::wstring String;
|
|
typedef int ConstKeyRef; // Better than <const int&>
|
|
|
|
|
|
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<CharT>().narrow( msg, msg + N, '?', dst.begin() );
|
|
|
|
return dst;
|
|
}
|
|
}
|
|
|
|
String GetWide( ConstKeyRef id ) const
|
|
{
|
|
return Get( id );
|
|
}
|
|
};
|
|
|
|
#endif//SUPPORTS_WCHART
|
|
|
|
#endif//RAD_OLDCODE
|
|
|
|
|