|
|
|
1 |
|
// xlocale internal header (from <locale>) |
2 |
|
#pragma once |
3 |
|
#ifndef _XLOCALE_ |
4 |
|
#define _XLOCALE_ |
5 |
|
#ifndef RC_INVOKED |
6 |
|
#include <climits> |
7 |
|
#include <cstring> |
8 |
|
#include <stdexcept> |
9 |
|
#include <typeinfo> |
10 |
|
#include <xdebug> |
11 |
|
#include <xlocinfo> |
12 |
|
|
13 |
|
#ifdef _MSC_VER |
14 |
|
#pragma pack(push,_CRT_PACKING) |
15 |
|
#pragma warning(push,3) |
16 |
|
#pragma warning(disable:4412) |
17 |
|
#endif /* _MSC_VER */ |
18 |
|
|
19 |
|
_STD_BEGIN |
20 |
|
|
21 |
|
// TEMPLATE CLASS _Locbase |
22 |
|
template<class _Dummy> |
23 |
|
class _Locbase |
24 |
|
{ // define templatized category constants, instantiate on demand |
25 |
|
public: |
26 |
|
_PGLOBAL static const int collate = _M_COLLATE; |
27 |
|
_PGLOBAL static const int ctype = _M_CTYPE; |
28 |
|
_PGLOBAL static const int monetary = _M_MONETARY; |
29 |
|
_PGLOBAL static const int numeric = _M_NUMERIC; |
30 |
|
_PGLOBAL static const int time = _M_TIME; |
31 |
|
_PGLOBAL static const int messages = _M_MESSAGES; |
32 |
|
_PGLOBAL static const int all = _M_ALL; |
33 |
|
_PGLOBAL static const int none = 0; |
34 |
|
}; |
35 |
|
|
36 |
|
template<class _Dummy> |
37 |
|
const int _Locbase<_Dummy>::collate; |
38 |
|
template<class _Dummy> |
39 |
|
const int _Locbase<_Dummy>::ctype; |
40 |
|
template<class _Dummy> |
41 |
|
const int _Locbase<_Dummy>::monetary; |
42 |
|
template<class _Dummy> |
43 |
|
const int _Locbase<_Dummy>::numeric; |
44 |
|
template<class _Dummy> |
45 |
|
const int _Locbase<_Dummy>::time; |
46 |
|
template<class _Dummy> |
47 |
|
const int _Locbase<_Dummy>::messages; |
48 |
|
template<class _Dummy> |
49 |
|
const int _Locbase<_Dummy>::all; |
50 |
|
template<class _Dummy> |
51 |
|
const int _Locbase<_Dummy>::none; |
52 |
|
|
53 |
|
// CLASS locale |
54 |
|
class locale; |
55 |
|
template<class _Facet> |
56 |
|
const _Facet& __CRTDECL use_facet(const locale&); |
57 |
|
|
58 |
|
// warning 4412 is benign here |
59 |
|
#pragma warning(push) |
60 |
|
#pragma warning(disable:4412) |
61 |
|
class _CRTIMP2_PURE locale |
62 |
|
: public _Locbase<int> |
63 |
|
{ // nonmutable collection of facets that describe a locale |
64 |
|
public: |
65 |
|
typedef int category; |
66 |
|
|
67 |
|
// CLASS id |
68 |
|
class _CRTIMP2_PURE id |
69 |
|
{ // identifier stamp, unique for each distinct kind of facet |
70 |
|
public: |
71 |
|
__CLR_OR_THIS_CALL id(size_t _Val = 0) |
72 |
|
: _Id(_Val) |
73 |
|
{ // construct with specified stamp value |
74 |
|
} |
75 |
|
|
76 |
|
__CLR_OR_THIS_CALL operator size_t() |
77 |
|
{ // get stamp, with lazy allocation |
78 |
|
if (_Id == 0) |
79 |
|
{ // still zero, allocate stamp |
80 |
|
_BEGIN_LOCK(_LOCK_LOCALE) |
81 |
|
if (_Id == 0) |
82 |
|
_Id = ++_Id_cnt; |
83 |
|
_END_LOCK() |
84 |
|
} |
85 |
|
return (_Id); |
86 |
|
} |
87 |
|
|
88 |
|
private: |
89 |
|
__CLR_OR_THIS_CALL id(const id&); // not defined |
90 |
|
id& __CLR_OR_THIS_CALL operator=(const id&); // not defined |
91 |
|
|
92 |
|
size_t _Id; // the identifier stamp |
93 |
|
static _MRTIMP2_NPURE int& __cdecl _Id_cnt_func(); |
94 |
|
#ifdef _M_CEE_PURE |
95 |
|
static int& _Id_cnt; // static source of unique stamps |
96 |
|
#else |
97 |
|
__PURE_APPDOMAIN_GLOBAL static int _Id_cnt; // static source of unique stamps |
98 |
|
#endif |
99 |
|
}; |
100 |
|
|
101 |
|
class _Locimp; |
102 |
|
|
103 |
|
// class facet |
104 |
|
class facet |
105 |
|
{ // base class for all locale facets, performs reference counting |
106 |
|
friend class locale; |
107 |
|
friend class _Locimp; |
108 |
|
|
109 |
|
public: |
110 |
|
_CRTIMP2_PURE static size_t __CLRCALL_OR_CDECL _Getcat(const facet ** = 0, |
111 |
|
const locale * = 0) |
112 |
|
{ // get category value, or -1 if no corresponding C category |
113 |
|
return ((size_t)(-1)); |
114 |
|
} |
115 |
|
|
116 |
|
_CRTIMP2_PURE void __CLR_OR_THIS_CALL _Incref() |
117 |
|
{ // safely increment the reference count |
118 |
|
_BEGIN_LOCK(_LOCK_LOCALE) |
119 |
|
if (_Refs < (size_t)(-1)) |
120 |
|
++_Refs; |
121 |
|
_END_LOCK() |
122 |
|
} |
123 |
|
|
124 |
|
_CRTIMP2_PURE facet *__CLR_OR_THIS_CALL _Decref() |
125 |
|
{ // safely decrement the reference count, return this when dead |
126 |
|
_BEGIN_LOCK(_LOCK_LOCALE) |
127 |
|
if (0 < _Refs && _Refs < (size_t)(-1)) |
128 |
|
--_Refs; |
129 |
|
return (_Refs == 0 ? this : 0); |
130 |
|
_END_LOCK() |
131 |
|
} |
132 |
|
|
133 |
|
void __CLR_OR_THIS_CALL _Register() |
134 |
|
{ |
135 |
|
#if defined(_M_CEE) |
136 |
|
facet_Register_m(this); |
137 |
|
#else |
138 |
|
facet_Register(this); |
139 |
|
#endif |
140 |
|
} |
141 |
|
|
142 |
|
#if defined(_DEBUG) && !defined(_M_X64) |
143 |
|
_CRTIMP2_PURE void * __CLRCALL_OR_CDECL operator new(size_t _Size) |
144 |
|
{ // replace operator new |
145 |
|
return (operator new(_Size, std::_DebugHeapTag_func(), |
146 |
|
__FILE__, __LINE__)); |
147 |
|
} |
148 |
|
|
149 |
|
_CRTIMP2_PURE void * __CLRCALL_OR_CDECL operator new(size_t _Size, |
150 |
|
const std::_DebugHeapTag_t& _Tag, _In_opt_z_ char *_File, int _Line) |
151 |
|
{ // replace debugging operator new |
152 |
|
return (::operator new(_Size, _Tag, _File, _Line)); |
153 |
|
} |
154 |
|
|
155 |
|
_CRTIMP2_PURE void __CLRCALL_OR_CDECL operator delete(void *_Ptr, |
156 |
|
const std::_DebugHeapTag_t&, _In_opt_z_ char *, int) |
157 |
|
{ // replace debugging operator delete |
158 |
|
operator delete(_Ptr); |
159 |
|
} |
160 |
|
|
161 |
|
_CRTIMP2_PURE void __CLRCALL_OR_CDECL operator delete(void *_Ptr) |
162 |
|
{ // replace operator delete |
163 |
|
std::_DebugHeapDelete((facet*)_Ptr); |
164 |
|
} |
165 |
|
#endif /* defined(_DEBUG) */ |
166 |
|
|
167 |
|
|
168 |
|
// _PROTECTED: |
169 |
|
_CRTIMP2_PURE virtual __CLR_OR_THIS_CALL ~facet() |
170 |
|
{ // destroy the object |
171 |
|
} |
172 |
|
|
173 |
|
protected: |
174 |
|
_CRTIMP2_PURE explicit __CLR_OR_THIS_CALL facet(size_t _Initrefs = 0) |
175 |
|
: _Refs(_Initrefs) |
176 |
|
{ // construct with initial reference count |
177 |
|
} |
178 |
|
|
179 |
|
private: |
180 |
|
#if defined(_M_CEE) |
181 |
|
static void __CLRCALL_OR_CDECL facet_Register_m(facet *); // queue up lazy facet for destruction |
182 |
|
#else |
183 |
|
static void __CLRCALL_OR_CDECL facet_Register(facet *); // queue up lazy facet for destruction |
184 |
|
#endif |
185 |
|
|
186 |
|
__CLR_OR_THIS_CALL facet(const facet&); // not defined |
187 |
|
facet& __CLR_OR_THIS_CALL operator=(const facet&); // not defined |
188 |
|
|
189 |
|
size_t _Refs; // the reference count |
190 |
|
}; |
191 |
|
|
192 |
|
#pragma warning(push) |
193 |
|
#pragma warning(disable:4275) |
194 |
|
// CLASS _Locimp |
195 |
|
class _CRTIMP2_PURE _Locimp |
196 |
|
: public facet |
197 |
|
{ // reference-counted actual implementation of a locale |
198 |
|
_PROTECTED: |
199 |
|
__CLR_OR_THIS_CALL ~_Locimp() |
200 |
|
{ |
201 |
|
_Locimp_dtor(this); |
202 |
|
} |
203 |
|
|
204 |
|
private: |
205 |
|
static _MRTIMP2_NPURE void __cdecl _Locimp_dtor(_Locimp *); // destoy the object |
206 |
|
static void _Locimp_ctor(_Locimp *,const _Locimp&); // copy a _Locimp |
207 |
|
static _MRTIMP2_NPURE void __cdecl _Locimp_Addfac(_Locimp *,facet *, size_t); // add a facet |
208 |
|
friend class locale; |
209 |
|
|
210 |
|
__CLR_OR_THIS_CALL _Locimp(bool _Transparent = false) |
211 |
|
: locale::facet(1), _Facetvec(0), _Facetcount(0), |
212 |
|
_Catmask(none), _Xparent(_Transparent), _Name("*") |
213 |
|
{ } |
214 |
|
|
215 |
|
__CLR_OR_THIS_CALL _Locimp(const _Locimp& _Right) |
216 |
|
: locale::facet(1), _Facetvec(0), _Facetcount(_Right._Facetcount), |
217 |
|
_Catmask(_Right._Catmask), _Xparent(_Right._Xparent), _Name(_Right._Name) |
218 |
|
{ |
219 |
|
_Locimp_ctor(this, _Right); |
220 |
|
} |
221 |
|
|
222 |
|
void __CLR_OR_THIS_CALL _Addfac(facet *_Pfacet, size_t _Id) |
223 |
|
{ |
224 |
|
_Locimp_Addfac(this, _Pfacet, _Id); |
225 |
|
} |
226 |
|
|
227 |
|
static _Locimp * _Makeloc(const _Locinfo&, |
228 |
|
category, _Locimp *, const locale *); // make essential facets |
229 |
|
|
230 |
|
static void _Makewloc(const _Locinfo&, |
231 |
|
category, _Locimp *, const locale *); // make wchar_t facets |
232 |
|
|
233 |
|
#ifdef _NATIVE_WCHAR_T_DEFINED |
234 |
|
static void _Makeushloc(const _Locinfo&, |
235 |
|
category, _Locimp *, const locale *); // make ushort facets |
236 |
|
#endif /* _NATIVE_WCHAR_T_DEFINED */ |
237 |
|
|
238 |
|
static void _Makexloc(const _Locinfo&, |
239 |
|
category, _Locimp *, const locale *); // make remaining facets |
240 |
|
|
241 |
|
facet **_Facetvec; // pointer to vector of facets |
242 |
|
size_t _Facetcount; // size of vector of facets |
243 |
|
category _Catmask; // mask describing implemented categories |
244 |
|
bool _Xparent; // true if locale is transparent |
245 |
|
_STRING_CRT _Name; // locale name, or "*" if not known |
246 |
|
|
247 |
|
static _MRTIMP2_NPURE _Locimp *& __cdecl _Clocptr_func(); // pointer to "C" locale object |
248 |
|
#ifdef _M_CEE_PURE |
249 |
|
static _Locimp *&_Clocptr; // pointer to "C" locale object |
250 |
|
#else |
251 |
|
__PURE_APPDOMAIN_GLOBAL static _Locimp *_Clocptr; // pointer to "C" locale object |
252 |
|
#endif |
253 |
|
private: |
254 |
|
_Locimp& __CLR_OR_THIS_CALL operator=(const _Locimp&); // not defined |
255 |
|
|
256 |
|
}; |
257 |
|
#pragma warning(pop) |
258 |
|
|
259 |
|
_DEPRECATED locale& __CLR_OR_THIS_CALL _Addfac(facet *_Fac, size_t _Id, |
260 |
|
size_t _Catmask) |
261 |
|
{ |
262 |
|
if (1 < this->_Ptr->_Refs) |
263 |
|
{ // shared, make private copy before altering |
264 |
|
this->_Ptr->_Decref(); |
265 |
|
this->_Ptr = _NEW_CRT _Locimp(*this->_Ptr); |
266 |
|
} |
267 |
|
this->_Ptr->_Addfac(_Fac, _Id); |
268 |
|
|
269 |
|
if (_Catmask != 0) |
270 |
|
this->_Ptr->_Name = "*"; |
271 |
|
return (*this); |
272 |
|
} |
273 |
|
|
274 |
|
|
275 |
|
template<class _Elem, |
276 |
|
class _Traits, |
277 |
|
class _Alloc> |
278 |
|
bool __CLR_OR_THIS_CALL operator()(const basic_string<_Elem, _Traits, _Alloc>& _Left, |
279 |
|
const basic_string<_Elem, _Traits, _Alloc>& _Right) const |
280 |
|
{ // compare _Left and _Right strings using collate facet in locale |
281 |
|
const std::collate<_Elem>& _Coll_fac = |
282 |
|
std::use_facet<std::collate<_Elem> >(*this); |
283 |
|
|
284 |
|
return (_Coll_fac.compare(_Left.c_str(), _Left.c_str() + _Left.size(), |
285 |
|
_Right.c_str(), _Right.c_str() + _Right.size()) < 0); |
286 |
|
} |
287 |
|
|
288 |
|
template<class _Facet> |
289 |
|
locale __CLR_OR_THIS_CALL combine(const locale& _Loc) const |
290 |
|
{ // combine two locales |
291 |
|
_Facet *_Facptr; |
292 |
|
|
293 |
|
_TRY_BEGIN |
294 |
|
_Facptr = (_Facet *)&std::use_facet<_Facet>(_Loc); |
295 |
|
_CATCH_ALL |
296 |
|
_THROW(runtime_error, "locale::combine facet missing"); |
297 |
|
_CATCH_END |
298 |
|
|
299 |
|
_Locimp *_Newimp = _NEW_CRT _Locimp(*_Ptr); |
300 |
|
_Newimp->_Addfac(_Facptr, _Facet::id); |
301 |
|
_Newimp->_Catmask = 0; |
302 |
|
_Newimp->_Name = "*"; |
303 |
|
return (locale(_Newimp)); |
304 |
|
} |
305 |
|
|
306 |
|
template<class _Facet> |
307 |
|
__CLR_OR_THIS_CALL locale(const locale& _Loc, const _Facet *_Facptr) |
308 |
|
: _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr)) |
309 |
|
{ // construct from _Loc, replacing facet with *_Facptr |
310 |
|
if (_Facptr != 0) |
311 |
|
{ // replace facet |
312 |
|
_Ptr->_Addfac((_Facet *)_Facptr, _Facet::id); |
313 |
|
if (_Facet::_Getcat() != (size_t)(-1)) |
314 |
|
{ // no C category |
315 |
|
_Ptr->_Catmask = 0; |
316 |
|
_Ptr->_Name = "*"; |
317 |
|
} |
318 |
|
} |
319 |
|
} |
320 |
|
|
321 |
|
|
322 |
|
__CLR_OR_THIS_CALL locale() _THROW0() |
323 |
|
: _Ptr(_Init()) |
324 |
|
{ // construct from current locale |
325 |
|
_Getgloballocale()->_Incref(); |
326 |
|
} |
327 |
|
|
328 |
|
__CLR_OR_THIS_CALL locale(_Uninitialized) |
329 |
|
{ // defer construction |
330 |
|
} |
331 |
|
|
332 |
|
__CLR_OR_THIS_CALL locale(const locale& _Right) _THROW0() |
333 |
|
: _Ptr(_Right._Ptr) |
334 |
|
{ // construct by copying |
335 |
|
_Ptr->_Incref(); |
336 |
|
} |
337 |
|
|
338 |
|
__CLR_OR_THIS_CALL locale(const locale& _Loc, const locale& _Other, |
339 |
|
category _Cat) // construct from locale and category in another locale |
340 |
|
: _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr)) |
341 |
|
{ // construct a locale by copying named facets |
342 |
|
_TRY_BEGIN |
343 |
|
_BEGIN_LOCINFO(_Lobj(_Loc._Ptr->_Catmask, _Loc._Ptr->_Name.c_str())) |
344 |
|
_Locimp::_Makeloc(_Lobj._Addcats(_Cat & _Other._Ptr->_Catmask, |
345 |
|
_Other._Ptr->_Name.c_str()), _Cat, _Ptr, &_Other); |
346 |
|
_END_LOCINFO() |
347 |
|
_CATCH_ALL |
348 |
|
_DELETE_CRT(_Ptr->_Decref()); |
349 |
|
_RERAISE; |
350 |
|
_CATCH_END |
351 |
|
} |
352 |
|
|
353 |
|
explicit __CLR_OR_THIS_CALL locale(const char *_Locname, |
354 |
|
category _Cat = all) // construct from named locale for category |
355 |
|
: _Ptr(_NEW_CRT _Locimp) |
356 |
|
{ // construct a locale with named facets |
357 |
|
_TRY_BEGIN |
358 |
|
_Init(); |
359 |
|
_BEGIN_LOCINFO(_Lobj(_Cat, _Locname)) |
360 |
|
if (_Lobj._Getname().compare("*") == 0) |
361 |
|
_THROW(runtime_error, "bad locale name"); |
362 |
|
_Locimp::_Makeloc(_Lobj, _Cat, _Ptr, 0); |
363 |
|
_END_LOCINFO() |
364 |
|
_CATCH_ALL |
365 |
|
_DELETE_CRT(_Ptr->_Decref()); |
366 |
|
_RERAISE; |
367 |
|
_CATCH_END |
368 |
|
} |
369 |
|
|
370 |
|
__CLR_OR_THIS_CALL locale(const locale& _Loc, const char * _Locname, |
371 |
|
category _Cat) // construct from locale and category in named locale |
372 |
|
: _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr)) |
373 |
|
{ // construct a locale by copying, replacing named facets |
374 |
|
_TRY_BEGIN |
375 |
|
_BEGIN_LOCINFO(_Lobj(_Loc._Ptr->_Catmask, _Loc._Ptr->_Name.c_str())) |
376 |
|
bool _Hadname = _Lobj._Getname().compare("*") != 0; |
377 |
|
_Lobj._Addcats(_Cat, _Locname); |
378 |
|
|
379 |
|
if (_Hadname && _Lobj._Getname().compare("*") == 0) |
380 |
|
_THROW(runtime_error, "bad locale name"); |
381 |
|
_Locimp::_Makeloc(_Lobj, _Cat, _Ptr, 0); |
382 |
|
_END_LOCINFO() |
383 |
|
_CATCH_ALL |
384 |
|
_DELETE_CRT(_Ptr->_Decref()); |
385 |
|
_RERAISE; |
386 |
|
_CATCH_END |
387 |
|
} |
388 |
|
|
389 |
|
__CLR_OR_THIS_CALL ~locale() _THROW0() |
390 |
|
{ // destroy the object |
391 |
|
if (_Ptr != 0) |
392 |
|
_DELETE_CRT(_Ptr->_Decref()); |
393 |
|
} |
394 |
|
|
395 |
|
locale& __CLR_OR_THIS_CALL operator=(const locale& _Right) _THROW0() |
396 |
|
{ // assign a locale |
397 |
|
if (_Ptr != _Right._Ptr) |
398 |
|
{ // different implementation, point at new one |
399 |
|
_DELETE_CRT(_Ptr->_Decref()); |
400 |
|
_Ptr = _Right._Ptr; |
401 |
|
_Ptr->_Incref(); |
402 |
|
} |
403 |
|
return (*this); |
404 |
|
} |
405 |
|
|
406 |
|
string __CLR_OR_THIS_CALL name() const |
407 |
|
{ // return locale name |
408 |
|
return (_Ptr->_Name); |
409 |
|
} |
410 |
|
|
411 |
|
const facet *__CLR_OR_THIS_CALL _Getfacet(size_t _Id) const // get facet by id |
412 |
|
{ // look up a facet in locale object |
413 |
|
const facet *_Facptr = _Id < _Ptr->_Facetcount |
414 |
|
? _Ptr->_Facetvec[_Id] : 0; // null if id off end |
415 |
|
if (_Facptr != 0 || !_Ptr->_Xparent) |
416 |
|
return (_Facptr); // found facet or not transparent, return pointer |
417 |
|
else |
418 |
|
{ // look in current locale |
419 |
|
locale::_Locimp *_Ptr = _Getgloballocale(); |
420 |
|
return (_Id < _Ptr->_Facetcount |
421 |
|
? _Ptr->_Facetvec[_Id] // get from current locale |
422 |
|
: 0); // no entry in current locale |
423 |
|
} |
424 |
|
} |
425 |
|
|
426 |
|
|
427 |
|
bool __CLR_OR_THIS_CALL operator==(const locale& _Loc) const |
428 |
|
{ // compare locales for equality |
429 |
|
return (_Ptr == _Loc._Ptr |
430 |
|
|| name().compare("*") != 0 && name().compare(_Loc.name()) == 0); |
431 |
|
} |
432 |
|
|
433 |
|
bool __CLR_OR_THIS_CALL operator!=(const locale& _Right) const |
434 |
|
{ // test for locale inequality |
435 |
|
return (!(*this == _Right)); |
436 |
|
} |
437 |
|
|
438 |
|
static _MRTIMP2_NPURE const locale& __cdecl classic(); // return classic "C" locale |
439 |
|
|
440 |
|
static _MRTIMP2_NPURE locale __cdecl global(const locale&); // return current locale |
441 |
|
|
442 |
|
static _MRTIMP2_NPURE locale __cdecl empty(); // return empty (transparent) locale |
443 |
|
|
444 |
|
private: |
445 |
|
locale(_Locimp *_Ptrimp) |
446 |
|
: _Ptr(_Ptrimp) |
447 |
|
{ // construct from _Locimp pointer |
448 |
|
} |
449 |
|
|
450 |
|
static _MRTIMP2_NPURE _Locimp *__cdecl _Getgloballocale(); |
451 |
|
static _MRTIMP2_NPURE _Locimp *__cdecl _Init(); // initialize locale |
452 |
|
static _MRTIMP2_NPURE void __cdecl _Setgloballocale(void *); |
453 |
|
|
454 |
|
_Locimp *_Ptr; // pointer to locale implementation object |
455 |
|
}; |
456 |
|
#pragma warning(pop) |
457 |
|
|
458 |
|
// SUPPORT TEMPLATES |
459 |
|
template<class _Facet> |
460 |
|
struct _Facetptr |
461 |
|
{ // store pointer to lazy facet for use_facet |
462 |
|
__PURE_APPDOMAIN_GLOBAL static const locale::facet *_Psave; |
463 |
|
}; |
464 |
|
|
465 |
|
template<class _Facet> |
466 |
|
__PURE_APPDOMAIN_GLOBAL const locale::facet *_Facetptr<_Facet>::_Psave = 0; |
467 |
|
|
468 |
|
template<class _Facet> inline _DEPRECATED |
469 |
|
locale _Addfac(locale _Loc, const _Facet *_Facptr) |
470 |
|
{ // add facet to locale -- retained |
471 |
|
size_t _Cat = _Facet::_Getcat(0, 0); |
472 |
|
locale _Newloc = _Loc._Addfac((_Facet *)_Facptr, _Facet::id, _Cat); |
473 |
|
|
474 |
|
return (_Newloc); |
475 |
|
} |
476 |
|
|
477 |
|
#define _ADDFAC(loc, pfac) locale(loc, pfac) /* add facet to locale */ |
478 |
|
|
479 |
|
#define _USE(loc, fac) \ |
480 |
|
use_facet<fac >(loc) /* get facet reference from locale */ |
481 |
|
|
482 |
|
template<class _Facet> inline |
483 |
|
const _Facet& __CRTDECL use_facet(const locale& _Loc) |
484 |
|
|
485 |
|
|
486 |
|
{ // get facet reference from locale |
487 |
|
_BEGIN_LOCK(_LOCK_LOCALE) // the thread lock, make get atomic |
488 |
|
const locale::facet *_Psave = |
489 |
|
_Facetptr<_Facet>::_Psave; // static pointer to lazy facet |
490 |
|
|
491 |
|
size_t _Id = _Facet::id; |
492 |
|
const locale::facet *_Pf = _Loc._Getfacet(_Id); |
493 |
|
|
494 |
|
if (_Pf != 0) |
495 |
|
; // got facet from locale |
496 |
|
else if (_Psave != 0) |
497 |
|
_Pf = _Psave; // lazy facet already allocated |
498 |
|
else if (_Facet::_Getcat(&_Psave, &_Loc) == (size_t)(-1)) |
499 |
|
|
500 |
|
#if _HAS_EXCEPTIONS |
501 |
|
_THROW_NCEE(bad_cast, _EMPTY_ARGUMENT); // lazy disallowed |
502 |
|
|
503 |
|
#else /* _HAS_EXCEPTIONS */ |
504 |
|
abort(); // lazy disallowed |
505 |
|
#endif /* _HAS_EXCEPTIONS */ |
506 |
|
|
507 |
|
else |
508 |
|
{ // queue up lazy facet for destruction |
509 |
|
_Pf = _Psave; |
510 |
|
_Facetptr<_Facet>::_Psave = _Psave; |
511 |
|
|
512 |
|
locale::facet *_Pfmod = (_Facet *)_Psave; |
513 |
|
_Pfmod->_Incref(); |
514 |
|
_Pfmod->_Register(); |
515 |
|
} |
516 |
|
|
517 |
|
return ((const _Facet&)(*_Pf)); // should be dynamic_cast |
518 |
|
_END_LOCK() |
519 |
|
} |
520 |
|
|
521 |
|
template<class _Facet> inline _DEPRECATED |
522 |
|
const _Facet& __CRTDECL use_facet(const locale& _Loc, const _Facet *, |
523 |
|
bool = false) |
524 |
|
{ // get facet reference from locale -- retained, 2/3 arg versions |
525 |
|
return use_facet<_Facet>(_Loc); |
526 |
|
} |
527 |
|
|
528 |
|
// TEMPLATE FUNCTION _Getloctxt |
529 |
|
template<class _Elem, |
530 |
|
class _InIt> inline |
531 |
|
int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields, |
532 |
|
const _Elem *_Ptr) |
533 |
|
{ // find field at _Ptr that matches longest in [_First, _Last) |
534 |
|
for (size_t _Off = 0; _Ptr[_Off] != (_Elem)0; ++_Off) |
535 |
|
if (_Ptr[_Off] == _Ptr[0]) |
536 |
|
++_Numfields; // add fields with leading mark to initial count |
537 |
|
string _Str(_Numfields, '\0'); // one column counter for each field |
538 |
|
|
539 |
|
int _Ans = -2; // no candidates so far |
540 |
|
for (size_t _Column = 1; ; ++_Column, ++_First, _Ans = -1) |
541 |
|
{ // test each element against all viable fields |
542 |
|
bool _Prefix = false; // seen at least one valid prefix |
543 |
|
size_t _Off = 0; // offset into fields |
544 |
|
size_t _Field = 0; // current field number |
545 |
|
|
546 |
|
for (; _Field < _Numfields; ++_Field) |
547 |
|
{ // test element at _Column in field _Field |
548 |
|
for (; _Ptr[_Off] != (_Elem)0 && _Ptr[_Off] != _Ptr[0]; ++_Off) |
549 |
|
; // find beginning of field |
550 |
|
|
830 |
|
|
831 |
|
// STATIC codecvt::id OBJECT |
832 |
|
template<class _Elem, |
833 |
|
class _Byte, |
834 |
|
class _Statype> |
835 |
|
__PURE_APPDOMAIN_GLOBAL locale::id codecvt<_Elem, _Byte, _Statype>::id; |
836 |
|
|
837 |
|
// CLASS codecvt<wchar_t, char, _Mbstatet> |
838 |
|
template<> class _CRTIMP2_PURE codecvt<wchar_t, char, _Mbstatet> |
839 |
|
: public codecvt_base |
840 |
|
{ // facet for converting between wchar_t and char (_Byte) sequences |
841 |
|
public: |
842 |
|
typedef wchar_t _Elem; |
843 |
|
typedef char _Byte; |
844 |
|
typedef _Mbstatet _Statype; |
845 |
|
typedef _Elem intern_type; |
846 |
|
typedef _Byte extern_type; |
847 |
|
typedef _Statype state_type; |
848 |
|
|
849 |
|
result __CLR_OR_THIS_CALL in(_Statype& _State, |
850 |
|
const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1, |
851 |
|
_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const |
852 |
|
{ // convert bytes [_First1, _Last1) to [_First2, _Last) |
853 |
|
return (do_in(_State, |
854 |
|
_First1, _Last1, _Mid1, _First2, _Last2, _Mid2)); |
855 |
|
} |
856 |
|
|
857 |
|
result __CLR_OR_THIS_CALL out(_Statype& _State, |
858 |
|
const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1, |
859 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
860 |
|
{ // convert [_First1, _Last1) to bytes [_First2, _Last) |
861 |
|
return (do_out(_State, |
862 |
|
_First1, _Last1, _Mid1, _First2, _Last2, _Mid2)); |
863 |
|
} |
864 |
|
|
865 |
|
result __CLR_OR_THIS_CALL unshift(_Statype& _State, |
866 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
867 |
|
{ // generate bytes to return to default shift state |
868 |
|
return (do_unshift(_State, |
869 |
|
_First2, _Last2, _Mid2)); |
870 |
|
} |
871 |
|
|
872 |
|
int __CLR_OR_THIS_CALL length(const _Statype& _State, const _Byte *_First1, |
873 |
|
const _Byte *_Last1, size_t _Count) const |
874 |
|
{ // return min(_Count, converted length of bytes [_First1, _Last1)) |
875 |
|
return (do_length(_State, _First1, _Last1, _Count)); |
876 |
|
} |
877 |
|
|
878 |
|
static _MRTIMP2_NPURE locale::id& __cdecl _Id_func(); |
879 |
|
#ifdef _M_CEE_PURE |
880 |
|
static locale::id& id; // unique facet id |
881 |
|
#else |
882 |
|
__PURE_APPDOMAIN_GLOBAL static locale::id id; // unique facet id |
883 |
|
#endif |
884 |
|
|
885 |
|
explicit __CLR_OR_THIS_CALL codecvt(size_t _Refs = 0) |
886 |
|
: codecvt_base(_Refs) |
887 |
|
{ // construct from current locale |
888 |
|
_BEGIN_LOCINFO(_Lobj) |
889 |
|
_Init(_Lobj); |
890 |
|
_END_LOCINFO() |
891 |
|
} |
892 |
|
|
893 |
|
__CLR_OR_THIS_CALL codecvt(const _Locinfo& _Lobj, size_t _Refs = 0) |
894 |
|
: codecvt_base(_Refs) |
895 |
|
{ // construct from specified locale |
896 |
|
_Init(_Lobj); |
897 |
|
} |
898 |
|
|
899 |
|
static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0, |
900 |
|
const locale *_Ploc = 0) |
901 |
|
{ // return locale category mask and construct standard facet |
902 |
|
if (_Ppf != 0 && *_Ppf == 0) |
903 |
|
*_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>( |
904 |
|
_Locinfo(_Ploc->name())); |
905 |
|
return (_X_CTYPE); |
906 |
|
} |
907 |
|
|
908 |
|
_PROTECTED: |
909 |
|
virtual __CLR_OR_THIS_CALL ~codecvt() |
910 |
|
{ // destroy the object |
911 |
|
} |
912 |
|
|
913 |
|
protected: |
914 |
|
void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) |
915 |
|
{ // initialize from _Lobj |
916 |
|
_Cvt = _Lobj._Getcvt(); |
917 |
|
} |
918 |
|
|
919 |
|
virtual result __CLR_OR_THIS_CALL do_in(_Statype& _State, |
920 |
|
const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1, |
921 |
|
_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const |
922 |
|
{ // convert bytes [_First1, _Last1) to [_First2, _Last) |
923 |
|
_DEBUG_RANGE(_First1, _Last1); |
924 |
|
_DEBUG_RANGE(_First2, _Last2); |
925 |
|
_Mid1 = _First1, _Mid2 = _First2; |
926 |
|
result _Ans = _Mid1 == _Last1 ? ok : partial; |
927 |
|
int _Bytes; |
928 |
|
|
929 |
|
while (_Mid1 != _Last1 && _Mid2 != _Last2) |
930 |
|
switch (_Bytes = _Mbrtowc(_Mid2, _Mid1, _Last1 - _Mid1, |
931 |
|
&_State, &_Cvt)) |
932 |
|
{ // test result of locale-specific mbrtowc call |
933 |
|
case -2: // partial conversion |
934 |
|
_Mid1 = _Last1; |
935 |
|
return (_Ans); |
936 |
|
|
937 |
|
case -1: // failed conversion |
938 |
|
return (error); |
939 |
|
|
940 |
|
case 0: // may have converted null character |
941 |
|
if (*_Mid2 == (_Elem)0) |
942 |
|
_Bytes = (int)::strlen(_Mid1) + 1; |
943 |
|
// fall through |
944 |
|
|
945 |
|
default: // converted _Bytes bytes to a wchar_t |
946 |
|
if (_Bytes == -3) |
947 |
|
_Bytes = 0; // wchar_t generated from state info |
948 |
|
_Mid1 += _Bytes; |
949 |
|
++_Mid2; |
950 |
|
_Ans = ok; |
951 |
|
} |
952 |
|
return (_Ans); |
953 |
|
} |
954 |
|
|
955 |
|
virtual result __CLR_OR_THIS_CALL do_out(_Statype& _State, |
956 |
|
const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1, |
957 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
958 |
|
{ // convert [_First1, _Last1) to bytes [_First2, _Last) |
959 |
|
_DEBUG_RANGE(_First1, _Last1); |
960 |
|
_DEBUG_RANGE(_First2, _Last2); |
961 |
|
_Mid1 = _First1, _Mid2 = _First2; |
962 |
|
result _Ans = _Mid1 == _Last1 ? ok : partial; |
963 |
|
int _Bytes; |
964 |
|
|
965 |
|
while (_Mid1 != _Last1 && _Mid2 != _Last2) |
966 |
|
if ((int)MB_CUR_MAX <= _Last2 - _Mid2) |
967 |
|
if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1, |
968 |
|
&_State, &_Cvt)) < 0) |
969 |
|
return (error); // locale-specific wcrtomb failed |
970 |
|
else |
971 |
|
++_Mid1, _Mid2 += _Bytes, _Ans = ok; |
972 |
|
else |
973 |
|
{ // destination possibly too small, convert into buffer |
974 |
|
_Byte _Buf[MB_LEN_MAX]; |
975 |
|
_Statype _Stsave = _State; |
976 |
|
|
977 |
|
if ((_Bytes = _Wcrtomb(_Buf, *_Mid1, |
978 |
|
&_State, &_Cvt)) < 0) |
979 |
|
return (error); // locale-specific wcrtomb failed |
980 |
|
else if (_Last2 - _Mid2 < _Bytes) |
981 |
|
{ // converted too many, roll back and return previous |
982 |
|
_State = _Stsave; |
983 |
|
return (_Ans); |
984 |
|
} |
985 |
|
else |
986 |
|
{ // copy converted bytes from buffer |
987 |
|
_CRT_SECURE_MEMCPY(_Mid2, _Last2 - _Mid2, _Buf, _Bytes); |
988 |
|
++_Mid1, _Mid2 += _Bytes, _Ans = ok; |
989 |
|
} |
990 |
|
} |
991 |
|
return (_Ans); |
992 |
|
} |
993 |
|
|
994 |
|
virtual result __CLR_OR_THIS_CALL do_unshift(_Statype& _State, |
995 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
996 |
|
{ // generate bytes to return to default shift state |
997 |
|
_DEBUG_RANGE(_First2, _Last2); |
998 |
|
_Mid2 = _First2; |
999 |
|
result _Ans = ok; |
1000 |
|
int _Bytes; |
1001 |
|
_Byte _Buf[MB_LEN_MAX]; |
1002 |
|
_Statype _Stsave = _State; |
1003 |
|
|
1004 |
|
if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0) |
1005 |
|
_Ans = error; // locale-specific wcrtomb failed |
1006 |
|
else if (_Last2 - _Mid2 < --_Bytes) |
1007 |
|
{ // converted too many, roll back and return |
1008 |
|
_State = _Stsave; |
1009 |
|
_Ans = partial; |
1010 |
|
} |
1011 |
|
else if (0 < _Bytes) |
1012 |
|
{ // copy converted bytes from buffer |
1013 |
|
_CRT_SECURE_MEMCPY(_Mid2, _Last2 - _Mid2, _Buf, _Bytes); |
1014 |
|
_Mid2 += _Bytes; |
1015 |
|
} |
1016 |
|
return (_Ans); |
1017 |
|
} |
1018 |
|
|
1019 |
|
virtual int __CLR_OR_THIS_CALL do_length(const _Statype& _State, const _Byte *_First1, |
1020 |
|
const _Byte *_Last1, size_t _Count) const |
1021 |
|
{ // return min(_Count, converted length of bytes [_First1, _Last1)) |
1022 |
|
|
1023 |
|
#if _HAS_STRICT_CONFORMANCE |
1024 |
|
return ((int)(_Count < (size_t)(_Last1 - _First1) |
1025 |
|
? _Count : _Last1 - _First1)); // assume 1-to-1 conversion |
1026 |
|
|
1027 |
|
#else /* _HAS_STRICT_CONFORMANCE */ |
1028 |
|
_DEBUG_RANGE(_First1, _Last1); |
1029 |
|
int _Wchars; |
1030 |
|
const _Byte *_Mid1; |
1031 |
|
_Statype _Mystate = _State; |
1032 |
|
|
1033 |
|
for (_Wchars = 0, _Mid1 = _First1; |
1034 |
|
(size_t)_Wchars < _Count && _Mid1 != _Last1; ) |
1035 |
|
{ // convert another wchar_t |
1036 |
|
int _Bytes; |
1037 |
|
_Elem _Ch; |
1038 |
|
|
1039 |
|
switch (_Bytes = _Mbrtowc(&_Ch, _Mid1, _Last1 - _Mid1, |
1040 |
|
&_Mystate, &_Cvt)) |
1041 |
|
{ // test result of locale-specific mbrtowc call |
1042 |
|
case -2: // partial conversion |
1043 |
|
return (_Wchars); |
1044 |
|
|
1045 |
|
case -1: // failed conversion |
1046 |
|
return (_Wchars); |
1047 |
|
|
1048 |
|
case 0: // may have converted null character |
1049 |
|
if (_Ch == (_Elem)0) |
1050 |
|
_Bytes = (int)::strlen(_Mid1) + 1; |
1051 |
|
// fall through |
1052 |
|
|
1053 |
|
default: // converted _Bytes bytes to a wchar_t |
1054 |
|
if (_Bytes == -3) |
1055 |
|
_Bytes = 0; // wchar_t generated from state info |
1056 |
|
_Mid1 += _Bytes; |
1057 |
|
++_Wchars; |
1058 |
|
} |
1059 |
|
} |
1060 |
|
return (_Wchars); |
1061 |
|
#endif /* _HAS_STRICT_CONFORMANCE */ |
1062 |
|
} |
1063 |
|
|
1064 |
|
virtual bool __CLR_OR_THIS_CALL do_always_noconv() const _THROW0() |
1065 |
|
{ // return true if conversions never change input |
1066 |
|
return (false); |
1067 |
|
} |
1068 |
|
|
1069 |
|
virtual int __CLR_OR_THIS_CALL do_max_length() const _THROW0() |
1070 |
|
{ // return maximum length required for a conversion (from codecvt) |
1071 |
|
return (MB_LEN_MAX); |
1072 |
|
} |
1073 |
|
|
1074 |
|
private: |
1075 |
|
_Locinfo::_Cvtvec _Cvt; // locale info passed to _Mbrtowc, _Wcrtomb |
1076 |
|
}; |
1077 |
|
|
1078 |
|
#ifdef _NATIVE_WCHAR_T_DEFINED |
1079 |
|
// CLASS codecvt<unsigned short, char, _Mbstatet> |
1080 |
|
template<> class _CRTIMP2_PURE codecvt<unsigned short, char, _Mbstatet> |
1081 |
|
: public codecvt_base |
1082 |
|
{ // facet for converting between unsigned short and char sequences |
1083 |
|
public: |
1084 |
|
typedef unsigned short _Elem; |
1085 |
|
typedef char _Byte; |
1086 |
|
typedef _Mbstatet _Statype; |
1087 |
|
typedef _Elem intern_type; |
1088 |
|
typedef _Byte extern_type; |
1089 |
|
typedef _Statype state_type; |
1090 |
|
|
1091 |
|
result __CLR_OR_THIS_CALL in(_Statype& _State, |
1092 |
|
const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1, |
1093 |
|
_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const |
1094 |
|
{ // convert bytes [_First1, _Last1) to [_First2, _Last) |
1095 |
|
return (do_in(_State, |
1096 |
|
_First1, _Last1, _Mid1, _First2, _Last2, _Mid2)); |
1097 |
|
} |
1098 |
|
|
1099 |
|
result __CLR_OR_THIS_CALL out(_Statype& _State, |
1100 |
|
const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1, |
1101 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
1102 |
|
{ // convert [_First1, _Last1) to bytes [_First2, _Last) |
1103 |
|
return (do_out(_State, |
1104 |
|
_First1, _Last1, _Mid1, _First2, _Last2, _Mid2)); |
1105 |
|
} |
1106 |
|
|
1107 |
|
result __CLR_OR_THIS_CALL unshift(_Statype& _State, |
1108 |
|
_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const |
1109 |
|
{ // generate bytes to return to default shift state |
1110 |
|
return (do_unshift(_State, |
1111 |
|
_First2, _Last2, _Mid2)); |
1112 |
|
} |
1113 |
|
|
1114 |
|
int __CLR_OR_THIS_CALL length(const _Statype& _State, const _Byte *_First1, |
1115 |
|
const _Byte *_Last1, size_t _Count) const |
1116 |
|
{ // return min(_Count, converted length of bytes [_First1, _Last1)) |
1117 |
|
return (do_length(_State, _First1, _Last1, _Count)); |
1118 |
|
} |
1119 |
|
|
1120 |
|
static _MRTIMP2_NPURE locale::id& __cdecl _Id_func(); |
1121 |
|
#ifdef _M_CEE_PURE |
1122 |
|
static locale::id& id; // unique facet id |
1123 |
|
#else |
1124 |
|
__PURE_APPDOMAIN_GLOBAL static locale::id id; // unique facet id |
1125 |
|
#endif |
1126 |
|
|
1127 |
|
explicit __CLR_OR_THIS_CALL codecvt(size_t _Refs = 0) |
1128 |
|
: codecvt_base(_Refs) |
1129 |
|
{ // construct from current locale |
1130 |
|
_BEGIN_LOCINFO(_Lobj) |
1131 |
|
_Init(_Lobj); |
1132 |
|
_END_LOCINFO() |
1133 |
|
} |
1134 |
|
|
1135 |
|
__CLR_OR_THIS_CALL codecvt(const _Locinfo& _Lobj, size_t _Refs = 0) |
1136 |
|
: codecvt_base(_Refs) |
1137 |
|
{ // construct from specified locale |
1138 |
|
_Init(_Lobj); |
1139 |
|
} |
1140 |
|
|
1141 |
|
static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0, |
1142 |
|
const locale *_Ploc = 0) |
1143 |
|
{ // return locale category mask and construct standard facet |
1144 |
|
if (_Ppf != 0 && *_Ppf == 0) |
1145 |
|
*_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>( |
1146 |
|
_Locinfo(_Ploc->name())); |
1147 |
|
return (_X_CTYPE); |
1148 |
|
} |
1149 |
|
|
1150 |
|
_PROTECTED: |
1151 |
|
virtual __CLR_OR_THIS_CALL ~codecvt() |
1152 |
|
{ // destroy the object |
1153 |
|
} |
1154 |
|
|
1155 |
|
protected: |
1156 |
|
__CLR_OR_THIS_CALL codecvt(const char *_Locname, size_t _Refs = 0) |
1157 |
|
: codecvt_base(_Refs) |
1158 |
|
{ // construct from specified locale |
1159 |
|
_BEGIN_LOCINFO(_Lobj(_Locname)) |
1160 |
|
_Init(_Lobj); |
1161 |
|
_END_LOCINFO() |
1162 |
|
} |
1163 |
|
|
1164 |
|
void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) |
1165 |
|
{ // initialize from _Lobj |
1166 |
|
_Cvt = _Lobj._Getcvt(); |
1167 |
|
} |
1168 |
|
|
1169 |
|
virtual result __CLR_OR_THIS_CALL do_in(_Statype& _State, |
1170 |
|
const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1, |
1171 |
|
_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const |
1711 |
|
return (do_toupper(_First, _Last)); |
1712 |
|
} |
1713 |
|
|
1714 |
|
_Elem __CLR_OR_THIS_CALL widen(char _Byte) const |
1715 |
|
{ // widen char |
1716 |
|
return (do_widen(_Byte)); |
1717 |
|
} |
1718 |
|
|
1719 |
|
_SCL_INSECURE_DEPRECATE |
1720 |
|
const _Elem *__CLR_OR_THIS_CALL widen(const char *_First, const char *_Last, |
1721 |
|
_Elem *_Dest) const |
1722 |
|
{ // widen chars in [_First, _Last) |
1723 |
|
// assume there is enough space in _Dest |
1724 |
|
#pragma warning(push) |
1725 |
|
#pragma warning(disable:4996) |
1726 |
|
return (do_widen(_First, _Last, _Dest)); |
1727 |
|
#pragma warning(pop) |
1728 |
|
} |
1729 |
|
|
1730 |
|
const _Elem *__CLR_OR_THIS_CALL _Widen_s(const char *_First, const char *_Last, |
1731 |
|
_Elem *_Dest, size_t _Dest_size) const |
1732 |
|
{ // widen chars in [_First, _Last) |
1733 |
|
return (_Do_widen_s(_First, _Last, _Dest, _Dest_size)); |
1734 |
|
} |
1735 |
|
|
1736 |
|
_Elem __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const |
1737 |
|
{ // narrow element to char |
1738 |
|
return (do_narrow(_Ch, _Dflt)); |
1739 |
|
} |
1740 |
|
|
1741 |
|
_SCL_INSECURE_DEPRECATE |
1742 |
|
const _Elem *__CLR_OR_THIS_CALL narrow(const _Elem *_First, const _Elem *_Last, |
1743 |
|
char _Dflt, _Out_cap_x_(_Last-_First) char *_Dest) const |
1744 |
|
{ // narrow elements in [_First, _Last) to chars |
1745 |
|
// assume there is enough space in _Dest |
1746 |
|
#pragma warning(push) |
1747 |
|
#pragma warning(disable:4996) |
1748 |
|
return (do_narrow(_First, _Last, _Dflt, _Dest)); |
1749 |
|
#pragma warning(pop) |
1750 |
|
} |
1751 |
|
|
1752 |
|
const _Elem *__CLR_OR_THIS_CALL _Narrow_s(const _Elem *_First, const _Elem *_Last, |
1753 |
|
char _Dflt, _Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
1754 |
|
size_t _Dest_size) const |
1755 |
|
{ // narrow elements in [_First, _Last) to chars |
1756 |
|
return (_Do_narrow_s(_First, _Last, _Dflt, _Dest, _Dest_size)); |
1757 |
|
} |
1758 |
|
|
1759 |
|
static _MRTIMP2_NPURE locale::id& __cdecl _Id_func(); |
1760 |
|
#ifdef _M_CEE_PURE |
1761 |
|
static locale::id& id; // unique facet id |
1762 |
|
#else |
1763 |
|
__PURE_APPDOMAIN_GLOBAL static locale::id id; // unique facet id |
1764 |
|
#endif |
1765 |
|
|
1766 |
|
explicit __CLR_OR_THIS_CALL ctype(const mask *_Table = 0, |
1767 |
|
bool _Deletetable = false, |
1768 |
|
size_t _Refs = 0) |
1769 |
|
: ctype_base(_Refs) |
1770 |
|
{ // construct with specified table and delete flag for table |
1771 |
|
_BEGIN_LOCINFO(_Lobj) |
1772 |
|
_Init(_Lobj); |
1773 |
|
_END_LOCINFO() |
1774 |
|
if (_Table != 0) |
1775 |
|
{ // replace existing char to mask table |
1776 |
|
_Tidy(); |
1777 |
|
_Ctype._Table = _Table; |
1778 |
|
_Ctype._Delfl = _Deletetable ? -1 : 0; |
1779 |
|
} |
1780 |
|
} |
1781 |
|
|
1782 |
|
__CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) |
1783 |
|
: ctype_base(_Refs) |
1784 |
|
{ // construct from current locale |
1785 |
|
_Init(_Lobj); |
1786 |
|
} |
1787 |
|
|
1788 |
|
static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0, |
1789 |
|
const locale *_Ploc = 0) |
1790 |
|
{ // return locale category mask and construct standard facet |
1791 |
|
if (_Ppf != 0 && *_Ppf == 0) |
1792 |
|
*_Ppf = _NEW_CRT ctype<_Elem>( |
1793 |
|
_Locinfo(_Ploc->name())); |
1794 |
|
return (_X_CTYPE); |
1795 |
|
} |
1796 |
|
|
1797 |
|
_PGLOBAL static const size_t table_size = 1 << 8/*CHAR_BIT*/; // size of _Ctype._Table (char to mask) |
1798 |
|
|
1799 |
|
_PROTECTED: |
1800 |
|
virtual __CLR_OR_THIS_CALL ~ctype() |
1801 |
|
{ // destroy the object |
1802 |
|
_Tidy(); |
1803 |
|
} |
1804 |
|
|
1805 |
|
protected: |
1806 |
|
void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) |
1807 |
|
{ // initialize from _Lobj |
1808 |
|
_Ctype = _Lobj._Getctype(); |
1809 |
|
} |
1810 |
|
|
1811 |
|
void __CLR_OR_THIS_CALL _Tidy() |
1812 |
|
{ // free any allocated storage |
1813 |
|
if (0 < _Ctype._Delfl) |
1814 |
|
free((void *)_Ctype._Table); |
1815 |
|
else if (_Ctype._Delfl < 0) |
1816 |
|
delete[] (void *)_Ctype._Table; |
1817 |
|
} |
1818 |
|
|
1819 |
|
virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const |
1820 |
|
{ // convert element to lower case |
1821 |
|
return ((_Elem)_Tolower((unsigned char)_Ch, &_Ctype)); |
1822 |
|
} |
1823 |
|
|
1824 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_tolower(_Elem *_First, |
1825 |
|
const _Elem *_Last) const |
1826 |
|
{ // convert [_First, _Last) in place to lower case |
1827 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
1828 |
|
for (; _First != _Last; ++_First) |
1829 |
|
*_First = (_Elem)_Tolower((unsigned char)*_First, &_Ctype); |
1830 |
|
return ((const _Elem *)_First); |
1831 |
|
} |
1832 |
|
|
1833 |
|
virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const |
1834 |
|
{ // convert element to upper case |
1835 |
|
return ((_Elem)_Toupper((unsigned char)_Ch, &_Ctype)); |
1836 |
|
} |
1837 |
|
|
1838 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_toupper(_Elem *_First, |
1839 |
|
const _Elem *_Last) const |
1840 |
|
{ // convert [_First, _Last) in place to upper case |
1841 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
1842 |
|
for (; _First != _Last; ++_First) |
1843 |
|
*_First = (_Elem)_Toupper((unsigned char)*_First, &_Ctype); |
1844 |
|
return ((const _Elem *)_First); |
1845 |
|
} |
1846 |
|
|
1847 |
|
virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const |
1848 |
|
{ // widen char |
1849 |
|
return (_Byte); |
1850 |
|
} |
1851 |
|
|
1852 |
|
_SCL_INSECURE_DEPRECATE |
1853 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_widen(const char *_First, |
1854 |
|
const char *_Last, _Elem *_Dest) const |
1855 |
|
{ // widen chars in [_First, _Last) |
1856 |
|
// assume there is enough space in _Dest |
1857 |
|
return _Do_widen_s(_First, _Last, _Dest, _Last - _First); |
1858 |
|
} |
1859 |
|
|
1860 |
|
virtual const _Elem *__CLR_OR_THIS_CALL _Do_widen_s(const char *_First, |
1861 |
|
const char *_Last, _Elem *_Dest, size_t _Dest_size) const |
1862 |
|
{ // widen chars in [_First, _Last) |
1863 |
|
_DEBUG_RANGE(_First, _Last); |
1864 |
|
_DEBUG_POINTER(_Dest); |
1865 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
1866 |
|
_CRT_SECURE_MEMCPY(_Dest, _Dest_size, _First, _Last - _First); |
1867 |
|
return (_Last); |
1868 |
|
} |
1869 |
|
|
1870 |
|
virtual _Elem __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char) const |
1871 |
|
{ // narrow char |
1872 |
|
return (_Ch); |
1873 |
|
} |
1874 |
|
|
1875 |
|
_SCL_INSECURE_DEPRECATE |
1876 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_narrow(const _Elem *_First, |
1877 |
|
const _Elem *_Last, char _Dflt, |
1878 |
|
_Out_cap_x_(_Last-_First) char *_Dest) const |
1879 |
|
{ // narrow elements in [_First, _Last) to chars |
1880 |
|
// assume there is enough space in _Dest |
1881 |
|
return _Do_narrow_s(_First, _Last, _Dflt, _Dest, _Last - _First); |
1882 |
|
} |
1883 |
|
|
1884 |
|
virtual const _Elem *__CLR_OR_THIS_CALL _Do_narrow_s(const _Elem *_First, |
1885 |
|
const _Elem *_Last, char, _Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
1886 |
|
size_t _Dest_size) const |
1887 |
|
{ // narrow elements in [_First, _Last) to chars |
1888 |
|
_DEBUG_RANGE(_First, _Last); |
1889 |
|
_DEBUG_POINTER(_Dest); |
1890 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
1891 |
|
_CRT_SECURE_MEMCPY(_Dest, _Dest_size, _First, _Last - _First); |
1892 |
|
return (_Last); |
1893 |
|
} |
1894 |
|
|
1895 |
|
const mask *__CLR_OR_THIS_CALL table() const _THROW0() |
1896 |
|
{ // return address of char to mask table |
1897 |
|
return (_Ctype._Table); |
1898 |
|
} |
1899 |
|
|
1900 |
|
static const mask *__CLRCALL_OR_CDECL classic_table() _THROW0() |
1901 |
|
{ // return address of char to mask table for "C" locale |
1902 |
|
const _Myt& _Ctype_fac = _USE(locale::classic(), _Myt); |
1903 |
|
return (_Ctype_fac.table()); |
1904 |
|
} |
1905 |
|
|
1906 |
|
private: |
1907 |
|
_Locinfo::_Ctypevec _Ctype; // information |
1908 |
|
}; |
1909 |
|
|
1910 |
|
// CLASS ctype<wchar_t> |
1911 |
|
template<> class _CRTIMP2_PURE ctype<wchar_t> |
1912 |
|
: public ctype_base |
1913 |
|
{ // facet for classifying wchar_t elements, converting cases |
1914 |
|
typedef ctype<wchar_t> _Myt; |
1915 |
|
|
1916 |
|
public: |
1917 |
|
typedef wchar_t _Elem; |
1918 |
|
typedef _Elem char_type; |
1919 |
|
|
1920 |
|
bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const |
1921 |
|
{ // test if element fits any mask classifications |
1922 |
|
return (do_is(_Maskval, _Ch)); |
1923 |
|
} |
1924 |
|
|
1925 |
|
const _Elem *__CLR_OR_THIS_CALL is(const _Elem *_First, const _Elem *_Last, |
1926 |
|
mask *_Dest) const |
1927 |
|
{ // get mask sequence for elements in [_First, _Last) |
1928 |
|
return (do_is(_First, _Last, _Dest)); |
1929 |
|
} |
1930 |
|
|
1931 |
|
const _Elem *__CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem *_First, |
1932 |
|
const _Elem *_Last) const |
1933 |
|
{ // find first in [_First, _Last) that fits mask classification |
1934 |
|
return (do_scan_is(_Maskval, _First, _Last)); |
1935 |
|
} |
1936 |
|
|
1937 |
|
const _Elem *__CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem *_First, |
1938 |
|
const _Elem *_Last) const |
1939 |
|
{ // find first in [_First, _Last) not fitting mask classification |
1940 |
|
return (do_scan_not(_Maskval, _First, _Last)); |
1941 |
|
} |
1942 |
|
|
1943 |
|
_Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const |
1944 |
|
{ // convert element to lower case |
1945 |
|
return (do_tolower(_Ch)); |
1946 |
|
} |
1947 |
|
|
1948 |
|
const _Elem *__CLR_OR_THIS_CALL tolower(_Elem *_First, const _Elem *_Last) const |
1949 |
|
{ // convert [_First, _Last) in place to lower case |
1950 |
|
return (do_tolower(_First, _Last)); |
1951 |
|
} |
1952 |
|
|
1953 |
|
_Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const |
1954 |
|
{ // convert element to upper case |
1955 |
|
return (do_toupper(_Ch)); |
1956 |
|
} |
1957 |
|
|
1958 |
|
const _Elem *__CLR_OR_THIS_CALL toupper(_Elem *_First, const _Elem *_Last) const |
1959 |
|
{ // convert [_First, _Last) in place to upper case |
1960 |
|
return (do_toupper(_First, _Last)); |
1961 |
|
} |
1962 |
|
|
1963 |
|
_Elem __CLR_OR_THIS_CALL widen(char _Byte) const |
1964 |
|
{ // widen char |
1965 |
|
return (do_widen(_Byte)); |
1966 |
|
} |
1967 |
|
|
1968 |
|
_SCL_INSECURE_DEPRECATE |
1969 |
|
const char *__CLR_OR_THIS_CALL widen(const char *_First, const char *_Last, |
1970 |
|
_Elem *_Dest) const |
1971 |
|
{ // widen chars in [_First, _Last) |
1972 |
|
// assume there is enough space in _Dest |
1973 |
|
#pragma warning(push) |
1974 |
|
#pragma warning(disable:4996) |
1975 |
|
return (do_widen(_First, _Last, _Dest)); |
1976 |
|
#pragma warning(pop) |
1977 |
|
} |
1978 |
|
|
1979 |
|
const char *__CLR_OR_THIS_CALL _Widen_s(const char *_First, const char *_Last, |
1980 |
|
_Elem *_Dest, size_t _Dest_size) const |
1981 |
|
{ // widen chars in [_First, _Last) |
1982 |
|
return (_Do_widen_s(_First, _Last, _Dest, _Dest_size)); |
1983 |
|
} |
1984 |
|
|
1985 |
|
char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const |
1986 |
|
{ // narrow element to char |
1987 |
|
return (do_narrow(_Ch, _Dflt)); |
1988 |
|
} |
1989 |
|
|
1990 |
|
_SCL_INSECURE_DEPRECATE |
1991 |
|
const _Elem *__CLR_OR_THIS_CALL narrow(const _Elem *_First, const _Elem *_Last, |
1992 |
|
char _Dflt, _Out_cap_x_(_Last-_First) char *_Dest) const |
1993 |
|
{ // narrow elements in [_First, _Last) to chars |
1994 |
|
// assume there is enough space in _Dest |
1995 |
|
#pragma warning(push) |
1996 |
|
#pragma warning(disable:4996) |
1997 |
|
return (do_narrow(_First, _Last, _Dflt, _Dest)); |
1998 |
|
#pragma warning(pop) |
1999 |
|
} |
2000 |
|
|
2001 |
|
const _Elem *__CLR_OR_THIS_CALL _Narrow_s(const _Elem *_First, const _Elem *_Last, |
2002 |
|
char _Dflt, _Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
2003 |
|
size_t _Dest_size) const |
2004 |
|
{ // narrow elements in [_First, _Last) to chars |
2005 |
|
return (_Do_narrow_s(_First, _Last, _Dflt, _Dest, _Dest_size)); |
2006 |
|
} |
2007 |
|
|
2008 |
|
static _MRTIMP2_NPURE locale::id& __cdecl _Id_func(); |
2009 |
|
#ifdef _M_CEE_PURE |
2010 |
|
static locale::id& id; // unique facet id |
2011 |
|
#else |
2012 |
|
__PURE_APPDOMAIN_GLOBAL static locale::id id; // unique facet id |
2013 |
|
#endif |
2014 |
|
|
2015 |
|
explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) |
2016 |
|
: ctype_base(_Refs) |
2017 |
|
{ // construct from current locale |
2018 |
|
_BEGIN_LOCINFO(_Lobj) |
2019 |
|
_Init(_Lobj); |
2020 |
|
_END_LOCINFO() |
2021 |
|
} |
2022 |
|
|
2023 |
|
__CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) |
2024 |
|
: ctype_base(_Refs) |
2025 |
|
{ // construct from specified locale |
2026 |
|
_Init(_Lobj); |
2027 |
|
} |
2028 |
|
|
2029 |
|
static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0, |
2030 |
|
const locale *_Ploc = 0) |
2031 |
|
{ // return locale category mask and construct standard facet |
2032 |
|
if (_Ppf != 0 && *_Ppf == 0) |
2033 |
|
*_Ppf = _NEW_CRT ctype<_Elem>( |
2034 |
|
_Locinfo(_Ploc->name())); |
2035 |
|
return (_X_CTYPE); |
2036 |
|
} |
2037 |
|
|
2038 |
|
_PROTECTED: |
2039 |
|
virtual __CLR_OR_THIS_CALL ~ctype() |
2040 |
|
{ // destroy the object |
2041 |
|
if (_Ctype._Delfl) |
2042 |
|
free((void *)_Ctype._Table); |
2043 |
|
} |
2044 |
|
|
2045 |
|
protected: |
2046 |
|
void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) |
2047 |
|
{ // initialize from _Lobj |
2048 |
|
_Ctype = _Lobj._Getctype(); |
2049 |
|
_Cvt = _Lobj._Getcvt(); |
2050 |
|
} |
2051 |
|
|
2052 |
|
virtual bool __CLR_OR_THIS_CALL do_is(mask _Maskval, _Elem _Ch) const |
2053 |
|
{ // test if element fits any mask classifications |
2054 |
|
return ((::_Getwctype(_Ch, &_Ctype) & _Maskval) != 0); |
2055 |
|
} |
2056 |
|
|
2057 |
|
virtual const wchar_t *__CLR_OR_THIS_CALL do_is(const _Elem *_First, |
2058 |
|
const _Elem *_Last, mask *_Dest) const |
2059 |
|
{ // get mask sequence for elements in [_First, _Last) |
2060 |
|
_DEBUG_RANGE(_First, _Last); |
2061 |
|
_DEBUG_POINTER(_Dest); |
2062 |
|
return (::_Getwctypes(_First, _Last, _Dest, &_Ctype)); |
2063 |
|
} |
2064 |
|
|
2065 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_scan_is(mask _Maskval, |
2066 |
|
const _Elem *_First, const _Elem *_Last) const |
2067 |
|
{ // find first in [_First, _Last) that fits mask classification |
2068 |
|
_DEBUG_RANGE(_First, _Last); |
2069 |
|
for (; _First != _Last && !is(_Maskval, *_First); ++_First) |
2070 |
|
; |
2071 |
|
return (_First); |
2072 |
|
} |
2073 |
|
|
2074 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_scan_not(mask _Maskval, |
2075 |
|
const _Elem *_First, const _Elem *_Last) const |
2076 |
|
{ // find first in [_First, _Last) not fitting mask classification |
2077 |
|
_DEBUG_RANGE(_First, _Last); |
2078 |
|
for (; _First != _Last && is(_Maskval, *_First); ++_First) |
2079 |
|
; |
2080 |
|
return (_First); |
2081 |
|
} |
2082 |
|
|
2083 |
|
virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const |
2084 |
|
{ // convert element to lower case |
2085 |
|
return (_Towlower(_Ch, &_Ctype)); |
2086 |
|
} |
2087 |
|
|
2088 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_tolower(_Elem *_First, |
2089 |
|
const _Elem *_Last) const |
2090 |
|
{ // convert [_First, _Last) in place to lower case |
2091 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
2092 |
|
for (; _First != _Last; ++_First) |
2093 |
|
*_First = _Towlower(*_First, &_Ctype); |
2094 |
|
return ((const _Elem *)_First); |
2095 |
|
} |
2096 |
|
|
2097 |
|
virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const |
2098 |
|
{ // convert element to upper case |
2099 |
|
return (_Towupper(_Ch, &_Ctype)); |
2100 |
|
} |
2101 |
|
|
2102 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_toupper(_Elem *_First, |
2103 |
|
const _Elem *_Last) const |
2104 |
|
{ // convert [_First, _Last) in place to upper case |
2105 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
2106 |
|
for (; _First != _Last; ++_First) |
2107 |
|
*_First = _Towupper(*_First, &_Ctype); |
2108 |
|
return ((const _Elem *)_First); |
2109 |
|
} |
2110 |
|
|
2111 |
|
_Elem __CLR_OR_THIS_CALL _Dowiden(char _Byte) const |
2112 |
|
{ // widen char |
2113 |
|
_Mbstinit(_Mbst); |
2114 |
|
wchar_t _Wc; |
2115 |
|
return (_Mbrtowc(&_Wc, &_Byte, 1, &_Mbst, &_Cvt) < 0 |
2116 |
|
? (wchar_t)WEOF : _Wc); |
2117 |
|
} |
2118 |
|
|
2119 |
|
virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const |
2120 |
|
{ // widen char |
2121 |
|
return (_Dowiden(_Byte)); |
2122 |
|
} |
2123 |
|
|
2124 |
|
_SCL_INSECURE_DEPRECATE |
2125 |
|
virtual const char *__CLR_OR_THIS_CALL do_widen(const char *_First, |
2126 |
|
const char *_Last, _Elem *_Dest) const |
2127 |
|
{ // widen chars in [_First, _Last) |
2128 |
|
// assume there is enough space in _Dest |
2129 |
|
return _Do_widen_s(_First, _Last, _Dest, _Last - _First); |
2130 |
|
} |
2131 |
|
|
2132 |
|
virtual const char *__CLR_OR_THIS_CALL _Do_widen_s(const char *_First, |
2133 |
|
const char *_Last, _Elem *_Dest, size_t _Dest_size) const |
2134 |
|
{ // widen chars in [_First, _Last) |
2135 |
|
_DEBUG_RANGE(_First, _Last); |
2136 |
|
_DEBUG_POINTER(_Dest); |
2137 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
2138 |
|
for (; _First != _Last; ++_First, ++_Dest) |
2139 |
|
*_Dest = _Dowiden(*_First); |
2140 |
|
return (_First); |
2141 |
|
} |
2142 |
|
|
2143 |
|
char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const |
2144 |
|
{ // narrow element to char |
2145 |
|
char _Buf[MB_LEN_MAX]; |
2146 |
|
_Mbstinit(_Mbst); |
2147 |
|
return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1 |
2148 |
|
? _Dflt : _Buf[0]); |
2149 |
|
} |
2150 |
|
|
2151 |
|
virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const |
2152 |
|
{ // narrow element to char |
2153 |
|
return (_Donarrow(_Ch, _Dflt)); |
2154 |
|
} |
2155 |
|
|
2156 |
|
_SCL_INSECURE_DEPRECATE |
2157 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_narrow(const _Elem *_First, |
2158 |
|
const _Elem *_Last, char _Dflt, |
2159 |
|
_Out_cap_x_(_Last-_First) char *_Dest) const |
2160 |
|
{ // narrow elements in [_First, _Last) to chars |
2161 |
|
// assume there is enough space in _Dest |
2162 |
|
return _Do_narrow_s(_First, _Last, _Dflt, _Dest, _Last - _First); |
2163 |
|
} |
2164 |
|
|
2165 |
|
virtual const _Elem *__CLR_OR_THIS_CALL _Do_narrow_s(const _Elem *_First, |
2166 |
|
const _Elem *_Last, char _Dflt, |
2167 |
|
_Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
2168 |
|
size_t _Dest_size) const |
2169 |
|
{ // narrow elements in [_First, _Last) to chars |
2170 |
|
_DEBUG_RANGE(_First, _Last); |
2171 |
|
_DEBUG_POINTER(_Dest); |
2172 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
2173 |
|
for (; _First != _Last; ++_First, ++_Dest) |
2174 |
|
*_Dest = _Donarrow(*_First, _Dflt); |
2175 |
|
return (_First); |
2176 |
|
} |
2177 |
|
|
2178 |
|
private: |
2179 |
|
_Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. |
2180 |
|
_Locinfo::_Cvtvec _Cvt; // conversion information |
2181 |
|
}; |
2182 |
|
|
2183 |
|
#ifdef _NATIVE_WCHAR_T_DEFINED |
2184 |
|
// CLASS ctype<unsigned short> |
2185 |
|
template<> class _CRTIMP2_PURE ctype<unsigned short> |
2186 |
|
: public ctype_base |
2187 |
|
{ // facet for classifying unsigned short elements, converting cases |
2188 |
|
typedef ctype<unsigned short> _Myt; |
2189 |
|
|
2190 |
|
public: |
2191 |
|
typedef unsigned short _Elem; |
2192 |
|
typedef _Elem char_type; |
2193 |
|
|
2194 |
|
bool __CLR_OR_THIS_CALL is(mask _Maskval, _Elem _Ch) const |
2195 |
|
{ // test if element fits any mask classifications |
2196 |
|
return (do_is(_Maskval, _Ch)); |
2197 |
|
} |
2198 |
|
|
2199 |
|
const _Elem *__CLR_OR_THIS_CALL is(const _Elem *_First, const _Elem *_Last, |
2200 |
|
mask *_Dest) const |
2201 |
|
{ // get mask sequence for elements in [_First, _Last) |
2202 |
|
return (do_is(_First, _Last, _Dest)); |
2203 |
|
} |
2204 |
|
|
2205 |
|
const _Elem *__CLR_OR_THIS_CALL scan_is(mask _Maskval, const _Elem *_First, |
2206 |
|
const _Elem *_Last) const |
2207 |
|
{ // find first in [_First, _Last) that fits mask classification |
2208 |
|
return (do_scan_is(_Maskval, _First, _Last)); |
2209 |
|
} |
2210 |
|
|
2211 |
|
const _Elem *__CLR_OR_THIS_CALL scan_not(mask _Maskval, const _Elem *_First, |
2212 |
|
const _Elem *_Last) const |
2213 |
|
{ // find first in [_First, _Last) not fitting mask classification |
2214 |
|
return (do_scan_not(_Maskval, _First, _Last)); |
2215 |
|
} |
2216 |
|
|
2217 |
|
_Elem __CLR_OR_THIS_CALL tolower(_Elem _Ch) const |
2218 |
|
{ // convert element to lower case |
2219 |
|
return (do_tolower(_Ch)); |
2220 |
|
} |
2221 |
|
|
2222 |
|
const _Elem *__CLR_OR_THIS_CALL tolower(_Elem *_First, const _Elem *_Last) const |
2223 |
|
{ // convert [_First, _Last) in place to lower case |
2224 |
|
return (do_tolower(_First, _Last)); |
2225 |
|
} |
2226 |
|
|
2227 |
|
_Elem __CLR_OR_THIS_CALL toupper(_Elem _Ch) const |
2228 |
|
{ // convert element to upper case |
2229 |
|
return (do_toupper(_Ch)); |
2230 |
|
} |
2231 |
|
|
2232 |
|
const _Elem *__CLR_OR_THIS_CALL toupper(_Elem *_First, const _Elem *_Last) const |
2233 |
|
{ // convert [_First, _Last) in place to upper case |
2234 |
|
return (do_toupper(_First, _Last)); |
2235 |
|
} |
2236 |
|
|
2237 |
|
_Elem __CLR_OR_THIS_CALL widen(char _Byte) const |
2238 |
|
{ // widen char |
2239 |
|
return (do_widen(_Byte)); |
2240 |
|
} |
2241 |
|
|
2242 |
|
_SCL_INSECURE_DEPRECATE |
2243 |
|
const char *__CLR_OR_THIS_CALL widen(const char *_First, const char *_Last, |
2244 |
|
_Elem *_Dest) const |
2245 |
|
{ // widen chars in [_First, _Last) |
2246 |
|
// assume there is enough space in _Dest |
2247 |
|
#pragma warning(push) |
2248 |
|
#pragma warning(disable:4996) |
2249 |
|
return (do_widen(_First, _Last, _Dest)); |
2250 |
|
#pragma warning(pop) |
2251 |
|
} |
2252 |
|
|
2253 |
|
const char *__CLR_OR_THIS_CALL _Widen_s(const char *_First, const char *_Last, |
2254 |
|
_Elem *_Dest, size_t _Dest_size) const |
2255 |
|
{ // widen chars in [_First, _Last) |
2256 |
|
return (_Do_widen_s(_First, _Last, _Dest, _Dest_size)); |
2257 |
|
} |
2258 |
|
|
2259 |
|
char __CLR_OR_THIS_CALL narrow(_Elem _Ch, char _Dflt = '\0') const |
2260 |
|
{ // narrow element to char |
2261 |
|
return (do_narrow(_Ch, _Dflt)); |
2262 |
|
} |
2263 |
|
|
2264 |
|
_SCL_INSECURE_DEPRECATE |
2265 |
|
const _Elem *__CLR_OR_THIS_CALL narrow(const _Elem *_First, const _Elem *_Last, |
2266 |
|
char _Dflt, _Out_cap_x_(_Last-_First) char *_Dest) const |
2267 |
|
{ // narrow elements in [_First, _Last) to chars |
2268 |
|
// assume there is enough space in _Dest |
2269 |
|
#pragma warning(push) |
2270 |
|
#pragma warning(disable:4996) |
2271 |
|
return (do_narrow(_First, _Last, _Dflt, _Dest)); |
2272 |
|
#pragma warning(pop) |
2273 |
|
} |
2274 |
|
|
2275 |
|
const _Elem *__CLR_OR_THIS_CALL _Narrow_s(const _Elem *_First, const _Elem *_Last, |
2276 |
|
char _Dflt, _Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
2277 |
|
size_t _Dest_size) const |
2278 |
|
{ // narrow elements in [_First, _Last) to chars |
2279 |
|
return (_Do_narrow_s(_First, _Last, _Dflt, _Dest, _Dest_size)); |
2280 |
|
} |
2281 |
|
|
2282 |
|
static _MRTIMP2_NPURE locale::id& __cdecl _Id_func(); |
2283 |
|
#ifdef _M_CEE_PURE |
2284 |
|
static locale::id& id; // unique facet id |
2285 |
|
#else |
2286 |
|
__PURE_APPDOMAIN_GLOBAL static locale::id id; // unique facet id |
2287 |
|
#endif |
2288 |
|
|
2289 |
|
explicit __CLR_OR_THIS_CALL ctype(size_t _Refs = 0) |
2290 |
|
: ctype_base(_Refs) |
2291 |
|
{ // construct from current locale |
2292 |
|
_BEGIN_LOCINFO(_Lobj) |
2293 |
|
_Init(_Lobj); |
2294 |
|
_END_LOCINFO() |
2295 |
|
} |
2296 |
|
|
2297 |
|
__CLR_OR_THIS_CALL ctype(const _Locinfo& _Lobj, size_t _Refs = 0) |
2298 |
|
: ctype_base(_Refs) |
2299 |
|
{ // construct from specified locale |
2300 |
|
_Init(_Lobj); |
2301 |
|
} |
2302 |
|
|
2303 |
|
static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0, |
2304 |
|
const locale *_Ploc = 0) |
2305 |
|
{ // return locale category mask and construct standard facet |
2306 |
|
if (_Ppf != 0 && *_Ppf == 0) |
2307 |
|
*_Ppf = _NEW_CRT ctype<_Elem>( |
2308 |
|
_Locinfo(_Ploc->name())); |
2309 |
|
return (_X_CTYPE); |
2310 |
|
} |
2311 |
|
|
2312 |
|
_PROTECTED: |
2313 |
|
virtual __CLR_OR_THIS_CALL ~ctype() |
2314 |
|
{ // destroy the object |
2315 |
|
if (_Ctype._Delfl) |
2316 |
|
free((void *)_Ctype._Table); |
2317 |
|
} |
2318 |
|
|
2319 |
|
protected: |
2320 |
|
__CLR_OR_THIS_CALL ctype(const char *_Locname, size_t _Refs = 0) |
2321 |
|
: ctype_base(_Refs) |
2322 |
|
{ // construct from specified locale |
2323 |
|
_BEGIN_LOCINFO(_Lobj(_Locname)) |
2324 |
|
_Init(_Lobj); |
2325 |
|
_END_LOCINFO() |
2326 |
|
} |
2327 |
|
|
2328 |
|
void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj) |
2329 |
|
{ // initialize from _Lobj |
2330 |
|
_Ctype = _Lobj._Getctype(); |
2331 |
|
_Cvt = _Lobj._Getcvt(); |
2332 |
|
} |
2333 |
|
|
2334 |
|
virtual bool __CLR_OR_THIS_CALL do_is(mask _Maskval, _Elem _Ch) const |
2335 |
|
{ // test if element fits any mask classifications |
2336 |
|
return ((::_Getwctype(_Ch, &_Ctype) & _Maskval) != 0); |
2337 |
|
} |
2338 |
|
|
2339 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_is(const _Elem *_First, |
2340 |
|
const _Elem *_Last, mask *_Dest) const |
2341 |
|
{ // get mask sequence for elements in [_First, _Last) |
2342 |
|
_DEBUG_RANGE(_First, _Last); |
2343 |
|
_DEBUG_POINTER(_Dest); |
2344 |
|
return ((const _Elem *)::_Getwctypes((const wchar_t *)_First, |
2345 |
|
(const wchar_t *)_Last, _Dest, &_Ctype)); |
2346 |
|
} |
2347 |
|
|
2348 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_scan_is(mask _Maskval, |
2349 |
|
const _Elem *_First, const _Elem *_Last) const |
2350 |
|
{ // find first in [_First, _Last) that fits mask classification |
2351 |
|
_DEBUG_RANGE(_First, _Last); |
2352 |
|
for (; _First != _Last && !is(_Maskval, *_First); ++_First) |
2353 |
|
; |
2354 |
|
return (_First); |
2355 |
|
} |
2356 |
|
|
2357 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_scan_not(mask _Maskval, |
2358 |
|
const _Elem *_First, const _Elem *_Last) const |
2359 |
|
{ // find first in [_First, _Last) not fitting mask classification |
2360 |
|
_DEBUG_RANGE(_First, _Last); |
2361 |
|
for (; _First != _Last && is(_Maskval, *_First); ++_First) |
2362 |
|
; |
2363 |
|
return (_First); |
2364 |
|
} |
2365 |
|
|
2366 |
|
virtual _Elem __CLR_OR_THIS_CALL do_tolower(_Elem _Ch) const |
2367 |
|
{ // convert element to lower case |
2368 |
|
return (_Towlower(_Ch, &_Ctype)); |
2369 |
|
} |
2370 |
|
|
2371 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_tolower(_Elem *_First, |
2372 |
|
const _Elem *_Last) const |
2373 |
|
{ // convert [_First, _Last) in place to lower case |
2374 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
2375 |
|
for (; _First != _Last; ++_First) |
2376 |
|
*_First = _Towlower(*_First, &_Ctype); |
2377 |
|
return ((const _Elem *)_First); |
2378 |
|
} |
2379 |
|
|
2380 |
|
virtual _Elem __CLR_OR_THIS_CALL do_toupper(_Elem _Ch) const |
2381 |
|
{ // convert element to upper case |
2382 |
|
return (_Towupper(_Ch, &_Ctype)); |
2383 |
|
} |
2384 |
|
|
2385 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_toupper(_Elem *_First, |
2386 |
|
const _Elem *_Last) const |
2387 |
|
{ // convert [_First, _Last) in place to upper case |
2388 |
|
_DEBUG_RANGE((const _Elem *)_First, _Last); |
2389 |
|
for (; _First != _Last; ++_First) |
2390 |
|
*_First = _Towupper(*_First, &_Ctype); |
2391 |
|
return ((const _Elem *)_First); |
2392 |
|
} |
2393 |
|
|
2394 |
|
_Elem __CLR_OR_THIS_CALL _Dowiden(char _Byte) const |
2395 |
|
{ // widen char |
2396 |
|
_Mbstinit(_Mbst); |
2397 |
|
unsigned short _Wc; |
2398 |
|
return (_Mbrtowc((wchar_t *)&_Wc, &_Byte, 1, &_Mbst, &_Cvt) < 0 |
2399 |
|
? (unsigned short)WEOF : _Wc); |
2400 |
|
} |
2401 |
|
|
2402 |
|
virtual _Elem __CLR_OR_THIS_CALL do_widen(char _Byte) const |
2403 |
|
{ // widen char |
2404 |
|
return (_Dowiden(_Byte)); |
2405 |
|
} |
2406 |
|
|
2407 |
|
_SCL_INSECURE_DEPRECATE |
2408 |
|
virtual const char *__CLR_OR_THIS_CALL do_widen(const char *_First, |
2409 |
|
const char *_Last, _Elem *_Dest) const |
2410 |
|
{ // widen chars in [_First, _Last) |
2411 |
|
// assume there is enough space in _Dest |
2412 |
|
return _Do_widen_s(_First, _Last, _Dest, _Last - _First); |
2413 |
|
} |
2414 |
|
|
2415 |
|
virtual const char *__CLR_OR_THIS_CALL _Do_widen_s(const char *_First, |
2416 |
|
const char *_Last, _Elem *_Dest, size_t _Dest_size) const |
2417 |
|
{ // widen chars in [_First, _Last) |
2418 |
|
_DEBUG_RANGE(_First, _Last); |
2419 |
|
_DEBUG_POINTER(_Dest); |
2420 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
2421 |
|
for (; _First != _Last; ++_First, ++_Dest) |
2422 |
|
*_Dest = _Dowiden(*_First); |
2423 |
|
return (_First); |
2424 |
|
} |
2425 |
|
|
2426 |
|
char __CLR_OR_THIS_CALL _Donarrow(_Elem _Ch, char _Dflt) const |
2427 |
|
{ // narrow element to char |
2428 |
|
char _Buf[MB_LEN_MAX]; |
2429 |
|
_Mbstinit(_Mbst); |
2430 |
|
return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1 |
2431 |
|
? _Dflt : _Buf[0]); |
2432 |
|
} |
2433 |
|
|
2434 |
|
virtual char __CLR_OR_THIS_CALL do_narrow(_Elem _Ch, char _Dflt) const |
2435 |
|
{ // narrow element to char |
2436 |
|
return (_Donarrow(_Ch, _Dflt)); |
2437 |
|
} |
2438 |
|
|
2439 |
|
_SCL_INSECURE_DEPRECATE |
2440 |
|
virtual const _Elem *__CLR_OR_THIS_CALL do_narrow(const _Elem *_First, |
2441 |
|
const _Elem *_Last, char _Dflt, _Out_cap_x_(_Last-_First) char *_Dest) const |
2442 |
|
{ // narrow elements in [_First, _Last) to chars |
2443 |
|
// assume there is enough space in _Dest |
2444 |
|
return _Do_narrow_s(_First, _Last, _Dflt, _Dest, _Last - _First); |
2445 |
|
} |
2446 |
|
|
2447 |
|
virtual const _Elem *__CLR_OR_THIS_CALL _Do_narrow_s(const _Elem *_First, |
2448 |
|
const _Elem *_Last, char _Dflt, |
2449 |
|
_Out_cap_(_Dest_size) _Post_count_x_( _Last-_First) char *_Dest, |
2450 |
|
size_t _Dest_size) const |
2451 |
|
{ // narrow elements in [_First, _Last) to chars |
2452 |
|
_DEBUG_RANGE(_First, _Last); |
2453 |
|
_DEBUG_POINTER(_Dest); |
2454 |
|
_SCL_SECURE_ALWAYS_VALIDATE_RANGE(_Dest_size >= (size_t)(_Last - _First)); |
2455 |
|
for (; _First != _Last; ++_First, ++_Dest) |
2456 |
|
*_Dest = _Donarrow(*_First, _Dflt); |
2457 |
|
return (_First); |
2458 |
|
} |
2459 |
|
|
2460 |
|
private: |
2461 |
|
_Locinfo::_Ctypevec _Ctype; // locale info passed to _Tolower, etc. |
2462 |
|
_Locinfo::_Cvtvec _Cvt; // conversion information |
2463 |
|
}; |
2464 |
|
#endif /* _NATIVE_WCHAR_T_DEFINED */ |
2465 |
|
|
2466 |
|
// TEMPLATE CLASS ctype_byname |
2467 |
|
template<class _Elem> |
2468 |
|
class ctype_byname |
2469 |
|
: public ctype<_Elem> |
2470 |
|
{ // ctype for named locale |
2471 |
|
public: |
2472 |
|
explicit __CLR_OR_THIS_CALL ctype_byname(const char *_Locname, size_t _Refs = 0) |
2473 |
|
: ctype<_Elem>(_Locname, _Refs) |
2474 |
|
{ // construct from named locale |
2475 |
|
} |
2476 |
|
|
2477 |
|
_PROTECTED: |
2478 |
|
virtual __CLR_OR_THIS_CALL ~ctype_byname() |
2479 |
|
{ // destroy the object |
2480 |
|
} |
2481 |
|
}; |
2482 |
|
|
2483 |
|
// TEMPLATE CLASS ctype_byname<char> |
2484 |
|
template<> class ctype_byname<char> |
2485 |
|
: public ctype<char> |
2486 |
|
{ // ctype_byname<char> for named locale |
2487 |
|
public: |
2488 |
|
explicit __CLR_OR_THIS_CALL ctype_byname(const char *_Locname, size_t _Refs = 0) |
2489 |
|
: ctype<char>(_Locname, _Refs) |
2490 |
|
{ // construct from named locale |
2491 |
|
} |
2492 |
|
|
2493 |
|
_PROTECTED: |
2494 |
|
virtual __CLR_OR_THIS_CALL ~ctype_byname() |
2495 |
|
{ // destroy the object |
2496 |
|
} |
2497 |
|
}; |
2498 |
|
|
2499 |
|
#if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE) |
2500 |
|
|
2501 |
|
template class _CRTIMP2_PURE codecvt<char, char, _Mbstatet>; |
2502 |
|
|
2503 |
|
#endif /* _DLL_CPPLIB */ |
2504 |
|
_STD_END |
2505 |
|
|
2506 |
|
#ifdef _MSC_VER |
2507 |
|
#pragma warning(pop) |
2508 |
|
#pragma pack(pop) |
2509 |
|
#endif /* _MSC_VER */ |
2510 |
|
|
2511 |
|
#endif /* RC_INVOKED */ |
2512 |
|
#endif /* _XLOCALE_ */ |
2513 |
|
|
2514 |
|
/* |
2515 |
|
* Copyright (c) 1992-2007 by P.J. Plauger. ALL RIGHTS RESERVED. |
2516 |
|
* Consult your license regarding permissions and restrictions. |
2517 |
|
V5.03:0009 */ |
2518 |
|
|
|
|
|