228 lines
6.2 KiB
C++
228 lines
6.2 KiB
C++
// locale -- class locale member functions
|
|
#include <cstdlib>
|
|
#include <istream>
|
|
#include <locale>
|
|
#include <xdebug>
|
|
#include <dbgint.h>
|
|
|
|
_C_STD_BEGIN
|
|
_EXTERN_C
|
|
std::locale::_Locimp *__cdecl _Getgloballocale();
|
|
|
|
void __cdecl _Setgloballocale(void *);
|
|
_END_EXTERN_C
|
|
_C_STD_END
|
|
|
|
_STD_BEGIN
|
|
|
|
typedef char_traits<char> _Traits;
|
|
typedef istreambuf_iterator<char, _Traits> _Initer;
|
|
typedef ostreambuf_iterator<char, _Traits> _Outiter;
|
|
|
|
locale::locale(const locale& loc, const locale& other, category cat)
|
|
: _Ptr(_NEW_CRT _Locimp(*loc._Ptr))
|
|
{ // construct a locale by copying named facets
|
|
_TRY_BEGIN
|
|
_Locinfo _Lobj(loc._Ptr->_Catmask, loc._Ptr->_Name.c_str());
|
|
_Locimp::_Makeloc(_Lobj._Addcats(cat & other._Ptr->_Catmask,
|
|
other._Ptr->_Name.c_str()), cat, _Ptr, &other);
|
|
_CATCH_ALL
|
|
_DELETE_CRT(_Ptr->_Decref());
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
locale::locale(const char *locname, category cat)
|
|
: _Ptr(_NEW_CRT _Locimp)
|
|
{ // construct a locale with named facets
|
|
_TRY_BEGIN
|
|
_Init();
|
|
_Locinfo _Lobj(cat, locname);
|
|
|
|
if (_Lobj._Getname().compare("*") == 0)
|
|
_THROW(runtime_error, "bad locale name");
|
|
_Locimp::_Makeloc(_Lobj, cat, _Ptr, 0);
|
|
_CATCH_ALL
|
|
_DELETE_CRT(_Ptr->_Decref());
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
locale::locale(const locale& loc, const char *locname, category cat)
|
|
: _Ptr(_NEW_CRT _Locimp(*loc._Ptr))
|
|
{ // construct a locale by copying, replacing named facets
|
|
_TRY_BEGIN
|
|
_Locinfo _Lobj(loc._Ptr->_Catmask, loc._Ptr->_Name.c_str());
|
|
bool _Hadname = _Lobj._Getname().compare("*") != 0;
|
|
_Lobj._Addcats(cat, locname);
|
|
|
|
if (_Hadname && _Lobj._Getname().compare("*") == 0)
|
|
_THROW(runtime_error, "bad locale name");
|
|
_Locimp::_Makeloc(_Lobj, cat, _Ptr, 0);
|
|
_CATCH_ALL
|
|
_DELETE_CRT(_Ptr->_Decref());
|
|
_RERAISE;
|
|
_CATCH_END
|
|
}
|
|
|
|
_DEPRECATED locale& locale::_Addfac(facet *fac, size_t id, size_t catmask)
|
|
{ // add a facet, copying on write
|
|
if (1 < _Ptr->_Refs)
|
|
{ // shared, make private copy before altering
|
|
_Ptr->_Decref();
|
|
_Ptr = _NEW_CRT _Locimp(*_Ptr);
|
|
}
|
|
_Ptr->_Addfac(fac, id);
|
|
|
|
if (catmask != 0)
|
|
_Ptr->_Name = "*";
|
|
return (*this);
|
|
}
|
|
|
|
locale __cdecl locale::global(const locale& loc)
|
|
{ // change global locale
|
|
locale _Oldglobal;
|
|
_Lockit lock(_LOCK_LOCALE);
|
|
locale::_Locimp *_Ptr = ::_Getgloballocale();
|
|
|
|
if (_Ptr != loc._Ptr)
|
|
{ // set new global locale
|
|
_DELETE_CRT(_Ptr->_Decref());
|
|
::_Setgloballocale(_Ptr = loc._Ptr);
|
|
_Ptr->_Incref();
|
|
category _Cmask = _Ptr->_Catmask & all;
|
|
if (_Cmask == all)
|
|
setlocale(LC_ALL, _Ptr->_Name.c_str());
|
|
else
|
|
for (int catindex = 0; catindex <= _X_MAX; ++catindex)
|
|
if ((_CATMASK(catindex) & _Cmask) != 0)
|
|
setlocale(catindex, _Ptr->_Name.c_str());
|
|
}
|
|
return (_Oldglobal);
|
|
}
|
|
|
|
// facets associated with C categories
|
|
#define ADDFAC(Facet, cat, ptrimp, ptrloc) \
|
|
if ((_CATMASK(Facet::_Getcat()) & cat) == 0) \
|
|
; \
|
|
else if (ptrloc == 0) \
|
|
ptrimp->_Addfac(_NEW_CRT Facet(lobj), Facet::id); \
|
|
else \
|
|
ptrimp->_Addfac((locale::facet *)&_USE(*ptrloc, Facet), Facet::id);
|
|
|
|
typedef ctype<char> _T1;
|
|
typedef num_get<char, _Initer> _T2;
|
|
typedef num_put<char, _Outiter> _T3;
|
|
typedef numpunct<char> _T4;
|
|
// others moved to wlocale and xlocale to ease subsetting
|
|
typedef codecvt<char, char, mbstate_t> _Tc1;
|
|
|
|
_TEMPLATE_STAT locale::id ctype<char>::id;
|
|
|
|
|
|
locale::_Locimp *__cdecl locale::_Locimp::_Makeloc(const _Locinfo& lobj,
|
|
locale::category cat, _Locimp *ptrimp, const locale *ptrloc)
|
|
{ // setup a new locale
|
|
ADDFAC(_T1, cat, ptrimp, ptrloc);
|
|
ADDFAC(_T2, cat, ptrimp, ptrloc);
|
|
ADDFAC(_T3, cat, ptrimp, ptrloc);
|
|
ADDFAC(_T4, cat, ptrimp, ptrloc);
|
|
//...
|
|
ADDFAC(_Tc1, cat, ptrimp, ptrloc);
|
|
|
|
_Locimp::_Makexloc(lobj, cat, ptrimp, ptrloc);
|
|
_Locimp::_Makewloc(lobj, cat, ptrimp, ptrloc);
|
|
#ifdef _NATIVE_WCHAR_T_DEFINED
|
|
_Locimp::_Makeushloc(lobj, cat, ptrimp, ptrloc);
|
|
#endif
|
|
ptrimp->_Catmask |= cat;
|
|
ptrimp->_Name = lobj._Getname();
|
|
return (ptrimp);
|
|
}
|
|
|
|
locale::_Locimp::_Locimp(const locale::_Locimp& imp)
|
|
: locale::facet(1), _Facetvec(0), _Facetcount(imp._Facetcount),
|
|
_Catmask(imp._Catmask), _Xparent(imp._Xparent), _Name(imp._Name)
|
|
{ // construct a _Locimp from a copy
|
|
if (&imp == _Clocptr)
|
|
_Makeloc(_Locinfo(), locale::all, this, 0);
|
|
else
|
|
{ // lock to keep facets from disappearing
|
|
_Lockit lock(_LOCK_LOCALE);
|
|
if (0 < _Facetcount)
|
|
{ // copy over nonempty facet vector
|
|
if ((_Facetvec = (locale::facet **)_malloc_crt(
|
|
_Facetcount * sizeof (locale::facet *))) == 0)
|
|
_Nomemory();
|
|
for (size_t count = _Facetcount; 0 < count; )
|
|
{ // copy over facet pointers
|
|
locale::facet *ptrfac = imp._Facetvec[--count];
|
|
if ((_Facetvec[count] = ptrfac) != 0)
|
|
ptrfac->_Incref();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void locale::_Locimp::_Addfac(locale::facet *ptrfac, size_t id)
|
|
{ // add a facet to a locale
|
|
_Lockit lock(_LOCK_LOCALE);
|
|
const size_t MINCAT = 40; // minimum number of facets in a locale
|
|
|
|
if (_Facetcount <= id)
|
|
{ // make facet vector larger
|
|
size_t count = id + 1;
|
|
if (count < MINCAT)
|
|
count = MINCAT;
|
|
locale::facet **ptrnewvec = (locale::facet **)_realloc_crt(_Facetvec,
|
|
count * sizeof (locale::facet **));
|
|
if (ptrnewvec == 0)
|
|
_Nomemory();
|
|
|
|
_Facetvec = ptrnewvec;
|
|
for (; _Facetcount < count; ++_Facetcount)
|
|
_Facetvec[_Facetcount] = 0;
|
|
}
|
|
|
|
ptrfac->_Incref();
|
|
if (_Facetvec[id] != 0)
|
|
_DELETE_CRT(_Facetvec[id]->_Decref());
|
|
_Facetvec[id] = ptrfac;
|
|
}
|
|
|
|
_CRTIMP2 _Locinfo::_Locinfo(int cat, const char *locname)
|
|
: _Lock(_LOCK_LOCALE)
|
|
{ // capture a named locale
|
|
_Oldlocname = setlocale(LC_ALL, 0);
|
|
_Addcats(cat, locname);
|
|
}
|
|
|
|
_CRTIMP2 _Locinfo& _Locinfo::_Addcats(int cat, const char *locname)
|
|
{ // merge in another named locale
|
|
const char *oldlocname = 0;
|
|
if (locname[0] == '*' && locname[1] == '\0')
|
|
;
|
|
else if (cat == 0)
|
|
oldlocname = setlocale(LC_ALL, 0);
|
|
else if (cat == _M_ALL)
|
|
oldlocname = setlocale(LC_ALL, locname);
|
|
else
|
|
{ // alter selected categories
|
|
for (int catindex = 0; catindex <= _X_MAX; ++catindex)
|
|
if ((_CATMASK(catindex) & cat) != 0)
|
|
setlocale(catindex, locname);
|
|
oldlocname = setlocale(LC_ALL, locname);
|
|
}
|
|
if (oldlocname == 0)
|
|
_Newlocname = "*";
|
|
else if (_Newlocname.compare("*") != 0)
|
|
_Newlocname = oldlocname;
|
|
return (*this);
|
|
}
|
|
_STD_END
|
|
|
|
/*
|
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
|
* Consult your license regarding permissions and restrictions.
|
|
V3.10:0009 */
|