478 lines
15 KiB
C++
478 lines
15 KiB
C++
#ifndef __LOCIMPL_H
|
||
#define __LOCIMPL_H
|
||
#pragma option push -b -a8 -pc -Vx- -Ve- -w-inl -w-aus -w-sig
|
||
// -*- C++ -*-
|
||
/***************************************************************************
|
||
*
|
||
* rw/locimpl - Declarations for the Standard Library locale private
|
||
* implementation classes.
|
||
*
|
||
***************************************************************************
|
||
*
|
||
* Copyright (c) 1994-1999 Rogue Wave Software, Inc. All Rights Reserved.
|
||
*
|
||
* This computer software is owned by Rogue Wave Software, Inc. and is
|
||
* protected by U.S. copyright laws and other laws and by international
|
||
* treaties. This computer software is furnished by Rogue Wave Software,
|
||
* Inc. pursuant to a written license agreement and may be used, copied,
|
||
* transmitted, and stored only in accordance with the terms of such
|
||
* license and with the inclusion of the above copyright notice. This
|
||
* computer software or any other copies thereof may not be provided or
|
||
* otherwise made available to any other person.
|
||
*
|
||
* U.S. Government Restricted Rights. This computer software is provided
|
||
* with Restricted Rights. Use, duplication, or disclosure by the
|
||
* Government is subject to restrictions as set forth in subparagraph (c)
|
||
* (1) (ii) of The Rights in Technical Data and Computer Software clause
|
||
* at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
|
||
* Commercial Computer Software – Restricted Rights at 48 CFR 52.227-19,
|
||
* as applicable. Manufacturer is Rogue Wave Software, Inc., 5500
|
||
* Flatiron Parkway, Boulder, Colorado 80301 USA.
|
||
*
|
||
**************************************************************************/
|
||
|
||
#ifndef __STD_RW_LOCIMPL__
|
||
#define __STD_RW_LOCIMPL__
|
||
|
||
#include <stdcomp.h>
|
||
|
||
// Macro for declaring all the has_facet and use_facet functions to be friends.
|
||
|
||
#ifndef _RWSTD_NO_FRIEND_TEMPLATES
|
||
#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
|
||
#define _RWSTD_FRIEND_USE_HAS_FACET \
|
||
template <class Facet> friend \
|
||
inline const Facet& use_facet (const locale&); \
|
||
template <class Facet> friend \
|
||
inline bool has_facet (const locale&) _RWSTD_THROW_SPEC_NULL;
|
||
#else
|
||
#define _RWSTD_FRIEND_USE_HAS_FACET \
|
||
template <class Facet> friend \
|
||
inline const Facet& use_facet (const locale&,Facet*); \
|
||
template <class Facet> friend \
|
||
inline bool has_facet (const locale&,Facet*) _RWSTD_THROW_SPEC_NULL;
|
||
#endif // _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
|
||
#else
|
||
#define _RWSTD_FRIEND_USE_HAS_FACET public:
|
||
#endif
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
namespace __rwstd {
|
||
using std::use_facet;
|
||
using std::locale;
|
||
#endif
|
||
|
||
// Implementation class template -- timepunct<charT>
|
||
//
|
||
// A facet such as this should have been included in the standard. We just
|
||
// declare it here; the definition occurs below, after locale::facet has been
|
||
// defined.
|
||
|
||
template <class charT> class timepunct;
|
||
|
||
#ifdef __TURBOC__
|
||
|
||
// Instantiations that go in the library:
|
||
|
||
template class _RWSTDExport timepunct<char>;
|
||
#ifndef _RWSTD_NO_WIDE_CHAR
|
||
template class _RWSTDExport timepunct<wchar_t>;
|
||
#endif
|
||
|
||
#endif // __TURBOC__
|
||
|
||
// Implementation forward declarations:
|
||
|
||
class _RWSTDExport locale_imp;
|
||
class _RWSTDExport facet_imp;
|
||
|
||
class _RWSTDExport digit_map_base;
|
||
template <class charT> class _RWSTDExportTemplate digit_map;
|
||
template <class charT> class _RWSTDExportTemplate keyword_def;
|
||
template <class charT> class _RWSTDExportTemplate keyword_map;
|
||
template <class charT> class _RWSTDExportTemplate keyword_cracker;
|
||
|
||
class _RWSTDExport digit_reader_base;
|
||
template <class charT> class digit_reader_base_1;
|
||
template <class charT,class InputIterator>
|
||
class _RWSTDExportTemplate digit_reader;
|
||
|
||
class _RWSTDExport digit_writer_base;
|
||
template <class charT>
|
||
class _RWSTDExportTemplate digit_writer_base_1;
|
||
template <class charT,class OutputIterator>
|
||
class _RWSTDExportTemplate digit_writer;
|
||
|
||
// ------------------------------------
|
||
// Implementation class -- ref_counted.
|
||
// ------------------------------------
|
||
|
||
// Common base class for reference-counted classes. Currently used only by
|
||
// locale_imp and facet_imp, but could be used more generally.
|
||
|
||
class _RWSTDExport ref_counted {
|
||
friend class _RW_STD::locale;
|
||
|
||
size_t __ref_count;
|
||
#ifdef _RWSTD_MULTI_THREAD
|
||
_RWSTDMutex __mutex;
|
||
#endif
|
||
|
||
protected:
|
||
ref_counted (size_t initial_refs):
|
||
__ref_count(initial_refs) { }
|
||
|
||
// Ensure derived class destructors are always virtual.
|
||
virtual ~ref_counted (void);
|
||
|
||
// Does protected access make these accessible to friends of derived classes?
|
||
// We're about to find out ...
|
||
|
||
static void add_reference (ref_counted *ob) {
|
||
STDGUARD(ob->__mutex);
|
||
++ob->__ref_count;
|
||
}
|
||
|
||
static void remove_reference (ref_counted *ob) {
|
||
size_t refs;
|
||
{
|
||
STDGUARD(ob->__mutex);
|
||
refs=--ob->__ref_count;
|
||
}
|
||
if (!refs)
|
||
delete ob;
|
||
}
|
||
|
||
static void add_possible_reference (ref_counted *ob) {
|
||
if (ob)
|
||
add_reference(ob);
|
||
}
|
||
|
||
static void remove_possible_reference (ref_counted *ob) {
|
||
if (ob)
|
||
remove_reference(ob);
|
||
}
|
||
};
|
||
|
||
// We would prefer to define locale::id and locale::facet entirely as nested
|
||
// classes of locale, but current compilers have problems with out-of-line
|
||
// definition of members of such classes, so we have to derive most of their
|
||
// behavior from unnested implementation classes:
|
||
|
||
// --------------------------------------
|
||
// Implementation class -- locale_id_imp.
|
||
// --------------------------------------
|
||
|
||
class _RWSTDExport locale_id_imp {
|
||
protected:
|
||
_MUTABLE size_t __id_value;
|
||
static size_t __last_used_id;
|
||
|
||
locale_id_imp() : __id_value(0) {;}
|
||
|
||
#ifdef _RWSTD_MULTI_THREAD
|
||
static _RWSTDMutex __mutex;
|
||
#endif
|
||
|
||
void __initid () const;
|
||
};
|
||
|
||
// ----------------------------------
|
||
// Implementation class -- facet_imp.
|
||
// ----------------------------------
|
||
|
||
class _RWSTDExport facet_imp: public ref_counted
|
||
{
|
||
_RWSTD_FRIEND_USE_HAS_FACET
|
||
friend class locale_imp;
|
||
friend class _RW_STD::locale;
|
||
public:
|
||
enum {
|
||
__facet_cat = 0,
|
||
__ok_implicit = 0,
|
||
__initdone = 1
|
||
};
|
||
|
||
private:
|
||
int __flags;
|
||
int __category; // Should be same type as locale::category
|
||
|
||
protected:
|
||
facet_imp (size_t refs, int cat=0):
|
||
ref_counted(refs), __flags(0), __category(cat) { }
|
||
|
||
// __initfacet() is called by locale::__install the first time a facet is
|
||
// installed in its first locale. Some facets override it to set up private
|
||
// data that depends on return values of virtual do_xxx functions that can't
|
||
// be called yet in a constructor.
|
||
virtual void __initfacet (const locale*) { }
|
||
};
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
}
|
||
#endif
|
||
|
||
#include <rw/locvector>
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
namespace __rwstd {
|
||
#endif
|
||
|
||
// -----------------------------------
|
||
// Implementation class -- locale_imp.
|
||
// -----------------------------------
|
||
|
||
class _RWSTDExport locale_imp: public ref_counted
|
||
{
|
||
_RWSTD_FRIEND_USE_HAS_FACET
|
||
friend class _RW_STD::locale;
|
||
|
||
// Same type as locale::category ...
|
||
typedef int locale_category;
|
||
locale_vector<_RW_STD::string> names_;
|
||
locale_vector<facet_imp*> vec_;
|
||
|
||
locale_category native_cats_;
|
||
locale_category named_cats_;
|
||
_RW_STD::string big_name_;
|
||
bool named_;
|
||
|
||
locale_imp (size_t sz=36, size_t refs=0);
|
||
locale_imp (const locale_imp&,size_t refs);
|
||
~locale_imp ();
|
||
|
||
public:
|
||
inline facet_imp *get_facet (size_t i) const
|
||
{ return i<vec_.size()? vec_[i] : NULL; }
|
||
|
||
private:
|
||
const char *category_name (locale_category) const;
|
||
|
||
// Map C library LC_xxx constants into facet categories.
|
||
static locale_category map_category (locale_category);
|
||
|
||
// Parse a locale name into category names.
|
||
static bool parse_name (locale_vector<_RW_STD::string>&,const char*);
|
||
|
||
// Clean up name if necessary
|
||
static _RW_STD::string clean_name(_RW_STD::string s)
|
||
{
|
||
#ifdef __BORLANDC__
|
||
return _RW_STD::string(s,s.find('=')+1);
|
||
#else
|
||
return s;
|
||
#endif // __BORLANDC__
|
||
}
|
||
|
||
// Combine category names to create a locale name.
|
||
static bool build_name (_RW_STD::string&,const locale_vector<_RW_STD::string>&);
|
||
};
|
||
|
||
// ---------------------------------------
|
||
// Implementation class -- digit_map_base.
|
||
// ---------------------------------------
|
||
|
||
// A place to stash some static constants, so that each instantiation of the
|
||
// derived class rwstd::digit_map does not have to have a separate copy.
|
||
|
||
struct _RWSTDExport digit_map_base {
|
||
enum { zero, minus, plus, X, x, E, e };
|
||
static const char punct_chars[7]; // "0-+XxEe"
|
||
static const char digit_chars[22]; // "0123456789ABCDEFabcdef"
|
||
static const char char_values[22]; // Corresponding values in range 0-15
|
||
};
|
||
|
||
// --------------------------------------------------
|
||
// Implementation class template -- digit_map<charT>.
|
||
// --------------------------------------------------
|
||
|
||
// Maps digits into their corresponding numeric values, and caches widened
|
||
// equivalents of some number-related punctuation characters that don't depend
|
||
// on the numpunct facet. A private instance of this class is hidden in
|
||
// ctype<charT> for use by numeric conversion facets. A call to init must
|
||
// precede the first call to eval if is_inited() is false. Eval returns 0-15
|
||
// if argument is a valid digit, a negative value otherwise.
|
||
//
|
||
// Specialized for char for performance. The specialization assumes digits
|
||
// fit into the char code-set in an ASCII-like manner ('0'..'9' contiguous,
|
||
// 'A'..'F' contiguous, 'a'..'f' contiguous, '0' < 'A' < 'a').
|
||
|
||
_RWSTD_TEMPLATE
|
||
class _RWSTDExportTemplate digit_map<char>:
|
||
public digit_map_base
|
||
{
|
||
public:
|
||
typedef char char_type;
|
||
|
||
bool is_inited (void) const { return true; }
|
||
const char *get_punct (void) const { return punct_chars; }
|
||
inline int eval (char c) const;
|
||
static inline const digit_map<char>&
|
||
get_digit_map (const _RW_STD::ctype<char>&);
|
||
};
|
||
|
||
// Inline members of digit_map<char>:
|
||
//
|
||
// (Note that the definition of get_digit_map is in <rw/ctype> because it
|
||
// has to come after the definition of ctype<char>.)
|
||
|
||
inline int digit_map<char>::eval (char c) const {
|
||
int num=c;
|
||
if ((num-='0')>9) {
|
||
if (((num-=('A'-'0'))>5 && (num-=('a'-'A'))>5) || (num+=10)<10)
|
||
num=-1;
|
||
}
|
||
return num;
|
||
}
|
||
|
||
template <class charT>
|
||
class _RWSTDExportTemplate digit_map:
|
||
public digit_map_base
|
||
{
|
||
bool inited;
|
||
charT punct_array[7];
|
||
charT digit_array[22];
|
||
char value_array[22];
|
||
public:
|
||
typedef charT char_type;
|
||
|
||
digit_map (void): inited(false) { }
|
||
bool is_inited (void) const { return inited; }
|
||
void init (const _RW_STD::ctype<charT>& ct);
|
||
const charT *get_punct (void) const { return punct_array; }
|
||
int eval (charT) const;
|
||
|
||
// Can-opener for getting the digit_map out of a ctype. (Works because of
|
||
// the friend declaration in ctype_helper<charT> below.)
|
||
static inline const digit_map<charT>&
|
||
get_digit_map (const _RW_STD::ctype<charT>& ct)
|
||
{
|
||
if (!ct.__digit_map.inited)
|
||
(_RWSTD_CONST_CAST(digit_map<char_type>&,ct.__digit_map))
|
||
.init(ct);
|
||
return ct.__digit_map;
|
||
}
|
||
};
|
||
|
||
// ----------------------------------------------------
|
||
// Implementation class template -- keyword_def<charT>.
|
||
// ----------------------------------------------------
|
||
|
||
// Helper class used in parsing keywords from input (such as true/false in
|
||
// num_get, month and day names in time_get, etc).
|
||
|
||
template <class charT>
|
||
class _RWSTDExportTemplate keyword_def {
|
||
public:
|
||
const charT *s;
|
||
int v;
|
||
};
|
||
|
||
// ----------------------------------------------------
|
||
// Implementation class template -- keyword_map<charT>.
|
||
// ----------------------------------------------------
|
||
|
||
// Defines a set of keywords to be recognized on input and to be written to
|
||
// output. Private instances are hidden in numpunct (for true/false) and
|
||
// rwstd::timepunct (for month and weekday names).
|
||
|
||
template <class charT>
|
||
class _RWSTDExportTemplate keyword_map {
|
||
public:
|
||
int num_defs_;
|
||
const keyword_def<charT> *defs_;
|
||
};
|
||
|
||
// ---------------------------------------------------
|
||
// Implementation class template -- punct_data<charT>.
|
||
// ---------------------------------------------------
|
||
|
||
// Common base class for rwstd::numpunct_data and rwstd::moneypunct_data.
|
||
|
||
template <class charT>
|
||
class _RWSTDExportTemplate punct_data {
|
||
friend class digit_reader_base_1<charT>;
|
||
friend class digit_writer_base_1<charT>;
|
||
public:
|
||
typedef _RW_STD::basic_string<charT,_RW_STD::char_traits<charT>,_RW_STD::allocator<charT> > string_type;
|
||
protected:
|
||
charT dp_, ts_;
|
||
_RW_STD::string gr_;
|
||
};
|
||
|
||
// ------------------------------------------------------
|
||
// Implementation function templates -- create_xxx_facet.
|
||
// ------------------------------------------------------
|
||
|
||
// The facet_maker<Facet>::maker_func functions described above delegate the
|
||
// actual construction of facets to three inline function templates named
|
||
// create_xxx_facet, where xxx is 'classic' or 'native' or 'named'. The
|
||
// default (template) versions of these functions construct facets as follows:
|
||
//
|
||
// classic -- default constructor for the facet with only the refs argument.
|
||
// native -- calls create_named_facet with a name of "".
|
||
// named -- calls create_classic_facet, ignoring the passed name.
|
||
//
|
||
// This default behavior is overridden (specialized) for certain facet types.
|
||
// In particular, create_named_facet is specialized for all facet types that
|
||
// have a derived _byname version, to construct that version with the passed
|
||
// name (see <rw/rwlocale>) and create_native_facet is specialized for all
|
||
// facet types whose "native" behavior (as determined by the vendor) differs
|
||
// from the byname facet with a name of "" (see <rw/vendor>).
|
||
|
||
template <class Facet>
|
||
inline Facet* _RWSTDExportTemplate create_named_facet
|
||
(Facet*,const char*,size_t refs);
|
||
|
||
template <class Facet>
|
||
inline Facet* _RWSTDExportTemplate create_native_facet (Facet*);
|
||
|
||
template <class Facet>
|
||
inline Facet* _RWSTDExportTemplate create_classic_facet (Facet*)
|
||
{
|
||
return new Facet(1);
|
||
}
|
||
|
||
// ----------------------------------------------------
|
||
// Implementation class template -- facet_maker<Facet>.
|
||
// ----------------------------------------------------
|
||
|
||
// When use_facet (inline) finds that a locale does not contain an explicit
|
||
// facet of the requested type, it calls locale::__make_explicit (non-template)
|
||
// to create or find the facet in a cache, and install it in the locale. As a
|
||
// parameter to __make_explicit, use_facet passes a call-back function which
|
||
// __make_explicit can call to construct a facet of the requested type if
|
||
// needed. The call-back functions are obtained by instantiating the following
|
||
// helper class template:
|
||
|
||
template <class Facet>
|
||
class _RWSTDExportTemplate facet_maker {
|
||
public:
|
||
static facet_imp *maker_func (int t, const char* name, size_t refs)
|
||
{
|
||
if (t==0)
|
||
return create_classic_facet ((Facet*)0);
|
||
else if (t==1)
|
||
return create_native_facet ((Facet*)0);
|
||
else
|
||
return create_named_facet ((Facet*)0,name,refs);
|
||
}
|
||
};
|
||
|
||
// Typedef for the above facet_maker functions, for use in the declaration
|
||
// of locale::__make_explicit.
|
||
|
||
typedef facet_imp *facet_maker_func (int,const char*,size_t);
|
||
|
||
#ifndef _RWSTD_NO_NAMESPACE
|
||
} // namespace __rwstd
|
||
#endif
|
||
|
||
#ifdef _RWSTD_COMPILE_INSTANTIATE
|
||
#include <rw/locimpl.cc>
|
||
#endif
|
||
|
||
#endif // __STD_RW_LOCIMPL__
|
||
#pragma option pop
|
||
#endif /* __LOCIMPL_H */
|