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 <EFBFBD> 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 */
|