// locale -- class locale member functions #include #include #include #include #include _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 _Traits; typedef istreambuf_iterator _Initer; typedef ostreambuf_iterator _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 _T1; typedef num_get _T2; typedef num_put _T3; typedef numpunct _T4; // others moved to wlocale and xlocale to ease subsetting typedef codecvt _Tc1; _TEMPLATE_STAT locale::id ctype::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 */