474 lines
13 KiB
C++
474 lines
13 KiB
C++
//
|
|
// The developer of the original code and/or files is Tripwire, Inc.
|
|
// Portions created by Tripwire, Inc. are copyright (C) 2000-2019 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())
|
|
{
|
|
#ifdef DEBUG
|
|
std::cerr << "*** Error Resource_Class::Get() [" __FILE__ ":" << __LINE__ << "]: Resource not found\n";
|
|
#endif
|
|
|
|
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
|
|
} // namespace rsc
|
|
} // namespace 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
|