Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1533 lines
40 KiB

  1. // xlocale internal header (from <locale>)
  2. #pragma once
  3. #ifndef _XLOCALE_
  4. #define _XLOCALE_
  5. #include <climits>
  6. #include <cstring>
  7. #include <stdexcept>
  8. #include <typeinfo>
  9. #include <xlocinfo>
  10. #include <xdebug>
  11. #pragma pack(push,8)
  12. #pragma warning(push,3)
  13. _STD_BEGIN
  14. // TEMPLATE CLASS _Locbase
  15. template<class _Dummy>
  16. class _Locbase
  17. { // define templatized category constants, instantiate on demand
  18. public:
  19. static const int collate = _M_COLLATE;
  20. static const int ctype = _M_CTYPE;
  21. static const int monetary = _M_MONETARY;
  22. static const int numeric = _M_NUMERIC;
  23. static const int time = _M_TIME;
  24. static const int messages = _M_MESSAGE;
  25. static const int all = _M_ALL;
  26. static const int none = 0;
  27. };
  28. template<class _Dummy>
  29. const int _Locbase<_Dummy>::collate;
  30. template<class _Dummy>
  31. const int _Locbase<_Dummy>::ctype;
  32. template<class _Dummy>
  33. const int _Locbase<_Dummy>::monetary;
  34. template<class _Dummy>
  35. const int _Locbase<_Dummy>::numeric;
  36. template<class _Dummy>
  37. const int _Locbase<_Dummy>::time;
  38. template<class _Dummy>
  39. const int _Locbase<_Dummy>::messages;
  40. template<class _Dummy>
  41. const int _Locbase<_Dummy>::all;
  42. template<class _Dummy>
  43. const int _Locbase<_Dummy>::none;
  44. // CLASS locale
  45. class _CRTIMP2 locale
  46. : public _Locbase<int>
  47. { // nonmutable collection of facets that describe a locale
  48. public:
  49. typedef int category;
  50. // CLASS id
  51. class _CRTIMP2 id
  52. { // identifier stamp, unique for each distinct kind of facet
  53. public:
  54. id(size_t _Val = 0)
  55. : _Id(_Val)
  56. { // construct with specified stamp value
  57. }
  58. operator size_t()
  59. { // get stamp, with lazy allocation
  60. if (_Id == 0)
  61. { // still zero, allocate stamp
  62. _Lockit _Lock(_LOCK_LOCALE);
  63. if (_Id == 0)
  64. _Id = ++_Id_cnt;
  65. }
  66. return (_Id);
  67. }
  68. private:
  69. id(const id&); // not defined
  70. id& operator=(const id&); // not defined
  71. size_t _Id; // the identifier stamp
  72. static int _Id_cnt; // static source of unique stamps
  73. };
  74. class _Locimp;
  75. // class facet
  76. class _CRTIMP2 facet
  77. { // base class for all locale facets, performs reference counting
  78. friend class locale;
  79. friend class _Locimp;
  80. public:
  81. static size_t __cdecl _Getcat(const facet ** = 0)
  82. { // get category value, or -1 if no corresponding C category
  83. return ((size_t)(-1));
  84. }
  85. void _Incref()
  86. { // safely increment the reference count
  87. _Lockit _Lock(_LOCK_LOCALE);
  88. if (_Refs < (size_t)(-1))
  89. ++_Refs;
  90. }
  91. facet *_Decref()
  92. { // safely decrement the reference count, return this when dead
  93. _Lockit _Lock(_LOCK_LOCALE);
  94. if (0 < _Refs && _Refs < (size_t)(-1))
  95. --_Refs;
  96. return (_Refs == 0 ? this : 0);
  97. }
  98. void _Register(); // queue up lazy facet for destruction
  99. // _PROTECTED:
  100. virtual ~facet()
  101. { // destroy the object
  102. }
  103. protected:
  104. explicit facet(size_t _Initrefs = 0)
  105. : _Refs(_Initrefs)
  106. { // construct with initial reference count
  107. }
  108. private:
  109. facet(const facet&); // not defined
  110. facet& operator=(const facet&); // not defined
  111. size_t _Refs; // the reference count
  112. };
  113. // CLASS _Locimp
  114. class _Locimp
  115. : public facet
  116. { // reference-counted actual implementation of a locale
  117. _PROTECTED:
  118. ~_Locimp(); // destroy the object
  119. private:
  120. friend class locale;
  121. _Locimp(bool _Transparent = false); // construct from current locale
  122. _CRTIMP2 _Locimp(const _Locimp&); // copy a _Locimp
  123. _CRTIMP2 void _Addfac(facet *, size_t); // add a facet
  124. static _Locimp *__cdecl _Makeloc(const _Locinfo&,
  125. category, _Locimp *, const locale *); // make essential facets
  126. static void __cdecl _Makewloc(const _Locinfo&,
  127. category, _Locimp *, const locale *); // make wchar_t facets
  128. static void __cdecl _Makexloc(const _Locinfo&,
  129. category, _Locimp *, const locale *); // make remaining facets
  130. facet **_Facetvec; // pointer to vector of facets
  131. size_t _Facetcount; // size of vector of facets
  132. category _Catmask; // mask describing implemented categories
  133. bool _Xparent; // true if locale is transparent
  134. _STRING_CRT _Name; // locale name, or "*" if not known
  135. static _CRTIMP2 _Locimp *_Clocptr; // pointer to "C" locale object
  136. };
  137. _DEPRECATED locale& _Addfac(facet *, size_t,
  138. size_t); // add a facet, copying on write
  139. template<class _Elem,
  140. class _Traits,
  141. class _Alloc>
  142. bool operator()(const basic_string<_Elem, _Traits, _Alloc>& _Left,
  143. const basic_string<_Elem, _Traits, _Alloc>& _Right) const
  144. { // compare _Left and _Right strings using collate facet in locale
  145. const std::collate<_Elem>& _Fac =
  146. std::use_facet<std::collate<_Elem> >(*this);
  147. return (_Fac.compare(_Left.c_str(), _Left.c_str() + _Left.size(),
  148. _Right.c_str(), _Right.c_str() + _Right.size()) < 0);
  149. }
  150. template<class _Facet>
  151. locale combine(const locale& _Loc) const
  152. { // combine two locales
  153. _Facet *_Facptr;
  154. _TRY_BEGIN
  155. _Facptr = (_Facet *)&std::use_facet<_Facet>(_Loc);
  156. _CATCH_ALL
  157. _THROW(runtime_error, "locale::combine facet missing");
  158. _CATCH_END
  159. _Locimp *_Newimp = _NEW_CRT _Locimp(*_Ptr);
  160. _Newimp->_Addfac(_Facptr, _Facet::id);
  161. if (_Facet::_Getcat() != (size_t)(-1))
  162. { // not a standard facet, result has no name
  163. _Newimp->_Catmask = 0;
  164. _Newimp->_Name = "*";
  165. }
  166. return (locale(_Newimp));
  167. }
  168. template<class _Facet>
  169. locale(const locale& _Loc, _Facet *_Facptr)
  170. : _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr))
  171. { // construct from _Loc, replacing facet with *_Facptr
  172. if (_Facptr != 0)
  173. { // replace facet
  174. _Ptr->_Addfac(_Facptr, _Facet::id);
  175. if (_Facet::_Getcat() != (size_t)(-1))
  176. _Ptr->_Catmask = 0, _Ptr->_Name = "*"; // no C category
  177. }
  178. }
  179. locale() _THROW0(); // construct from current locale
  180. locale(_Uninitialized)
  181. { // defer construction
  182. }
  183. locale(const locale& _Right) _THROW0()
  184. : _Ptr(_Right._Ptr)
  185. { // construct by copying
  186. _Ptr->_Incref();
  187. }
  188. locale(const locale&, const locale&,
  189. category); // construct from locale and category in another locale
  190. explicit locale(const char *,
  191. category = all); // construct from named locale for category
  192. locale(const locale&, const char *,
  193. category); // construct from locale and category in named locale
  194. ~locale() _THROW0()
  195. { // destroy the object
  196. if (_Ptr != 0)
  197. _DELETE_CRT(_Ptr->_Decref());
  198. }
  199. locale& operator=(const locale& _Right) _THROW0()
  200. { // assign a locale
  201. if (_Ptr != _Right._Ptr)
  202. { // different implementation, point at new one
  203. _DELETE_CRT(_Ptr->_Decref());
  204. _Ptr = _Right._Ptr;
  205. _Ptr->_Incref();
  206. }
  207. return (*this);
  208. }
  209. string name() const
  210. { // return locale name
  211. return (_Ptr->_Name);
  212. }
  213. const facet *_Getfacet(size_t) const; // get facet by id
  214. bool operator==(const locale&) const; // test for locale equality
  215. bool operator!=(const locale& _Right) const
  216. { // test for locale inequality
  217. return (!(*this == _Right));
  218. }
  219. static const locale& __cdecl classic(); // return classic "C" locale
  220. static locale __cdecl global(const locale&); // return current locale
  221. static locale __cdecl empty(); // return empty (transparent) locale
  222. private:
  223. locale(_Locimp *_Ptrimp)
  224. : _Ptr(_Ptrimp)
  225. { // construct from _Locimp pointer
  226. }
  227. static _Locimp *__cdecl _Init(); // initialize locale
  228. _Locimp *_Ptr; // pointer to locale implementation object
  229. };
  230. // SUPPORT TEMPLATES
  231. template<class _Facet> inline _DEPRECATED
  232. locale _Addfac(locale _Loc, _Facet *_Fac)
  233. { // add facet to locale -- retained
  234. return (_Loc._Addfac(_Fac, _Facet::id, _Facet::_Getcat()));
  235. }
  236. #define _ADDFAC(loc, pfac) locale(loc, pfac) /* add facet to locale */
  237. #define _USE(loc, fac) \
  238. use_facet<fac >(loc) /* get facet reference from locale */
  239. template<class _Facet> inline
  240. const _Facet& __cdecl use_facet(const locale& _Loc)
  241. { // get facet reference from locale
  242. _Lockit _Lock(_LOCK_LOCALE); // the thread lock, make get atomic
  243. static const locale::facet *_Psave; // static pointer to lazy facet
  244. size_t _Id = _Facet::id;
  245. const locale::facet *_Pf = _Loc._Getfacet(_Id);
  246. if (_Pf != 0)
  247. ; // got facet from locale
  248. else if (_Psave != 0)
  249. _Pf = _Psave; // lazy facet already allocated
  250. else if (_Facet::_Getcat(&_Psave) == (size_t)(-1))
  251. #if _HAS_EXCEPTIONS
  252. throw bad_cast(); // lazy disallowed
  253. #else /* _HAS_EXCEPTIONS */
  254. abort(); // lazy disallowed
  255. #endif /* _HAS_EXCEPTIONS */
  256. else
  257. { // queue up lazy facet for destruction
  258. _Pf = _Psave;
  259. locale::facet *_Pfmod = (_Facet *)_Psave;
  260. _Pfmod->_Incref();
  261. _Pfmod->_Register();
  262. }
  263. return ((const _Facet&)(*_Pf)); // should be dynamic_cast
  264. }
  265. template<class _Facet> inline _DEPRECATED
  266. const _Facet& __cdecl use_facet(const locale& _Loc, const _Facet *,
  267. bool = false)
  268. { // get facet reference from locale -- retained, 2/3 arg versions
  269. return use_facet<_Facet>(_Loc);
  270. }
  271. // TEMPLATE FUNCTION _Narrow
  272. #define _NARROW(T, V) _Narrow(static_cast<T>(V)) /* convert T to char */
  273. template<class _Elem> inline
  274. char _Narrow(_Elem _Ch)
  275. { // convert _Elem to char
  276. return ((char)_Ch); // needs _Elem::operator char()
  277. }
  278. template<> inline
  279. char _Narrow(wchar_t _Ch)
  280. { // convert wchar_t to char (using current locale, no state)
  281. return ((char)wctob(_Ch));
  282. }
  283. // TEMPLATE FUNCTION _Widen
  284. #define _WIDEN(T, V) _Widen(V, (T *)0) /* convert char to T */
  285. template<class _Elem> inline
  286. _Elem _Widen(char _Ch, _Elem *)
  287. { // convert char to _Elem
  288. return ((_Elem)(unsigned char)_Ch); // needs _Elem(char)
  289. }
  290. template<> inline
  291. wchar_t _Widen(char _Ch, wchar_t *)
  292. { // convert char to wchar_t (using current locale, no state)
  293. return (btowc(_Ch));
  294. }
  295. // TEMPLATE FUNCTION _Getloctxt
  296. template<class _Elem,
  297. class _InIt> inline
  298. int __cdecl _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields,
  299. const _Elem *_Ptr)
  300. { // find field at _Ptr that matches longest in [_First, _Last)
  301. for (size_t _Off = 0; _Ptr[_Off] != (_Elem)0; ++_Off)
  302. if (_Ptr[_Off] == _Ptr[0])
  303. ++_Numfields; // add fields with leading mark to initial count
  304. string _Str(_Numfields, '\0'); // one column counter for each field
  305. int _Ans = -2; // no candidates so far
  306. for (size_t _Column = 1; ; ++_Column, ++_First, _Ans = -1)
  307. { // test each element against all viable fields
  308. bool _Prefix = false; // seen at least one valid prefix
  309. size_t _Off = 0; // offset into fields
  310. size_t _Field = 0; // current field number
  311. for (; _Field < _Numfields; ++_Field)
  312. { // test element at _Column in field _Field
  313. for (; _Ptr[_Off] != (_Elem)0 && _Ptr[_Off] != _Ptr[0]; ++_Off)
  314. ; // find beginning of field
  315. if (_Str[_Field] != '\0')
  316. _Off += _Str[_Field]; // skip tested columns in field
  317. else if (_Ptr[_Off += _Column] == _Ptr[0]
  318. || _Ptr[_Off] == (_Elem)0)
  319. { // matched all of field, save as possible answer
  320. _Str[_Field] = (char)(_Column < 127
  321. ? _Column : 127); // save skip count if small enough
  322. _Ans = (int)_Field; // save answer
  323. }
  324. else if (_First == _Last || _Ptr[_Off] != *_First)
  325. _Str[_Field] = (char)(_Column < 127
  326. ? _Column : 127); // no match, just save skip count
  327. else
  328. _Prefix = true; // still a valid prefix
  329. }
  330. if (!_Prefix || _First == _Last)
  331. break; // no pending prefixes or no input, give up
  332. }
  333. return (_Ans); // return field number or negative value on failure
  334. }
  335. // TEMPLATE FUNCTION _Maklocstr
  336. #define _MAKLOCSTR(_Elem, _Str, _Cvt) \
  337. _Maklocstr(_Str, (_Elem *)0, _Cvt) // convert C string to _Elem sequence
  338. template<class _Elem> inline
  339. _Elem *__cdecl _Maklocstr(const char *_Ptr, _Elem *,
  340. const _Locinfo::_Cvtvec &)
  341. { // convert C string to _Elem sequence
  342. size_t _Count = ::strlen(_Ptr) + 1;
  343. _Elem *_Ptrdest = _NEW_CRT _Elem[_Count];
  344. for (_Elem *_Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr)
  345. *_Ptrnext = _WIDEN(_Elem, *_Ptr);
  346. return (_Ptrdest);
  347. }
  348. template<> inline
  349. wchar_t *__cdecl _Maklocstr(const char *_Ptr, wchar_t *,
  350. const _Locinfo::_Cvtvec &_Cvt)
  351. { // convert C string to wchar_t sequence
  352. size_t _Count, _Count1;
  353. size_t _Wchars;
  354. const char *_Ptr1;
  355. wchar_t *_Ptrdest, *_Ptrnext;
  356. _Mbstinit(_Mbst1);
  357. _Count = _Count1 = ::strlen(_Ptr) + 1;
  358. for (_Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; ++_Wchars)
  359. { // determine length of wide string
  360. int _Bytes;
  361. if ((_Bytes = _Mbrtowc(0, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0)
  362. break;
  363. _Ptr1 += _Bytes;
  364. _Count -= _Bytes;
  365. }
  366. ++_Wchars;
  367. _Ptrdest = _NEW_CRT wchar_t[_Wchars];
  368. _Mbstinit(_Mbst2);
  369. for (_Ptrnext = _Ptrdest; 0 < _Wchars; --_Wchars, ++_Ptrnext)
  370. { // widen string
  371. int _Bytes;
  372. if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst1, &_Cvt)) <= 0)
  373. break;
  374. _Ptr += _Bytes;
  375. _Count1 -= _Bytes;
  376. }
  377. *_Ptrnext = 0;
  378. return (_Ptrdest);
  379. }
  380. // STRUCT codecvt_base
  381. class _CRTIMP2 codecvt_base
  382. : public locale::facet
  383. { // base class for codecvt
  384. public:
  385. enum
  386. { // constants for different parse states
  387. ok, partial, error, noconv};
  388. typedef int result;
  389. codecvt_base(size_t _Refs = 0)
  390. : locale::facet(_Refs)
  391. { // default constructor
  392. }
  393. bool always_noconv() const _THROW0()
  394. { // return true if conversions never change input (from codecvt)
  395. return (do_always_noconv());
  396. }
  397. int max_length() const _THROW0()
  398. { // return maximum length required for a conversion (from codecvt)
  399. return (do_max_length());
  400. }
  401. int encoding() const _THROW0()
  402. { // return length of code sequence (from codecvt)
  403. return (do_encoding());
  404. }
  405. ~codecvt_base()
  406. { // destroy the object
  407. }
  408. protected:
  409. virtual bool do_always_noconv() const _THROW0()
  410. { // return true if conversions never change input (from codecvt)
  411. return (true);
  412. }
  413. virtual int do_max_length() const _THROW0()
  414. { // return maximum length required for a conversion (from codecvt)
  415. return (1);
  416. }
  417. virtual int do_encoding() const _THROW0()
  418. { // return length of code sequence (from codecvt)
  419. return (1); // -1 ==> state dependent, 0 ==> varying length
  420. }
  421. };
  422. // TEMPLATE CLASS codecvt
  423. template<class _Elem,
  424. class _Byte,
  425. class _Statype>
  426. class codecvt
  427. : public codecvt_base
  428. { // facet for converting between _Elem and char (_Byte) sequences
  429. public:
  430. typedef _Elem intern_type;
  431. typedef _Byte extern_type;
  432. typedef _Statype state_type;
  433. result in(_Statype& _State,
  434. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  435. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  436. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  437. return (do_in(_State,
  438. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  439. }
  440. result out(_Statype& _State,
  441. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  442. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  443. { // convert [_First1, _Last1) to bytes [_First2, _Last2)
  444. return (do_out(_State,
  445. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  446. }
  447. result unshift(_Statype& _State,
  448. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  449. { // generate bytes to return to default shift state
  450. return (do_unshift(_State, _First2, _Last2, _Mid2));
  451. }
  452. int length(const _Statype& _State, const _Byte *_First1,
  453. const _Byte *_Last1, size_t _Count) const _THROW0()
  454. { // return min(_Count, converted length of bytes [_First1, _Last1))
  455. return (do_length(_State, _First1, _Last1, _Count));
  456. }
  457. static locale::id id; // unique facet id
  458. explicit codecvt(size_t _Refs = 0)
  459. : codecvt_base(_Refs)
  460. { // construct from current locale
  461. _Init(_Locinfo());
  462. }
  463. codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
  464. : codecvt_base(_Refs)
  465. { // construct from specified locale
  466. _Init(_Lobj);
  467. }
  468. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  469. { // return locale category mask and construct standard facet
  470. if (_Ppf != 0 && *_Ppf == 0)
  471. *_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
  472. return (_X_CTYPE);
  473. }
  474. _PROTECTED:
  475. virtual ~codecvt()
  476. { // destroy the object
  477. }
  478. protected:
  479. void _Init(const _Locinfo& _Lobj)
  480. { // initialize from _Lobj
  481. _Cvt = _Lobj._Getcvt();
  482. }
  483. virtual result do_in(_Statype&,
  484. const _Byte *_First1, const _Byte *, const _Byte *& _Mid1,
  485. _Elem *_First2, _Elem *, _Elem *& _Mid2) const
  486. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  487. _Mid1 = _First1, _Mid2 = _First2;
  488. return (noconv); // convert nothing
  489. }
  490. virtual result do_out(_Statype&,
  491. const _Elem *_First1, const _Elem *, const _Elem *& _Mid1,
  492. _Byte *_First2, _Byte *, _Byte *& _Mid2) const
  493. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  494. _Mid1 = _First1, _Mid2 = _First2;
  495. return (noconv); // convert nothing
  496. }
  497. virtual result do_unshift(_Statype&,
  498. _Byte *, _Byte *, _Byte *&) const
  499. { // generate bytes to return to default shift state
  500. return (noconv); // convert nothing
  501. }
  502. virtual int do_length(const _Statype&, const _Byte *_First1,
  503. const _Byte *_Last1, size_t _Count) const _THROW0()
  504. { // return min(_Count, converted length of bytes [_First1, _Last1))
  505. return (int)(_Count < (size_t)(_Last1 - _First1)
  506. ? _Count : _Last1 - _First1); // assume one-to-one conversion
  507. }
  508. private:
  509. _Locinfo::_Cvtvec _Cvt; // used by codecvt<wchar_t, char, mbstate_t>
  510. };
  511. // STATIC codecvt::id OBJECT
  512. template<class _Elem,
  513. class _Byte,
  514. class _Statype>
  515. locale::id codecvt<_Elem, _Byte, _Statype>::id;
  516. // CLASS codecvt<wchar_t, char, mbstate_t>
  517. template<> class _CRTIMP2 codecvt<wchar_t, char, mbstate_t>
  518. : public codecvt_base
  519. { // facet for converting between wchar_t and char (_Byte) sequences
  520. public:
  521. typedef wchar_t _Elem;
  522. typedef char _Byte;
  523. typedef mbstate_t _Statype;
  524. typedef _Elem intern_type;
  525. typedef _Byte extern_type;
  526. typedef _Statype state_type;
  527. result in(_Statype& _State,
  528. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  529. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  530. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  531. return (do_in(_State,
  532. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  533. }
  534. result out(_Statype& _State,
  535. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  536. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  537. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  538. return (do_out(_State,
  539. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  540. }
  541. result unshift(_Statype& _State,
  542. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  543. { // generate bytes to return to default shift state
  544. return (do_unshift(_State,
  545. _First2, _Last2, _Mid2));
  546. }
  547. int length(const _Statype& _State, const _Byte *_First1,
  548. const _Byte *_Last1, size_t _N2) const _THROW0()
  549. { // return min(_Count, converted length of bytes [_First1, _Last1))
  550. return (do_length(_State, _First1, _Last1, _N2));
  551. }
  552. static locale::id id; // unique facet id
  553. explicit codecvt(size_t _Refs = 0)
  554. : codecvt_base(_Refs)
  555. { // construct from current locale
  556. _Init(_Locinfo());
  557. }
  558. codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
  559. : codecvt_base(_Refs)
  560. { // construct from specified locale
  561. _Init(_Lobj);
  562. }
  563. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  564. { // return locale category mask and construct standard facet
  565. if (_Ppf != 0 && *_Ppf == 0)
  566. *_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
  567. return (_X_CTYPE);
  568. }
  569. _PROTECTED:
  570. virtual ~codecvt()
  571. { // destroy the object
  572. }
  573. protected:
  574. void _Init(const _Locinfo& _Lobj)
  575. { // initialize from _Lobj
  576. _Cvt = _Lobj._Getcvt();
  577. }
  578. virtual result do_in(_Statype& _State,
  579. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  580. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  581. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  582. _Mid1 = _First1, _Mid2 = _First2;
  583. result _Ans = _Mid1 == _Last1 ? ok : partial;
  584. int _Bytes;
  585. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  586. switch (_Bytes = _Mbrtowc(_Mid2, _Mid1, _Last1 - _Mid1,
  587. &_State, &_Cvt))
  588. { // test result of locale-specific mbrtowc call
  589. case -2: // partial conversion
  590. _Mid1 = _Last1;
  591. return (_Ans);
  592. case -1: // failed conversion
  593. return (error);
  594. case 0: // converted null character
  595. _Bytes = (int)::strlen(_Mid1) + 1;
  596. // fall through
  597. default: // converted _Bytes bytes to a wchar_t
  598. _Mid1 += _Bytes, ++_Mid2, _Ans = ok;
  599. }
  600. return (_Ans);
  601. }
  602. virtual result do_out(_Statype& _State,
  603. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  604. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  605. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  606. _Mid1 = _First1, _Mid2 = _First2;
  607. result _Ans = _Mid1 == _Last1 ? ok : partial;
  608. int _Bytes;
  609. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  610. if (___mb_cur_max_func() <= _Last2 - _Mid2)
  611. if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1,
  612. &_State, &_Cvt)) <= 0)
  613. return (error); // locale-specific wcrtomb failed
  614. else
  615. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  616. else
  617. { // destination too small, convert into buffer
  618. _Byte _Buf[MB_LEN_MAX];
  619. _Statype _Stsave = _State;
  620. if ((_Bytes = _Wcrtomb(_Buf, *_Mid1,
  621. &_State, &_Cvt)) <= 0)
  622. return (error); // locale-specific wcrtomb failed
  623. else if (_Last2 - _Mid2 < _Bytes)
  624. { // converted too many, roll back and return previous
  625. _State = _Stsave;
  626. return (_Ans);
  627. }
  628. else
  629. { // copy converted bytes from buffer
  630. memcpy(_Mid2, _Buf, _Bytes);
  631. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  632. }
  633. }
  634. return (_Ans);
  635. }
  636. virtual result do_unshift(_Statype& _State,
  637. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  638. { // generate bytes to return to default shift state
  639. _Mid2 = _First2;
  640. result _Ans = ok;
  641. int _Bytes;
  642. _Byte _Buf[MB_LEN_MAX];
  643. _Statype _Stsave = _State;
  644. if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0)
  645. _Ans = error; // locale-specific wcrtomb failed
  646. else if (_Last2 - _Mid2 < --_Bytes)
  647. { // converted too many, roll back and return
  648. _State = _Stsave;
  649. _Ans = partial;
  650. }
  651. else if (0 < _Bytes)
  652. { // copy converted bytes from buffer
  653. memcpy(_Mid2, _Buf, _Bytes);
  654. _Mid2 += _Bytes;
  655. }
  656. return (_Ans);
  657. }
  658. virtual int do_length(const _Statype& _State, const _Byte *_First1,
  659. const _Byte *_Last1, size_t _Count) const _THROW0()
  660. { // return min(_Count, converted length of bytes [_First1, _Last1))
  661. int _Wchars;
  662. const _Byte *_Mid1;
  663. _Statype _Mystate = _State;
  664. for (_Wchars = 0, _Mid1 = _First1;
  665. (size_t)_Wchars < _Count && _Mid1 != _Last1; )
  666. { // convert another wchar_t
  667. int _Bytes;
  668. _Elem _Ch;
  669. switch (_Bytes = _Mbrtowc(&_Ch, _Mid1, _Last1 - _Mid1,
  670. &_Mystate, &_Cvt))
  671. { // test result of locale-specific mbrtowc call
  672. case -2: // partial conversion
  673. return (_Wchars);
  674. case -1: // failed conversion
  675. return (_Wchars);
  676. case 0: // converted null character
  677. _Bytes = (int)::strlen(_Mid1) + 1;
  678. // fall through
  679. default: // converted _Bytes bytes to a wchar_t
  680. _Mid1 += _Bytes, ++_Wchars;
  681. }
  682. }
  683. return (_Wchars);
  684. }
  685. virtual bool do_always_noconv() const _THROW0()
  686. { // return true if conversions never change input
  687. return (false);
  688. }
  689. virtual int do_max_length() const _THROW0()
  690. { // return maximum length required for a conversion (from codecvt)
  691. return (MB_LEN_MAX);
  692. }
  693. virtual int do_encoding() const _THROW0()
  694. { // return length of code sequence (from codecvt)
  695. return (0);
  696. }
  697. private:
  698. _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb
  699. };
  700. // TEMPLATE CLASS codecvt_byname
  701. template<class _Elem,
  702. class _Byte,
  703. class _Statype>
  704. class codecvt_byname
  705. : public codecvt<_Elem, _Byte, _Statype>
  706. { // codecvt for named locale
  707. public:
  708. explicit codecvt_byname(const char *_Locname, size_t _Refs = 0)
  709. : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Locname), _Refs)
  710. { // construct for named locale
  711. }
  712. _PROTECTED:
  713. virtual ~codecvt_byname()
  714. { // destroy the object
  715. }
  716. };
  717. // STRUCT ctype_base
  718. struct _CRTIMP2 ctype_base
  719. : public locale::facet
  720. { // base for ctype
  721. enum
  722. { // constants for character classifications
  723. alnum = _DI|_LO|_UP|_XA, alpha = _LO|_UP|_XA,
  724. cntrl = _BB, digit = _DI, graph = _DI|_LO|_PU|_UP|_XA,
  725. lower = _LO, print = _DI|_LO|_PU|_SP|_UP|_XA|_XD,
  726. punct = _PU, space = _CN|_SP|_XS, upper = _UP,
  727. xdigit = _XD};
  728. typedef short mask; // to match <ctype.h>
  729. ctype_base(size_t _Refs = 0)
  730. : locale::facet(_Refs)
  731. { // default constructor
  732. }
  733. ~ctype_base()
  734. { // destroy the object
  735. }
  736. };
  737. // TEMPLATE CLASS ctype
  738. template<class _Elem>
  739. class ctype
  740. : public ctype_base
  741. { // facet for classifying elements, converting cases
  742. public:
  743. typedef _Elem char_type;
  744. bool is(mask _Maskval, _Elem _Ch) const
  745. { // test if element fits any mask classifications
  746. return (do_is(_Maskval, _Ch));
  747. }
  748. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  749. mask *_Dest) const
  750. { // get mask sequence for elements in [_First, _Last)
  751. return (do_is(_First, _Last, _Dest));
  752. }
  753. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  754. const _Elem *_Last) const
  755. { // find first in [_First, _Last) that fits mask classification
  756. return (do_scan_is(_Maskval, _First, _Last));
  757. }
  758. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  759. const _Elem *_Last) const
  760. { // find first in [_First, _Last) not fitting mask classification
  761. return (do_scan_not(_Maskval, _First, _Last));
  762. }
  763. _Elem tolower(_Elem _Ch) const
  764. { // convert element to lower case
  765. return (do_tolower(_Ch));
  766. }
  767. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  768. { // convert [_First, _Last) in place to lower case
  769. return (do_tolower(_First, _Last));
  770. }
  771. _Elem toupper(_Elem _Ch) const
  772. { // convert element to upper case
  773. return (do_toupper(_Ch));
  774. }
  775. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  776. { // convert [_First, _Last) in place to upper case
  777. return (do_toupper(_First, _Last));
  778. }
  779. _Elem widen(char _Byte) const
  780. { // widen char
  781. return (do_widen(_Byte));
  782. }
  783. const char *widen(const char *_First, const char *_Last,
  784. _Elem *_Dest) const
  785. { // widen chars in [_First, _Last)
  786. return (do_widen(_First, _Last, _Dest));
  787. }
  788. char narrow(_Elem _Ch, char _Dflt = '\0') const
  789. { // narrow element to char
  790. return (do_narrow(_Ch, _Dflt));
  791. }
  792. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  793. char _Dflt, char *_Dest) const
  794. { // narrow elements in [_First, _Last) to chars
  795. return (do_narrow(_First, _Last, _Dflt, _Dest));
  796. }
  797. static locale::id id; // unique facet id
  798. explicit ctype(size_t _Refs = 0)
  799. : ctype_base(_Refs)
  800. { // construct from current locale
  801. _Init(_Locinfo());
  802. }
  803. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  804. : ctype_base(_Refs)
  805. { // construct from specified locale
  806. _Init(_Lobj);
  807. }
  808. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  809. { // return locale category mask and construct standard facet
  810. if (_Ppf != 0 && *_Ppf == 0)
  811. *_Ppf = _NEW_CRT ctype<_Elem>;
  812. return (_X_CTYPE);
  813. }
  814. _PROTECTED:
  815. virtual ~ctype()
  816. { // destroy the object
  817. if (_Ctype._Delfl)
  818. free((void *)_Ctype._Table);
  819. }
  820. protected:
  821. void _Init(const _Locinfo& _Lobj)
  822. { // initialize from _Lobj
  823. _Ctype = _Lobj._Getctype();
  824. }
  825. virtual bool do_is(mask _Maskval, _Elem _Ch) const
  826. { // test if element fits any mask classifications
  827. return ((_Ctype._Table[(unsigned char)narrow(_Ch)]
  828. & _Maskval) != 0);
  829. }
  830. virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
  831. mask *_Dest) const
  832. { // get mask sequence for elements in [_First, _Last)
  833. for (; _First != _Last; ++_First, ++_Dest)
  834. *_Dest = _Ctype._Table[(unsigned char)narrow(*_First)];
  835. return (_First);
  836. }
  837. virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
  838. const _Elem *_Last) const
  839. { // find first in [_First, _Last) that fits mask classification
  840. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  841. ;
  842. return (_First);
  843. }
  844. virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
  845. const _Elem *_Last) const
  846. { // find first in [_First, _Last) not fitting mask classification
  847. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  848. ;
  849. return (_First);
  850. }
  851. virtual _Elem do_tolower(_Elem _Ch) const
  852. { // convert element to lower case
  853. return (widen((char)_Tolower((unsigned char)narrow(_Ch),
  854. &_Ctype)));
  855. }
  856. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  857. { // convert [_First, _Last) in place to lower case
  858. for (; _First != _Last; ++_First)
  859. *_First = widen((char)_Tolower((unsigned char)narrow(*_First),
  860. &_Ctype));
  861. return ((const _Elem *)_First);
  862. }
  863. virtual _Elem do_toupper(_Elem _Ch) const
  864. { // convert element to upper case
  865. return (widen((char)_Toupper((unsigned char)narrow(_Ch),
  866. &_Ctype)));
  867. }
  868. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  869. { // convert [_First, _Last) in place to upper case
  870. for (; _First != _Last; ++_First)
  871. *_First = widen((char)_Toupper((unsigned char)narrow(*_First),
  872. &_Ctype));
  873. return ((const _Elem *)_First);
  874. }
  875. virtual _Elem do_widen(char _Byte) const
  876. { // widen char
  877. return (_WIDEN(_Elem, _Byte));
  878. }
  879. virtual const char *do_widen(const char *_First, const char *_Last,
  880. _Elem *_Dest) const
  881. { // widen chars in [_First, _Last)
  882. for (; _First != _Last; ++_First, ++_Dest)
  883. *_Dest = _WIDEN(_Elem, *_First);
  884. return (_First);
  885. }
  886. virtual char do_narrow(_Elem _Ch, char) const
  887. { // narrow element to char
  888. return (_NARROW(_Elem, _Ch));
  889. }
  890. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  891. char, char *_Dest) const
  892. { // narrow elements in [_First, _Last) to chars
  893. for (; _First != _Last; ++_First, ++_Dest)
  894. *_Dest = _NARROW(_Elem, *_First);
  895. return (_First);
  896. }
  897. private:
  898. _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc.
  899. };
  900. // STATIC ctype::id OBJECT
  901. template<class _Elem>
  902. locale::id ctype<_Elem>::id;
  903. // CLASS ctype<char>
  904. template<> class _CRTIMP2 ctype<char>
  905. : public ctype_base
  906. { // facet for classifying char elements, converting cases
  907. typedef ctype<char> _Myt;
  908. public:
  909. typedef char _Elem;
  910. typedef _Elem char_type;
  911. bool is(mask _Maskval, _Elem _Ch) const
  912. { // test if element fits any mask classifications
  913. return ((_Ctype._Table[(unsigned char)_Ch] & _Maskval) != 0);
  914. }
  915. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  916. mask *_Dest) const
  917. { // get mask sequence for elements in [_First, _Last)
  918. for (; _First != _Last; ++_First, ++_Dest)
  919. *_Dest = _Ctype._Table[(unsigned char)*_First];
  920. return (_First);
  921. }
  922. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  923. const _Elem *_Last) const
  924. { // find first in [_First, _Last) that fits mask classification
  925. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  926. ;
  927. return (_First);
  928. }
  929. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  930. const _Elem *_Last) const
  931. { // find first in [_First, _Last) not fitting mask classification
  932. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  933. ;
  934. return (_First);
  935. }
  936. _Elem tolower(_Elem _Ch) const
  937. { // convert element to lower case
  938. return (do_tolower(_Ch));
  939. }
  940. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  941. { // convert [_First, _Last) in place to lower case
  942. return (do_tolower(_First, _Last));
  943. }
  944. _Elem toupper(_Elem _Ch) const
  945. { // convert element to upper case
  946. return (do_toupper(_Ch));
  947. }
  948. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  949. { // convert [_First, _Last) in place to upper case
  950. return (do_toupper(_First, _Last));
  951. }
  952. _Elem widen(char _Byte) const
  953. { // widen char
  954. return (do_widen(_Byte));
  955. }
  956. const _Elem *widen(const char *_First, const char *_Last,
  957. _Elem *_Dest) const
  958. { // widen chars in [_First, _Last)
  959. return (do_widen(_First, _Last, _Dest));
  960. }
  961. _Elem narrow(_Elem _Ch, char _Dflt = '\0') const
  962. { // narrow element to char
  963. return (do_narrow(_Ch, _Dflt));
  964. }
  965. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  966. char _Dflt, char *_Dest) const
  967. { // narrow elements in [_First, _Last) to chars
  968. return (do_narrow(_First, _Last, _Dflt, _Dest));
  969. }
  970. static locale::id id; // unique facet id
  971. explicit ctype(const mask *_Table = 0, bool _Deletetable = false,
  972. size_t _Refs = 0)
  973. : ctype_base(_Refs)
  974. { // construct with specified table and delete flag for table
  975. _Init(_Locinfo());
  976. if (_Table != 0)
  977. { // replace existing char to mask table
  978. _Tidy();
  979. _Ctype._Table = _Table;
  980. _Ctype._Delfl = _Deletetable ? -1 : 0;
  981. }
  982. }
  983. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  984. : ctype_base(_Refs)
  985. { // construct from current locale
  986. _Init(_Lobj);
  987. }
  988. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  989. { // construct from specified locale
  990. if (_Ppf != 0 && *_Ppf == 0)
  991. *_Ppf = _NEW_CRT ctype<_Elem>;
  992. return (_X_CTYPE);
  993. }
  994. static const size_t table_size; // size of _Ctype._Table (char to mask)
  995. _PROTECTED:
  996. virtual ~ctype()
  997. { // destroy the object
  998. _Tidy();
  999. }
  1000. protected:
  1001. void _Init(const _Locinfo& _Lobj)
  1002. { // initialize from _Lobj
  1003. _Ctype = _Lobj._Getctype();
  1004. }
  1005. void _Tidy()
  1006. { // free any allocated storage
  1007. if (0 < _Ctype._Delfl)
  1008. free((void *)_Ctype._Table);
  1009. else if (_Ctype._Delfl < 0)
  1010. delete[] (void *)_Ctype._Table;
  1011. }
  1012. virtual _Elem do_tolower(_Elem _Ch) const
  1013. { // convert element to lower case
  1014. return ((_Elem)_Tolower((unsigned char)_Ch, &_Ctype));
  1015. }
  1016. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1017. { // convert [_First, _Last) in place to lower case
  1018. for (; _First != _Last; ++_First)
  1019. *_First = (_Elem)_Tolower((unsigned char)*_First, &_Ctype);
  1020. return ((const _Elem *)_First);
  1021. }
  1022. virtual _Elem do_toupper(_Elem _Ch) const
  1023. { // convert element to upper case
  1024. return ((_Elem)_Toupper((unsigned char)_Ch, &_Ctype));
  1025. }
  1026. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1027. { // convert [_First, _Last) in place to upper case
  1028. for (; _First != _Last; ++_First)
  1029. *_First = (_Elem)_Toupper((unsigned char)*_First, &_Ctype);
  1030. return ((const _Elem *)_First);
  1031. }
  1032. virtual _Elem do_widen(char _Byte) const
  1033. { // widen char
  1034. return (_Byte);
  1035. }
  1036. virtual const _Elem *do_widen(const char *_First, const char *_Last,
  1037. _Elem *_Dest) const
  1038. { // widen chars in [_First, _Last)
  1039. memcpy(_Dest, _First, _Last - _First);
  1040. return (_Last);
  1041. }
  1042. virtual _Elem do_narrow(_Elem _Ch, char) const
  1043. { // narrow char
  1044. return (_Ch);
  1045. }
  1046. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1047. char, char *_Dest) const
  1048. { // narrow elements in [_First, _Last) to chars
  1049. memcpy(_Dest, _First, _Last - _First);
  1050. return (_Last);
  1051. }
  1052. const mask *table() const _THROW0()
  1053. { // return address of char to mask table
  1054. return (_Ctype._Table);
  1055. }
  1056. static const mask *__cdecl classic_table() _THROW0()
  1057. { // return address of char to mask table for "C" locale
  1058. const _Myt& _Fac = _USE(locale::classic(), _Myt);
  1059. return (_Fac.table());
  1060. }
  1061. private:
  1062. _Locinfo::_Ctypevec _Ctype; // information
  1063. };
  1064. // CLASS ctype<wchar_t>
  1065. template<> class _CRTIMP2 ctype<wchar_t>
  1066. : public ctype_base
  1067. { // facet for classifying wchar_t elements, converting cases
  1068. typedef ctype<wchar_t> _Myt;
  1069. public:
  1070. typedef wchar_t _Elem;
  1071. typedef _Elem char_type;
  1072. bool is(mask _Maskval, _Elem _Ch) const
  1073. { // test if element fits any mask classifications
  1074. return (do_is(_Maskval, _Ch));
  1075. }
  1076. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  1077. mask *_Dest) const
  1078. { // get mask sequence for elements in [_First, _Last)
  1079. return (do_is(_First, _Last, _Dest));
  1080. }
  1081. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  1082. const _Elem *_Last) const
  1083. { // find first in [_First, _Last) that fits mask classification
  1084. return (do_scan_is(_Maskval, _First, _Last));
  1085. }
  1086. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  1087. const _Elem *_Last) const
  1088. { // find first in [_First, _Last) not fitting mask classification
  1089. return (do_scan_not(_Maskval, _First, _Last));
  1090. }
  1091. _Elem tolower(_Elem _Ch) const
  1092. { // convert element to lower case
  1093. return (do_tolower(_Ch));
  1094. }
  1095. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  1096. { // convert [_First, _Last) in place to lower case
  1097. return (do_tolower(_First, _Last));
  1098. }
  1099. _Elem toupper(_Elem _Ch) const
  1100. { // convert element to upper case
  1101. return (do_toupper(_Ch));
  1102. }
  1103. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  1104. { // convert [_First, _Last) in place to upper case
  1105. return (do_toupper(_First, _Last));
  1106. }
  1107. _Elem widen(char _Byte) const
  1108. { // widen char
  1109. return (do_widen(_Byte));
  1110. }
  1111. const char *widen(const char *_First, const char *_Last,
  1112. _Elem *_Dest) const
  1113. { // widen chars in [_First, _Last)
  1114. return (do_widen(_First, _Last, _Dest));
  1115. }
  1116. char narrow(_Elem _Ch, char _Dflt = '\0') const
  1117. { // narrow element to char
  1118. return (do_narrow(_Ch, _Dflt));
  1119. }
  1120. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  1121. char _Dflt, char *_Dest) const
  1122. { // narrow elements in [_First, _Last) to chars
  1123. return (do_narrow(_First, _Last, _Dflt, _Dest));
  1124. }
  1125. static locale::id id; // unique facet id
  1126. explicit ctype(size_t _Refs = 0)
  1127. : ctype_base(_Refs)
  1128. { // construct from current locale
  1129. _Init(_Locinfo());
  1130. }
  1131. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  1132. : ctype_base(_Refs)
  1133. { // construct from specified locale
  1134. _Init(_Lobj);
  1135. }
  1136. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  1137. { // return locale category mask and construct standard facet
  1138. if (_Ppf != 0 && *_Ppf == 0)
  1139. *_Ppf = _NEW_CRT ctype<_Elem>;
  1140. return (_X_CTYPE);
  1141. }
  1142. _PROTECTED:
  1143. virtual ~ctype()
  1144. { // destroy the object
  1145. if (_Ctype._Delfl)
  1146. free((void *)_Ctype._Table);
  1147. }
  1148. protected:
  1149. void _Init(const _Locinfo& _Lobj)
  1150. { // initialize from _Lobj
  1151. _Ctype = _Lobj._Getctype();
  1152. _Cvt = _Lobj._Getcvt();
  1153. }
  1154. virtual bool do_is(mask _Maskval, _Elem _Ch) const
  1155. { // test if element fits any mask classifications
  1156. return ((_Getwctype(_Ch, &_Ctype) & _Maskval) != 0);
  1157. }
  1158. virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
  1159. mask *_Dest) const
  1160. { // get mask sequence for elements in [_First, _Last)
  1161. return (_Getwctypes(_First, _Last, _Dest, &_Ctype));
  1162. }
  1163. virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
  1164. const _Elem *_Last) const
  1165. { // find first in [_First, _Last) that fits mask classification
  1166. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  1167. ;
  1168. return (_First);
  1169. }
  1170. virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
  1171. const _Elem *_Last) const
  1172. { // find first in [_First, _Last) not fitting mask classification
  1173. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  1174. ;
  1175. return (_First);
  1176. }
  1177. virtual _Elem do_tolower(_Elem _Ch) const
  1178. { // convert element to lower case
  1179. return (widen((char)_Tolower((unsigned char)narrow(_Ch),
  1180. &_Ctype)));
  1181. }
  1182. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1183. { // convert [_First, _Last) in place to lower case
  1184. for (; _First != _Last; ++_First)
  1185. *_First = widen((char)_Tolower((unsigned char)narrow(*_First),
  1186. &_Ctype));
  1187. return ((const _Elem *)_First);
  1188. }
  1189. virtual _Elem do_toupper(_Elem _Ch) const
  1190. { // convert element to upper case
  1191. return (widen((char)_Toupper((unsigned char)narrow(_Ch),
  1192. &_Ctype)));
  1193. }
  1194. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1195. { // convert [_First, _Last) in place to upper case
  1196. for (; _First != _Last; ++_First)
  1197. *_First = widen((char)_Toupper((unsigned char)narrow(*_First),
  1198. &_Ctype));
  1199. return ((const _Elem *)_First);
  1200. }
  1201. virtual _Elem do_widen(char _Byte) const
  1202. { // widen char
  1203. _Mbstinit(_Mbst);
  1204. wchar_t _Wc;
  1205. return (_Mbrtowc(&_Wc, &_Byte, 1, &_Mbst, &_Cvt) <= 0
  1206. ? (wchar_t)(unsigned char)_Byte : _Wc);
  1207. }
  1208. virtual const char *do_widen(const char *_First, const char *_Last,
  1209. _Elem *_Dest) const
  1210. { // widen chars in [_First, _Last)
  1211. _Mbstinit(_Mbst);
  1212. while (_First != _Last)
  1213. {
  1214. int _Bytes;
  1215. switch (_Bytes = _Mbrtowc(_Dest, _First, _Last - _First,
  1216. &_Mbst, &_Cvt))
  1217. { // test result of locale-specific mbrtowc call
  1218. case -2: // partial conversion
  1219. case -1: // failed conversion
  1220. return (_First);
  1221. case 0: // converted null character
  1222. _Bytes = (int)::strlen(_First) + 1;
  1223. // fall through
  1224. default: // converted _Bytes bytes to a wchar_t
  1225. _First += _Bytes, ++_Dest;
  1226. }
  1227. }
  1228. return (_First);
  1229. }
  1230. virtual char do_narrow(_Elem _Ch, char _Dflt) const
  1231. { // narrow element to char
  1232. char _Buf[MB_LEN_MAX];
  1233. _Mbstinit(_Mbst);
  1234. return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1
  1235. ? _Dflt : _Buf[0]);
  1236. }
  1237. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1238. char _Dflt, char *_Dest) const
  1239. { // narrow elements in [_First, _Last) to chars
  1240. _Mbstinit(_Mbst);
  1241. for (; _First != _Last; ++_First)
  1242. {
  1243. int _Bytes;
  1244. if ((_Bytes = _Wcrtomb(_Dest, *_First, &_Mbst, &_Cvt)) <= 0)
  1245. {
  1246. _Bytes = 1;
  1247. *_Dest = _Dflt;
  1248. }
  1249. _Dest += _Bytes;
  1250. }
  1251. return (_First);
  1252. }
  1253. private:
  1254. _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc.
  1255. _Locinfo::_Cvtvec _Cvt; // conversion information
  1256. };
  1257. // TEMPLATE CLASS ctype_byname
  1258. template<class _Elem>
  1259. class ctype_byname
  1260. : public ctype<_Elem>
  1261. { // ctype for named locale
  1262. public:
  1263. explicit ctype_byname(const char *_Locname, size_t _Refs = 0)
  1264. : ctype<_Elem>(_Locinfo(_Locname), _Refs)
  1265. { // construct from named locale
  1266. }
  1267. _PROTECTED:
  1268. virtual ~ctype_byname()
  1269. { // destroy the object
  1270. }
  1271. };
  1272. #ifdef _DLL_CPPLIB
  1273. template class _CRTIMP2 codecvt<char, char, int>;
  1274. #endif // _DLL_CPPLIB
  1275. _STD_END
  1276. #pragma warning(pop)
  1277. #pragma pack(pop)
  1278. #endif /* _XLOCALE_ */
  1279. /*
  1280. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  1281. * Consult your license regarding permissions and restrictions.
  1282. V3.10:0009 */