| /*************************************************************************** |
| * |
| * locale_combine.cpp - definition of std::locale::combine() and related |
| * member functions |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the License); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| * Copyright 1994-2008 Rogue Wave Software, Inc. |
| * |
| **************************************************************************/ |
| |
| #define _RWSTD_LIB_SRC |
| |
| #include <rw/_defs.h> |
| |
| #include <locale.h> |
| #include <stdio.h> |
| #include <string.h> // for memxxx() and strxxx() functions |
| |
| #include <loc/_locale.h> |
| |
| #include "access.h" |
| #include "locale_body.h" |
| #include "setlocale.h" |
| |
| #if 6 == _RWSTD_HP_aCC_MAJOR && _RWSTD_HP_aCC_MINOR <= 1600 |
| // silence bogus HP aCC 6.16/cadvise warning #20200-D: |
| // Potential null pointer dereference |
| # pragma diag_suppress 20200 |
| #endif |
| |
| |
| _RWSTD_NAMESPACE (__rw) { |
| |
| |
| // constructs a new locale name from two locale names, combining |
| // all but the category given by `cat' from `name_1' and the rest |
| // from `name_2' |
| static void |
| __rw_combine_names (__rw_chararray &locname, |
| const char *name_1, const char *name_2, int cat) |
| { |
| _RWSTD_ASSERT (0 != name_1); |
| _RWSTD_ASSERT (0 != name_2); |
| |
| // `cat' must be a locale::category (and not a LC_XXX value) |
| _RWSTD_ASSERT (__rw_locale::_C_check_category (cat)); |
| |
| for (size_t i = 0; i != __rw_n_cats; ++i) { |
| const char *nxt1 = strchr (name_1, *_RWSTD_CAT_SEP); |
| const char *nxt2 = strchr (name_2, *_RWSTD_CAT_SEP); |
| |
| if (!nxt1 || !*nxt1) |
| nxt1 = name_1 + strlen (name_1); |
| |
| if (!nxt2 || !*nxt2) |
| nxt2 = name_2 + strlen (name_2); |
| |
| // convert a LC_XXX constant to a locale::category value |
| const int c = __rw_locale::_C_LC2category (__rw_cats [i].cat); |
| |
| const char *from; // copy from where |
| size_t len; // this many chars |
| |
| if (cat & c) { // category comes from `other' |
| from = name_2; |
| len = nxt2 - name_2; |
| } |
| else { // category comes from `one' |
| from = name_1; |
| len = nxt1 - name_1; |
| } |
| |
| if (locname.size ()) |
| locname.append (_RWSTD_CAT_SEP, 1); |
| |
| locname.append (from, len); |
| |
| // advance to the next category name in each name |
| if (*nxt1) |
| name_1 = nxt1 + 1; |
| |
| if (*nxt2) |
| name_2 = nxt2 + 1; |
| } |
| } |
| |
| |
| void __rw_locale:: |
| _C_construct (const __rw_locale &rhs, const __rw_facet *pfacet) |
| { |
| // called from ctor only, members are not initialized |
| _C_ref = 1; |
| |
| // copy standard facets from other locale |
| #if defined (__i386__) || !defined (__GNUG__) || __GNUG__ < 3 |
| |
| memcpy (_C_std_facets, rhs._C_std_facets, |
| _C_n_std_facets * sizeof *_C_std_facets); |
| |
| #else // !i86 || !gcc 3.x |
| |
| // Working around a bug (most probably) identical to the one described |
| // and fixed in __rw_locale::__rw_locale, but related to the use of |
| // memcpy. |
| |
| for (size_t i = 0; i != _C_n_std_facets; i++) |
| _C_std_facets [i] = rhs._C_std_facets [i]; |
| |
| #endif // i86/gcc 3.x |
| |
| _RWSTD_ASSERT (!pfacet || pfacet->_C_pid); |
| |
| // get facet's index into one of the facet arrays |
| size_t inx = pfacet |
| ? rhs._C_get_facet_inx (*pfacet->_C_pid) : size_t (-1); |
| |
| // extend size if facet isn't installed in `rhs' |
| _C_n_usr_facets = rhs._C_n_usr_facets |
| + (inx > rhs._C_n_usr_facets + _C_n_std_facets); |
| |
| // allocate a buffer for user facets if necesary |
| _C_usr_facets = _C_n_usr_facets ? new __rw_facet* [_C_n_usr_facets] : 0; |
| |
| // copy facets from other locale |
| memcpy (_C_usr_facets, rhs._C_usr_facets, |
| rhs._C_n_usr_facets * sizeof *_C_usr_facets); |
| |
| _RWSTD_ASSERT (rhs._C_name); |
| |
| _C_name = 0; |
| |
| // copy facet bits from `rhs' and adjust below as necessary |
| _C_std_facet_bits = rhs._C_std_facet_bits; |
| _C_byname_facet_bits = rhs._C_byname_facet_bits; |
| |
| if (pfacet) { |
| __rw_facet* const pf = _RWSTD_CONST_CAST (__rw_facet*, pfacet); |
| // overwrite an existing pointer or add a new one |
| if (inx < _C_n_std_facets) { |
| _C_std_facets [inx] = pf; |
| |
| const size_t facet_bit = 1UL << inx; |
| |
| // set or clear a corresponding bit based on whether |
| // the facet is one of the standard facets or not |
| // (user-defined objects even if they are of standard |
| // facet types, are not considered standard facets) |
| if (pf->_C_type > 0) |
| _C_std_facet_bits |= facet_bit; |
| else |
| _C_std_facet_bits &= ~facet_bit; |
| |
| // ditto for named facet bitmap |
| if (pf->_C_type & 1) // even types are _byname |
| _C_byname_facet_bits &= ~facet_bit; |
| else |
| _C_byname_facet_bits |= facet_bit; |
| |
| // construct a new name |
| // _C_name = |
| // _C_make_name (_C_namebuf, sizeof _C_namebuf, rhs, *pfacet); |
| } |
| else if (size_t (-1) == inx) |
| _C_usr_facets [_C_n_usr_facets - 1] = pf; |
| else |
| _C_usr_facets [inx - _C_n_std_facets] = pf; |
| } |
| |
| if (!_C_name) { |
| // simply copy name from `rhs' |
| const size_t size = strlen (rhs._C_name) + 1; |
| char* const name = size <= sizeof _C_namebuf |
| ? _C_namebuf : new char [size]; |
| |
| memcpy (name, rhs._C_name, size); |
| _C_name = name; |
| } |
| |
| // increment reference counts for facets (including the newly added one) |
| for (inx = 0; inx != _C_n_std_facets; ++inx) { |
| if (_C_std_facets [inx]) |
| _RWSTD_ATOMIC_PREINCREMENT (_C_std_facets [inx]->_C_ref, |
| _C_std_facets [inx]->_C_mutex); |
| } |
| |
| for (inx = 0; inx != _C_n_usr_facets; ++inx) { |
| _RWSTD_ATOMIC_PREINCREMENT (_C_usr_facets [inx]->_C_ref, |
| _C_usr_facets [inx]->_C_mutex); |
| } |
| } |
| |
| |
| void __rw_locale:: |
| _C_construct (const __rw_locale &one, const __rw_locale &other, int cat) |
| { |
| // category must be valid at this point (checked by caller) |
| _RWSTD_ASSERT (_C_check_category (cat)); |
| |
| // called from ctor only, members are not initialized |
| _C_ref = 1; |
| |
| // size is the same as that of `one' |
| _C_n_usr_facets = one._C_n_usr_facets; |
| |
| // allocate only if internal buffer is insufficient |
| _C_usr_facets = _C_n_usr_facets ? new __rw_facet* [_C_n_usr_facets] : 0; |
| |
| // copy standard facets to `one' from `other' |
| memcpy (_C_std_facets, one._C_std_facets, |
| _C_n_std_facets * sizeof *_C_std_facets); |
| |
| // copy user-defined facets (if any) |
| memcpy (_C_usr_facets, one._C_usr_facets, |
| _C_n_usr_facets * sizeof *_C_usr_facets); |
| |
| // compute and assign facet bitmaps |
| const int bits = _C_LC2facet_bits (cat); |
| |
| _C_std_facet_bits = (one._C_std_facet_bits & ~bits) |
| | (other._C_std_facet_bits & bits); |
| |
| _C_byname_facet_bits = (one._C_byname_facet_bits & ~bits) |
| | (other._C_byname_facet_bits & bits); |
| |
| for (size_t i = 0; i != _C_n_std_facets; ++i) { |
| |
| // each facet is stored at an index equal to its (id - 1) |
| // convert an LC_XXX constant to a locale::category value |
| const int c = _C_LC2category (__rw_get_cat (int (i) + 1)); |
| |
| if (cat & c) { |
| // assign/overwrite corresponding facets |
| _C_std_facets [i] = other._C_std_facets [i]; |
| } |
| |
| if (_C_std_facets [i]) { |
| // bump up the facet's reference count of *this' facet |
| _RWSTD_ATOMIC_PREINCREMENT (_C_std_facets [i]->_C_ref, |
| _C_std_facets [i]->_C_mutex); |
| } |
| } |
| |
| // increment the ref count of user-defined facets (if any) |
| for (size_t j = 0; j != _C_n_usr_facets; ++j) { |
| |
| _RWSTD_ASSERT (_C_usr_facets [j]); |
| |
| _RWSTD_ATOMIC_PREINCREMENT (_C_usr_facets [j]->_C_ref, |
| _C_usr_facets [j]->_C_mutex); |
| } |
| |
| __rw_chararray locname; |
| |
| __rw_combine_names (locname, one._C_name, other._C_name, cat); |
| |
| if (locname.size () >= one._C_namebuf_size) |
| _C_name = locname.release (); |
| else { |
| _C_name = _C_namebuf; |
| memcpy (_C_namebuf, locname.data (), locname.size () + 1); |
| } |
| } |
| |
| |
| _RW::__rw_locale* __rw_locale:: |
| _C_combine (const __rw_facet *pfacet) const |
| { |
| _RWSTD_ASSERT (pfacet); |
| |
| // template ctor: locale::locale (const locale&, Facet*) |
| // with `facet' being installed (e.g., adding or replacing |
| // an existing one) |
| |
| // verify that Facet::id has been initialized |
| _RWSTD_ASSERT (pfacet->_C_pid); |
| _RWSTD_ASSERT (*pfacet->_C_pid); |
| |
| // get the locale name ("C" if it's NUL) |
| const char* const one_locname = _C_name ? _C_name : "C"; |
| |
| // get the name of the locale `*pfacet' belongs to |
| const char* const facet_locname = |
| pfacet->_C_name ? pfacet->_C_name : "C"; |
| |
| // get the locale::category that `*pfacet' belongs to |
| const int facet_cat = |
| _C_LC2category (__rw_get_cat (int (*pfacet->_C_pid))); |
| |
| bool managed = false; |
| |
| if (pfacet->_C_type && !_C_n_usr_facets) { |
| |
| // facet is one of the (perhaps byname) standard facets |
| |
| // compute the number of the bit in _C_std_facet_bits or |
| //_C_byname_facet_bits corresponding to the facet being |
| // used (i.e., `*pfacet') |
| const size_t facet_bit = size_t (1U) << (*pfacet->_C_pid - 1U); |
| |
| // a locale object is globally managed if all its facets are objects |
| // of standard facet types (ordinary or byname) that were constructed |
| // by the library and within each locale category all facets belong |
| // to the same facet |
| // managed locales have names that completely describe their facets |
| // and from which they can be unambiguously and fully constructed |
| // |
| // note that in the code snippet below, x0 is not a managed locale |
| // (its name is "*"), but y0 is a managed locale (on SunOS, its name |
| // is "/de_DE/de_DE/de_DE/de_DE/de_DE/en_US"); x1 is the same as x0 |
| // and y1 is the same as de: |
| // |
| // locale de ("de_DE"); |
| // locale en ("en_US"); |
| // locale x0 = de.combine<messages<char> >(en); |
| // locale y0 = x0.combine<messages<wchar_t> >(en); |
| // locale x1 = y0.combine<messages<wchar_t> >(de); |
| // locale y1 = x1.combine<messages<char> >(de); |
| // assert (de == y1); |
| // assert (x0 == x1); |
| |
| if (__rw_locale::_C_all == (_C_std_facet_bits | facet_bit)) { |
| |
| // compute the bitmask corresponding to all the facets in |
| // the same category as the one to which `*pfacet' belongs |
| const int cat_bits = _C_LC2facet_bits (facet_cat); |
| |
| // get the index into the _C_std_facets array for `pfacet' |
| const size_t facet_inx = _C_get_facet_inx (*pfacet->_C_pid); |
| |
| managed = true; |
| |
| // iterate over all facets that belong the same category |
| // as `*pfacet' and compare the name of each with the name |
| // of `*pfacet' to determine if they all have the same name |
| // _byname facets that are not installed yet (i.e., whose |
| // pointers are 0 come from a locale whose name is given |
| // by the name of the whole locale |
| for (size_t i = 0; i != _C_n_std_facets; ++i) { |
| |
| // skip facets from other categories |
| if (!((1 << i) & cat_bits)) |
| continue; |
| |
| // skip the facet being replaced |
| if (facet_inx == i) |
| continue; |
| |
| const char* const ones_facet_locname = |
| _C_std_facets [i] ? _C_std_facets [i]->_C_name |
| ? _C_std_facets [i]->_C_name : "C" : one_locname; |
| |
| if (strcmp (facet_locname, ones_facet_locname)) { |
| managed = false; |
| break; |
| } |
| } |
| } |
| } |
| |
| __rw_locale *plocale; |
| |
| if (managed) { |
| |
| __rw_chararray locname; |
| __rw_combine_names (locname, one_locname, facet_locname, facet_cat); |
| |
| plocale = __rw_locale::_C_manage (0, locname.data ()); |
| |
| _RWSTD_ASSERT (0 != plocale); |
| _RWSTD_ASSERT (plocale->_C_is_managed (_STD::locale::none)); |
| } |
| else { |
| plocale = new __rw_locale (*this, pfacet); |
| |
| _RWSTD_ASSERT (0 != plocale); |
| _RWSTD_ASSERT (!plocale->_C_is_managed (_STD::locale::none)); |
| } |
| |
| return plocale; |
| } |
| |
| |
| __rw_locale* __rw_locale:: |
| _C_combine (const __rw_locale &other, int cat) |
| { |
| // convert a possible LC_XXX constant to a locale::category value |
| cat = _C_LC2category (cat); |
| |
| // verify that the category argument is valid |
| if (!_C_check_category (cat)) |
| return 0; |
| |
| |
| // combining ctor: locale (const locale&, const locale&, cat) |
| |
| if (this == &other || _STD::locale::none == cat) { |
| // same as copy ctor (copying all facets from `*this') |
| // body may or may not be globally managed |
| _RWSTD_ATOMIC_PREINCREMENT (_C_ref, false); |
| |
| return this; |
| } |
| |
| #if 0 // disabled |
| |
| // 22.1.1.2, p14: only facets that implement categories in `cat' are |
| // to be copied from `other', i.e., not necessarily user-defined facets |
| |
| if (_RWSTD_LC_ALL == cat || _STD::locale::all == cat) { |
| // same as copy ctor (copying all facets from `other') |
| // body may or may not be globally managed |
| _RWSTD_ATOMIC_PREINCREMENT (other._C_ref, false); |
| return &other; |
| } |
| |
| #endif // 0/1 |
| |
| if ( _C_is_managed (_STD::locale::all & ~cat) |
| && other._C_is_managed (cat)) { |
| |
| // determine new locale name from `*this' and `other's, taking all of |
| // this's category names except for those given by `cat', which come |
| // from `other' |
| |
| const char *name_1 = _C_name; |
| const char *name_2 = other._C_name; |
| |
| if (0 == strcmp (name_1, name_2)) { |
| // if locale names are the same, return a globally managed body |
| __rw_locale* const plocale = __rw_locale::_C_manage (0, name_1); |
| |
| _RWSTD_ASSERT (0 != plocale); |
| _RWSTD_ASSERT (plocale->_C_is_managed (_STD::locale::none)); |
| |
| return plocale; |
| } |
| |
| __rw_chararray locname; |
| |
| // compose the new name |
| __rw_combine_names (locname, name_1, name_2, cat); |
| |
| // return a globally managed body |
| __rw_locale* const plocale = |
| __rw_locale::_C_manage (0, locname.data ()); |
| |
| _RWSTD_ASSERT (0 != plocale); |
| _RWSTD_ASSERT (plocale->_C_is_managed (_STD::locale::none)); |
| |
| return plocale; |
| } |
| |
| // one or both locales are not globally managed (one or more of |
| // their facets are of use-defined types, possibly derived from |
| // the standard facets), and thus the combined locale cannot be |
| // globally managed either |
| __rw_locale *plocale = new __rw_locale (*this, other, cat); |
| |
| _RWSTD_ASSERT (!plocale->_C_is_managed (_STD::locale::none)); |
| |
| return plocale; |
| } |
| |
| |
| /* static */ __rw_locale* __rw_locale:: |
| _C_get_body (__rw_locale *one, |
| __rw_locale *other, |
| const char *locname, |
| int cat, |
| const __rw_facet *pfacet) |
| { |
| __rw_chararray realname; |
| |
| // see if `locname' contains embedded "LC_XXX=..." sequences |
| if (locname && !strncmp (locname, "LC_", 3)) { |
| |
| // convert a combined locale name (consisting of a sequence |
| // of `sep'-separated LC_XXX=<name> substrings) to a normalized |
| // form in the expected (internal) format and order |
| |
| const char *pcatnames [__rw_n_cats] = { 0 }; |
| |
| // try the libc "native" separator first, semicolon next |
| const char* const psep = strchr (locname, *_RWSTD_CAT_SEP); |
| const char sep = psep ? *psep : ';'; |
| |
| // redundant check for s being non-null shuts up a bogus |
| // HP cadvise null pointer derefence warning #20200 |
| for (const char *s = locname; s && *s; ) { |
| |
| const char* const endcat = strchr (s, '='); |
| if (!endcat) |
| return 0; // error: missing `=' after LC_XXX |
| |
| // go through the LC_XXX category names, trying to find |
| // a match; if found, remember its position (duplicates |
| // are not allowed) |
| |
| for (size_t i = 0; i != __rw_n_cats; ++i) { |
| if (!strncmp (__rw_cats [i].name, s, endcat - s)) { |
| if (pcatnames [i]) |
| return 0; // error: duplicate LC_XXX |
| |
| pcatnames [i] = endcat + 1; |
| break; |
| } |
| } |
| |
| // advance just past the next separator if one exists |
| const char* const next = strchr (s, sep); |
| s = next ? next + 1 : s + strlen (s); |
| } |
| |
| // compose a normalized locale name out of category names |
| size_t size = 0; |
| for (size_t i = 0; i != __rw_n_cats; ++i) { |
| |
| if (!pcatnames [i]) { |
| // use "C" for missing LC_XXX values |
| pcatnames [i] = "C"; |
| } |
| |
| const char *endcat = strchr (pcatnames [i], sep); |
| |
| if (!endcat) |
| endcat = pcatnames [i] + strlen (pcatnames [i]); |
| |
| const size_t catsize = endcat - pcatnames [i]; |
| |
| // append name followed by the libc "native" separator |
| realname.append (pcatnames [i], catsize); |
| realname.append (_RWSTD_CAT_SEP, 1); |
| |
| size += catsize; |
| } |
| |
| locname = realname.data (); |
| } |
| else if (locname && *locname == *_RWSTD_CAT_SEP) { |
| // advance past the leading category separator if present |
| ++locname; |
| } |
| |
| if (!one && !other && !locname && _STD::locale::none == cat && !pfacet) { |
| // implements default ctor: locale::locale () throw () |
| __rw_locale* const global = __rw_locale::_C_manage (0, 0); |
| |
| _RWSTD_ASSERT (0 != global); |
| |
| return global; |
| } |
| |
| if (one && !other && !locname && _STD::locale::none == cat && !pfacet) { |
| // copy ctor: locale::locale (const locale&) |
| // or combining ctor: locale::locale (const locale&, Facet*) |
| // (in the second case with Facet* being 0) |
| // body may or may not be globally managed |
| // or locale::operator=(const locale&) |
| _RWSTD_ATOMIC_PREINCREMENT (one->_C_ref, false); |
| return one; |
| } |
| |
| if (!one && !other && locname && _STD::locale::none == cat && !pfacet) { |
| // ctor: locale::locale (const char*) |
| // if successful, body is globally managed |
| __rw_locale* const plocale = __rw_locale::_C_manage (0, locname); |
| |
| _RWSTD_ASSERT (!plocale || plocale->_C_is_managed (_STD::locale::none)); |
| |
| return plocale; |
| } |
| |
| if (one && !other && !locname && _STD::locale::none == cat && pfacet) { |
| // template ctor: locale::locale (const locale&, Facet*) |
| // with `pfacet' being installed (e.g., adding or replacing |
| // an existing one) |
| // template <class Facet> locale::combine(const locale&) is |
| // trivially implemented inline in terms of the template ctor |
| __rw_locale* const plocale = one->_C_combine (pfacet); |
| |
| _RWSTD_ASSERT (0 != plocale); |
| |
| return plocale; |
| } |
| |
| if (one && !other && locname && !pfacet) { |
| // combining ctor: locale (const locale&, const char*, category) |
| |
| // construct a temporary locale from locale name `locname' |
| const _STD::locale tmp (locname); |
| |
| // construct a locale combined from `one' and the temporary |
| __rw_locale* const plocale = one->_C_combine (*tmp._C_body, cat); |
| |
| return plocale; |
| } |
| |
| if (one && other && !locname && !pfacet) { |
| // combining ctor: locale (const locale&, const locale&, category) |
| return one->_C_combine (*other, cat); |
| } |
| |
| _RWSTD_ASSERT (!"logic error: bad combination of arguments"); |
| |
| return 0; |
| } |
| |
| } // namespace __rw |
| |
| |
| _RWSTD_NAMESPACE (std) { |
| |
| |
| // outlined to hide implementation details |
| locale:: |
| locale (const char *locname) |
| { |
| // verify 22.1.1.2, p7: `locname' must not be null |
| _RWSTD_REQUIRES (locname, |
| (_RWSTD_ERROR_LOCALE_BAD_NAME, |
| _RWSTD_FUNC ("locale::locale (const char*)"), "(null)")); |
| |
| _C_body = _RW::__rw_locale::_C_get_body (0, 0, locname, none, 0); |
| |
| // verify 22.1.1.2, p7: `locname' must be valid |
| _RWSTD_REQUIRES (_C_body, |
| (_RWSTD_ERROR_LOCALE_BAD_NAME, |
| _RWSTD_FUNC ("locale::locale (const char*)"), locname)); |
| } |
| |
| |
| // outlined to hide implementation details |
| locale:: |
| locale (const locale &rhs, const char *locname, category cat) |
| { |
| // verify 22.1.1.2, p10: `locname' must not ne null |
| _RWSTD_REQUIRES (locname, |
| (_RWSTD_ERROR_LOCALE_BAD_NAME, |
| _RWSTD_FUNC ("locale::locale (const locale&, " |
| "const char*, category)"), "(null")); |
| |
| _C_body = _RW::__rw_locale::_C_get_body (rhs._C_body, 0, locname, cat, 0); |
| |
| // verify 22.1.1.2, p10: `locname' must be valid |
| _RWSTD_REQUIRES (_C_body, |
| (_RWSTD_ERROR_LOCALE_BAD_NAME, |
| _RWSTD_FUNC ("locale::locale (const locale&, " |
| "const char*, category)"), locname)); |
| } |
| |
| |
| // outlined to hide implementation details |
| locale:: |
| locale (const locale &one, const locale &other, category cat) |
| : _C_body (_RW::__rw_locale::_C_get_body (one._C_body, other._C_body, |
| 0, cat, 0)) |
| { |
| // verify 22.1.1.2, p14 (missing requirement): category must be valid |
| _RWSTD_REQUIRES (_C_body, |
| (_RWSTD_ERROR_LOCALE_BAD_CAT, |
| _RWSTD_FUNC ("locale::locale (const locale&, " |
| "const locale&, category)"), cat)); |
| } |
| |
| |
| // outlined to hide implementation details |
| /* private */ locale:: |
| locale (_RW::__rw_locale &rhs, const facet *pfacet) |
| : _C_body (_RW::__rw_locale::_C_get_body (&rhs, 0, 0, none, pfacet)) |
| { |
| // empty |
| } |
| |
| |
| const locale::facet* locale:: |
| _C_get_facet (const id &fid) const |
| { |
| // initialize id if not yet initialized |
| if (!fid._C_id) |
| fid._C_init (); |
| |
| // properly initialized facet id's are non-zero |
| _RWSTD_ASSERT (0 != fid._C_id); |
| |
| _RWSTD_ASSERT (0 != _C_body); |
| |
| // find the index at which the facet is stored in one of the facet arrays |
| const size_t inx = _C_body->_C_get_facet_inx (fid._C_id); |
| if (size_t (-1) == inx) |
| return 0; |
| |
| const locale::facet* const pfacet = inx < _RW::__rw_locale::_C_n_std_facets |
| ? _C_body->_C_std_facets [inx] |
| : _C_body->_C_usr_facets [inx - _RW::__rw_locale::_C_n_std_facets]; |
| |
| if (pfacet) { |
| // facet id must have been initialized to point |
| // to the numeric member of the static Facet::id |
| _RWSTD_ASSERT (pfacet->_C_pid); |
| |
| // make sure the static Facet::id matches its (non-static) id member |
| _RWSTD_ASSERT (*pfacet->_C_pid == fid._C_id); |
| } |
| |
| return pfacet; |
| } |
| |
| |
| } // namespace std |