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.

2036 lines
54 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. #ifdef _CRTBLD_NATIVE_WCHAR_T
  129. static void __cdecl _Makeushloc(const _Locinfo&,
  130. category, _Locimp *, const locale *); // make unsigned short facets
  131. #endif
  132. static void __cdecl _Makexloc(const _Locinfo&,
  133. category, _Locimp *, const locale *); // make remaining facets
  134. facet **_Facetvec; // pointer to vector of facets
  135. size_t _Facetcount; // size of vector of facets
  136. category _Catmask; // mask describing implemented categories
  137. bool _Xparent; // true if locale is transparent
  138. _STRING_CRT _Name; // locale name, or "*" if not known
  139. static _CRTIMP2 _Locimp *_Clocptr; // pointer to "C" locale object
  140. };
  141. _DEPRECATED locale& _Addfac(facet *, size_t,
  142. size_t); // add a facet, copying on write
  143. template<class _Elem,
  144. class _Traits,
  145. class _Alloc>
  146. bool operator()(const basic_string<_Elem, _Traits, _Alloc>& _Left,
  147. const basic_string<_Elem, _Traits, _Alloc>& _Right) const
  148. { // compare _Left and _Right strings using collate facet in locale
  149. const std::collate<_Elem>& _Fac =
  150. std::use_facet<std::collate<_Elem> >(*this);
  151. return (_Fac.compare(_Left.c_str(), _Left.c_str() + _Left.size(),
  152. _Right.c_str(), _Right.c_str() + _Right.size()) < 0);
  153. }
  154. template<class _Facet>
  155. locale combine(const locale& _Loc) const
  156. { // combine two locales
  157. _Facet *_Facptr;
  158. _TRY_BEGIN
  159. _Facptr = (_Facet *)&std::use_facet<_Facet>(_Loc);
  160. _CATCH_ALL
  161. _THROW(runtime_error, "locale::combine facet missing");
  162. _CATCH_END
  163. _Locimp *_Newimp = _NEW_CRT _Locimp(*_Ptr);
  164. _Newimp->_Addfac(_Facptr, _Facet::id);
  165. if (_Facet::_Getcat() != (size_t)(-1))
  166. { // not a standard facet, result has no name
  167. _Newimp->_Catmask = 0;
  168. _Newimp->_Name = "*";
  169. }
  170. return (locale(_Newimp));
  171. }
  172. template<class _Facet>
  173. locale(const locale& _Loc, _Facet *_Facptr)
  174. : _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr))
  175. { // construct from _Loc, replacing facet with *_Facptr
  176. if (_Facptr != 0)
  177. { // replace facet
  178. _Ptr->_Addfac(_Facptr, _Facet::id);
  179. if (_Facet::_Getcat() != (size_t)(-1))
  180. _Ptr->_Catmask = 0, _Ptr->_Name = "*"; // no C category
  181. }
  182. }
  183. locale() _THROW0(); // construct from current locale
  184. locale(_Uninitialized)
  185. { // defer construction
  186. }
  187. locale(const locale& _Right) _THROW0()
  188. : _Ptr(_Right._Ptr)
  189. { // construct by copying
  190. _Ptr->_Incref();
  191. }
  192. locale(const locale&, const locale&,
  193. category); // construct from locale and category in another locale
  194. explicit locale(const char *,
  195. category = all); // construct from named locale for category
  196. locale(const locale&, const char *,
  197. category); // construct from locale and category in named locale
  198. ~locale() _THROW0()
  199. { // destroy the object
  200. if (_Ptr != 0)
  201. _DELETE_CRT(_Ptr->_Decref());
  202. }
  203. locale& operator=(const locale& _Right) _THROW0()
  204. { // assign a locale
  205. if (_Ptr != _Right._Ptr)
  206. { // different implementation, point at new one
  207. _DELETE_CRT(_Ptr->_Decref());
  208. _Ptr = _Right._Ptr;
  209. _Ptr->_Incref();
  210. }
  211. return (*this);
  212. }
  213. string name() const
  214. { // return locale name
  215. return (_Ptr->_Name);
  216. }
  217. const facet *_Getfacet(size_t) const; // get facet by id
  218. bool operator==(const locale&) const; // test for locale equality
  219. bool operator!=(const locale& _Right) const
  220. { // test for locale inequality
  221. return (!(*this == _Right));
  222. }
  223. static const locale& __cdecl classic(); // return classic "C" locale
  224. static locale __cdecl global(const locale&); // return current locale
  225. static locale __cdecl empty(); // return empty (transparent) locale
  226. private:
  227. locale(_Locimp *_Ptrimp)
  228. : _Ptr(_Ptrimp)
  229. { // construct from _Locimp pointer
  230. }
  231. static _Locimp *__cdecl _Init(); // initialize locale
  232. _Locimp *_Ptr; // pointer to locale implementation object
  233. };
  234. // SUPPORT TEMPLATES
  235. template<class _Facet> inline _DEPRECATED
  236. locale _Addfac(locale _Loc, _Facet *_Fac)
  237. { // add facet to locale -- retained
  238. return (_Loc._Addfac(_Fac, _Facet::id, _Facet::_Getcat()));
  239. }
  240. #define _ADDFAC(loc, pfac) locale(loc, pfac) /* add facet to locale */
  241. #define _USE(loc, fac) \
  242. use_facet<fac >(loc) /* get facet reference from locale */
  243. template<class _Facet> inline
  244. const _Facet& __cdecl use_facet(const locale& _Loc)
  245. { // get facet reference from locale
  246. _Lockit _Lock(_LOCK_LOCALE); // the thread lock, make get atomic
  247. static const locale::facet *_Psave; // static pointer to lazy facet
  248. size_t _Id = _Facet::id;
  249. const locale::facet *_Pf = _Loc._Getfacet(_Id);
  250. if (_Pf != 0)
  251. ; // got facet from locale
  252. else if (_Psave != 0)
  253. _Pf = _Psave; // lazy facet already allocated
  254. else if (_Facet::_Getcat(&_Psave) == (size_t)(-1))
  255. #if _HAS_EXCEPTIONS
  256. throw bad_cast(); // lazy disallowed
  257. #else /* _HAS_EXCEPTIONS */
  258. abort(); // lazy disallowed
  259. #endif /* _HAS_EXCEPTIONS */
  260. else
  261. { // queue up lazy facet for destruction
  262. _Pf = _Psave;
  263. locale::facet *_Pfmod = (_Facet *)_Psave;
  264. _Pfmod->_Incref();
  265. _Pfmod->_Register();
  266. }
  267. return ((const _Facet&)(*_Pf)); // should be dynamic_cast
  268. }
  269. template<class _Facet> inline _DEPRECATED
  270. const _Facet& __cdecl use_facet(const locale& _Loc, const _Facet *,
  271. bool = false)
  272. { // get facet reference from locale -- retained, 2/3 arg versions
  273. return use_facet<_Facet>(_Loc);
  274. }
  275. // TEMPLATE FUNCTION _Narrow
  276. #define _NARROW(T, V) _Narrow(static_cast<T>(V)) /* convert T to char */
  277. template<class _Elem> inline
  278. char _Narrow(_Elem _Ch)
  279. { // convert _Elem to char
  280. return ((char)_Ch); // needs _Elem::operator char()
  281. }
  282. template<> inline
  283. char _Narrow(wchar_t _Ch)
  284. { // convert wchar_t to char (using current locale, no state)
  285. return ((char)wctob(_Ch));
  286. }
  287. #ifdef _CRTBLD_NATIVE_WCHAR_T
  288. template<> inline
  289. char _Narrow(unsigned short _Ch)
  290. { // convert unsigned short to char (using current locale, no state)
  291. return ((char)wctob(_Ch));
  292. }
  293. #endif
  294. // TEMPLATE FUNCTION _Widen
  295. #define _WIDEN(T, V) _Widen(V, (T *)0) /* convert char to T */
  296. template<class _Elem> inline
  297. _Elem _Widen(char _Ch, _Elem *)
  298. { // convert char to _Elem
  299. return ((_Elem)(unsigned char)_Ch); // needs _Elem(char)
  300. }
  301. template<> inline
  302. wchar_t _Widen(char _Ch, wchar_t *)
  303. { // convert char to wchar_t (using current locale, no state)
  304. return (btowc(_Ch));
  305. }
  306. #ifdef _CRTBLD_NATIVE_WCHAR_T
  307. template<> inline
  308. unsigned short _Widen(char _Ch, unsigned short *)
  309. { // convert char to unsigned short (using current locale, no state)
  310. return (btowc(_Ch));
  311. }
  312. #endif
  313. // TEMPLATE FUNCTION _Getloctxt
  314. template<class _Elem,
  315. class _InIt> inline
  316. int __cdecl _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields,
  317. const _Elem *_Ptr)
  318. { // find field at _Ptr that matches longest in [_First, _Last)
  319. for (size_t _Off = 0; _Ptr[_Off] != (_Elem)0; ++_Off)
  320. if (_Ptr[_Off] == _Ptr[0])
  321. ++_Numfields; // add fields with leading mark to initial count
  322. string _Str(_Numfields, '\0'); // one column counter for each field
  323. int _Ans = -2; // no candidates so far
  324. for (size_t _Column = 1; ; ++_Column, ++_First, _Ans = -1)
  325. { // test each element against all viable fields
  326. bool _Prefix = false; // seen at least one valid prefix
  327. size_t _Off = 0; // offset into fields
  328. size_t _Field = 0; // current field number
  329. for (; _Field < _Numfields; ++_Field)
  330. { // test element at _Column in field _Field
  331. for (; _Ptr[_Off] != (_Elem)0 && _Ptr[_Off] != _Ptr[0]; ++_Off)
  332. ; // find beginning of field
  333. if (_Str[_Field] != '\0')
  334. _Off += _Str[_Field]; // skip tested columns in field
  335. else if (_Ptr[_Off += _Column] == _Ptr[0]
  336. || _Ptr[_Off] == (_Elem)0)
  337. { // matched all of field, save as possible answer
  338. _Str[_Field] = (char)(_Column < 127
  339. ? _Column : 127); // save skip count if small enough
  340. _Ans = (int)_Field; // save answer
  341. }
  342. else if (_First == _Last || _Ptr[_Off] != *_First)
  343. _Str[_Field] = (char)(_Column < 127
  344. ? _Column : 127); // no match, just save skip count
  345. else
  346. _Prefix = true; // still a valid prefix
  347. }
  348. if (!_Prefix || _First == _Last)
  349. break; // no pending prefixes or no input, give up
  350. }
  351. return (_Ans); // return field number or negative value on failure
  352. }
  353. // TEMPLATE FUNCTION _Maklocstr
  354. #define _MAKLOCSTR(_Elem, _Str, _Cvt) \
  355. _Maklocstr(_Str, (_Elem *)0, _Cvt) // convert C string to _Elem sequence
  356. template<class _Elem> inline
  357. _Elem *__cdecl _Maklocstr(const char *_Ptr, _Elem *,
  358. const _Locinfo::_Cvtvec &)
  359. { // convert C string to _Elem sequence
  360. size_t _Count = ::strlen(_Ptr) + 1;
  361. _Elem *_Ptrdest = _NEW_CRT _Elem[_Count];
  362. for (_Elem *_Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr)
  363. *_Ptrnext = _WIDEN(_Elem, *_Ptr);
  364. return (_Ptrdest);
  365. }
  366. template<> inline
  367. wchar_t *__cdecl _Maklocstr(const char *_Ptr, wchar_t *,
  368. const _Locinfo::_Cvtvec &_Cvt)
  369. { // convert C string to wchar_t sequence
  370. size_t _Count, _Count1;
  371. size_t _Wchars;
  372. const char *_Ptr1;
  373. wchar_t *_Ptrdest, *_Ptrnext;
  374. _Mbstinit(_Mbst1);
  375. _Count = _Count1 = ::strlen(_Ptr) + 1;
  376. for (_Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; ++_Wchars)
  377. { // determine length of wide string
  378. int _Bytes;
  379. if ((_Bytes = _Mbrtowc(0, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0)
  380. break;
  381. _Ptr1 += _Bytes;
  382. _Count -= _Bytes;
  383. }
  384. ++_Wchars;
  385. _Ptrdest = _NEW_CRT wchar_t[_Wchars];
  386. _Mbstinit(_Mbst2);
  387. for (_Ptrnext = _Ptrdest; 0 < _Wchars; --_Wchars, ++_Ptrnext)
  388. { // widen string
  389. int _Bytes;
  390. if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst1, &_Cvt)) <= 0)
  391. break;
  392. _Ptr += _Bytes;
  393. _Count1 -= _Bytes;
  394. }
  395. *_Ptrnext = 0;
  396. return (_Ptrdest);
  397. }
  398. #ifdef _CRTBLD_NATIVE_WCHAR_T
  399. template<> inline
  400. unsigned short *__cdecl _Maklocstr(const char *_Ptr, unsigned short *,
  401. const _Locinfo::_Cvtvec &_Cvt)
  402. { // convert C string to unsigned short sequence
  403. size_t _Count, _Count1;
  404. size_t _Wchars;
  405. const char *_Ptr1;
  406. wchar_t *_Ptrdest, *_Ptrnext;
  407. _Mbstinit(_Mbst1);
  408. _Count = _Count1 = ::strlen(_Ptr) + 1;
  409. for (_Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; ++_Wchars)
  410. { // determine length of wide string
  411. int _Bytes;
  412. if ((_Bytes = _Mbrtowc(0, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0)
  413. break;
  414. _Ptr1 += _Bytes;
  415. _Count -= _Bytes;
  416. }
  417. ++_Wchars;
  418. _Ptrdest = _NEW_CRT wchar_t[_Wchars];
  419. _Mbstinit(_Mbst2);
  420. for (_Ptrnext = _Ptrdest; 0 < _Wchars; --_Wchars, ++_Ptrnext)
  421. { // widen string
  422. int _Bytes;
  423. if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst1, &_Cvt)) <= 0)
  424. break;
  425. _Ptr += _Bytes;
  426. _Count1 -= _Bytes;
  427. }
  428. *_Ptrnext = 0;
  429. return ((unsigned short *)_Ptrdest);
  430. }
  431. #endif
  432. // STRUCT codecvt_base
  433. class _CRTIMP2 codecvt_base
  434. : public locale::facet
  435. { // base class for codecvt
  436. public:
  437. enum
  438. { // constants for different parse states
  439. ok, partial, error, noconv};
  440. typedef int result;
  441. codecvt_base(size_t _Refs = 0)
  442. : locale::facet(_Refs)
  443. { // default constructor
  444. }
  445. bool always_noconv() const _THROW0()
  446. { // return true if conversions never change input (from codecvt)
  447. return (do_always_noconv());
  448. }
  449. int max_length() const _THROW0()
  450. { // return maximum length required for a conversion (from codecvt)
  451. return (do_max_length());
  452. }
  453. int encoding() const _THROW0()
  454. { // return length of code sequence (from codecvt)
  455. return (do_encoding());
  456. }
  457. ~codecvt_base()
  458. { // destroy the object
  459. }
  460. protected:
  461. virtual bool do_always_noconv() const _THROW0()
  462. { // return true if conversions never change input (from codecvt)
  463. return (true);
  464. }
  465. virtual int do_max_length() const _THROW0()
  466. { // return maximum length required for a conversion (from codecvt)
  467. return (1);
  468. }
  469. virtual int do_encoding() const _THROW0()
  470. { // return length of code sequence (from codecvt)
  471. return (1); // -1 ==> state dependent, 0 ==> varying length
  472. }
  473. };
  474. // TEMPLATE CLASS codecvt
  475. template<class _Elem,
  476. class _Byte,
  477. class _Statype>
  478. class codecvt
  479. : public codecvt_base
  480. { // facet for converting between _Elem and char (_Byte) sequences
  481. public:
  482. typedef _Elem intern_type;
  483. typedef _Byte extern_type;
  484. typedef _Statype state_type;
  485. result in(_Statype& _State,
  486. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  487. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  488. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  489. return (do_in(_State,
  490. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  491. }
  492. result out(_Statype& _State,
  493. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  494. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  495. { // convert [_First1, _Last1) to bytes [_First2, _Last2)
  496. return (do_out(_State,
  497. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  498. }
  499. result unshift(_Statype& _State,
  500. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  501. { // generate bytes to return to default shift state
  502. return (do_unshift(_State, _First2, _Last2, _Mid2));
  503. }
  504. int length(const _Statype& _State, const _Byte *_First1,
  505. const _Byte *_Last1, size_t _Count) const _THROW0()
  506. { // return min(_Count, converted length of bytes [_First1, _Last1))
  507. return (do_length(_State, _First1, _Last1, _Count));
  508. }
  509. static locale::id id; // unique facet id
  510. explicit codecvt(size_t _Refs = 0)
  511. : codecvt_base(_Refs)
  512. { // construct from current locale
  513. _Init(_Locinfo());
  514. }
  515. codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
  516. : codecvt_base(_Refs)
  517. { // construct from specified locale
  518. _Init(_Lobj);
  519. }
  520. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  521. { // return locale category mask and construct standard facet
  522. if (_Ppf != 0 && *_Ppf == 0)
  523. *_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
  524. return (_X_CTYPE);
  525. }
  526. _PROTECTED:
  527. virtual ~codecvt()
  528. { // destroy the object
  529. }
  530. protected:
  531. void _Init(const _Locinfo& _Lobj)
  532. { // initialize from _Lobj
  533. _Cvt = _Lobj._Getcvt();
  534. }
  535. virtual result do_in(_Statype&,
  536. const _Byte *_First1, const _Byte *, const _Byte *& _Mid1,
  537. _Elem *_First2, _Elem *, _Elem *& _Mid2) const
  538. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  539. _Mid1 = _First1, _Mid2 = _First2;
  540. return (noconv); // convert nothing
  541. }
  542. virtual result do_out(_Statype&,
  543. const _Elem *_First1, const _Elem *, const _Elem *& _Mid1,
  544. _Byte *_First2, _Byte *, _Byte *& _Mid2) const
  545. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  546. _Mid1 = _First1, _Mid2 = _First2;
  547. return (noconv); // convert nothing
  548. }
  549. virtual result do_unshift(_Statype&,
  550. _Byte *, _Byte *, _Byte *&) const
  551. { // generate bytes to return to default shift state
  552. return (noconv); // convert nothing
  553. }
  554. virtual int do_length(const _Statype&, const _Byte *_First1,
  555. const _Byte *_Last1, size_t _Count) const _THROW0()
  556. { // return min(_Count, converted length of bytes [_First1, _Last1))
  557. return (int)(_Count < (size_t)(_Last1 - _First1)
  558. ? _Count : _Last1 - _First1); // assume one-to-one conversion
  559. }
  560. private:
  561. _Locinfo::_Cvtvec _Cvt; // used by codecvt<wchar_t, char, mbstate_t>
  562. };
  563. // STATIC codecvt::id OBJECT
  564. template<class _Elem,
  565. class _Byte,
  566. class _Statype>
  567. locale::id codecvt<_Elem, _Byte, _Statype>::id;
  568. // CLASS codecvt<wchar_t, char, mbstate_t>
  569. template<> class _CRTIMP2 codecvt<wchar_t, char, mbstate_t>
  570. : public codecvt_base
  571. { // facet for converting between wchar_t and char (_Byte) sequences
  572. public:
  573. typedef wchar_t _Elem;
  574. typedef char _Byte;
  575. typedef mbstate_t _Statype;
  576. typedef _Elem intern_type;
  577. typedef _Byte extern_type;
  578. typedef _Statype state_type;
  579. result in(_Statype& _State,
  580. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  581. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  582. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  583. return (do_in(_State,
  584. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  585. }
  586. result out(_Statype& _State,
  587. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  588. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  589. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  590. return (do_out(_State,
  591. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  592. }
  593. result unshift(_Statype& _State,
  594. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  595. { // generate bytes to return to default shift state
  596. return (do_unshift(_State,
  597. _First2, _Last2, _Mid2));
  598. }
  599. int length(const _Statype& _State, const _Byte *_First1,
  600. const _Byte *_Last1, size_t _N2) const _THROW0()
  601. { // return min(_Count, converted length of bytes [_First1, _Last1))
  602. return (do_length(_State, _First1, _Last1, _N2));
  603. }
  604. static locale::id id; // unique facet id
  605. explicit codecvt(size_t _Refs = 0)
  606. : codecvt_base(_Refs)
  607. { // construct from current locale
  608. _Init(_Locinfo());
  609. }
  610. codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
  611. : codecvt_base(_Refs)
  612. { // construct from specified locale
  613. _Init(_Lobj);
  614. }
  615. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  616. { // return locale category mask and construct standard facet
  617. if (_Ppf != 0 && *_Ppf == 0)
  618. *_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
  619. return (_X_CTYPE);
  620. }
  621. _PROTECTED:
  622. virtual ~codecvt()
  623. { // destroy the object
  624. }
  625. protected:
  626. void _Init(const _Locinfo& _Lobj)
  627. { // initialize from _Lobj
  628. _Cvt = _Lobj._Getcvt();
  629. }
  630. virtual result do_in(_Statype& _State,
  631. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  632. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  633. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  634. _Mid1 = _First1, _Mid2 = _First2;
  635. result _Ans = _Mid1 == _Last1 ? ok : partial;
  636. int _Bytes;
  637. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  638. switch (_Bytes = _Mbrtowc(_Mid2, _Mid1, _Last1 - _Mid1,
  639. &_State, &_Cvt))
  640. { // test result of locale-specific mbrtowc call
  641. case -2: // partial conversion
  642. _Mid1 = _Last1;
  643. return (_Ans);
  644. case -1: // failed conversion
  645. return (error);
  646. case 0: // converted null character
  647. _Bytes = (int)::strlen(_Mid1) + 1;
  648. // fall through
  649. default: // converted _Bytes bytes to a wchar_t
  650. _Mid1 += _Bytes, ++_Mid2, _Ans = ok;
  651. }
  652. return (_Ans);
  653. }
  654. virtual result do_out(_Statype& _State,
  655. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  656. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  657. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  658. _Mid1 = _First1, _Mid2 = _First2;
  659. result _Ans = _Mid1 == _Last1 ? ok : partial;
  660. int _Bytes;
  661. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  662. if (___mb_cur_max_func() <= _Last2 - _Mid2)
  663. if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1,
  664. &_State, &_Cvt)) <= 0)
  665. return (error); // locale-specific wcrtomb failed
  666. else
  667. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  668. else
  669. { // destination too small, convert into buffer
  670. _Byte _Buf[MB_LEN_MAX];
  671. _Statype _Stsave = _State;
  672. if ((_Bytes = _Wcrtomb(_Buf, *_Mid1,
  673. &_State, &_Cvt)) <= 0)
  674. return (error); // locale-specific wcrtomb failed
  675. else if (_Last2 - _Mid2 < _Bytes)
  676. { // converted too many, roll back and return previous
  677. _State = _Stsave;
  678. return (_Ans);
  679. }
  680. else
  681. { // copy converted bytes from buffer
  682. memcpy(_Mid2, _Buf, _Bytes);
  683. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  684. }
  685. }
  686. return (_Ans);
  687. }
  688. virtual result do_unshift(_Statype& _State,
  689. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  690. { // generate bytes to return to default shift state
  691. _Mid2 = _First2;
  692. result _Ans = ok;
  693. int _Bytes;
  694. _Byte _Buf[MB_LEN_MAX];
  695. _Statype _Stsave = _State;
  696. if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0)
  697. _Ans = error; // locale-specific wcrtomb failed
  698. else if (_Last2 - _Mid2 < --_Bytes)
  699. { // converted too many, roll back and return
  700. _State = _Stsave;
  701. _Ans = partial;
  702. }
  703. else if (0 < _Bytes)
  704. { // copy converted bytes from buffer
  705. memcpy(_Mid2, _Buf, _Bytes);
  706. _Mid2 += _Bytes;
  707. }
  708. return (_Ans);
  709. }
  710. virtual int do_length(const _Statype& _State, const _Byte *_First1,
  711. const _Byte *_Last1, size_t _Count) const _THROW0()
  712. { // return min(_Count, converted length of bytes [_First1, _Last1))
  713. int _Wchars;
  714. const _Byte *_Mid1;
  715. _Statype _Mystate = _State;
  716. for (_Wchars = 0, _Mid1 = _First1;
  717. (size_t)_Wchars < _Count && _Mid1 != _Last1; )
  718. { // convert another wchar_t
  719. int _Bytes;
  720. _Elem _Ch;
  721. switch (_Bytes = _Mbrtowc(&_Ch, _Mid1, _Last1 - _Mid1,
  722. &_Mystate, &_Cvt))
  723. { // test result of locale-specific mbrtowc call
  724. case -2: // partial conversion
  725. return (_Wchars);
  726. case -1: // failed conversion
  727. return (_Wchars);
  728. case 0: // converted null character
  729. _Bytes = (int)::strlen(_Mid1) + 1;
  730. // fall through
  731. default: // converted _Bytes bytes to a wchar_t
  732. _Mid1 += _Bytes, ++_Wchars;
  733. }
  734. }
  735. return (_Wchars);
  736. }
  737. virtual bool do_always_noconv() const _THROW0()
  738. { // return true if conversions never change input
  739. return (false);
  740. }
  741. virtual int do_max_length() const _THROW0()
  742. { // return maximum length required for a conversion (from codecvt)
  743. return (MB_LEN_MAX);
  744. }
  745. virtual int do_encoding() const _THROW0()
  746. { // return length of code sequence (from codecvt)
  747. return (0);
  748. }
  749. private:
  750. _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb
  751. };
  752. #ifdef _CRTBLD_NATIVE_WCHAR_T
  753. // CLASS codecvt<unsigned short, char, mbstate_t>
  754. template<> class _CRTIMP2 codecvt<unsigned short, char, mbstate_t>
  755. : public codecvt_base
  756. { // facet for converting between unsigned short and char (_Byte) sequences
  757. public:
  758. typedef unsigned short _Elem;
  759. typedef char _Byte;
  760. typedef mbstate_t _Statype;
  761. typedef _Elem intern_type;
  762. typedef _Byte extern_type;
  763. typedef _Statype state_type;
  764. result in(_Statype& _State,
  765. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  766. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  767. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  768. return (do_in(_State,
  769. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  770. }
  771. result out(_Statype& _State,
  772. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  773. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  774. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  775. return (do_out(_State,
  776. _First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
  777. }
  778. result unshift(_Statype& _State,
  779. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  780. { // generate bytes to return to default shift state
  781. return (do_unshift(_State,
  782. _First2, _Last2, _Mid2));
  783. }
  784. int length(const _Statype& _State, const _Byte *_First1,
  785. const _Byte *_Last1, size_t _N2) const _THROW0()
  786. { // return min(_Count, converted length of bytes [_First1, _Last1))
  787. return (do_length(_State, _First1, _Last1, _N2));
  788. }
  789. static locale::id id; // unique facet id
  790. explicit codecvt(size_t _Refs = 0)
  791. : codecvt_base(_Refs)
  792. { // construct from current locale
  793. _Init(_Locinfo());
  794. }
  795. codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
  796. : codecvt_base(_Refs)
  797. { // construct from specified locale
  798. _Init(_Lobj);
  799. }
  800. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  801. { // return locale category mask and construct standard facet
  802. if (_Ppf != 0 && *_Ppf == 0)
  803. *_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
  804. return (_X_CTYPE);
  805. }
  806. _PROTECTED:
  807. virtual ~codecvt()
  808. { // destroy the object
  809. }
  810. protected:
  811. void _Init(const _Locinfo& _Lobj)
  812. { // initialize from _Lobj
  813. _Cvt = _Lobj._Getcvt();
  814. }
  815. virtual result do_in(_Statype& _State,
  816. const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
  817. _Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
  818. { // convert bytes [_First1, _Last1) to [_First2, _Last)
  819. _Mid1 = _First1, _Mid2 = _First2;
  820. result _Ans = _Mid1 == _Last1 ? ok : partial;
  821. int _Bytes;
  822. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  823. switch (_Bytes = _Mbrtowc((wchar_t *)_Mid2, _Mid1, _Last1 - _Mid1,
  824. &_State, &_Cvt))
  825. { // test result of locale-specific mbrtowc call
  826. case -2: // partial conversion
  827. _Mid1 = _Last1;
  828. return (_Ans);
  829. case -1: // failed conversion
  830. return (error);
  831. case 0: // converted null character
  832. _Bytes = (int)::strlen(_Mid1) + 1;
  833. // fall through
  834. default: // converted _Bytes bytes to an unsigned short
  835. _Mid1 += _Bytes, ++_Mid2, _Ans = ok;
  836. }
  837. return (_Ans);
  838. }
  839. virtual result do_out(_Statype& _State,
  840. const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
  841. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  842. { // convert [_First1, _Last1) to bytes [_First2, _Last)
  843. _Mid1 = _First1, _Mid2 = _First2;
  844. result _Ans = _Mid1 == _Last1 ? ok : partial;
  845. int _Bytes;
  846. while (_Mid1 != _Last1 && _Mid2 != _Last2)
  847. if (___mb_cur_max_func() <= _Last2 - _Mid2)
  848. if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1,
  849. &_State, &_Cvt)) <= 0)
  850. return (error); // locale-specific wcrtomb failed
  851. else
  852. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  853. else
  854. { // destination too small, convert into buffer
  855. _Byte _Buf[MB_LEN_MAX];
  856. _Statype _Stsave = _State;
  857. if ((_Bytes = _Wcrtomb(_Buf, *_Mid1,
  858. &_State, &_Cvt)) <= 0)
  859. return (error); // locale-specific wcrtomb failed
  860. else if (_Last2 - _Mid2 < _Bytes)
  861. { // converted too many, roll back and return previous
  862. _State = _Stsave;
  863. return (_Ans);
  864. }
  865. else
  866. { // copy converted bytes from buffer
  867. memcpy(_Mid2, _Buf, _Bytes);
  868. ++_Mid1, _Mid2 += _Bytes, _Ans = ok;
  869. }
  870. }
  871. return (_Ans);
  872. }
  873. virtual result do_unshift(_Statype& _State,
  874. _Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
  875. { // generate bytes to return to default shift state
  876. _Mid2 = _First2;
  877. result _Ans = ok;
  878. int _Bytes;
  879. _Byte _Buf[MB_LEN_MAX];
  880. _Statype _Stsave = _State;
  881. if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0)
  882. _Ans = error; // locale-specific wcrtomb failed
  883. else if (_Last2 - _Mid2 < --_Bytes)
  884. { // converted too many, roll back and return
  885. _State = _Stsave;
  886. _Ans = partial;
  887. }
  888. else if (0 < _Bytes)
  889. { // copy converted bytes from buffer
  890. memcpy(_Mid2, _Buf, _Bytes);
  891. _Mid2 += _Bytes;
  892. }
  893. return (_Ans);
  894. }
  895. virtual int do_length(const _Statype& _State, const _Byte *_First1,
  896. const _Byte *_Last1, size_t _Count) const _THROW0()
  897. { // return min(_Count, converted length of bytes [_First1, _Last1))
  898. int _Wchars;
  899. const _Byte *_Mid1;
  900. _Statype _Mystate = _State;
  901. for (_Wchars = 0, _Mid1 = _First1;
  902. (size_t)_Wchars < _Count && _Mid1 != _Last1; )
  903. { // convert another unsigned short
  904. int _Bytes;
  905. _Elem _Ch;
  906. switch (_Bytes = _Mbrtowc((wchar_t *)&_Ch, _Mid1, _Last1 - _Mid1,
  907. &_Mystate, &_Cvt))
  908. { // test result of locale-specific mbrtowc call
  909. case -2: // partial conversion
  910. return (_Wchars);
  911. case -1: // failed conversion
  912. return (_Wchars);
  913. case 0: // converted null character
  914. _Bytes = (int)::strlen(_Mid1) + 1;
  915. // fall through
  916. default: // converted _Bytes bytes to an unsigned short
  917. _Mid1 += _Bytes, ++_Wchars;
  918. }
  919. }
  920. return (_Wchars);
  921. }
  922. virtual bool do_always_noconv() const _THROW0()
  923. { // return true if conversions never change input
  924. return (false);
  925. }
  926. virtual int do_max_length() const _THROW0()
  927. { // return maximum length required for a conversion (from codecvt)
  928. return (MB_LEN_MAX);
  929. }
  930. virtual int do_encoding() const _THROW0()
  931. { // return length of code sequence (from codecvt)
  932. return (0);
  933. }
  934. private:
  935. _Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb
  936. };
  937. #endif
  938. // TEMPLATE CLASS codecvt_byname
  939. template<class _Elem,
  940. class _Byte,
  941. class _Statype>
  942. class codecvt_byname
  943. : public codecvt<_Elem, _Byte, _Statype>
  944. { // codecvt for named locale
  945. public:
  946. explicit codecvt_byname(const char *_Locname, size_t _Refs = 0)
  947. : codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Locname), _Refs)
  948. { // construct for named locale
  949. }
  950. _PROTECTED:
  951. virtual ~codecvt_byname()
  952. { // destroy the object
  953. }
  954. };
  955. // STRUCT ctype_base
  956. struct _CRTIMP2 ctype_base
  957. : public locale::facet
  958. { // base for ctype
  959. enum
  960. { // constants for character classifications
  961. alnum = _DI|_LO|_UP|_XA, alpha = _LO|_UP|_XA,
  962. cntrl = _BB, digit = _DI, graph = _DI|_LO|_PU|_UP|_XA,
  963. lower = _LO, print = _DI|_LO|_PU|_SP|_UP|_XA|_XD,
  964. punct = _PU, space = _CN|_SP|_XS, upper = _UP,
  965. xdigit = _XD};
  966. typedef short mask; // to match <ctype.h>
  967. ctype_base(size_t _Refs = 0)
  968. : locale::facet(_Refs)
  969. { // default constructor
  970. }
  971. ~ctype_base()
  972. { // destroy the object
  973. }
  974. };
  975. // TEMPLATE CLASS ctype
  976. template<class _Elem>
  977. class ctype
  978. : public ctype_base
  979. { // facet for classifying elements, converting cases
  980. public:
  981. typedef _Elem char_type;
  982. bool is(mask _Maskval, _Elem _Ch) const
  983. { // test if element fits any mask classifications
  984. return (do_is(_Maskval, _Ch));
  985. }
  986. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  987. mask *_Dest) const
  988. { // get mask sequence for elements in [_First, _Last)
  989. return (do_is(_First, _Last, _Dest));
  990. }
  991. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  992. const _Elem *_Last) const
  993. { // find first in [_First, _Last) that fits mask classification
  994. return (do_scan_is(_Maskval, _First, _Last));
  995. }
  996. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  997. const _Elem *_Last) const
  998. { // find first in [_First, _Last) not fitting mask classification
  999. return (do_scan_not(_Maskval, _First, _Last));
  1000. }
  1001. _Elem tolower(_Elem _Ch) const
  1002. { // convert element to lower case
  1003. return (do_tolower(_Ch));
  1004. }
  1005. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  1006. { // convert [_First, _Last) in place to lower case
  1007. return (do_tolower(_First, _Last));
  1008. }
  1009. _Elem toupper(_Elem _Ch) const
  1010. { // convert element to upper case
  1011. return (do_toupper(_Ch));
  1012. }
  1013. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  1014. { // convert [_First, _Last) in place to upper case
  1015. return (do_toupper(_First, _Last));
  1016. }
  1017. _Elem widen(char _Byte) const
  1018. { // widen char
  1019. return (do_widen(_Byte));
  1020. }
  1021. const char *widen(const char *_First, const char *_Last,
  1022. _Elem *_Dest) const
  1023. { // widen chars in [_First, _Last)
  1024. return (do_widen(_First, _Last, _Dest));
  1025. }
  1026. char narrow(_Elem _Ch, char _Dflt = '\0') const
  1027. { // narrow element to char
  1028. return (do_narrow(_Ch, _Dflt));
  1029. }
  1030. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  1031. char _Dflt, char *_Dest) const
  1032. { // narrow elements in [_First, _Last) to chars
  1033. return (do_narrow(_First, _Last, _Dflt, _Dest));
  1034. }
  1035. static locale::id id; // unique facet id
  1036. explicit ctype(size_t _Refs = 0)
  1037. : ctype_base(_Refs)
  1038. { // construct from current locale
  1039. _Init(_Locinfo());
  1040. }
  1041. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  1042. : ctype_base(_Refs)
  1043. { // construct from specified locale
  1044. _Init(_Lobj);
  1045. }
  1046. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  1047. { // return locale category mask and construct standard facet
  1048. if (_Ppf != 0 && *_Ppf == 0)
  1049. *_Ppf = _NEW_CRT ctype<_Elem>;
  1050. return (_X_CTYPE);
  1051. }
  1052. _PROTECTED:
  1053. virtual ~ctype()
  1054. { // destroy the object
  1055. if (_Ctype._Delfl)
  1056. free((void *)_Ctype._Table);
  1057. }
  1058. protected:
  1059. void _Init(const _Locinfo& _Lobj)
  1060. { // initialize from _Lobj
  1061. _Ctype = _Lobj._Getctype();
  1062. }
  1063. virtual bool do_is(mask _Maskval, _Elem _Ch) const
  1064. { // test if element fits any mask classifications
  1065. return ((_Ctype._Table[(unsigned char)narrow(_Ch)]
  1066. & _Maskval) != 0);
  1067. }
  1068. virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
  1069. mask *_Dest) const
  1070. { // get mask sequence for elements in [_First, _Last)
  1071. for (; _First != _Last; ++_First, ++_Dest)
  1072. *_Dest = _Ctype._Table[(unsigned char)narrow(*_First)];
  1073. return (_First);
  1074. }
  1075. virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
  1076. const _Elem *_Last) const
  1077. { // find first in [_First, _Last) that fits mask classification
  1078. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  1079. ;
  1080. return (_First);
  1081. }
  1082. virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
  1083. const _Elem *_Last) const
  1084. { // find first in [_First, _Last) not fitting mask classification
  1085. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  1086. ;
  1087. return (_First);
  1088. }
  1089. virtual _Elem do_tolower(_Elem _Ch) const
  1090. { // convert element to lower case
  1091. return (widen((char)_Tolower((unsigned char)narrow(_Ch),
  1092. &_Ctype)));
  1093. }
  1094. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1095. { // convert [_First, _Last) in place to lower case
  1096. for (; _First != _Last; ++_First)
  1097. *_First = widen((char)_Tolower((unsigned char)narrow(*_First),
  1098. &_Ctype));
  1099. return ((const _Elem *)_First);
  1100. }
  1101. virtual _Elem do_toupper(_Elem _Ch) const
  1102. { // convert element to upper case
  1103. return (widen((char)_Toupper((unsigned char)narrow(_Ch),
  1104. &_Ctype)));
  1105. }
  1106. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1107. { // convert [_First, _Last) in place to upper case
  1108. for (; _First != _Last; ++_First)
  1109. *_First = widen((char)_Toupper((unsigned char)narrow(*_First),
  1110. &_Ctype));
  1111. return ((const _Elem *)_First);
  1112. }
  1113. virtual _Elem do_widen(char _Byte) const
  1114. { // widen char
  1115. return (_WIDEN(_Elem, _Byte));
  1116. }
  1117. virtual const char *do_widen(const char *_First, const char *_Last,
  1118. _Elem *_Dest) const
  1119. { // widen chars in [_First, _Last)
  1120. for (; _First != _Last; ++_First, ++_Dest)
  1121. *_Dest = _WIDEN(_Elem, *_First);
  1122. return (_First);
  1123. }
  1124. virtual char do_narrow(_Elem _Ch, char) const
  1125. { // narrow element to char
  1126. return (_NARROW(_Elem, _Ch));
  1127. }
  1128. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1129. char, char *_Dest) const
  1130. { // narrow elements in [_First, _Last) to chars
  1131. for (; _First != _Last; ++_First, ++_Dest)
  1132. *_Dest = _NARROW(_Elem, *_First);
  1133. return (_First);
  1134. }
  1135. private:
  1136. _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc.
  1137. };
  1138. // STATIC ctype::id OBJECT
  1139. template<class _Elem>
  1140. locale::id ctype<_Elem>::id;
  1141. // CLASS ctype<char>
  1142. template<> class _CRTIMP2 ctype<char>
  1143. : public ctype_base
  1144. { // facet for classifying char elements, converting cases
  1145. typedef ctype<char> _Myt;
  1146. public:
  1147. typedef char _Elem;
  1148. typedef _Elem char_type;
  1149. bool is(mask _Maskval, _Elem _Ch) const
  1150. { // test if element fits any mask classifications
  1151. return ((_Ctype._Table[(unsigned char)_Ch] & _Maskval) != 0);
  1152. }
  1153. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  1154. mask *_Dest) const
  1155. { // get mask sequence for elements in [_First, _Last)
  1156. for (; _First != _Last; ++_First, ++_Dest)
  1157. *_Dest = _Ctype._Table[(unsigned char)*_First];
  1158. return (_First);
  1159. }
  1160. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  1161. const _Elem *_Last) const
  1162. { // find first in [_First, _Last) that fits mask classification
  1163. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  1164. ;
  1165. return (_First);
  1166. }
  1167. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  1168. const _Elem *_Last) const
  1169. { // find first in [_First, _Last) not fitting mask classification
  1170. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  1171. ;
  1172. return (_First);
  1173. }
  1174. _Elem tolower(_Elem _Ch) const
  1175. { // convert element to lower case
  1176. return (do_tolower(_Ch));
  1177. }
  1178. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  1179. { // convert [_First, _Last) in place to lower case
  1180. return (do_tolower(_First, _Last));
  1181. }
  1182. _Elem toupper(_Elem _Ch) const
  1183. { // convert element to upper case
  1184. return (do_toupper(_Ch));
  1185. }
  1186. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  1187. { // convert [_First, _Last) in place to upper case
  1188. return (do_toupper(_First, _Last));
  1189. }
  1190. _Elem widen(char _Byte) const
  1191. { // widen char
  1192. return (do_widen(_Byte));
  1193. }
  1194. const _Elem *widen(const char *_First, const char *_Last,
  1195. _Elem *_Dest) const
  1196. { // widen chars in [_First, _Last)
  1197. return (do_widen(_First, _Last, _Dest));
  1198. }
  1199. _Elem narrow(_Elem _Ch, char _Dflt = '\0') const
  1200. { // narrow element to char
  1201. return (do_narrow(_Ch, _Dflt));
  1202. }
  1203. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  1204. char _Dflt, char *_Dest) const
  1205. { // narrow elements in [_First, _Last) to chars
  1206. return (do_narrow(_First, _Last, _Dflt, _Dest));
  1207. }
  1208. static locale::id id; // unique facet id
  1209. explicit ctype(const mask *_Table = 0, bool _Deletetable = false,
  1210. size_t _Refs = 0)
  1211. : ctype_base(_Refs)
  1212. { // construct with specified table and delete flag for table
  1213. _Init(_Locinfo());
  1214. if (_Table != 0)
  1215. { // replace existing char to mask table
  1216. _Tidy();
  1217. _Ctype._Table = _Table;
  1218. _Ctype._Delfl = _Deletetable ? -1 : 0;
  1219. }
  1220. }
  1221. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  1222. : ctype_base(_Refs)
  1223. { // construct from current locale
  1224. _Init(_Lobj);
  1225. }
  1226. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  1227. { // construct from specified locale
  1228. if (_Ppf != 0 && *_Ppf == 0)
  1229. *_Ppf = _NEW_CRT ctype<_Elem>;
  1230. return (_X_CTYPE);
  1231. }
  1232. static const size_t table_size; // size of _Ctype._Table (char to mask)
  1233. _PROTECTED:
  1234. virtual ~ctype()
  1235. { // destroy the object
  1236. _Tidy();
  1237. }
  1238. protected:
  1239. void _Init(const _Locinfo& _Lobj)
  1240. { // initialize from _Lobj
  1241. _Ctype = _Lobj._Getctype();
  1242. }
  1243. void _Tidy()
  1244. { // free any allocated storage
  1245. if (0 < _Ctype._Delfl)
  1246. free((void *)_Ctype._Table);
  1247. else if (_Ctype._Delfl < 0)
  1248. delete[] (void *)_Ctype._Table;
  1249. }
  1250. virtual _Elem do_tolower(_Elem _Ch) const
  1251. { // convert element to lower case
  1252. return ((_Elem)_Tolower((unsigned char)_Ch, &_Ctype));
  1253. }
  1254. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1255. { // convert [_First, _Last) in place to lower case
  1256. for (; _First != _Last; ++_First)
  1257. *_First = (_Elem)_Tolower((unsigned char)*_First, &_Ctype);
  1258. return ((const _Elem *)_First);
  1259. }
  1260. virtual _Elem do_toupper(_Elem _Ch) const
  1261. { // convert element to upper case
  1262. return ((_Elem)_Toupper((unsigned char)_Ch, &_Ctype));
  1263. }
  1264. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1265. { // convert [_First, _Last) in place to upper case
  1266. for (; _First != _Last; ++_First)
  1267. *_First = (_Elem)_Toupper((unsigned char)*_First, &_Ctype);
  1268. return ((const _Elem *)_First);
  1269. }
  1270. virtual _Elem do_widen(char _Byte) const
  1271. { // widen char
  1272. return (_Byte);
  1273. }
  1274. virtual const _Elem *do_widen(const char *_First, const char *_Last,
  1275. _Elem *_Dest) const
  1276. { // widen chars in [_First, _Last)
  1277. memcpy(_Dest, _First, _Last - _First);
  1278. return (_Last);
  1279. }
  1280. virtual _Elem do_narrow(_Elem _Ch, char) const
  1281. { // narrow char
  1282. return (_Ch);
  1283. }
  1284. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1285. char, char *_Dest) const
  1286. { // narrow elements in [_First, _Last) to chars
  1287. memcpy(_Dest, _First, _Last - _First);
  1288. return (_Last);
  1289. }
  1290. const mask *table() const _THROW0()
  1291. { // return address of char to mask table
  1292. return (_Ctype._Table);
  1293. }
  1294. static const mask *__cdecl classic_table() _THROW0()
  1295. { // return address of char to mask table for "C" locale
  1296. const _Myt& _Fac = _USE(locale::classic(), _Myt);
  1297. return (_Fac.table());
  1298. }
  1299. private:
  1300. _Locinfo::_Ctypevec _Ctype; // information
  1301. };
  1302. // CLASS ctype<wchar_t>
  1303. template<> class _CRTIMP2 ctype<wchar_t>
  1304. : public ctype_base
  1305. { // facet for classifying wchar_t elements, converting cases
  1306. typedef ctype<wchar_t> _Myt;
  1307. public:
  1308. typedef wchar_t _Elem;
  1309. typedef _Elem char_type;
  1310. bool is(mask _Maskval, _Elem _Ch) const
  1311. { // test if element fits any mask classifications
  1312. return (do_is(_Maskval, _Ch));
  1313. }
  1314. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  1315. mask *_Dest) const
  1316. { // get mask sequence for elements in [_First, _Last)
  1317. return (do_is(_First, _Last, _Dest));
  1318. }
  1319. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  1320. const _Elem *_Last) const
  1321. { // find first in [_First, _Last) that fits mask classification
  1322. return (do_scan_is(_Maskval, _First, _Last));
  1323. }
  1324. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  1325. const _Elem *_Last) const
  1326. { // find first in [_First, _Last) not fitting mask classification
  1327. return (do_scan_not(_Maskval, _First, _Last));
  1328. }
  1329. _Elem tolower(_Elem _Ch) const
  1330. { // convert element to lower case
  1331. return (do_tolower(_Ch));
  1332. }
  1333. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  1334. { // convert [_First, _Last) in place to lower case
  1335. return (do_tolower(_First, _Last));
  1336. }
  1337. _Elem toupper(_Elem _Ch) const
  1338. { // convert element to upper case
  1339. return (do_toupper(_Ch));
  1340. }
  1341. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  1342. { // convert [_First, _Last) in place to upper case
  1343. return (do_toupper(_First, _Last));
  1344. }
  1345. _Elem widen(char _Byte) const
  1346. { // widen char
  1347. return (do_widen(_Byte));
  1348. }
  1349. const char *widen(const char *_First, const char *_Last,
  1350. _Elem *_Dest) const
  1351. { // widen chars in [_First, _Last)
  1352. return (do_widen(_First, _Last, _Dest));
  1353. }
  1354. char narrow(_Elem _Ch, char _Dflt = '\0') const
  1355. { // narrow element to char
  1356. return (do_narrow(_Ch, _Dflt));
  1357. }
  1358. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  1359. char _Dflt, char *_Dest) const
  1360. { // narrow elements in [_First, _Last) to chars
  1361. return (do_narrow(_First, _Last, _Dflt, _Dest));
  1362. }
  1363. static locale::id id; // unique facet id
  1364. explicit ctype(size_t _Refs = 0)
  1365. : ctype_base(_Refs)
  1366. { // construct from current locale
  1367. _Init(_Locinfo());
  1368. }
  1369. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  1370. : ctype_base(_Refs)
  1371. { // construct from specified locale
  1372. _Init(_Lobj);
  1373. }
  1374. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  1375. { // return locale category mask and construct standard facet
  1376. if (_Ppf != 0 && *_Ppf == 0)
  1377. *_Ppf = _NEW_CRT ctype<_Elem>;
  1378. return (_X_CTYPE);
  1379. }
  1380. _PROTECTED:
  1381. virtual ~ctype()
  1382. { // destroy the object
  1383. if (_Ctype._Delfl)
  1384. free((void *)_Ctype._Table);
  1385. }
  1386. protected:
  1387. void _Init(const _Locinfo& _Lobj)
  1388. { // initialize from _Lobj
  1389. _Ctype = _Lobj._Getctype();
  1390. _Cvt = _Lobj._Getcvt();
  1391. }
  1392. virtual bool do_is(mask _Maskval, _Elem _Ch) const
  1393. { // test if element fits any mask classifications
  1394. return ((_Getwctype(_Ch, &_Ctype) & _Maskval) != 0);
  1395. }
  1396. virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
  1397. mask *_Dest) const
  1398. { // get mask sequence for elements in [_First, _Last)
  1399. return (_Getwctypes(_First, _Last, _Dest, &_Ctype));
  1400. }
  1401. virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
  1402. const _Elem *_Last) const
  1403. { // find first in [_First, _Last) that fits mask classification
  1404. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  1405. ;
  1406. return (_First);
  1407. }
  1408. virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
  1409. const _Elem *_Last) const
  1410. { // find first in [_First, _Last) not fitting mask classification
  1411. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  1412. ;
  1413. return (_First);
  1414. }
  1415. virtual _Elem do_tolower(_Elem _Ch) const
  1416. { // convert element to lower case
  1417. return (widen((char)_Tolower((unsigned char)narrow(_Ch),
  1418. &_Ctype)));
  1419. }
  1420. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1421. { // convert [_First, _Last) in place to lower case
  1422. for (; _First != _Last; ++_First)
  1423. *_First = widen((char)_Tolower((unsigned char)narrow(*_First),
  1424. &_Ctype));
  1425. return ((const _Elem *)_First);
  1426. }
  1427. virtual _Elem do_toupper(_Elem _Ch) const
  1428. { // convert element to upper case
  1429. return (widen((char)_Toupper((unsigned char)narrow(_Ch),
  1430. &_Ctype)));
  1431. }
  1432. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1433. { // convert [_First, _Last) in place to upper case
  1434. for (; _First != _Last; ++_First)
  1435. *_First = widen((char)_Toupper((unsigned char)narrow(*_First),
  1436. &_Ctype));
  1437. return ((const _Elem *)_First);
  1438. }
  1439. virtual _Elem do_widen(char _Byte) const
  1440. { // widen char
  1441. _Mbstinit(_Mbst);
  1442. wchar_t _Wc;
  1443. return (_Mbrtowc(&_Wc, &_Byte, 1, &_Mbst, &_Cvt) <= 0
  1444. ? (wchar_t)(unsigned char)_Byte : _Wc);
  1445. }
  1446. virtual const char *do_widen(const char *_First, const char *_Last,
  1447. _Elem *_Dest) const
  1448. { // widen chars in [_First, _Last)
  1449. _Mbstinit(_Mbst);
  1450. while (_First != _Last)
  1451. {
  1452. int _Bytes;
  1453. switch (_Bytes = _Mbrtowc(_Dest, _First, _Last - _First,
  1454. &_Mbst, &_Cvt))
  1455. { // test result of locale-specific mbrtowc call
  1456. case -2: // partial conversion
  1457. case -1: // failed conversion
  1458. return (_First);
  1459. case 0: // converted null character
  1460. _Bytes = (int)::strlen(_First) + 1;
  1461. // fall through
  1462. default: // converted _Bytes bytes to a wchar_t
  1463. _First += _Bytes, ++_Dest;
  1464. }
  1465. }
  1466. return (_First);
  1467. }
  1468. virtual char do_narrow(_Elem _Ch, char _Dflt) const
  1469. { // narrow element to char
  1470. char _Buf[MB_LEN_MAX];
  1471. _Mbstinit(_Mbst);
  1472. return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1
  1473. ? _Dflt : _Buf[0]);
  1474. }
  1475. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1476. char _Dflt, char *_Dest) const
  1477. { // narrow elements in [_First, _Last) to chars
  1478. _Mbstinit(_Mbst);
  1479. for (; _First != _Last; ++_First)
  1480. {
  1481. int _Bytes;
  1482. if ((_Bytes = _Wcrtomb(_Dest, *_First, &_Mbst, &_Cvt)) <= 0)
  1483. {
  1484. _Bytes = 1;
  1485. *_Dest = _Dflt;
  1486. }
  1487. _Dest += _Bytes;
  1488. }
  1489. return (_First);
  1490. }
  1491. private:
  1492. _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc.
  1493. _Locinfo::_Cvtvec _Cvt; // conversion information
  1494. };
  1495. #ifdef _CRTBLD_NATIVE_WCHAR_T
  1496. // CLASS ctype<unsigned short>
  1497. template<> class _CRTIMP2 ctype<unsigned short>
  1498. : public ctype_base
  1499. { // facet for classifying unsigned short elements, converting cases
  1500. typedef ctype<unsigned short> _Myt;
  1501. public:
  1502. typedef unsigned short _Elem;
  1503. typedef _Elem char_type;
  1504. bool is(mask _Maskval, _Elem _Ch) const
  1505. { // test if element fits any mask classifications
  1506. return (do_is(_Maskval, _Ch));
  1507. }
  1508. const _Elem *is(const _Elem *_First, const _Elem *_Last,
  1509. mask *_Dest) const
  1510. { // get mask sequence for elements in [_First, _Last)
  1511. return (do_is(_First, _Last, _Dest));
  1512. }
  1513. const _Elem *scan_is(mask _Maskval, const _Elem *_First,
  1514. const _Elem *_Last) const
  1515. { // find first in [_First, _Last) that fits mask classification
  1516. return (do_scan_is(_Maskval, _First, _Last));
  1517. }
  1518. const _Elem *scan_not(mask _Maskval, const _Elem *_First,
  1519. const _Elem *_Last) const
  1520. { // find first in [_First, _Last) not fitting mask classification
  1521. return (do_scan_not(_Maskval, _First, _Last));
  1522. }
  1523. _Elem tolower(_Elem _Ch) const
  1524. { // convert element to lower case
  1525. return (do_tolower(_Ch));
  1526. }
  1527. const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
  1528. { // convert [_First, _Last) in place to lower case
  1529. return (do_tolower(_First, _Last));
  1530. }
  1531. _Elem toupper(_Elem _Ch) const
  1532. { // convert element to upper case
  1533. return (do_toupper(_Ch));
  1534. }
  1535. const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
  1536. { // convert [_First, _Last) in place to upper case
  1537. return (do_toupper(_First, _Last));
  1538. }
  1539. _Elem widen(char _Byte) const
  1540. { // widen char
  1541. return (do_widen(_Byte));
  1542. }
  1543. const char *widen(const char *_First, const char *_Last,
  1544. _Elem *_Dest) const
  1545. { // widen chars in [_First, _Last)
  1546. return (do_widen(_First, _Last, _Dest));
  1547. }
  1548. char narrow(_Elem _Ch, char _Dflt = '\0') const
  1549. { // narrow element to char
  1550. return (do_narrow(_Ch, _Dflt));
  1551. }
  1552. const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
  1553. char _Dflt, char *_Dest) const
  1554. { // narrow elements in [_First, _Last) to chars
  1555. return (do_narrow(_First, _Last, _Dflt, _Dest));
  1556. }
  1557. static locale::id id; // unique facet id
  1558. explicit ctype(size_t _Refs = 0)
  1559. : ctype_base(_Refs)
  1560. { // construct from current locale
  1561. _Init(_Locinfo());
  1562. }
  1563. ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
  1564. : ctype_base(_Refs)
  1565. { // construct from specified locale
  1566. _Init(_Lobj);
  1567. }
  1568. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  1569. { // return locale category mask and construct standard facet
  1570. if (_Ppf != 0 && *_Ppf == 0)
  1571. *_Ppf = _NEW_CRT ctype<_Elem>;
  1572. return (_X_CTYPE);
  1573. }
  1574. _PROTECTED:
  1575. virtual ~ctype()
  1576. { // destroy the object
  1577. if (_Ctype._Delfl)
  1578. free((void *)_Ctype._Table);
  1579. }
  1580. protected:
  1581. void _Init(const _Locinfo& _Lobj)
  1582. { // initialize from _Lobj
  1583. _Ctype = _Lobj._Getctype();
  1584. _Cvt = _Lobj._Getcvt();
  1585. }
  1586. virtual bool do_is(mask _Maskval, _Elem _Ch) const
  1587. { // test if element fits any mask classifications
  1588. return ((_Getwctype(_Ch, &_Ctype) & _Maskval) != 0);
  1589. }
  1590. virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
  1591. mask *_Dest) const
  1592. { // get mask sequence for elements in [_First, _Last)
  1593. return ((const _Elem *)_Getwctypes((const wchar_t *)_First,
  1594. (const wchar_t *)_Last, _Dest, &_Ctype));
  1595. }
  1596. virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
  1597. const _Elem *_Last) const
  1598. { // find first in [_First, _Last) that fits mask classification
  1599. for (; _First != _Last && !is(_Maskval, *_First); ++_First)
  1600. ;
  1601. return (_First);
  1602. }
  1603. virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
  1604. const _Elem *_Last) const
  1605. { // find first in [_First, _Last) not fitting mask classification
  1606. for (; _First != _Last && is(_Maskval, *_First); ++_First)
  1607. ;
  1608. return (_First);
  1609. }
  1610. virtual _Elem do_tolower(_Elem _Ch) const
  1611. { // convert element to lower case
  1612. return (widen((char)_Tolower((unsigned char)narrow(_Ch),
  1613. &_Ctype)));
  1614. }
  1615. virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
  1616. { // convert [_First, _Last) in place to lower case
  1617. for (; _First != _Last; ++_First)
  1618. *_First = widen((char)_Tolower((unsigned char)narrow(*_First),
  1619. &_Ctype));
  1620. return ((const _Elem *)_First);
  1621. }
  1622. virtual _Elem do_toupper(_Elem _Ch) const
  1623. { // convert element to upper case
  1624. return (widen((char)_Toupper((unsigned char)narrow(_Ch),
  1625. &_Ctype)));
  1626. }
  1627. virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
  1628. { // convert [_First, _Last) in place to upper case
  1629. for (; _First != _Last; ++_First)
  1630. *_First = widen((char)_Toupper((unsigned char)narrow(*_First),
  1631. &_Ctype));
  1632. return ((const _Elem *)_First);
  1633. }
  1634. virtual _Elem do_widen(char _Byte) const
  1635. { // widen char
  1636. _Mbstinit(_Mbst);
  1637. unsigned short _Wc;
  1638. return (_Mbrtowc((wchar_t *)&_Wc, &_Byte, 1, &_Mbst, &_Cvt) <= 0
  1639. ? (unsigned short)(unsigned char)_Byte : _Wc);
  1640. }
  1641. virtual const char *do_widen(const char *_First, const char *_Last,
  1642. _Elem *_Dest) const
  1643. { // widen chars in [_First, _Last)
  1644. _Mbstinit(_Mbst);
  1645. while (_First != _Last)
  1646. {
  1647. int _Bytes;
  1648. switch (_Bytes = _Mbrtowc((wchar_t *)_Dest, _First, _Last - _First,
  1649. &_Mbst, &_Cvt))
  1650. { // test result of locale-specific mbrtowc call
  1651. case -2: // partial conversion
  1652. case -1: // failed conversion
  1653. return (_First);
  1654. case 0: // converted null character
  1655. _Bytes = (int)::strlen(_First) + 1;
  1656. // fall through
  1657. default: // converted _Bytes bytes to a wchar_t
  1658. _First += _Bytes, ++_Dest;
  1659. }
  1660. }
  1661. return (_First);
  1662. }
  1663. virtual char do_narrow(_Elem _Ch, char _Dflt) const
  1664. { // narrow element to char
  1665. char _Buf[MB_LEN_MAX];
  1666. _Mbstinit(_Mbst);
  1667. return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1
  1668. ? _Dflt : _Buf[0]);
  1669. }
  1670. virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
  1671. char _Dflt, char *_Dest) const
  1672. { // narrow elements in [_First, _Last) to chars
  1673. _Mbstinit(_Mbst);
  1674. for (; _First != _Last; ++_First)
  1675. {
  1676. int _Bytes;
  1677. if ((_Bytes = _Wcrtomb(_Dest, *_First, &_Mbst, &_Cvt)) <= 0)
  1678. {
  1679. _Bytes = 1;
  1680. *_Dest = _Dflt;
  1681. }
  1682. _Dest += _Bytes;
  1683. }
  1684. return (_First);
  1685. }
  1686. private:
  1687. _Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc.
  1688. _Locinfo::_Cvtvec _Cvt; // conversion information
  1689. };
  1690. #endif
  1691. // TEMPLATE CLASS ctype_byname
  1692. template<class _Elem>
  1693. class ctype_byname
  1694. : public ctype<_Elem>
  1695. { // ctype for named locale
  1696. public:
  1697. explicit ctype_byname(const char *_Locname, size_t _Refs = 0)
  1698. : ctype<_Elem>(_Locinfo(_Locname), _Refs)
  1699. { // construct from named locale
  1700. }
  1701. _PROTECTED:
  1702. virtual ~ctype_byname()
  1703. { // destroy the object
  1704. }
  1705. };
  1706. #ifdef _DLL_CPPLIB
  1707. #ifdef __FORCE_INSTANCE
  1708. template class _CRTIMP2 codecvt<char, char, int>;
  1709. #endif // __FORCE_INSTANCE
  1710. #endif // _DLL_CPPLIB
  1711. _STD_END
  1712. #pragma warning(pop)
  1713. #pragma pack(pop)
  1714. #endif /* _XLOCALE_ */
  1715. /*
  1716. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  1717. * Consult your license regarding permissions and restrictions.
  1718. V3.10:0009 */