home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / Xenon / C++ / FreeCommandLineTools.exe / Include / Rw / locimpl.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-31  |  15.6 KB  |  478 lines

  1. #ifndef __LOCIMPL_H
  2. #define __LOCIMPL_H
  3. #pragma option push -b -a8 -pc -Vx- -Ve- -w-inl -w-aus -w-sig
  4. // -*- C++ -*-
  5. /***************************************************************************
  6.  *
  7.  * rw/locimpl - Declarations for the Standard Library locale private
  8.  *              implementation classes.
  9.  *
  10.  ***************************************************************************
  11.  *
  12.  * Copyright (c) 1994-1999 Rogue Wave Software, Inc.  All Rights Reserved.
  13.  *
  14.  * This computer software is owned by Rogue Wave Software, Inc. and is
  15.  * protected by U.S. copyright laws and other laws and by international
  16.  * treaties.  This computer software is furnished by Rogue Wave Software,
  17.  * Inc. pursuant to a written license agreement and may be used, copied,
  18.  * transmitted, and stored only in accordance with the terms of such
  19.  * license and with the inclusion of the above copyright notice.  This
  20.  * computer software or any other copies thereof may not be provided or
  21.  * otherwise made available to any other person.
  22.  *
  23.  * U.S. Government Restricted Rights.  This computer software is provided
  24.  * with Restricted Rights.  Use, duplication, or disclosure by the
  25.  * Government is subject to restrictions as set forth in subparagraph (c)
  26.  * (1) (ii) of The Rights in Technical Data and Computer Software clause
  27.  * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the
  28.  * Commercial Computer Software รป Restricted Rights at 48 CFR 52.227-19,
  29.  * as applicable.  Manufacturer is Rogue Wave Software, Inc., 5500
  30.  * Flatiron Parkway, Boulder, Colorado 80301 USA.
  31.  *
  32.  **************************************************************************/
  33.  
  34. #ifndef __STD_RW_LOCIMPL__
  35. #define __STD_RW_LOCIMPL__
  36.  
  37. #include <stdcomp.h>
  38.  
  39. // Macro for declaring all the has_facet and use_facet functions to be friends.
  40.  
  41. #ifndef _RWSTD_NO_FRIEND_TEMPLATES
  42. #ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  43. #define _RWSTD_FRIEND_USE_HAS_FACET                                     \
  44.   template <class Facet> friend                                         \
  45.       inline const Facet& use_facet (const locale&);                    \
  46.   template <class Facet> friend                                         \
  47.       inline bool has_facet (const locale&) _RWSTD_THROW_SPEC_NULL;
  48. #else
  49. #define _RWSTD_FRIEND_USE_HAS_FACET                                     \
  50.   template <class Facet> friend                                         \
  51.     inline const Facet& use_facet (const locale&,Facet*);               \
  52.   template <class Facet> friend                                         \
  53.     inline bool has_facet (const locale&,Facet*) _RWSTD_THROW_SPEC_NULL;
  54. #endif // _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE
  55. #else
  56. #define _RWSTD_FRIEND_USE_HAS_FACET public:
  57. #endif
  58.  
  59. #ifndef _RWSTD_NO_NAMESPACE
  60. namespace __rwstd {
  61.   using std::use_facet;
  62.   using std::locale;
  63. #endif
  64.  
  65. // Implementation class template -- timepunct<charT>
  66. //
  67. // A facet such as this should have been included in the standard.  We just
  68. // declare it here; the definition occurs below, after locale::facet has been
  69. // defined.
  70.  
  71. template <class charT> class timepunct;
  72.  
  73. #ifdef __TURBOC__
  74.  
  75. // Instantiations that go in the library:
  76.  
  77. template class _RWSTDExport timepunct<char>;
  78. #ifndef _RWSTD_NO_WIDE_CHAR
  79. template class _RWSTDExport timepunct<wchar_t>;
  80. #endif
  81.  
  82. #endif // __TURBOC__
  83.  
  84. // Implementation forward declarations:
  85.  
  86. class _RWSTDExport locale_imp;
  87. class _RWSTDExport facet_imp;
  88.  
  89. class _RWSTDExport digit_map_base;
  90. template <class charT> class _RWSTDExportTemplate digit_map;
  91. template <class charT> class _RWSTDExportTemplate keyword_def;
  92. template <class charT> class _RWSTDExportTemplate keyword_map;
  93. template <class charT> class _RWSTDExportTemplate keyword_cracker;
  94.  
  95. class _RWSTDExport digit_reader_base;
  96. template <class charT> class digit_reader_base_1;
  97. template <class charT,class InputIterator>
  98.   class _RWSTDExportTemplate digit_reader;
  99.  
  100. class _RWSTDExport digit_writer_base;
  101. template <class charT>
  102.   class _RWSTDExportTemplate digit_writer_base_1;
  103. template <class charT,class OutputIterator>
  104.   class _RWSTDExportTemplate digit_writer;
  105.  
  106. // ------------------------------------
  107. // Implementation class -- ref_counted.
  108. // ------------------------------------
  109.  
  110. // Common base class for reference-counted classes.  Currently used only by
  111. // locale_imp and facet_imp, but could be used more generally.
  112.  
  113. class _RWSTDExport ref_counted {
  114.   friend class _RW_STD::locale;
  115.  
  116.   size_t __ref_count;
  117.   #ifdef _RWSTD_MULTI_THREAD
  118.   _RWSTDMutex __mutex;
  119.   #endif
  120.  
  121.  protected:
  122.   ref_counted (size_t initial_refs):
  123.       __ref_count(initial_refs) { }
  124.  
  125.   // Ensure derived class destructors are always virtual.
  126.   virtual ~ref_counted (void);
  127.  
  128.   // Does protected access make these accessible to friends of derived classes?
  129.   // We're about to find out ...
  130.  
  131.   static void add_reference (ref_counted *ob) {
  132.     STDGUARD(ob->__mutex);
  133.     ++ob->__ref_count;
  134.   }
  135.  
  136.   static void remove_reference (ref_counted *ob) {
  137.     size_t refs;
  138.     {
  139.       STDGUARD(ob->__mutex);
  140.       refs=--ob->__ref_count;
  141.     }
  142.     if (!refs)
  143.       delete ob;
  144.   }
  145.  
  146.   static void add_possible_reference (ref_counted *ob) {
  147.     if (ob)
  148.       add_reference(ob);
  149.   }
  150.  
  151.   static void remove_possible_reference (ref_counted *ob) {
  152.     if (ob)
  153.       remove_reference(ob);
  154.   }
  155. };
  156.  
  157. // We would prefer to define locale::id and locale::facet entirely as nested
  158. // classes of locale, but current compilers have problems with out-of-line
  159. // definition of members of such classes, so we have to derive most of their
  160. // behavior from unnested implementation classes:
  161.  
  162. // --------------------------------------
  163. // Implementation class -- locale_id_imp.
  164. // --------------------------------------
  165.  
  166. class _RWSTDExport locale_id_imp {
  167.  protected:
  168.   _MUTABLE size_t __id_value;
  169.   static size_t __last_used_id;
  170.   
  171.   locale_id_imp() :  __id_value(0) {;}
  172.  
  173.   #ifdef _RWSTD_MULTI_THREAD
  174.   static _RWSTDMutex __mutex;
  175.   #endif
  176.  
  177.   void __initid () const;
  178. };
  179.  
  180. // ----------------------------------
  181. // Implementation class -- facet_imp.
  182. // ----------------------------------
  183.  
  184. class _RWSTDExport facet_imp: public ref_counted
  185. {
  186.   _RWSTD_FRIEND_USE_HAS_FACET
  187.   friend class locale_imp;
  188.   friend class _RW_STD::locale;
  189. public:
  190.   enum {
  191.     __facet_cat = 0,
  192.     __ok_implicit = 0,
  193.     __initdone = 1
  194.   };
  195.  
  196.  private:
  197.   int __flags;
  198.   int __category;     // Should be same type as locale::category
  199.  
  200.  protected:
  201.   facet_imp (size_t refs, int cat=0):
  202.       ref_counted(refs), __flags(0), __category(cat) { }
  203.  
  204.   // __initfacet() is called by locale::__install the first time a facet is 
  205.   // installed in its first locale.  Some facets override it to set up private 
  206.   // data that depends on return values of virtual do_xxx functions that can't
  207.   // be called yet in a constructor.
  208.   virtual void __initfacet (const locale*) { }
  209. };
  210.  
  211. #ifndef _RWSTD_NO_NAMESPACE
  212. }
  213. #endif
  214.  
  215. #include <rw/locvector> 
  216.  
  217. #ifndef _RWSTD_NO_NAMESPACE
  218. namespace __rwstd {
  219. #endif
  220.  
  221. // -----------------------------------
  222. // Implementation class -- locale_imp.
  223. // -----------------------------------
  224.  
  225. class _RWSTDExport locale_imp: public ref_counted
  226. {
  227.   _RWSTD_FRIEND_USE_HAS_FACET
  228.   friend class _RW_STD::locale;
  229.  
  230.   // Same type as locale::category ...
  231.   typedef int locale_category;
  232.   locale_vector<_RW_STD::string> names_;
  233.   locale_vector<facet_imp*> vec_;
  234.  
  235.   locale_category native_cats_;
  236.   locale_category named_cats_;
  237.   _RW_STD::string big_name_;
  238.   bool named_;
  239.  
  240.   locale_imp (size_t sz=36, size_t refs=0);
  241.   locale_imp (const locale_imp&,size_t refs);
  242.   ~locale_imp ();
  243.  
  244.  public:
  245.   inline facet_imp *get_facet (size_t i) const
  246.     { return i<vec_.size()? vec_[i] : NULL; }
  247.  
  248.  private:
  249.   const char *category_name (locale_category) const;
  250.  
  251.   // Map C library LC_xxx constants into facet categories.
  252.   static locale_category map_category (locale_category);
  253.  
  254.   // Parse a locale name into category names.
  255.   static bool parse_name (locale_vector<_RW_STD::string>&,const char*);
  256.  
  257.   // Clean up name if necessary
  258.   static _RW_STD::string clean_name(_RW_STD::string s)
  259.   {
  260. #ifdef __BORLANDC__
  261.     return _RW_STD::string(s,s.find('=')+1);
  262. #else
  263.     return s;
  264. #endif // __BORLANDC__
  265.   }
  266.  
  267.   // Combine category names to create a locale name.
  268.   static bool build_name (_RW_STD::string&,const locale_vector<_RW_STD::string>&);
  269. };
  270.  
  271. // ---------------------------------------
  272. // Implementation class -- digit_map_base.
  273. // ---------------------------------------
  274.  
  275. // A place to stash some static constants, so that each instantiation of the
  276. // derived class rwstd::digit_map does not have to have a separate copy.
  277.  
  278. struct _RWSTDExport digit_map_base {
  279.   enum { zero, minus, plus, X, x, E, e };
  280.   static const char punct_chars[7];   // "0-+XxEe"
  281.   static const char digit_chars[22];  // "0123456789ABCDEFabcdef"
  282.   static const char char_values[22];  // Corresponding values in range 0-15
  283. };
  284.  
  285. // --------------------------------------------------
  286. // Implementation class template -- digit_map<charT>.
  287. // --------------------------------------------------
  288.  
  289. // Maps digits into their corresponding numeric values, and caches widened
  290. // equivalents of some number-related punctuation characters that don't depend
  291. // on the numpunct facet.  A private instance of this class is hidden in
  292. // ctype<charT> for use by numeric conversion facets.  A call to init must
  293. // precede the first call to eval if is_inited() is false.  Eval returns 0-15
  294. // if argument is a valid digit, a negative value otherwise.
  295. //
  296. // Specialized for char for performance.  The specialization assumes digits
  297. // fit into the char code-set in an ASCII-like manner ('0'..'9' contiguous,
  298. // 'A'..'F' contiguous, 'a'..'f' contiguous, '0' < 'A' < 'a').
  299.  
  300. _RWSTD_TEMPLATE
  301. class _RWSTDExportTemplate digit_map<char>:
  302.     public digit_map_base
  303. {
  304.  public:
  305.   typedef char char_type;
  306.  
  307.   bool is_inited (void) const { return true; }
  308.   const char *get_punct (void) const { return punct_chars; }
  309.   inline int eval (char c) const;
  310.   static inline const digit_map<char>&
  311.       get_digit_map (const _RW_STD::ctype<char>&);
  312. };
  313.  
  314. // Inline members of digit_map<char>:
  315. //
  316. // (Note that the definition of get_digit_map is in <rw/ctype> because it
  317. //  has to come after the definition of ctype<char>.)
  318.  
  319. inline int digit_map<char>::eval (char c) const {
  320.   int num=c;
  321.   if ((num-='0')>9) {
  322.     if (((num-=('A'-'0'))>5 && (num-=('a'-'A'))>5) || (num+=10)<10)
  323.       num=-1;
  324.   }
  325.   return num;
  326. }
  327.  
  328. template <class charT>
  329. class _RWSTDExportTemplate digit_map:
  330.     public digit_map_base
  331. {
  332.   bool inited;
  333.   charT punct_array[7];
  334.   charT digit_array[22];
  335.   char value_array[22];
  336.  public:
  337.   typedef charT char_type;
  338.  
  339.   digit_map (void): inited(false) { }
  340.   bool is_inited (void) const { return inited; }
  341.   void init (const _RW_STD::ctype<charT>& ct);
  342.   const charT *get_punct (void) const { return punct_array; }
  343.   int eval (charT) const;
  344.  
  345.   // Can-opener for getting the digit_map out of a ctype.  (Works because of
  346.   // the friend declaration in ctype_helper<charT> below.)
  347.   static inline const digit_map<charT>&
  348.       get_digit_map (const _RW_STD::ctype<charT>& ct)
  349.   {
  350.     if (!ct.__digit_map.inited)
  351.       (_RWSTD_CONST_CAST(digit_map<char_type>&,ct.__digit_map))
  352.           .init(ct);
  353.     return ct.__digit_map;
  354.   }
  355. };
  356.  
  357. // ----------------------------------------------------
  358. // Implementation class template -- keyword_def<charT>.
  359. // ----------------------------------------------------
  360.  
  361. // Helper class used in parsing keywords from input (such as true/false in
  362. // num_get, month and day names in time_get, etc).
  363.  
  364. template <class charT>
  365. class _RWSTDExportTemplate keyword_def {
  366.  public:
  367.   const charT *s;
  368.   int v;
  369. };
  370.  
  371. // ----------------------------------------------------
  372. // Implementation class template -- keyword_map<charT>.
  373. // ----------------------------------------------------
  374.  
  375. // Defines a set of keywords to be recognized on input and to be written to
  376. // output.  Private instances are hidden in numpunct (for true/false) and
  377. // rwstd::timepunct (for month and weekday names).
  378.  
  379. template <class charT>
  380. class _RWSTDExportTemplate keyword_map {
  381.  public:
  382.   int num_defs_;
  383.   const keyword_def<charT> *defs_;
  384. };
  385.  
  386. // ---------------------------------------------------
  387. // Implementation class template -- punct_data<charT>.
  388. // ---------------------------------------------------
  389.  
  390. // Common base class for rwstd::numpunct_data and rwstd::moneypunct_data.
  391.  
  392. template <class charT>
  393. class _RWSTDExportTemplate punct_data {
  394.   friend class digit_reader_base_1<charT>;
  395.   friend class digit_writer_base_1<charT>;
  396.  public:
  397.   typedef _RW_STD::basic_string<charT,_RW_STD::char_traits<charT>,_RW_STD::allocator<charT> > string_type;
  398.  protected:
  399.   charT dp_, ts_;
  400.   _RW_STD::string gr_;
  401. };
  402.  
  403. // ------------------------------------------------------
  404. // Implementation function templates -- create_xxx_facet.
  405. // ------------------------------------------------------
  406.  
  407. // The facet_maker<Facet>::maker_func functions described above delegate the
  408. // actual construction of facets to three inline function templates named
  409. // create_xxx_facet, where xxx is 'classic' or 'native' or 'named'.  The
  410. // default (template) versions of these functions construct facets as follows:
  411. //
  412. //   classic -- default constructor for the facet with only the refs argument.
  413. //   native -- calls create_named_facet with a name of "".
  414. //   named -- calls create_classic_facet, ignoring the passed name.
  415. //
  416. // This default behavior is overridden (specialized) for certain facet types.
  417. // In particular, create_named_facet is specialized for all facet types that
  418. // have a derived _byname version, to construct that version with the passed
  419. // name (see <rw/rwlocale>) and create_native_facet is specialized for all
  420. // facet types whose "native" behavior (as determined by the vendor) differs
  421. // from the byname facet with a name of "" (see <rw/vendor>).
  422.  
  423. template <class Facet>
  424. inline Facet*  _RWSTDExportTemplate create_named_facet
  425.     (Facet*,const char*,size_t refs);
  426.  
  427. template <class Facet>
  428. inline Facet*  _RWSTDExportTemplate create_native_facet (Facet*);
  429.  
  430. template <class Facet>
  431. inline Facet* _RWSTDExportTemplate create_classic_facet (Facet*)
  432. {
  433.  return new Facet(1);
  434. }
  435.  
  436. // ----------------------------------------------------
  437. // Implementation class template -- facet_maker<Facet>.
  438. // ----------------------------------------------------
  439.  
  440. // When use_facet (inline) finds that a locale does not contain an explicit
  441. // facet of the requested type, it calls locale::__make_explicit (non-template)
  442. // to create or find the facet in a cache, and install it in the locale.  As a
  443. // parameter to __make_explicit, use_facet passes a call-back function which
  444. // __make_explicit can call to construct a facet of the requested type if
  445. // needed.  The call-back functions are obtained by instantiating the following
  446. // helper class template:
  447.  
  448. template <class Facet>
  449. class _RWSTDExportTemplate facet_maker {
  450.  public:
  451.   static facet_imp *maker_func (int t, const char* name, size_t refs)
  452.   {
  453.     if (t==0)
  454.       return create_classic_facet ((Facet*)0);
  455.     else if (t==1)
  456.       return create_native_facet ((Facet*)0);
  457.     else
  458.       return create_named_facet ((Facet*)0,name,refs);
  459.   }
  460. };
  461.  
  462. // Typedef for the above facet_maker functions, for use in the declaration
  463. // of locale::__make_explicit.
  464.  
  465. typedef facet_imp *facet_maker_func (int,const char*,size_t);
  466.  
  467. #ifndef _RWSTD_NO_NAMESPACE
  468. } // namespace __rwstd
  469. #endif
  470.  
  471. #ifdef _RWSTD_COMPILE_INSTANTIATE
  472. #include <rw/locimpl.cc>
  473. #endif
  474.  
  475. #endif // __STD_RW_LOCIMPL__
  476. #pragma option pop
  477. #endif /* __LOCIMPL_H */
  478.