msvcp60: Fixed num_put::fput implementation.
[wine] / dlls / msvcp60 / locale.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #include "msvcp.h"
24 #include "locale.h"
25 #include "errno.h"
26 #include "limits.h"
27 #include "math.h"
28 #include "stdio.h"
29
30 #include "wine/list.h"
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
38
39 char* __cdecl _Getdays(void);
40 char* __cdecl _Getmonths(void);
41 void* __cdecl _Gettnames(void);
42 unsigned int __cdecl ___lc_codepage_func(void);
43 LCID* __cdecl ___lc_handle_func(void);
44 static const locale_facet* locale__Getfacet(const locale*, MSVCP_size_t);
45
46 typedef int category;
47
48 typedef struct _locale__Locimp {
49     locale_facet facet;
50     locale_facet **facetvec;
51     MSVCP_size_t facet_cnt;
52     category catmask;
53     MSVCP_bool transparent;
54     basic_string_char name;
55 } locale__Locimp;
56
57 typedef struct {
58     void *timeptr;
59 } _Timevec;
60
61 typedef struct {
62     _Lockit lock;
63     basic_string_char days;
64     basic_string_char months;
65     basic_string_char oldlocname;
66     basic_string_char newlocname;
67 } _Locinfo;
68
69 typedef struct {
70     LCID handle;
71     unsigned page;
72 } _Collvec;
73
74 typedef struct {
75     locale_facet facet;
76     _Collvec coll;
77 } collate;
78
79 typedef struct {
80     locale_facet facet;
81     const char *grouping;
82     char dp;
83     char sep;
84     const char *false_name;
85     const char *true_name;
86 } numpunct_char;
87
88 typedef struct {
89     locale_facet facet;
90     const char *grouping;
91     wchar_t dp;
92     wchar_t sep;
93     const wchar_t *false_name;
94     const wchar_t *true_name;
95 } numpunct_wchar;
96
97 /* ?_Id_cnt@id@locale@std@@0HA */
98 int locale_id__Id_cnt = 0;
99
100 static locale__Locimp *global_locale;
101 static locale classic_locale;
102
103 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
104 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
105 locale__Locimp *locale__Locimp__Clocptr = NULL;
106
107 static char istreambuf_iterator_char_val(istreambuf_iterator_char *this)
108 {
109     if(this->strbuf && !this->got) {
110         int c = basic_streambuf_char_sgetc(this->strbuf);
111         if(c == EOF)
112             this->strbuf = NULL;
113         else
114             this->val = c;
115     }
116
117     this->got = TRUE;
118     return this->val;
119 }
120
121 static wchar_t istreambuf_iterator_wchar_val(istreambuf_iterator_wchar *this)
122 {
123     if(this->strbuf && !this->got) {
124         unsigned short c = basic_streambuf_wchar_sgetc(this->strbuf);
125         if(c == WEOF)
126             this->strbuf = NULL;
127         else
128             this->val = c;
129     }
130
131     this->got = TRUE;
132     return this->val;
133 }
134
135 static void istreambuf_iterator_char_inc(istreambuf_iterator_char *this)
136 {
137     if(!this->strbuf || basic_streambuf_char_sbumpc(this->strbuf)==EOF) {
138         this->strbuf = NULL;
139         this->got = TRUE;
140     }else {
141         this->got = FALSE;
142         istreambuf_iterator_char_val(this);
143     }
144 }
145
146 static void istreambuf_iterator_wchar_inc(istreambuf_iterator_wchar *this)
147 {
148     if(!this->strbuf || basic_streambuf_wchar_sbumpc(this->strbuf)==WEOF) {
149         this->strbuf = NULL;
150         this->got = TRUE;
151     }else {
152         this->got = FALSE;
153         istreambuf_iterator_wchar_val(this);
154     }
155 }
156
157 static void ostreambuf_iterator_char_put(ostreambuf_iterator_char *this, char ch)
158 {
159     if(this->failed || basic_streambuf_char_sputc(this->strbuf, ch)==EOF)
160         this->failed = TRUE;
161 }
162
163 static void ostreambuf_iterator_wchar_put(ostreambuf_iterator_wchar *this, wchar_t ch)
164 {
165     if(this->failed || basic_streambuf_wchar_sputc(this->strbuf, ch)==WEOF)
166         this->failed = TRUE;
167 }
168
169 /* ??1facet@locale@std@@UAE@XZ */
170 /* ??1facet@locale@std@@UEAA@XZ */
171 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
172 void __thiscall locale_facet_dtor(locale_facet *this)
173 {
174     TRACE("(%p)\n", this);
175 }
176
177 DEFINE_THISCALL_WRAPPER(locale_facet_vector_dtor, 8)
178 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
179         locale_facet*, (locale_facet*, unsigned int), (this, flags))
180 locale_facet* __thiscall locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
181 {
182     TRACE("(%p %x)\n", this, flags);
183     if(flags & 2) {
184         /* we have an array, with the number of elements stored before the first object */
185         INT_PTR i, *ptr = (INT_PTR *)this-1;
186
187         for(i=*ptr-1; i>=0; i--)
188             locale_facet_dtor(this+i);
189         MSVCRT_operator_delete(ptr);
190     } else {
191         locale_facet_dtor(this);
192         if(flags & 1)
193             MSVCRT_operator_delete(this);
194     }
195
196     return this;
197 }
198
199 typedef struct
200 {
201     locale_facet *fac;
202     struct list entry;
203 } facets_elem;
204 static struct list lazy_facets = LIST_INIT(lazy_facets);
205
206 /* Not exported from msvcp90 */
207 /* ?facet_Register@facet@locale@std@@CAXPAV123@@Z */
208 /* ?facet_Register@facet@locale@std@@CAXPEAV123@@Z */
209 static void locale_facet_register(locale_facet *add)
210 {
211     facets_elem *head = MSVCRT_operator_new(sizeof(*head));
212     if(!head) {
213         ERR("Out of memory\n");
214         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
215     }
216
217     head->fac = add;
218     list_add_head(&lazy_facets, &head->entry);
219 }
220
221 /* Not exported from msvcp90 */
222 /* ??_7facet@locale@std@@6B@ */
223 extern const vtable_ptr MSVCP_locale_facet_vtable;
224
225 /* ??Bid@locale@std@@QAEIXZ */
226 /* ??Bid@locale@std@@QEAA_KXZ */
227 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
228 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
229 {
230     _Lockit lock;
231
232     TRACE("(%p)\n", this);
233
234     if(!this->id) {
235         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
236         this->id = ++locale_id__Id_cnt;
237         _Lockit_dtor(&lock);
238     }
239
240     return this->id;
241 }
242
243 /* ??_Ffacet@locale@std@@QAEXXZ */
244 /* ??_Ffacet@locale@std@@QEAAXXZ */
245 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
246 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
247 {
248     TRACE("(%p)\n", this);
249     this->vtable = &MSVCP_locale_facet_vtable;
250     this->refs = 0;
251     return this;
252 }
253
254 /* ??0facet@locale@std@@IAE@I@Z */
255 /* ??0facet@locale@std@@IEAA@_K@Z */
256 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
257 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
258 {
259     TRACE("(%p %lu)\n", this, refs);
260     this->vtable = &MSVCP_locale_facet_vtable;
261     this->refs = refs;
262     return this;
263 }
264
265 /* ?_Incref@facet@locale@std@@QAEXXZ */
266 /* ?_Incref@facet@locale@std@@QEAAXXZ */
267 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
268 void __thiscall locale_facet__Incref(locale_facet *this)
269 {
270     _Lockit lock;
271
272     TRACE("(%p)\n", this);
273
274     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
275     this->refs++;
276     _Lockit_dtor(&lock);
277 }
278
279 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
280 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
281 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
282 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
283 {
284     _Lockit lock;
285     locale_facet *ret;
286
287     TRACE("(%p)\n", this);
288
289     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
290     if(this->refs)
291         this->refs--;
292
293     ret = this->refs ? NULL : this;
294     _Lockit_dtor(&lock);
295
296     return ret;
297 }
298
299 /* ??0_Timevec@std@@QAE@ABV01@@Z */
300 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
301 /* This copy constructor modifies copied object */
302 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
303 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
304 {
305     TRACE("(%p %p)\n", this, copy);
306     this->timeptr = copy->timeptr;
307     copy->timeptr = NULL;
308     return this;
309 }
310
311 /* ??0_Timevec@std@@QAE@PAX@Z */
312 /* ??0_Timevec@std@@QEAA@PEAX@Z */
313 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
314 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
315 {
316     TRACE("(%p %p)\n", this, timeptr);
317     this->timeptr = timeptr;
318     return this;
319 }
320
321 /* ??_F_Timevec@std@@QAEXXZ */
322 /* ??_F_Timevec@std@@QEAAXXZ */
323 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
324 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
325 {
326     TRACE("(%p)\n", this);
327     this->timeptr = NULL;
328     return this;
329 }
330
331 /* ??1_Timevec@std@@QAE@XZ */
332 /* ??1_Timevec@std@@QEAA@XZ */
333 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
334 void __thiscall _Timevec_dtor(_Timevec *this)
335 {
336     TRACE("(%p)\n", this);
337     free(this->timeptr);
338 }
339
340 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
341 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
342 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
343 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
344 {
345     TRACE("(%p %p)\n", this, right);
346     this->timeptr = right->timeptr;
347     right->timeptr = NULL;
348     return this;
349 }
350
351 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
352 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
353 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
354 void* __thiscall _Timevec__Getptr(_Timevec *this)
355 {
356     TRACE("(%p)\n", this);
357     return this->timeptr;
358 }
359
360 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
361 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
362 static _Locinfo* _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
363 {
364     const char *locale = NULL;
365
366     /* This function is probably modifying more global objects */
367     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
368
369     if(!locstr)
370         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
371
372     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
373     basic_string_char_ctor_cstr(&locinfo->days, "");
374     basic_string_char_ctor_cstr(&locinfo->months, "");
375     basic_string_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
376
377     if(category)
378         locale = setlocale(LC_ALL, locstr);
379     else
380         locale = setlocale(LC_ALL, NULL);
381
382     if(locale)
383         basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
384     else
385         basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
386
387     return locinfo;
388 }
389
390 /* ??0_Locinfo@std@@QAE@HPBD@Z */
391 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
392 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
393 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
394 {
395     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
396 }
397
398 /* ??0_Locinfo@std@@QAE@PBD@Z */
399 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
400 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
401 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
402 {
403     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
404 }
405
406 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
407 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
408 static void _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
409 {
410     TRACE("(%p)\n", locinfo);
411
412     setlocale(LC_ALL, basic_string_char_c_str(&locinfo->oldlocname));
413     basic_string_char_dtor(&locinfo->days);
414     basic_string_char_dtor(&locinfo->months);
415     basic_string_char_dtor(&locinfo->oldlocname);
416     basic_string_char_dtor(&locinfo->newlocname);
417     _Lockit_dtor(&locinfo->lock);
418 }
419
420 /* ??_F_Locinfo@std@@QAEXXZ */
421 /* ??_F_Locinfo@std@@QEAAXXZ */
422 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
423 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
424 {
425     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
426 }
427
428 /* ??1_Locinfo@std@@QAE@XZ */
429 /* ??1_Locinfo@std@@QEAA@XZ */
430 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
431 void __thiscall _Locinfo_dtor(_Locinfo *this)
432 {
433     _Locinfo__Locinfo_dtor(this);
434 }
435
436 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
437 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
438 static _Locinfo* _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
439 {
440     const char *locale = NULL;
441
442     /* This function is probably modifying more global objects */
443     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
444     if(!locstr)
445         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
446
447     basic_string_char_dtor(&locinfo->newlocname);
448
449     if(category)
450         locale = setlocale(LC_ALL, locstr);
451     else
452         locale = setlocale(LC_ALL, NULL);
453
454     if(locale)
455         basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
456     else
457         basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
458
459     return locinfo;
460 }
461
462 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
463 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
464 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
465 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
466 {
467     return _Locinfo__Locinfo_Addcats(this, category, locstr);
468 }
469
470 /* _Getcoll */
471 ULONGLONG __cdecl _Getcoll(void)
472 {
473     union {
474         _Collvec collvec;
475         ULONGLONG ull;
476     } ret;
477     _locale_t locale = _get_current_locale();
478
479     TRACE("\n");
480
481     ret.collvec.page = locale->locinfo->lc_collate_cp;
482     ret.collvec.handle = locale->locinfo->lc_handle[LC_COLLATE];
483     _free_locale(locale);
484     return ret.ull;
485 }
486
487 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
488 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
489 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 8)
490 _Collvec* __thiscall _Locinfo__Getcoll(const _Locinfo *this, _Collvec *ret)
491 {
492     ULONGLONG ull = _Getcoll();
493     memcpy(ret, &ull, sizeof(ull));
494     return ret;
495 }
496
497 /* _Getctype */
498 _Ctypevec* __cdecl _Getctype(_Ctypevec *ret)
499 {
500     _locale_t locale = _get_current_locale();
501     short *table;
502
503     TRACE("\n");
504
505     ret->page = locale->locinfo->lc_codepage;
506     ret->handle = locale->locinfo->lc_handle[LC_COLLATE];
507     ret->delfl = TRUE;
508     table = malloc(sizeof(short[256]));
509     if(!table) {
510         _free_locale(locale);
511         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
512     }
513     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
514     ret->table = table;
515     _free_locale(locale);
516     return ret;
517 }
518
519 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
520 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
521 DEFINE_THISCALL_WRAPPER(_Locinfo__Getctype, 8)
522 _Ctypevec* __thiscall _Locinfo__Getctype(const _Locinfo *this, _Ctypevec *ret)
523 {
524     return _Getctype(ret);
525 }
526
527 /* _Getcvt */
528 ULONGLONG __cdecl _Getcvt(void)
529 {
530     _locale_t locale = _get_current_locale();
531     union {
532         _Cvtvec cvtvec;
533         ULONGLONG ull;
534     } ret;
535
536     TRACE("\n");
537
538     ret.cvtvec.page = locale->locinfo->lc_codepage;
539     ret.cvtvec.handle = locale->locinfo->lc_handle[LC_CTYPE];
540     _free_locale(locale);
541     return ret.ull;
542 }
543
544 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
545 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
546 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 8)
547 _Cvtvec* __thiscall _Locinfo__Getcvt(const _Locinfo *this, _Cvtvec *ret)
548 {
549     ULONGLONG ull = _Getcvt();
550     memcpy(ret, &ull, sizeof(ull));
551     return ret;
552 }
553
554 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
555 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
556 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
557 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
558 {
559     char *days = _Getdays();
560
561     TRACE("(%p)\n", this);
562
563     if(days) {
564         basic_string_char_dtor(&this->days);
565         basic_string_char_ctor_cstr(&this->days, days);
566         free(days);
567     }
568
569     return this->days.size ? basic_string_char_c_str(&this->days) :
570         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
571 }
572
573 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
574 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
575 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
576 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
577 {
578     char *months = _Getmonths();
579
580     TRACE("(%p)\n", this);
581
582     if(months) {
583         basic_string_char_dtor(&this->months);
584         basic_string_char_ctor_cstr(&this->months, months);
585         free(months);
586     }
587
588     return this->months.size ? basic_string_char_c_str(&this->months) :
589         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
590         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
591 }
592
593 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
594 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
595 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
596 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
597 {
598     TRACE("(%p)\n", this);
599     return "false";
600 }
601
602 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
603 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
604 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
605 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
606 {
607     TRACE("(%p)\n", this);
608     return "true";
609 }
610
611 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
612 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
613 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
614 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
615 {
616     TRACE("(%p)\n", this);
617     return localeconv();
618 }
619
620 /* ?_Getname@_Locinfo@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
621 /* ?_Getname@_Locinfo@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
622 DEFINE_THISCALL_WRAPPER(_Locinfo__Getname, 8)
623 basic_string_char* __thiscall _Locinfo__Getname(const _Locinfo *this, basic_string_char *ret)
624 {
625     TRACE("(%p)\n", this);
626
627     basic_string_char_copy_ctor(ret, &this->newlocname);
628     return ret;
629 }
630
631 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
632 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
633 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 8)
634 _Timevec*__thiscall _Locinfo__Gettnames(const _Locinfo *this, _Timevec *ret)
635 {
636     TRACE("(%p)\n", this);
637
638     _Timevec_ctor_timeptr(ret, _Gettnames());
639     return ret;
640 }
641
642 /* ?id@?$collate@D@std@@2V0locale@2@A */
643 locale_id collate_char_id = {0};
644
645 /* ??_7?$collate@D@std@@6B@ */
646 extern const vtable_ptr MSVCP_collate_char_vtable;
647
648 /* ?_Init@?$collate@D@std@@IAEXABV_Locinfo@2@@Z */
649 /* ?_Init@?$collate@D@std@@IEAAXAEBV_Locinfo@2@@Z */
650 DEFINE_THISCALL_WRAPPER(collate_char__Init, 8)
651 void __thiscall collate_char__Init(collate *this, const _Locinfo *locinfo)
652 {
653     TRACE("(%p %p)\n", this, locinfo);
654     _Locinfo__Getcoll(locinfo, &this->coll);
655 }
656
657 /* ??0?$collate@D@std@@IAE@PBDI@Z */
658 /* ??0?$collate@D@std@@IEAA@PEBD_K@Z */
659 static collate* collate_char_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
660 {
661     _Locinfo locinfo;
662
663     TRACE("(%p %s %lu)\n", this, name, refs);
664
665     locale_facet_ctor_refs(&this->facet, refs);
666     this->facet.vtable = &MSVCP_collate_char_vtable;
667
668     _Locinfo_ctor_cstr(&locinfo, name);
669     collate_char__Init(this, &locinfo);
670     _Locinfo_dtor(&locinfo);
671     return this;
672 }
673
674 /* ??0?$collate@D@std@@QAE@ABV_Locinfo@1@I@Z */
675 /* ??0?$collate@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
676 DEFINE_THISCALL_WRAPPER(collate_char_ctor_locinfo, 12)
677 collate* __thiscall collate_char_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
678 {
679     TRACE("(%p %p %lu)\n", this, locinfo, refs);
680
681     locale_facet_ctor_refs(&this->facet, refs);
682     this->facet.vtable = &MSVCP_collate_char_vtable;
683     collate_char__Init(this, locinfo);
684     return this;
685 }
686
687 /* ??0?$collate@D@std@@QAE@I@Z */
688 /* ??0?$collate@D@std@@QEAA@_K@Z */
689 DEFINE_THISCALL_WRAPPER(collate_char_ctor_refs, 8)
690 collate* __thiscall collate_char_ctor_refs(collate *this, MSVCP_size_t refs)
691 {
692     return collate_char_ctor_name(this, "C", refs);
693 }
694
695 /* ??1?$collate@D@std@@MAE@XZ */
696 /* ??1?$collate@D@std@@MEAA@XZ */
697 static void collate_char_dtor(collate *this)
698 {
699     TRACE("(%p)\n", this);
700 }
701
702 DEFINE_THISCALL_WRAPPER(collate_char_vector_dtor, 8)
703 collate* __thiscall collate_char_vector_dtor(collate *this, unsigned int flags)
704 {
705     TRACE("(%p %x)\n", this, flags);
706     if(flags & 2) {
707         /* we have an array, with the number of elements stored before the first object */
708         INT_PTR i, *ptr = (INT_PTR *)this-1;
709
710         for(i=*ptr-1; i>=0; i--)
711             collate_char_dtor(this+i);
712         MSVCRT_operator_delete(ptr);
713     } else {
714         collate_char_dtor(this);
715         if(flags & 1)
716             MSVCRT_operator_delete(this);
717     }
718
719     return this;
720 }
721
722 /* ??_F?$collate@D@std@@QAEXXZ */
723 /* ??_F?$collate@D@std@@QEAAXXZ */
724 DEFINE_THISCALL_WRAPPER(collate_char_ctor, 4)
725 collate* __thiscall collate_char_ctor(collate *this)
726 {
727     return collate_char_ctor_name(this, "C", 0);
728 }
729
730 /* _Strcoll */
731 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
732         const char *last2, const _Collvec *coll)
733 {
734     LCID lcid;
735
736     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
737
738     if(coll)
739         lcid = coll->handle;
740     else
741         lcid = ___lc_handle_func()[LC_COLLATE];
742     return CompareStringA(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
743 }
744
745 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
746 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
747 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
748 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
749         (const collate*, const char*, const char*, const char*, const char*), \
750         (this, first1, last1, first2, last2))
751 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
752         const char *last1, const char *first2, const char *last2)
753 {
754     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
755     return _Strcoll(first1, last1, first2, last2, &this->coll);
756 }
757
758 /* ?compare@?$collate@D@std@@QBEHPBD000@Z */
759 /* ?compare@?$collate@D@std@@QEBAHPEBD000@Z */
760 DEFINE_THISCALL_WRAPPER(collate_char_compare, 20)
761 int __thiscall collate_char_compare(const collate *this, const char *first1,
762         const char *last1, const char *first2, const char *last2)
763 {
764     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
765     return call_collate_char_do_compare(this, first1, last1, first2, last2);
766 }
767
768 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
769 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
770 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
771 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
772         (const collate*, const char*, const char*), (this, first, last))
773 LONG __thiscall collate_char_do_hash(const collate *this,
774         const char *first, const char *last)
775 {
776     ULONG ret = 0;
777
778     TRACE("(%p %p %p)\n", this, first, last);
779
780     for(; first<last; first++)
781         ret = (ret<<8 | ret>>24) + *first;
782     return ret;
783 }
784
785 /* ?hash@?$collate@D@std@@QBEJPBD0@Z */
786 /* ?hash@?$collate@D@std@@QEBAJPEBD0@Z */
787 DEFINE_THISCALL_WRAPPER(collate_char_hash, 12)
788 LONG __thiscall collate_char_hash(const collate *this,
789         const char *first, const char *last)
790 {
791     TRACE("(%p %p %p)\n", this, first, last);
792     return call_collate_char_do_hash(this, first, last);
793 }
794
795 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
796 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
797 DEFINE_THISCALL_WRAPPER(collate_char_do_transform, 16)
798 basic_string_char* __thiscall collate_char_do_transform(const collate *this,
799         basic_string_char *ret, const char *first, const char *last)
800 {
801     FIXME("(%p %p %p) stub\n", this, first, last);
802     return ret;
803 }
804
805 /* ?transform@?$collate@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
806 /* ?transform@?$collate@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
807 DEFINE_THISCALL_WRAPPER(collate_char_transform, 16)
808 basic_string_char* __thiscall collate_char_transform(const collate *this,
809         basic_string_char *ret, const char *first, const char *last)
810 {
811     FIXME("(%p %p %p) stub\n", this, first, last);
812     return ret;
813 }
814
815 /* ?id@?$collate@G@std@@2V0locale@2@A */
816 locale_id collate_short_id = {0};
817
818 /* ??_7?$collate@_W@std@@6B@ */
819 extern const vtable_ptr MSVCP_collate_wchar_vtable;
820 /* ??_7?$collate@G@std@@6B@ */
821 extern const vtable_ptr MSVCP_collate_short_vtable;
822
823 /* ?_Init@?$collate@_W@std@@IAEXABV_Locinfo@2@@Z */
824 /* ?_Init@?$collate@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
825 /* ?_Init@?$collate@G@std@@IAEXABV_Locinfo@2@@Z */
826 /* ?_Init@?$collate@G@std@@IEAAXAEBV_Locinfo@2@@Z */
827 DEFINE_THISCALL_WRAPPER(collate_wchar__Init, 8)
828 void __thiscall collate_wchar__Init(collate *this, const _Locinfo *locinfo)
829 {
830     TRACE("(%p %p)\n", this, locinfo);
831     _Locinfo__Getcoll(locinfo, &this->coll);
832 }
833
834 /* ??0?$collate@_W@std@@IAE@PBDI@Z */
835 /* ??0?$collate@_W@std@@IEAA@PEBD_K@Z */
836 static collate* collate_wchar_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
837 {
838     _Locinfo locinfo;
839
840     TRACE("(%p %s %lu)\n", this, name, refs);
841
842     locale_facet_ctor_refs(&this->facet, refs);
843     this->facet.vtable = &MSVCP_collate_wchar_vtable;
844
845     _Locinfo_ctor_cstr(&locinfo, name);
846     collate_wchar__Init(this, &locinfo);
847     _Locinfo_dtor(&locinfo);
848     return this;
849 }
850
851 /* ??0?$collate@_W@std@@QAE@ABV_Locinfo@1@I@Z */
852 /* ??0?$collate@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
853 static collate* collate_wchar_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
854 {
855     TRACE("(%p %p %lu)\n", this, locinfo, refs);
856
857     locale_facet_ctor_refs(&this->facet, refs);
858     this->facet.vtable = &MSVCP_collate_wchar_vtable;
859     collate_wchar__Init(this, locinfo);
860     return this;
861 }
862
863 /* ??0?$collate@G@std@@QAE@ABV_Locinfo@1@I@Z */
864 /* ??0?$collate@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
865 DEFINE_THISCALL_WRAPPER(collate_short_ctor_locinfo, 12)
866 collate* __thiscall collate_short_ctor_locinfo(collate *this, _Locinfo *locinfo, MSVCP_size_t refs)
867 {
868     collate *ret = collate_wchar_ctor_locinfo(this, locinfo, refs);
869     ret->facet.vtable = &MSVCP_collate_short_vtable;
870     return ret;
871 }
872
873 /* ??0?$collate@_W@std@@QAE@I@Z */
874 /* ??0?$collate@_W@std@@QEAA@_K@Z */
875 static collate* collate_wchar_ctor_refs(collate *this, MSVCP_size_t refs)
876 {
877     return collate_wchar_ctor_name(this, "C", refs);
878 }
879
880 /* ??0?$collate@G@std@@QAE@I@Z */
881 /* ??0?$collate@G@std@@QEAA@_K@Z */
882 DEFINE_THISCALL_WRAPPER(collate_short_ctor_refs, 8)
883 collate* __thiscall collate_short_ctor_refs(collate *this, MSVCP_size_t refs)
884 {
885     collate *ret = collate_wchar_ctor_refs(this, refs);
886     ret->facet.vtable = &MSVCP_collate_short_vtable;
887     return ret;
888 }
889
890 /* ??1?$collate@_W@std@@MAE@XZ */
891 /* ??1?$collate@_W@std@@MEAA@XZ */
892 /* ??1?$collate@G@std@@MAE@XZ */
893 /* ??1?$collate@G@std@@MEAA@XZ */
894 static void collate_wchar_dtor(collate *this)
895 {
896     TRACE("(%p)\n", this);
897 }
898
899 DEFINE_THISCALL_WRAPPER(collate_wchar_vector_dtor, 8)
900 collate* __thiscall collate_wchar_vector_dtor(collate *this, unsigned int flags)
901 {
902     TRACE("(%p %x)\n", this, flags);
903     if(flags & 2) {
904         /* we have an array, with the number of elements stored before the first object */
905         INT_PTR i, *ptr = (INT_PTR *)this-1;
906
907         for(i=*ptr-1; i>=0; i--)
908             collate_wchar_dtor(this+i);
909         MSVCRT_operator_delete(ptr);
910     } else {
911         collate_wchar_dtor(this);
912         if(flags & 1)
913             MSVCRT_operator_delete(this);
914     }
915
916     return this;
917 }
918
919 /* ??_F?$collate@_W@std@@QAEXXZ */
920 /* ??_F?$collate@_W@std@@QEAAXXZ */
921 static collate* collate_wchar_ctor(collate *this)
922 {
923     return collate_wchar_ctor_name(this, "C", 0);
924 }
925
926 /* ??_F?$collate@G@std@@QAEXXZ */
927 /* ??_F?$collate@G@std@@QEAAXXZ */
928 DEFINE_THISCALL_WRAPPER(collate_short_ctor, 4)
929 collate* __thiscall collate_short_ctor(collate *this)
930 {
931     collate *ret = collate_wchar_ctor(this);
932     ret->facet.vtable = &MSVCP_collate_short_vtable;
933     return ret;
934 }
935
936 /* _Wcscoll */
937 static int _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
938         const wchar_t *last2, const _Collvec *coll)
939 {
940     LCID lcid;
941
942     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
943
944     if(coll)
945         lcid = coll->handle;
946     else
947         lcid = ___lc_handle_func()[LC_COLLATE];
948     return CompareStringW(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
949 }
950
951 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
952 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
953 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
954 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
955 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
956 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
957         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
958         (this, first1, last1, first2, last2))
959 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
960         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
961 {
962     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
963     return _Wcscoll(first1, last1, first2, last2, &this->coll);
964 }
965
966 /* ?compare@?$collate@_W@std@@QBEHPB_W000@Z */
967 /* ?compare@?$collate@_W@std@@QEBAHPEB_W000@Z */
968 /* ?compare@?$collate@G@std@@QBEHPBG000@Z */
969 /* ?compare@?$collate@G@std@@QEBAHPEBG000@Z */
970 DEFINE_THISCALL_WRAPPER(collate_wchar_compare, 20)
971 int __thiscall collate_wchar_compare(const collate *this, const wchar_t *first1,
972         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
973 {
974     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
975     return call_collate_wchar_do_compare(this, first1, last1, first2, last2);
976 }
977
978 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
979 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
980 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
981 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
982 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
983 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
984         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
985 LONG __thiscall collate_wchar_do_hash(const collate *this,
986         const wchar_t *first, const wchar_t *last)
987 {
988     ULONG ret = 0;
989
990     TRACE("(%p %p %p)\n", this, first, last);
991
992     for(; first<last; first++)
993         ret = (ret<<8 | ret>>24) + *first;
994     return ret;
995 }
996
997 /* ?hash@?$collate@_W@std@@QBEJPB_W0@Z */
998 /* ?hash@?$collate@_W@std@@QEBAJPEB_W0@Z */
999 /* ?hash@?$collate@G@std@@QBEJPBG0@Z */
1000 /* ?hash@?$collate@G@std@@QEBAJPEBG0@Z */
1001 DEFINE_THISCALL_WRAPPER(collate_wchar_hash, 12)
1002 LONG __thiscall collate_wchar_hash(const collate *this,
1003         const wchar_t *first, const wchar_t *last)
1004 {
1005     TRACE("(%p %p %p)\n", this, first, last);
1006     return call_collate_wchar_do_hash(this, first, last);
1007 }
1008
1009 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1010 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1011 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1012 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1013 DEFINE_THISCALL_WRAPPER(collate_wchar_do_transform, 16)
1014 basic_string_wchar* __thiscall collate_wchar_do_transform(const collate *this,
1015         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1016 {
1017     FIXME("(%p %p %p) stub\n", this, first, last);
1018     return ret;
1019 }
1020
1021 /* ?transform@?$collate@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1022 /* ?transform@?$collate@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1023 /* ?transform@?$collate@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1024 /* ?transform@?$collate@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1025 DEFINE_THISCALL_WRAPPER(collate_wchar_transform, 16)
1026 basic_string_wchar* __thiscall collate_wchar_transform(const collate *this,
1027         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1028 {
1029     FIXME("(%p %p %p) stub\n", this, first, last);
1030     return ret;
1031 }
1032
1033 /* ??_7ctype_base@std@@6B@ */
1034 extern const vtable_ptr MSVCP_ctype_base_vtable;
1035
1036 /* ??0ctype_base@std@@QAE@I@Z */
1037 /* ??0ctype_base@std@@QEAA@_K@Z */
1038 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
1039 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
1040 {
1041     TRACE("(%p %lu)\n", this, refs);
1042     locale_facet_ctor_refs(&this->facet, refs);
1043     this->facet.vtable = &MSVCP_ctype_base_vtable;
1044     return this;
1045 }
1046
1047 /* ??_Fctype_base@std@@QAEXXZ */
1048 /* ??_Fctype_base@std@@QEAAXXZ */
1049 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
1050 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
1051 {
1052     TRACE("(%p)\n", this);
1053     locale_facet_ctor_refs(&this->facet, 0);
1054     this->facet.vtable = &MSVCP_ctype_base_vtable;
1055     return this;
1056 }
1057
1058 /* ??1ctype_base@std@@UAE@XZ */
1059 /* ??1ctype_base@std@@UEAA@XZ */
1060 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
1061 void __thiscall ctype_base_dtor(ctype_base *this)
1062 {
1063     TRACE("(%p)\n", this);
1064 }
1065
1066 DEFINE_THISCALL_WRAPPER(ctype_base_vector_dtor, 8)
1067 ctype_base* __thiscall ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
1068 {
1069     TRACE("(%p %x)\n", this, flags);
1070     if(flags & 2) {
1071         /* we have an array, with the number of elements stored before the first object */
1072         INT_PTR i, *ptr = (INT_PTR *)this-1;
1073
1074         for(i=*ptr-1; i>=0; i--)
1075             ctype_base_dtor(this+i);
1076         MSVCRT_operator_delete(ptr);
1077     } else {
1078         ctype_base_dtor(this);
1079         if(flags & 1)
1080             MSVCRT_operator_delete(this);
1081     }
1082
1083     return this;
1084 }
1085
1086 /* ?id@?$ctype@D@std@@2V0locale@2@A */
1087 locale_id ctype_char_id = {0};
1088 /* ?table_size@?$ctype@D@std@@2IB */
1089 /* ?table_size@?$ctype@D@std@@2_KB */
1090 MSVCP_size_t ctype_char_table_size = 256;
1091
1092 /* ??_7?$ctype@D@std@@6B@ */
1093 extern const vtable_ptr MSVCP_ctype_char_vtable;
1094
1095 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
1096 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
1097 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
1098 void __thiscall ctype_char__Init(ctype_char *this, const _Locinfo *locinfo)
1099 {
1100     TRACE("(%p %p)\n", this, locinfo);
1101     _Locinfo__Getctype(locinfo, &this->ctype);
1102 }
1103
1104 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
1105 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
1106 static void ctype_char__Tidy(ctype_char *this)
1107 {
1108     TRACE("(%p)\n", this);
1109
1110     if(this->ctype.delfl)
1111         free((short*)this->ctype.table);
1112 }
1113
1114 /* ?classic_table@?$ctype@D@std@@KAPBFXZ */
1115 /* ?classic_table@?$ctype@D@std@@KAPEBFXZ */
1116 const short* __cdecl ctype_char_classic_table(void)
1117 {
1118     TRACE("()\n");
1119     return &((short*)GetProcAddress(GetModuleHandleA("msvcrt.dll"), "_ctype"))[1];
1120 }
1121
1122 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
1123 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1124 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
1125 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
1126         const _Locinfo *locinfo, MSVCP_size_t refs)
1127 {
1128     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1129     ctype_base_ctor_refs(&this->base, refs);
1130     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1131     ctype_char__Init(this, locinfo);
1132     return this;
1133 }
1134
1135 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
1136 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
1137 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
1138 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
1139         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
1140 {
1141     _Locinfo locinfo;
1142
1143     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
1144
1145     ctype_base_ctor_refs(&this->base, refs);
1146     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1147
1148     _Locinfo_ctor(&locinfo);
1149     ctype_char__Init(this, &locinfo);
1150     _Locinfo_dtor(&locinfo);
1151
1152     if(table) {
1153         ctype_char__Tidy(this);
1154         this->ctype.table = table;
1155         this->ctype.delfl = delete;
1156     }
1157     return this;
1158 }
1159
1160 /* ??_F?$ctype@D@std@@QAEXXZ */
1161 /* ??_F?$ctype@D@std@@QEAAXXZ */
1162 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
1163 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
1164 {
1165     return ctype_char_ctor_table(this, NULL, FALSE, 0);
1166 }
1167
1168 /* ??1?$ctype@D@std@@MAE@XZ */
1169 /* ??1?$ctype@D@std@@MEAA@XZ */
1170 static void ctype_char_dtor(ctype_char *this)
1171 {
1172     TRACE("(%p)\n", this);
1173     ctype_char__Tidy(this);
1174 }
1175
1176 DEFINE_THISCALL_WRAPPER(ctype_char_vector_dtor, 8)
1177 ctype_char* __thiscall ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1178 {
1179     TRACE("(%p %x)\n", this, flags);
1180     if(flags & 2) {
1181         /* we have an array, with the number of elements stored before the first object */
1182         INT_PTR i, *ptr = (INT_PTR *)this-1;
1183
1184         for(i=*ptr-1; i>=0; i--)
1185             ctype_char_dtor(this+i);
1186         MSVCRT_operator_delete(ptr);
1187     } else {
1188         ctype_char_dtor(this);
1189         if(flags & 1)
1190             MSVCRT_operator_delete(this);
1191     }
1192
1193     return this;
1194 }
1195
1196 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1197 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1198 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1199 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 32, \
1200         char, (const ctype_char*, char, char), (this, ch, unused))
1201 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1202 {
1203     TRACE("(%p %c %c)\n", this, ch, unused);
1204     return ch;
1205 }
1206
1207 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1208 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1209 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1210 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 28, \
1211         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1212         (this, first, last, unused, dest))
1213 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1214         const char *first, const char *last, char unused, char *dest)
1215 {
1216     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1217     memcpy(dest, first, last-first);
1218     return last;
1219 }
1220
1221 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1222 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1223 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1224 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1225 {
1226     TRACE("(%p %c %c)\n", this, ch, dflt);
1227     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1228 }
1229
1230 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1231 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1232 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1233 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1234         const char *first, const char *last, char dflt, char *dest)
1235 {
1236     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1237     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1238 }
1239
1240 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1241 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1242 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1243 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1244         char, (const ctype_char*, char), (this, ch))
1245 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1246 {
1247     TRACE("(%p %c)\n", this, ch);
1248     return ch;
1249 }
1250
1251 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1252 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1253 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1254 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1255         const char*, (const ctype_char*, const char*, const char*, char*), \
1256         (this, first, last, dest))
1257 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1258         const char *first, const char *last, char *dest)
1259 {
1260     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1261     memcpy(dest, first, last-first);
1262     return last;
1263 }
1264
1265 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1266 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1267 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1268 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1269 {
1270     TRACE("(%p %c)\n", this, ch);
1271     return call_ctype_char_do_widen_ch(this, ch);
1272 }
1273
1274 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1275 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1276 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1277 const char* __thiscall ctype_char_widen(const ctype_char *this,
1278         const char *first, const char *last, char *dest)
1279 {
1280     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1281     return call_ctype_char_do_widen(this, first, last, dest);
1282 }
1283
1284 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1285 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1286 static MSVCP_size_t ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1287 {
1288     TRACE("(%p %p)\n", facet, loc);
1289
1290     if(facet && !*facet) {
1291         _Locinfo locinfo;
1292
1293         *facet = MSVCRT_operator_new(sizeof(ctype_char));
1294         if(!*facet) {
1295             ERR("Out of memory\n");
1296             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1297             return 0;
1298         }
1299
1300         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
1301         ctype_char_ctor_locinfo((ctype_char*)*facet, &locinfo, 0);
1302         _Locinfo_dtor(&locinfo);
1303     }
1304
1305     return LC_CTYPE;
1306 }
1307
1308 ctype_char* ctype_char_use_facet(const locale *loc)
1309 {
1310     static ctype_char *obj = NULL;
1311
1312     _Lockit lock;
1313     const locale_facet *fac;
1314
1315     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1316     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_char_id));
1317     if(fac) {
1318         _Lockit_dtor(&lock);
1319         return (ctype_char*)fac;
1320     }
1321
1322     if(obj) {
1323         _Lockit_dtor(&lock);
1324         return obj;
1325     }
1326
1327     ctype_char__Getcat(&fac, loc);
1328     obj = (ctype_char*)fac;
1329     locale_facet__Incref(&obj->base.facet);
1330     locale_facet_register(&obj->base.facet);
1331     _Lockit_dtor(&lock);
1332
1333     return obj;
1334 }
1335
1336 /* _Tolower */
1337 int __cdecl _Tolower(int ch, const _Ctypevec *ctype)
1338 {
1339     unsigned int cp;
1340
1341     TRACE("%d %p\n", ch, ctype);
1342
1343     if(ctype)
1344         cp = ctype->page;
1345     else
1346         cp = ___lc_codepage_func();
1347
1348     /* Don't convert to unicode in case of C locale */
1349     if(!cp) {
1350         if(ch>='A' && ch<='Z')
1351             ch = ch-'A'+'a';
1352         return ch;
1353     } else {
1354         WCHAR wide, lower;
1355         char str[2];
1356         int size;
1357
1358         if(ch > 255) {
1359             str[0] = (ch>>8) & 255;
1360             str[1] = ch & 255;
1361             size = 2;
1362         } else {
1363             str[0] = ch & 255;
1364             size = 1;
1365         }
1366
1367         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1368             return ch;
1369
1370         lower = tolowerW(wide);
1371         if(lower == wide)
1372             return ch;
1373
1374         WideCharToMultiByte(cp, 0, &lower, 1, str, 2, NULL, NULL);
1375
1376         return str[0] + (str[1]<<8);
1377     }
1378 }
1379
1380 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1381 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1382 #define call_ctype_char_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 8, \
1383         char, (const ctype_char*, char), (this, ch))
1384 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1385 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1386 {
1387     TRACE("(%p %c)\n", this, ch);
1388     return _Tolower(ch, &this->ctype);
1389 }
1390
1391 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1392 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1393 #define call_ctype_char_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 4, \
1394         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1395 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1396 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1397 {
1398     TRACE("(%p %p %p)\n", this, first, last);
1399     for(; first<last; first++)
1400         *first = _Tolower(*first, &this->ctype);
1401     return last;
1402 }
1403
1404 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1405 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1406 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1407 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1408 {
1409     TRACE("(%p %c)\n", this, ch);
1410     return call_ctype_char_do_tolower_ch(this, ch);
1411 }
1412
1413 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1414 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1415 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1416 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1417 {
1418     TRACE("(%p %p %p)\n", this, first, last);
1419     return call_ctype_char_do_tolower(this, first, last);
1420 }
1421
1422 /* _Toupper */
1423 int __cdecl _Toupper(int ch, const _Ctypevec *ctype)
1424 {
1425     unsigned int cp;
1426
1427     TRACE("%d %p\n", ch, ctype);
1428
1429     if(ctype)
1430         cp = ctype->page;
1431     else
1432         cp = ___lc_codepage_func();
1433
1434     /* Don't convert to unicode in case of C locale */
1435     if(!cp) {
1436         if(ch>='a' && ch<='z')
1437             ch = ch-'a'+'A';
1438         return ch;
1439     } else {
1440         WCHAR wide, upper;
1441         char str[2];
1442         int size;
1443
1444         if(ch > 255) {
1445             str[0] = (ch>>8) & 255;
1446             str[1] = ch & 255;
1447             size = 2;
1448         } else {
1449             str[0] = ch & 255;
1450             size = 1;
1451         }
1452
1453         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1454             return ch;
1455
1456         upper = toupperW(wide);
1457         if(upper == wide)
1458             return ch;
1459
1460         WideCharToMultiByte(cp, 0, &upper, 1, str, 2, NULL, NULL);
1461
1462         return str[0] + (str[1]<<8);
1463     }
1464 }
1465
1466 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1467 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1468 #define call_ctype_char_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 16, \
1469         char, (const ctype_char*, char), (this, ch))
1470 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1471 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1472 {
1473     TRACE("(%p %c)\n", this, ch);
1474     return _Toupper(ch, &this->ctype);
1475 }
1476
1477 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1478 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1479 #define call_ctype_char_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 12, \
1480         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1481 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1482 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1483         char *first, const char *last)
1484 {
1485     TRACE("(%p %p %p)\n", this, first, last);
1486     for(; first<last; first++)
1487         *first = _Toupper(*first, &this->ctype);
1488     return last;
1489 }
1490
1491 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1492 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1493 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1494 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1495 {
1496     TRACE("(%p %c)\n", this, ch);
1497     return call_ctype_char_do_toupper_ch(this, ch);
1498 }
1499
1500 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1501 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1502 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1503 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1504 {
1505     TRACE("(%p %p %p)\n", this, first, last);
1506     return call_ctype_char_do_toupper(this, first, last);
1507 }
1508
1509 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1510 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1511 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1512 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1513 {
1514     TRACE("(%p %x %c)\n", this, mask, ch);
1515     return (this->ctype.table[(unsigned char)ch] & mask) != 0;
1516 }
1517
1518 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1519 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1520 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1521 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1522 {
1523     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1524     for(; first<last; first++)
1525         *dest++ = this->ctype.table[(unsigned char)*first];
1526     return last;
1527 }
1528
1529 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1530 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1531 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1532 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1533 {
1534     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1535     for(; first<last; first++)
1536         if(!ctype_char_is_ch(this, mask, *first))
1537             break;
1538     return first;
1539 }
1540
1541 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1542 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1543 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1544 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1545 {
1546     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1547     for(; first<last; first++)
1548         if(ctype_char_is_ch(this, mask, *first))
1549             break;
1550     return first;
1551 }
1552
1553 /* ?table@?$ctype@D@std@@IBEPBFXZ */
1554 /* ?table@?$ctype@D@std@@IEBAPEBFXZ */
1555 DEFINE_THISCALL_WRAPPER(ctype_char_table, 4)
1556 const short* __thiscall ctype_char_table(const ctype_char *this)
1557 {
1558     TRACE("(%p)\n", this);
1559     return this->ctype.table;
1560 }
1561
1562 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1563 static locale_id ctype_wchar_id = {0};
1564 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1565 locale_id ctype_short_id = {0};
1566
1567 /* ??_7?$ctype@_W@std@@6B@ */
1568 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1569 /* ??_7?$ctype@G@std@@6B@ */
1570 extern const vtable_ptr MSVCP_ctype_short_vtable;
1571
1572 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1573 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1574 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1575 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1576 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1577 void __thiscall ctype_wchar__Init(ctype_wchar *this, const _Locinfo *locinfo)
1578 {
1579     TRACE("(%p %p)\n", this, locinfo);
1580     _Locinfo__Getctype(locinfo, &this->ctype);
1581     _Locinfo__Getcvt(locinfo, &this->cvt);
1582 }
1583
1584 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1585 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1586 static ctype_wchar* ctype_wchar_ctor_locinfo(ctype_wchar *this,
1587         const _Locinfo *locinfo, MSVCP_size_t refs)
1588 {
1589     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1590     ctype_base_ctor_refs(&this->base, refs);
1591     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1592     ctype_wchar__Init(this, locinfo);
1593     return this;
1594 }
1595
1596 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1597 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1598 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1599 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1600         const _Locinfo *locinfo, MSVCP_size_t refs)
1601 {
1602     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1603     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1604     return ret;
1605 }
1606
1607 /* ??0?$ctype@_W@std@@QAE@I@Z */
1608 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1609 static ctype_wchar* ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1610 {
1611     _Locinfo locinfo;
1612
1613     TRACE("(%p %lu)\n", this, refs);
1614
1615     ctype_base_ctor_refs(&this->base, refs);
1616     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1617
1618     _Locinfo_ctor(&locinfo);
1619     ctype_wchar__Init(this, &locinfo);
1620     _Locinfo_dtor(&locinfo);
1621     return this;
1622 }
1623
1624 /* ??0?$ctype@G@std@@QAE@I@Z */
1625 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1626 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1627 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1628 {
1629     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1630     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1631     return ret;
1632 }
1633
1634 /* ??_F?$ctype@_W@std@@QAEXXZ */
1635 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1636 static ctype_wchar* ctype_wchar_ctor(ctype_wchar *this)
1637 {
1638     TRACE("(%p)\n", this);
1639     return ctype_short_ctor_refs(this, 0);
1640 }
1641
1642 /* ??_F?$ctype@G@std@@QAEXXZ */
1643 /* ??_F?$ctype@G@std@@QEAAXXZ */
1644 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1645 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1646 {
1647     ctype_wchar *ret = ctype_wchar_ctor(this);
1648     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1649     return ret;
1650 }
1651
1652 /* ??1?$ctype@_W@std@@MAE@XZ */
1653 /* ??1?$ctype@_W@std@@MEAA@XZ */
1654 /* ??1?$ctype@G@std@@MAE@XZ */
1655 /* ??1?$ctype@G@std@@MEAA@XZ */
1656 static void ctype_wchar_dtor(ctype_wchar *this)
1657 {
1658     TRACE("(%p)\n", this);
1659     if(this->ctype.delfl)
1660         free((void*)this->ctype.table);
1661 }
1662
1663 DEFINE_THISCALL_WRAPPER(ctype_wchar_vector_dtor, 8)
1664 ctype_wchar* __thiscall ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
1665 {
1666     TRACE("(%p %x)\n", this, flags);
1667     if(flags & 2) {
1668         /* we have an array, with the number of elements stored before the first object */
1669         INT_PTR i, *ptr = (INT_PTR *)this-1;
1670
1671         for(i=*ptr-1; i>=0; i--)
1672             ctype_wchar_dtor(this+i);
1673         MSVCRT_operator_delete(ptr);
1674     } else {
1675         ctype_wchar_dtor(this);
1676         if(flags & 1)
1677             MSVCRT_operator_delete(this);
1678     }
1679
1680     return this;
1681 }
1682
1683 /* _Wcrtomb */
1684 int __cdecl _Wcrtomb(char *s, wchar_t wch, int *state, const _Cvtvec *cvt)
1685 {
1686     int cp, size;
1687     BOOL def;
1688
1689     TRACE("%p %d %p %p\n", s, wch, state, cvt);
1690
1691     if(cvt)
1692         cp = cvt->page;
1693     else
1694         cp = ___lc_codepage_func();
1695
1696     if(!cp) {
1697         if(wch > 255) {
1698            *_errno() = EILSEQ;
1699            return -1;
1700         }
1701
1702         *s = wch & 255;
1703         return 1;
1704     }
1705
1706     size = WideCharToMultiByte(cp, 0, &wch, 1, s, MB_LEN_MAX, NULL, &def);
1707     if(!size || def) {
1708         *_errno() = EILSEQ;
1709         return -1;
1710     }
1711
1712     return size;
1713 }
1714
1715 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
1716 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
1717 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
1718 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
1719 static char ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
1720 {
1721     char buf[MB_LEN_MAX];
1722
1723     TRACE("(%p %d %d)\n", this, ch, dflt);
1724
1725     return _Wcrtomb(buf, ch, NULL, &this->cvt)==1 ? buf[0] : dflt;
1726 }
1727
1728 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
1729 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
1730 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
1731 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
1732 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
1733 #define call_ctype_wchar_do_narrow_ch(this, ch, dflt) CALL_VTBL_FUNC(this, 48, \
1734         char, (const ctype_wchar*, wchar_t, char), (this, ch, dflt))
1735 char __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1736 {
1737     return ctype_wchar__Donarrow(this, ch, dflt);
1738 }
1739
1740 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
1741 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
1742 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
1743 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
1744 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
1745 #define call_ctype_wchar_do_narrow(this, first, last, dflt, dest) CALL_VTBL_FUNC(this, 44, \
1746         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*), \
1747         (this, first, last, dflt, dest))
1748 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
1749         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1750 {
1751     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1752     for(; first<last; first++)
1753         *dest++ = ctype_wchar__Donarrow(this, *first, dflt);
1754     return last;
1755 }
1756
1757 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
1758 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
1759 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
1760 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
1761 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
1762 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1763 {
1764     TRACE("(%p %d %d)\n", this, ch, dflt);
1765     return call_ctype_wchar_do_narrow_ch(this, ch, dflt);
1766 }
1767
1768 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
1769 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
1770 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
1771 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
1772 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
1773 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
1774         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1775 {
1776     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1777     return call_ctype_wchar_do_narrow(this, first, last, dflt, dest);
1778 }
1779
1780 /* _Mbrtowc */
1781 int __cdecl _Mbrtowc(wchar_t *out, const char *in, MSVCP_size_t len, int *state, const _Cvtvec *cvt)
1782 {
1783     int i, cp;
1784     CPINFO cp_info;
1785     BOOL is_lead;
1786
1787     TRACE("(%p %p %lu %p %p)\n", out, in, len, state, cvt);
1788
1789     if(!len)
1790         return 0;
1791
1792     if(cvt)
1793         cp = cvt->page;
1794     else
1795         cp = ___lc_codepage_func();
1796
1797     if(!cp) {
1798         if(out)
1799             *out = (unsigned char)*in;
1800
1801         *state = 0;
1802         return *in ? 1 : 0;
1803     }
1804
1805     if(*state) {
1806         ((char*)state)[1] = *in;
1807
1808         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, (char*)state, 2, out, out ? 1 : 0)) {
1809             *state = 0;
1810             *_errno() = EILSEQ;
1811             return -1;
1812         }
1813
1814         *state = 0;
1815         return 2;
1816     }
1817
1818     GetCPInfo(cp, &cp_info);
1819     is_lead = FALSE;
1820     for(i=0; i<MAX_LEADBYTES; i+=2) {
1821         if(!cp_info.LeadByte[i+1])
1822             break;
1823         if((unsigned char)*in>=cp_info.LeadByte[i] && (unsigned char)*in<=cp_info.LeadByte[i+1]) {
1824             is_lead = TRUE;
1825             break;
1826         }
1827     }
1828
1829     if(is_lead) {
1830         if(len == 1) {
1831             *state = (unsigned char)*in;
1832             return -2;
1833         }
1834
1835         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 2, out, out ? 1 : 0)) {
1836             *_errno() = EILSEQ;
1837             return -1;
1838         }
1839         return 2;
1840     }
1841
1842     if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 1, out, out ? 1 : 0)) {
1843         *_errno() = EILSEQ;
1844         return -1;
1845     }
1846     return 1;
1847 }
1848
1849 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
1850 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
1851 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
1852 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
1853 static wchar_t ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
1854 {
1855     wchar_t ret;
1856     int state = 0;
1857     TRACE("(%p %d)\n", this, ch);
1858     return _Mbrtowc(&ret, &ch, 1, &state, &this->cvt)<0 ? WEOF : ret;
1859 }
1860
1861 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
1862 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
1863 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
1864 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
1865 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
1866 #define call_ctype_wchar_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 40, \
1867         wchar_t, (const ctype_wchar*, char), (this, ch))
1868 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
1869 {
1870     return ctype_wchar__Dowiden(this, ch);
1871 }
1872
1873 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
1874 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
1875 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
1876 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
1877 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
1878 #define call_ctype_wchar_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 36, \
1879         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*), \
1880         (this, first, last, dest))
1881 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
1882         const char *first, const char *last, wchar_t *dest)
1883 {
1884     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1885     for(; first<last; first++)
1886         *dest++ = ctype_wchar__Dowiden(this, *first);
1887     return last;
1888 }
1889
1890 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
1891 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
1892 /* ?widen@?$ctype@G@std@@QBEGD@Z */
1893 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
1894 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
1895 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
1896 {
1897     TRACE("(%p %d)\n", this, ch);
1898     return call_ctype_wchar_do_widen_ch(this, ch);
1899 }
1900
1901 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
1902 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
1903 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
1904 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
1905 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
1906 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
1907         const char *first, const char *last, wchar_t *dest)
1908 {
1909     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1910     return call_ctype_wchar_do_widen(this, first, last, dest);
1911 }
1912
1913 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1914 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1915 static MSVCP_size_t ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
1916 {
1917     TRACE("(%p %p)\n", facet, loc);
1918
1919     if(facet && !*facet) {
1920         _Locinfo locinfo;
1921
1922         *facet = MSVCRT_operator_new(sizeof(ctype_wchar));
1923         if(!*facet) {
1924             ERR("Out of memory\n");
1925             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1926             return 0;
1927         }
1928
1929         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
1930         ctype_wchar_ctor_locinfo((ctype_wchar*)*facet, &locinfo, 0);
1931         _Locinfo_dtor(&locinfo);
1932     }
1933
1934     return LC_CTYPE;
1935 }
1936
1937 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1938 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1939 static MSVCP_size_t ctype_short__Getcat(const locale_facet **facet, const locale *loc)
1940 {
1941     if(facet && !*facet) {
1942         ctype_wchar__Getcat(facet, loc);
1943         (*(locale_facet**)facet)->vtable = &MSVCP_ctype_short_vtable;
1944     }
1945
1946     return LC_CTYPE;
1947 }
1948
1949 /* _Towlower */
1950 static wchar_t _Towlower(wchar_t ch, const _Ctypevec *ctype)
1951 {
1952     TRACE("(%d %p)\n", ch, ctype);
1953     return tolowerW(ch);
1954 }
1955
1956 ctype_wchar* ctype_wchar_use_facet(const locale *loc)
1957 {
1958     static ctype_wchar *obj = NULL;
1959
1960     _Lockit lock;
1961     const locale_facet *fac;
1962
1963     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1964     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_wchar_id));
1965     if(fac) {
1966         _Lockit_dtor(&lock);
1967         return (ctype_wchar*)fac;
1968     }
1969
1970     if(obj) {
1971         _Lockit_dtor(&lock);
1972         return obj;
1973     }
1974
1975     ctype_wchar__Getcat(&fac, loc);
1976     obj = (ctype_wchar*)fac;
1977     locale_facet__Incref(&obj->base.facet);
1978     locale_facet_register(&obj->base.facet);
1979     _Lockit_dtor(&lock);
1980
1981     return obj;
1982 }
1983
1984 ctype_wchar* ctype_short_use_facet(const locale *loc)
1985 {
1986     static ctype_wchar *obj = NULL;
1987
1988     _Lockit lock;
1989     const locale_facet *fac;
1990
1991     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1992     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_short_id));
1993     if(fac) {
1994         _Lockit_dtor(&lock);
1995         return (ctype_wchar*)fac;
1996     }
1997
1998     if(obj) {
1999         _Lockit_dtor(&lock);
2000         return obj;
2001     }
2002
2003     ctype_short__Getcat(&fac, loc);
2004     obj = (ctype_wchar*)fac;
2005     locale_facet__Incref(&obj->base.facet);
2006     locale_facet_register(&obj->base.facet);
2007     _Lockit_dtor(&lock);
2008
2009     return obj;
2010 }
2011
2012 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
2013 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
2014 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
2015 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
2016 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
2017 #define call_ctype_wchar_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
2018         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2019 wchar_t __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
2020 {
2021     return _Towlower(ch, &this->ctype);
2022 }
2023
2024 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2025 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2026 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2027 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2028 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
2029 #define call_ctype_wchar_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 20, \
2030         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2031         (this, first, last))
2032 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
2033         wchar_t *first, const wchar_t *last)
2034 {
2035     TRACE("(%p %p %p)\n", this, first, last);
2036     for(; first<last; first++)
2037         *first = _Towlower(*first, &this->ctype);
2038     return last;
2039 }
2040
2041 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
2042 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
2043 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
2044 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
2045 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
2046 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
2047 {
2048     TRACE("(%p %d)\n", this, ch);
2049     return call_ctype_wchar_do_tolower_ch(this, ch);
2050 }
2051
2052 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2053 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2054 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2055 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2056 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
2057 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
2058         wchar_t *first, const wchar_t *last)
2059 {
2060     TRACE("(%p %p %p)\n", this, first, last);
2061     return call_ctype_wchar_do_tolower(this, first, last);
2062 }
2063
2064 /* _Towupper */
2065 static wchar_t _Towupper(wchar_t ch, const _Ctypevec *ctype)
2066 {
2067     TRACE("(%d %p)\n", ch, ctype);
2068     return toupperW(ch);
2069 }
2070
2071 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
2072 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
2073 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
2074 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
2075 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
2076 #define call_ctype_wchar_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 32, \
2077         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2078 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
2079 {
2080     return _Towupper(ch, &this->ctype);
2081 }
2082
2083 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2084 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2085 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2086 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2087 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
2088 #define call_ctype_wchar_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 28, \
2089         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2090         (this, first, last))
2091 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
2092         wchar_t *first, const wchar_t *last)
2093 {
2094     TRACE("(%p %p %p)\n", this, first, last);
2095     for(; first<last; first++)
2096         *first = _Towupper(*first, &this->ctype);
2097     return last;
2098 }
2099
2100 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
2101 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
2102 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
2103 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
2104 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
2105 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
2106 {
2107     TRACE("(%p %d)\n", this, ch);
2108     return call_ctype_wchar_do_toupper_ch(this, ch);
2109 }
2110
2111 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2112 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2113 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2114 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2115 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
2116 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
2117         wchar_t *first, const wchar_t *last)
2118 {
2119     TRACE("(%p %p %p)\n", this, first, last);
2120     return call_ctype_wchar_do_toupper(this, first, last);
2121 }
2122
2123 /* _Getwctypes */
2124 static const wchar_t* _Getwctypes(const wchar_t *first, const wchar_t *last,
2125         short *mask, const _Ctypevec *ctype)
2126 {
2127     TRACE("(%p %p %p %p)\n", first, last, mask, ctype);
2128     GetStringTypeW(CT_CTYPE1, first, last-first, (WORD*)mask);
2129     return last;
2130 }
2131
2132 /* _Getwctype */
2133 static short _Getwctype(wchar_t ch, const _Ctypevec *ctype)
2134 {
2135     short mask = 0;
2136     _Getwctypes(&ch, &ch+1, &mask, ctype);
2137     return mask;
2138 }
2139
2140 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
2141 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
2142 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
2143 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
2144 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
2145 #define call_ctype_wchar_do_is_ch(this, mask, ch) CALL_VTBL_FUNC(this, 8, \
2146         MSVCP_bool, (const ctype_wchar*, short, wchar_t), (this, mask, ch))
2147 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2148 {
2149     TRACE("(%p %x %d)\n", this, mask, ch);
2150     return (_Getwctype(ch, &this->ctype) & mask) != 0;
2151 }
2152
2153 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
2154 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
2155 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
2156 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
2157 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
2158 #define call_ctype_wchar_do_is(this, first, last, dest) CALL_VTBL_FUNC(this, 4, \
2159         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, short*), \
2160         (this, first, last, dest))
2161 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
2162         const wchar_t *first, const wchar_t *last, short *dest)
2163 {
2164     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2165     return _Getwctypes(first, last, dest, &this->ctype);
2166 }
2167
2168 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
2169 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
2170 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
2171 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
2172 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
2173 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2174 {
2175     TRACE("(%p %x %d)\n", this, mask, ch);
2176     return call_ctype_wchar_do_is_ch(this, mask, ch);
2177 }
2178
2179 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
2180 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
2181 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
2182 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
2183 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
2184 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
2185         const wchar_t *first, const wchar_t *last, short *dest)
2186 {
2187     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2188     return call_ctype_wchar_do_is(this, first, last, dest);
2189 }
2190
2191 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2192 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2193 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
2194 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2195 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
2196 #define call_ctype_wchar_do_scan_is(this, mask, first, last) CALL_VTBL_FUNC(this, 12, \
2197         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2198         (this, mask, first, last))
2199 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
2200         short mask, const wchar_t *first, const wchar_t *last)
2201 {
2202     TRACE("(%p %d %p %p)\n", this, mask, first, last);
2203     for(; first<last; first++)
2204         if(!ctype_wchar_is_ch(this, mask, *first))
2205             break;
2206     return first;
2207 }
2208
2209 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2210 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2211 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
2212 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2213 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
2214 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
2215         short mask, const wchar_t *first, const wchar_t *last)
2216 {
2217     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2218     return call_ctype_wchar_do_scan_is(this, mask, first, last);
2219 }
2220
2221 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2222 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2223 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2224 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2225 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2226 #define call_ctype_wchar_do_scan_not(this, mask, first, last) CALL_VTBL_FUNC(this, 16, \
2227         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2228         (this, mask, first, last))
2229 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2230         short mask, const wchar_t *first, const wchar_t *last)
2231 {
2232     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2233     for(; first<last; first++)
2234         if(ctype_wchar_is_ch(this, mask, *first))
2235             break;
2236     return first;
2237 }
2238
2239 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2240 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2241 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2242 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2243 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2244 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2245         short mask, const wchar_t *first, const wchar_t *last)
2246 {
2247     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2248     return call_ctype_wchar_do_scan_not(this, mask, first, last);
2249 }
2250
2251 /* ??_7codecvt_base@std@@6B@ */
2252 extern const vtable_ptr MSVCP_codecvt_base_vtable;
2253
2254 /* ??0codecvt_base@std@@QAE@I@Z */
2255 /* ??0codecvt_base@std@@QEAA@_K@Z */
2256 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor_refs, 8)
2257 codecvt_base* __thiscall codecvt_base_ctor_refs(codecvt_base *this, MSVCP_size_t refs)
2258 {
2259     TRACE("(%p %lu)\n", this, refs);
2260     locale_facet_ctor_refs(&this->facet, refs);
2261     this->facet.vtable = &MSVCP_codecvt_base_vtable;
2262     return this;
2263 }
2264
2265 /* ??_Fcodecvt_base@std@@QAEXXZ */
2266 /* ??_Fcodecvt_base@std@@QEAAXXZ */
2267 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor, 4)
2268 codecvt_base* __thiscall codecvt_base_ctor(codecvt_base *this)
2269 {
2270     return codecvt_base_ctor_refs(this, 0);
2271 }
2272
2273 /* ??1codecvt_base@std@@UAE@XZ */
2274 /* ??1codecvt_base@std@@UEAA@XZ */
2275 DEFINE_THISCALL_WRAPPER(codecvt_base_dtor, 4)
2276 void __thiscall codecvt_base_dtor(codecvt_base *this)
2277 {
2278     TRACE("(%p)\n", this);
2279     locale_facet_dtor(&this->facet);
2280 }
2281
2282 DEFINE_THISCALL_WRAPPER(codecvt_base_vector_dtor, 8)
2283 codecvt_base* __thiscall codecvt_base_vector_dtor(codecvt_base *this, unsigned int flags)
2284 {
2285     TRACE("(%p %x)\n", this, flags);
2286     if(flags & 2) {
2287         /* we have an array, with the number of elements stored before the first object */
2288         INT_PTR i, *ptr = (INT_PTR *)this-1;
2289
2290         for(i=*ptr-1; i>=0; i--)
2291             codecvt_base_dtor(this+i);
2292         MSVCRT_operator_delete(ptr);
2293     } else {
2294         codecvt_base_dtor(this);
2295         if(flags & 1)
2296             MSVCRT_operator_delete(this);
2297     }
2298
2299     return this;
2300 }
2301
2302 /* ?do_always_noconv@codecvt_base@std@@MBE_NXZ */
2303 /* ?do_always_noconv@codecvt_base@std@@MEBA_NXZ */
2304 #define call_codecvt_base_do_always_noconv(this) CALL_VTBL_FUNC(this, 4, \
2305         MSVCP_bool, (const codecvt_base*), (this))
2306 DEFINE_THISCALL_WRAPPER(codecvt_base_do_always_noconv, 4)
2307 MSVCP_bool __thiscall codecvt_base_do_always_noconv(const codecvt_base *this)
2308 {
2309     TRACE("(%p)\n", this);
2310     return TRUE;
2311 }
2312
2313 /* ?always_noconv@codecvt_base@std@@QBE_NXZ */
2314 /* ?always_noconv@codecvt_base@std@@QEBA_NXZ */
2315 DEFINE_THISCALL_WRAPPER(codecvt_base_always_noconv, 4)
2316 MSVCP_bool __thiscall codecvt_base_always_noconv(const codecvt_base *this)
2317 {
2318     TRACE("(%p)\n", this);
2319     return call_codecvt_base_do_always_noconv(this);
2320 }
2321
2322 /* ?do_max_length@codecvt_base@std@@MBEHXZ */
2323 /* ?do_max_length@codecvt_base@std@@MEBAHXZ */
2324 #define call_codecvt_base_do_max_length(this) CALL_VTBL_FUNC(this, 8, \
2325         int, (const codecvt_base*), (this))
2326 DEFINE_THISCALL_WRAPPER(codecvt_base_do_max_length, 4)
2327 int __thiscall codecvt_base_do_max_length(const codecvt_base *this)
2328 {
2329     TRACE("(%p)\n", this);
2330     return 1;
2331 }
2332
2333 /* ?max_length@codecvt_base@std@@QBEHXZ */
2334 /* ?max_length@codecvt_base@std@@QEBAHXZ */
2335 DEFINE_THISCALL_WRAPPER(codecvt_base_max_length, 4)
2336 int __thiscall codecvt_base_max_length(const codecvt_base *this)
2337 {
2338     TRACE("(%p)\n", this);
2339     return call_codecvt_base_do_max_length(this);
2340 }
2341
2342 /* ?do_encoding@codecvt_base@std@@MBEHXZ */
2343 /* ?do_encoding@codecvt_base@std@@MEBAHXZ */
2344 #define call_codecvt_base_do_encoding(this) CALL_VTBL_FUNC(this, 12, \
2345         int, (const codecvt_base*), (this))
2346 DEFINE_THISCALL_WRAPPER(codecvt_base_do_encoding, 4)
2347 int __thiscall codecvt_base_do_encoding(const codecvt_base *this)
2348 {
2349     TRACE("(%p)\n", this);
2350     return 1;
2351 }
2352
2353 /* ?encoding@codecvt_base@std@@QBEHXZ */
2354 /* ?encoding@codecvt_base@std@@QEBAHXZ */
2355 DEFINE_THISCALL_WRAPPER(codecvt_base_encoding, 4)
2356 int __thiscall codecvt_base_encoding(const codecvt_base *this)
2357 {
2358     TRACE("(%p)\n", this);
2359     return call_codecvt_base_do_encoding(this);
2360 }
2361
2362 /* ?id@?$codecvt@DDH@std@@2V0locale@2@A */
2363 locale_id codecvt_char_id = {0};
2364
2365 /* ??_7?$codecvt@DDH@std@@6B@ */
2366 extern const vtable_ptr MSVCP_codecvt_char_vtable;
2367
2368 /* ?_Init@?$codecvt@DDH@std@@IAEXABV_Locinfo@2@@Z */
2369 /* ?_Init@?$codecvt@DDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2370 DEFINE_THISCALL_WRAPPER(codecvt_char__Init, 8)
2371 void __thiscall codecvt_char__Init(codecvt_char *this, const _Locinfo *locinfo)
2372 {
2373     TRACE("(%p %p)\n", this, locinfo);
2374 }
2375
2376 /* ??0?$codecvt@DDH@std@@QAE@ABV_Locinfo@1@I@Z */
2377 /* ??0?$codecvt@DDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2378 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_locinfo, 12)
2379 codecvt_char* __thiscall codecvt_char_ctor_locinfo(codecvt_char *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2380 {
2381     TRACE("(%p %p %lu)\n", this, locinfo, refs);
2382     codecvt_base_ctor_refs(&this->base, refs);
2383     this->base.facet.vtable = &MSVCP_codecvt_char_vtable;
2384     return this;
2385 }
2386
2387 /* ??0?$codecvt@DDH@std@@QAE@I@Z */
2388 /* ??0?$codecvt@DDH@std@@QEAA@_K@Z */
2389 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_refs, 8)
2390 codecvt_char* __thiscall codecvt_char_ctor_refs(codecvt_char *this, MSVCP_size_t refs)
2391 {
2392     return codecvt_char_ctor_locinfo(this, NULL, refs);
2393 }
2394
2395 /* ??_F?$codecvt@DDH@std@@QAEXXZ */
2396 /* ??_F?$codecvt@DDH@std@@QEAAXXZ */
2397 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor, 4)
2398 codecvt_char* __thiscall codecvt_char_ctor(codecvt_char *this)
2399 {
2400     return codecvt_char_ctor_locinfo(this, NULL, 0);
2401 }
2402
2403 /* ??1?$codecvt@DDH@std@@MAE@XZ */
2404 /* ??1?$codecvt@DDH@std@@MEAA@XZ */
2405 static void codecvt_char_dtor(codecvt_char *this)
2406 {
2407     TRACE("(%p)\n", this);
2408     codecvt_base_dtor(&this->base);
2409 }
2410
2411 DEFINE_THISCALL_WRAPPER(codecvt_char_vector_dtor, 8)
2412 codecvt_char* __thiscall codecvt_char_vector_dtor(codecvt_char *this, unsigned int flags)
2413 {
2414     TRACE("(%p %x)\n", this, flags);
2415     if(flags & 2) {
2416         /* we have an array, with the number of elements stored before the first object */
2417         INT_PTR i, *ptr = (INT_PTR *)this-1;
2418
2419         for(i=*ptr-1; i>=0; i--)
2420             codecvt_char_dtor(this+i);
2421         MSVCRT_operator_delete(ptr);
2422     } else {
2423         codecvt_char_dtor(this);
2424         if(flags & 1)
2425             MSVCRT_operator_delete(this);
2426     }
2427
2428     return this;
2429 }
2430
2431 /* ?_Getcat@?$codecvt@DDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2432 /* ?_Getcat@?$codecvt@DDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2433 static MSVCP_size_t codecvt_char__Getcat(const locale_facet **facet, const locale *loc)
2434 {
2435     TRACE("(%p %p)\n", facet, loc);
2436
2437     if(facet && !*facet) {
2438         *facet = MSVCRT_operator_new(sizeof(codecvt_char));
2439         if(!*facet) {
2440             ERR("Out of memory\n");
2441             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2442             return 0;
2443         }
2444         codecvt_char_ctor((codecvt_char*)*facet);
2445     }
2446
2447     return LC_CTYPE;
2448 }
2449
2450 codecvt_char* codecvt_char_use_facet(const locale *loc)
2451 {
2452     static codecvt_char *obj = NULL;
2453
2454     _Lockit lock;
2455     const locale_facet *fac;
2456
2457     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2458     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_char_id));
2459     if(fac) {
2460         _Lockit_dtor(&lock);
2461         return (codecvt_char*)fac;
2462     }
2463
2464     if(obj) {
2465         _Lockit_dtor(&lock);
2466         return obj;
2467     }
2468
2469     codecvt_char__Getcat(&fac, loc);
2470     obj = (codecvt_char*)fac;
2471     locale_facet__Incref(&obj->base.facet);
2472     locale_facet_register(&obj->base.facet);
2473     _Lockit_dtor(&lock);
2474
2475     return obj;
2476 }
2477
2478 /* ?do_in@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2479 /* ?do_in@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2480 #define call_codecvt_char_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2481     CALL_VTBL_FUNC(this, 16, int, \
2482             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2483             (this, state, from, from_end, from_next, to, to_end, to_next))
2484 DEFINE_THISCALL_WRAPPER(codecvt_char_do_in, 32)
2485 int __thiscall codecvt_char_do_in(const codecvt_char *this, int *state,
2486         const char *from, const char *from_end, const char **from_next,
2487         char *to, char *to_end, char **to_next)
2488 {
2489     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2490             from_next, to, to_end, to_next);
2491     *from_next = from;
2492     *to_next = to;
2493     return CODECVT_noconv;
2494 }
2495
2496 /* ?in@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2497 /* ?in@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2498 DEFINE_THISCALL_WRAPPER(codecvt_char_in, 32)
2499 int __thiscall codecvt_char_in(const codecvt_char *this, int *state,
2500         const char *from, const char *from_end, const char **from_next,
2501         char *to, char *to_end, char **to_next)
2502 {
2503     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2504             from_next, to, to_end, to_next);
2505     return call_codecvt_char_do_in(this, state, from, from_end, from_next,
2506             to, to_end, to_next);
2507 }
2508
2509 /* ?do_out@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2510 /* ?do_out@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2511 #define call_codecvt_char_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2512     CALL_VTBL_FUNC(this, 20, int, \
2513             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2514             (this, state, from, from_end, from_next, to, to_end, to_next))
2515 DEFINE_THISCALL_WRAPPER(codecvt_char_do_out, 32)
2516 int __thiscall codecvt_char_do_out(const codecvt_char *this, int *state,
2517         const char *from, const char *from_end, const char **from_next,
2518         char *to, char *to_end, char **to_next)
2519 {
2520     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2521             from_end, from_next, to, to_end, to_next);
2522     *from_next = from;
2523     *to_next = to;
2524     return CODECVT_noconv;
2525 }
2526
2527 /* ?out@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2528 /* ?out@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2529 DEFINE_THISCALL_WRAPPER(codecvt_char_out, 32)
2530 int __thiscall codecvt_char_out(const codecvt_char *this, int *state,
2531         const char *from, const char *from_end, const char **from_next,
2532         char *to, char *to_end, char **to_next)
2533 {
2534     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2535             from_next, to, to_end, to_next);
2536     return call_codecvt_char_do_out(this, state, from, from_end, from_next,
2537             to, to_end, to_next);
2538 }
2539
2540 /* ?do_unshift@?$codecvt@DDH@std@@MBEHAAHPAD1AAPAD@Z */
2541 /* ?do_unshift@?$codecvt@DDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2542 #define call_codecvt_char_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2543         int, (const codecvt_char*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2544 DEFINE_THISCALL_WRAPPER(codecvt_char_do_unshift, 20)
2545 int __thiscall codecvt_char_do_unshift(const codecvt_char *this,
2546         int *state, char *to, char *to_end, char **to_next)
2547 {
2548     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2549     *to_next = to;
2550     return CODECVT_noconv;
2551 }
2552
2553 /* ?unshift@?$codecvt@DDH@std@@QBEHAAHPAD1AAPAD@Z */
2554 /* ?unshift@?$codecvt@DDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2555 int codecvt_char_unshift(const codecvt_char *this,
2556         int *state, char *to, char *to_end, char **to_next)
2557 {
2558     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2559     return call_codecvt_char_do_unshift(this, state, to, to_end, to_next);
2560 }
2561
2562 /* ?do_length@?$codecvt@DDH@std@@MBEHABHPBD1I@Z */
2563 /* ?do_length@?$codecvt@DDH@std@@MEBAHAEBHPEBD1_K@Z */
2564 #define call_codecvt_char_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2565         int, (const codecvt_char*, const int*, const char*, const char*, MSVCP_size_t), \
2566         (this, state, from, from_end, max))
2567 DEFINE_THISCALL_WRAPPER(codecvt_char_do_length, 20)
2568 int __thiscall codecvt_char_do_length(const codecvt_char *this, const int *state,
2569         const char *from, const char *from_end, MSVCP_size_t max)
2570 {
2571     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2572     return (from_end-from > max ? max : from_end-from);
2573 }
2574
2575 /* ?id@?$codecvt@_WDH@std@@2V0locale@2@A */
2576 static locale_id codecvt_wchar_id = {0};
2577 /* ?id@?$codecvt@GDH@std@@2V0locale@2@A */
2578 locale_id codecvt_short_id = {0};
2579
2580 /* ??_7?$codecvt@_WDH@std@@6B@ */
2581 extern const vtable_ptr MSVCP_codecvt_wchar_vtable;
2582 /* ??_7?$codecvt@GDH@std@@6B@ */
2583 extern const vtable_ptr MSVCP_codecvt_short_vtable;
2584
2585 /* ?_Init@?$codecvt@GDH@std@@IAEXABV_Locinfo@2@@Z */
2586 /* ?_Init@?$codecvt@GDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2587 /* ?_Init@?$codecvt@_WDH@std@@IAEXABV_Locinfo@2@@Z */
2588 /* ?_Init@?$codecvt@_WDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2589 DEFINE_THISCALL_WRAPPER(codecvt_wchar__Init, 8)
2590 void __thiscall codecvt_wchar__Init(codecvt_wchar *this, const _Locinfo *locinfo)
2591 {
2592     TRACE("(%p %p)\n", this, locinfo);
2593     _Locinfo__Getcvt(locinfo, &this->cvt);
2594 }
2595
2596 /* ??0?$codecvt@_WDH@std@@QAE@ABV_Locinfo@1@I@Z */
2597 /* ??0?$codecvt@_WDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2598 static codecvt_wchar* codecvt_wchar_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2599 {
2600     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2601
2602     codecvt_base_ctor_refs(&this->base, refs);
2603     this->base.facet.vtable = &MSVCP_codecvt_wchar_vtable;
2604
2605     codecvt_wchar__Init(this, locinfo);
2606     return this;
2607 }
2608
2609 /* ??0?$codecvt@GDH@std@@QAE@ABV_Locinfo@1@I@Z */
2610 /* ??0?$codecvt@GDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2611 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_locinfo, 12)
2612 codecvt_wchar* __thiscall codecvt_short_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2613 {
2614     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2615
2616     codecvt_wchar_ctor_locinfo(this, locinfo, refs);
2617     this->base.facet.vtable = &MSVCP_codecvt_short_vtable;
2618     return this;
2619 }
2620
2621 /* ??0?$codecvt@GDH@std@@QAE@I@Z */
2622 /* ??0?$codecvt@GDH@std@@QEAA@_K@Z */
2623 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_refs, 8)
2624 codecvt_wchar* __thiscall codecvt_short_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
2625 {
2626     _Locinfo locinfo;
2627
2628     TRACE("(%p %ld)\n", this, refs);
2629
2630     _Locinfo_ctor(&locinfo);
2631     codecvt_short_ctor_locinfo(this, &locinfo, refs);
2632     _Locinfo_dtor(&locinfo);
2633     return this;
2634 }
2635
2636 /* ??_F?$codecvt@GDH@std@@QAEXXZ */
2637 /* ??_F?$codecvt@GDH@std@@QEAAXXZ */
2638 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor, 4)
2639 codecvt_wchar* __thiscall codecvt_short_ctor(codecvt_wchar *this)
2640 {
2641     return codecvt_short_ctor_refs(this, 0);
2642 }
2643
2644 /* ??1?$codecvt@GDH@std@@MAE@XZ */
2645 /* ??1?$codecvt@GDH@std@@MEAA@XZ */
2646 /* ??1?$codecvt@_WDH@std@@MAE@XZ */
2647 /* ??1?$codecvt@_WDH@std@@MEAA@XZ */
2648 static void codecvt_wchar_dtor(codecvt_wchar *this)
2649 {
2650     TRACE("(%p)\n", this);
2651     codecvt_base_dtor(&this->base);
2652 }
2653
2654 DEFINE_THISCALL_WRAPPER(codecvt_wchar_vector_dtor, 8)
2655 codecvt_wchar* __thiscall codecvt_wchar_vector_dtor(codecvt_wchar *this, unsigned int flags)
2656 {
2657     TRACE("(%p %x)\n", this, flags);
2658     if(flags & 2) {
2659         /* we have an array, with the number of elements stored before the first object */
2660         INT_PTR i, *ptr = (INT_PTR *)this-1;
2661
2662         for(i=*ptr-1; i>=0; i--)
2663             codecvt_wchar_dtor(this+i);
2664         MSVCRT_operator_delete(ptr);
2665     } else {
2666         codecvt_wchar_dtor(this);
2667         if(flags & 1)
2668             MSVCRT_operator_delete(this);
2669     }
2670
2671     return this;
2672 }
2673
2674 /* ?_Getcat@?$codecvt@_WDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2675 /* ?_Getcat@?$codecvt@_WDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2676 static MSVCP_size_t codecvt_wchar__Getcat(const locale_facet **facet, const locale *loc)
2677 {
2678     TRACE("(%p %p)\n", facet, loc);
2679
2680     if(facet && !*facet) {
2681         _Locinfo locinfo;
2682
2683         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2684         if(!*facet) {
2685             ERR("Out of memory\n");
2686             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2687             return 0;
2688         }
2689
2690         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
2691         codecvt_wchar_ctor_locinfo((codecvt_wchar*)*facet, &locinfo, 0);
2692         _Locinfo_dtor(&locinfo);
2693     }
2694
2695     return LC_CTYPE;
2696 }
2697
2698 codecvt_wchar* codecvt_wchar_use_facet(const locale *loc)
2699 {
2700     static codecvt_wchar *obj = NULL;
2701
2702     _Lockit lock;
2703     const locale_facet *fac;
2704
2705     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2706     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_wchar_id));
2707     if(fac) {
2708         _Lockit_dtor(&lock);
2709         return (codecvt_wchar*)fac;
2710     }
2711
2712     if(obj) {
2713         _Lockit_dtor(&lock);
2714         return obj;
2715     }
2716
2717     codecvt_wchar__Getcat(&fac, loc);
2718     obj = (codecvt_wchar*)fac;
2719     locale_facet__Incref(&obj->base.facet);
2720     locale_facet_register(&obj->base.facet);
2721     _Lockit_dtor(&lock);
2722
2723     return obj;
2724 }
2725
2726 /* ?_Getcat@?$codecvt@GDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2727 /* ?_Getcat@?$codecvt@GDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2728 static MSVCP_size_t codecvt_short__Getcat(const locale_facet **facet, const locale *loc)
2729 {
2730     TRACE("(%p %p)\n", facet, loc);
2731
2732     if(facet && !*facet) {
2733         _Locinfo locinfo;
2734
2735         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2736         if(!*facet) {
2737             ERR("Out of memory\n");
2738             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2739             return 0;
2740         }
2741
2742         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
2743         codecvt_short_ctor((codecvt_wchar*)*facet);
2744         _Locinfo_dtor(&locinfo);
2745     }
2746
2747     return LC_CTYPE;
2748 }
2749
2750 codecvt_wchar* codecvt_short_use_facet(const locale *loc)
2751 {
2752     static codecvt_wchar *obj = NULL;
2753
2754     _Lockit lock;
2755     const locale_facet *fac;
2756
2757     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2758     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_short_id));
2759     if(fac) {
2760         _Lockit_dtor(&lock);
2761         return (codecvt_wchar*)fac;
2762     }
2763
2764     if(obj) {
2765         _Lockit_dtor(&lock);
2766         return obj;
2767     }
2768
2769     codecvt_short__Getcat(&fac, loc);
2770     obj = (codecvt_wchar*)fac;
2771     locale_facet__Incref(&obj->base.facet);
2772     locale_facet_register(&obj->base.facet);
2773     _Lockit_dtor(&lock);
2774
2775     return obj;
2776 }
2777
2778 /* ?do_always_noconv@?$codecvt@GDH@std@@MBE_NXZ */
2779 /* ?do_always_noconv@?$codecvt@GDH@std@@MEBA_NXZ */
2780 /* ?do_always_noconv@?$codecvt@_WDH@std@@MBE_NXZ */
2781 /* ?do_always_noconv@?$codecvt@_WDH@std@@MEBA_NXZ */
2782 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_always_noconv, 4)
2783 MSVCP_bool __thiscall codecvt_wchar_do_always_noconv(const codecvt_wchar *this)
2784 {
2785     TRACE("(%p)\n", this);
2786     return FALSE;
2787 }
2788
2789 /* ?do_max_length@?$codecvt@GDH@std@@MBEHXZ */
2790 /* ?do_max_length@?$codecvt@GDH@std@@MEBAHXZ */
2791 /* ?do_max_length@?$codecvt@_WDH@std@@MBEHXZ */
2792 /* ?do_max_length@?$codecvt@_WDH@std@@MEBAHXZ */
2793 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_max_length, 4)
2794 int __thiscall codecvt_wchar_do_max_length(const codecvt_wchar *this)
2795 {
2796     TRACE("(%p)\n", this);
2797     return MB_LEN_MAX;
2798 }
2799
2800 /* ?do_in@?$codecvt@GDH@std@@MBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2801 /* ?do_in@?$codecvt@GDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2802 /* ?do_in@?$codecvt@_WDH@std@@MBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2803 /* ?do_in@?$codecvt@_WDH@std@@MEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2804 #define call_codecvt_wchar_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2805     CALL_VTBL_FUNC(this, 16, int, \
2806             (const codecvt_wchar*, int*, const char*, const char*, const char**, wchar_t*, wchar_t*, wchar_t**), \
2807             (this, state, from, from_end, from_next, to, to_end, to_next))
2808 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_in, 32)
2809 int __thiscall codecvt_wchar_do_in(const codecvt_wchar *this, int *state,
2810         const char *from, const char *from_end, const char **from_next,
2811         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2812 {
2813     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2814             from_end, from_next, to, to_end, to_next);
2815
2816     *from_next = from;
2817     *to_next = to;
2818
2819     while(*from_next!=from_end && *to_next!=to_end) {
2820         switch(_Mbrtowc(*to_next, *from_next, from_end-*from_next, state, &this->cvt)) {
2821         case -2:
2822             *from_next = from_end;
2823             return CODECVT_partial;
2824         case -1:
2825             return CODECVT_error;
2826         case 2:
2827             (*from_next)++;
2828             /* fall through */
2829         case 0:
2830         case 1:
2831             (*from_next)++;
2832             (*to_next)++;
2833         }
2834     }
2835
2836     return CODECVT_ok;
2837 }
2838
2839 /* ?in@?$codecvt@GDH@std@@QBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2840 /* ?in@?$codecvt@GDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2841 /* ?in@?$codecvt@_WDH@std@@QBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2842 /* ?in@?$codecvt@_WDH@std@@QEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2843 DEFINE_THISCALL_WRAPPER(codecvt_wchar_in, 32)
2844 int __thiscall codecvt_wchar_in(const codecvt_wchar *this, int *state,
2845         const char *from, const char *from_end, const char **from_next,
2846         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2847 {
2848     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2849             from_end, from_next, to, to_end, to_next);
2850     return call_codecvt_wchar_do_in(this, state, from,
2851             from_end, from_next, to, to_end, to_next);
2852 }
2853
2854 /* ?do_out@?$codecvt@GDH@std@@MBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2855 /* ?do_out@?$codecvt@GDH@std@@MEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2856 /* ?do_out@?$codecvt@_WDH@std@@MBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2857 /* ?do_out@?$codecvt@_WDH@std@@MEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2858 #define call_codecvt_wchar_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2859     CALL_VTBL_FUNC(this, 20, int, \
2860             (const codecvt_wchar*, int*, const wchar_t*, const wchar_t*, const wchar_t**, char*, char*, char**), \
2861             (this, state, from, from_end, from_next, to, to_end, to_next))
2862 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_out, 32)
2863 int __thiscall codecvt_wchar_do_out(const codecvt_wchar *this, int *state,
2864         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2865         char *to, char *to_end, char **to_next)
2866 {
2867     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2868             from_end, from_next, to, to_end, to_next);
2869
2870     *from_next = from;
2871     *to_next = to;
2872
2873     while(*from_next!=from_end && *to_next!=to_end) {
2874         int old_state = *state, size;
2875         char buf[MB_LEN_MAX];
2876
2877         switch((size = _Wcrtomb(buf, **from_next, state, &this->cvt))) {
2878         case -1:
2879             return CODECVT_error;
2880         default:
2881             if(size > from_end-*from_next) {
2882                 *state = old_state;
2883                 return CODECVT_partial;
2884             }
2885
2886             (*from_next)++;
2887             memcpy_s(*to_next, to_end-*to_next, buf, size);
2888             (*to_next) += size;
2889         }
2890     }
2891
2892     return CODECVT_ok;
2893 }
2894
2895 /* ?out@?$codecvt@GDH@std@@QBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2896 /* ?out@?$codecvt@GDH@std@@QEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2897 /* ?out@?$codecvt@_WDH@std@@QBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2898 /* ?out@?$codecvt@_WDH@std@@QEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2899 DEFINE_THISCALL_WRAPPER(codecvt_wchar_out, 32)
2900 int __thiscall codecvt_wchar_out(const codecvt_wchar *this, int *state,
2901         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2902         char *to, char *to_end, char **to_next)
2903 {
2904     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2905             from_end, from_next, to, to_end, to_next);
2906     return call_codecvt_wchar_do_out(this, state, from,
2907             from_end, from_next, to, to_end, to_next);
2908 }
2909
2910 /* ?do_unshift@?$codecvt@GDH@std@@MBEHAAHPAD1AAPAD@Z */
2911 /* ?do_unshift@?$codecvt@GDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2912 /* ?do_unshift@?$codecvt@_WDH@std@@MBEHAAHPAD1AAPAD@Z */
2913 /* ?do_unshift@?$codecvt@_WDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2914 #define call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2915         int, (const codecvt_wchar*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2916 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_unshift, 20)
2917 int __thiscall codecvt_wchar_do_unshift(const codecvt_wchar *this,
2918         int *state, char *to, char *to_end, char **to_next)
2919 {
2920     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2921     if(*state)
2922         WARN("unexpected state: %x\n", *state);
2923
2924     *to_next = to;
2925     return CODECVT_ok;
2926 }
2927
2928 /* ?unshift@?$codecvt@GDH@std@@QBEHAAHPAD1AAPAD@Z */
2929 /* ?unshift@?$codecvt@GDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2930 /* ?unshift@?$codecvt@_WDH@std@@QBEHAAHPAD1AAPAD@Z */
2931 /* ?unshift@?$codecvt@_WDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2932 int codecvt_wchar_unshift(const codecvt_wchar *this,
2933         int *state, char *to, char *to_end, char **to_next)
2934 {
2935     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2936     return call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next);
2937 }
2938
2939 /* ?do_length@?$codecvt@GDH@std@@MBEHABHPBD1I@Z */
2940 /* ?do_length@?$codecvt@GDH@std@@MEBAHAEBHPEBD1_K@Z */
2941 /* ?do_length@?$codecvt@_WDH@std@@MBEHABHPBD1I@Z */
2942 /* ?do_length@?$codecvt@_WDH@std@@MEBAHAEBHPEBD1_K@Z */
2943 #define call_codecvt_wchar_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2944         int, (const codecvt_wchar*, const int*, const char*, const char*, MSVCP_size_t), \
2945         (this, state, from, from_end, max))
2946 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_length, 20)
2947 int __thiscall codecvt_wchar_do_length(const codecvt_wchar *this, const int *state,
2948         const char *from, const char *from_end, MSVCP_size_t max)
2949 {
2950     int tmp_state = *state, ret=0;
2951
2952     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
2953
2954     while(ret<max && from!=from_end) {
2955         switch(_Mbrtowc(NULL, from, from_end-from, &tmp_state, &this->cvt)) {
2956         case -2:
2957         case -1:
2958             return ret;
2959         case 2:
2960             from++;
2961             /* fall through */
2962         case 0:
2963         case 1:
2964             from++;
2965             ret++;
2966         }
2967     }
2968
2969     return ret;
2970 }
2971
2972 /* ?id@?$numpunct@D@std@@2V0locale@2@A */
2973 locale_id numpunct_char_id = {0};
2974
2975 /* ??_7?$numpunct@D@std@@6B@ */
2976 extern const vtable_ptr MSVCP_numpunct_char_vtable;
2977
2978 /* ?_Init@?$numpunct@D@std@@IAEXABV_Locinfo@2@_N@Z */
2979 /* ?_Init@?$numpunct@D@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2980 static void numpunct_char__Init(numpunct_char *this, const _Locinfo *locinfo, MSVCP_bool isdef)
2981 {
2982     int len;
2983
2984     TRACE("(%p %p %d)\n", this, locinfo, isdef);
2985
2986     len = strlen(_Locinfo__Getfalse(locinfo))+1;
2987     this->false_name = MSVCRT_operator_new(len);
2988     if(this->false_name)
2989         memcpy((char*)this->false_name, _Locinfo__Getfalse(locinfo), len);
2990
2991     len = strlen(_Locinfo__Gettrue(locinfo))+1;
2992     this->true_name = MSVCRT_operator_new(len);
2993     if(this->true_name)
2994         memcpy((char*)this->true_name, _Locinfo__Gettrue(locinfo), len);
2995
2996     if(isdef) {
2997         this->grouping = MSVCRT_operator_new(1);
2998         if(this->grouping)
2999             *(char*)this->grouping = 0;
3000
3001         this->dp = '.';
3002         this->sep = ',';
3003     } else {
3004         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3005
3006         len = strlen(lc->grouping)+1;
3007         this->grouping = MSVCRT_operator_new(len);
3008         if(this->grouping)
3009             memcpy((char*)this->grouping, lc->grouping, len);
3010
3011         this->dp = lc->decimal_point[0];
3012         this->sep = lc->thousands_sep[0];
3013     }
3014
3015     if(!this->false_name || !this->true_name || !this->grouping) {
3016         MSVCRT_operator_delete((char*)this->grouping);
3017         MSVCRT_operator_delete((char*)this->false_name);
3018         MSVCRT_operator_delete((char*)this->true_name);
3019
3020         ERR("Out of memory\n");
3021         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3022     }
3023 }
3024
3025 /* ?_Tidy@?$numpunct@D@std@@AAEXXZ */
3026 /* ?_Tidy@?$numpunct@D@std@@AEAAXXZ */
3027 static void numpunct_char__Tidy(numpunct_char *this)
3028 {
3029     TRACE("(%p)\n", this);
3030
3031     MSVCRT_operator_delete((char*)this->grouping);
3032     MSVCRT_operator_delete((char*)this->false_name);
3033     MSVCRT_operator_delete((char*)this->true_name);
3034 }
3035
3036 /* ??0?$numpunct@D@std@@QAE@ABV_Locinfo@1@I_N@Z */
3037 /* ??0?$numpunct@D@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3038 static numpunct_char* numpunct_char_ctor_locinfo(numpunct_char *this,
3039         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3040 {
3041     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3042     locale_facet_ctor_refs(&this->facet, refs);
3043     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3044     numpunct_char__Init(this, locinfo, usedef);
3045     return this;
3046 }
3047
3048 /* ??0?$numpunct@D@std@@IAE@PBDI_N@Z */
3049 /* ??0?$numpunct@D@std@@IEAA@PEBD_K_N@Z */
3050 static numpunct_char* numpunct_char_ctor_name(numpunct_char *this,
3051         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3052 {
3053     _Locinfo locinfo;
3054
3055     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3056     locale_facet_ctor_refs(&this->facet, refs);
3057     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3058
3059     _Locinfo_ctor_cstr(&locinfo, name);
3060     numpunct_char__Init(this, &locinfo, usedef);
3061     _Locinfo_dtor(&locinfo);
3062     return this;
3063 }
3064
3065 /* ??0?$numpunct@D@std@@QAE@I@Z */
3066 /* ??0?$numpunct@D@std@@QEAA@_K@Z */
3067 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_refs, 8)
3068 numpunct_char* __thiscall numpunct_char_ctor_refs(numpunct_char *this, MSVCP_size_t refs)
3069 {
3070     TRACE("(%p %lu)\n", this, refs);
3071     return numpunct_char_ctor_name(this, "C", refs, FALSE);
3072 }
3073
3074 /* ??_F?$numpunct@D@std@@QAEXXZ */
3075 /* ??_F?$numpunct@D@std@@QEAAXXZ */
3076 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor, 4)
3077 numpunct_char* __thiscall numpunct_char_ctor(numpunct_char *this)
3078 {
3079     return numpunct_char_ctor_refs(this, 0);
3080 }
3081
3082 /* ??1?$numpunct@D@std@@MAE@XZ */
3083 /* ??1?$numpunct@D@std@@MEAA@XZ */
3084 static void numpunct_char_dtor(numpunct_char *this)
3085 {
3086     TRACE("(%p)\n", this);
3087     numpunct_char__Tidy(this);
3088 }
3089
3090 DEFINE_THISCALL_WRAPPER(numpunct_char_vector_dtor, 8)
3091 numpunct_char* __thiscall numpunct_char_vector_dtor(numpunct_char *this, unsigned int flags)
3092 {
3093     TRACE("(%p %x)\n", this, flags);
3094     if(flags & 2) {
3095         /* we have an array, with the number of elements stored before the first object */
3096         INT_PTR i, *ptr = (INT_PTR *)this-1;
3097
3098         for(i=*ptr-1; i>=0; i--)
3099             numpunct_char_dtor(this+i);
3100         MSVCRT_operator_delete(ptr);
3101     } else {
3102         numpunct_char_dtor(this);
3103         if(flags & 1)
3104             MSVCRT_operator_delete(this);
3105     }
3106
3107     return this;
3108 }
3109
3110 /* ?_Getcat@?$numpunct@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3111 /* ?_Getcat@?$numpunct@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3112 static MSVCP_size_t numpunct_char__Getcat(const locale_facet **facet, const locale *loc)
3113 {
3114     TRACE("(%p %p)\n", facet, loc);
3115
3116     if(facet && !*facet) {
3117         *facet = MSVCRT_operator_new(sizeof(numpunct_char));
3118         if(!*facet) {
3119             ERR("Out of memory\n");
3120             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3121             return 0;
3122         }
3123         numpunct_char_ctor_name((numpunct_char*)*facet,
3124                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3125     }
3126
3127     return LC_NUMERIC;
3128 }
3129
3130 static numpunct_char* numpunct_char_use_facet(const locale *loc)
3131 {
3132     static numpunct_char *obj = NULL;
3133
3134     _Lockit lock;
3135     const locale_facet *fac;
3136
3137     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3138     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_char_id));
3139     if(fac) {
3140         _Lockit_dtor(&lock);
3141         return (numpunct_char*)fac;
3142     }
3143
3144     if(obj) {
3145         _Lockit_dtor(&lock);
3146         return obj;
3147     }
3148
3149     numpunct_char__Getcat(&fac, loc);
3150     obj = (numpunct_char*)fac;
3151     locale_facet__Incref(&obj->facet);
3152     locale_facet_register(&obj->facet);
3153     _Lockit_dtor(&lock);
3154
3155     return obj;
3156 }
3157
3158 /* ?do_decimal_point@?$numpunct@D@std@@MBEDXZ */
3159 /* ?do_decimal_point@?$numpunct@D@std@@MEBADXZ */
3160 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
3161 #define call_numpunct_char_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3162         char, (const numpunct_char *this), (this))
3163 char __thiscall numpunct_char_do_decimal_point(const numpunct_char *this)
3164 {
3165     TRACE("(%p)\n", this);
3166     return this->dp;
3167 }
3168
3169 /* ?decimal_point@?$numpunct@D@std@@QBEDXZ */
3170 /* ?decimal_point@?$numpunct@D@std@@QEBADXZ */
3171 DEFINE_THISCALL_WRAPPER(numpunct_char_decimal_point, 4)
3172 char __thiscall numpunct_char_decimal_point(const numpunct_char *this)
3173 {
3174     TRACE("(%p)\n", this);
3175     return call_numpunct_char_do_decimal_point(this);
3176 }
3177
3178 /* ?do_thousands_sep@?$numpunct@D@std@@MBEDXZ */
3179 /* ?do_thousands_sep@?$numpunct@D@std@@MEBADXZ */
3180 DEFINE_THISCALL_WRAPPER(numpunct_char_do_thousands_sep, 4)
3181 #define call_numpunct_char_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3182         char, (const numpunct_char*), (this))
3183 char __thiscall numpunct_char_do_thousands_sep(const numpunct_char *this)
3184 {
3185     TRACE("(%p)\n", this);
3186     return this->sep;
3187 }
3188
3189 /* ?thousands_sep@?$numpunct@D@std@@QBEDXZ */
3190 /* ?thousands_sep@?$numpunct@D@std@@QEBADXZ */
3191 DEFINE_THISCALL_WRAPPER(numpunct_char_thousands_sep, 4)
3192 char __thiscall numpunct_char_thousands_sep(const numpunct_char *this)
3193 {
3194     TRACE("(%p)\n", this);
3195     return call_numpunct_char_do_thousands_sep(this);
3196 }
3197
3198 /* ?do_grouping@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3199 /* ?do_grouping@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3200 DEFINE_THISCALL_WRAPPER(numpunct_char_do_grouping, 8)
3201 #define call_numpunct_char_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3202         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3203 basic_string_char* __thiscall numpunct_char_do_grouping(
3204         const numpunct_char *this, basic_string_char *ret)
3205 {
3206     TRACE("(%p)\n", this);
3207     return basic_string_char_ctor_cstr(ret, this->grouping);
3208 }
3209
3210 /* ?grouping@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3211 /* ?grouping@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3212 DEFINE_THISCALL_WRAPPER(numpunct_char_grouping, 8)
3213 basic_string_char* __thiscall numpunct_char_grouping(const numpunct_char *this, basic_string_char *ret)
3214 {
3215     TRACE("(%p)\n", this);
3216     return call_numpunct_char_do_grouping(this, ret);
3217 }
3218
3219 /* ?do_falsename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3220 /* ?do_falsename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3221 DEFINE_THISCALL_WRAPPER(numpunct_char_do_falsename, 8)
3222 #define call_numpunct_char_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3223         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3224 basic_string_char* __thiscall numpunct_char_do_falsename(
3225         const numpunct_char *this, basic_string_char *ret)
3226 {
3227     TRACE("(%p)\n", this);
3228     return basic_string_char_ctor_cstr(ret, this->false_name);
3229 }
3230
3231 /* ?falsename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3232 /* ?falsename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3233 DEFINE_THISCALL_WRAPPER(numpunct_char_falsename, 8)
3234 basic_string_char* __thiscall numpunct_char_falsename(const numpunct_char *this, basic_string_char *ret)
3235 {
3236     TRACE("(%p)\n", this);
3237     return call_numpunct_char_do_falsename(this, ret);
3238 }
3239
3240 /* ?do_truename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3241 /* ?do_truename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3242 DEFINE_THISCALL_WRAPPER(numpunct_char_do_truename, 8)
3243 #define call_numpunct_char_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3244         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3245 basic_string_char* __thiscall numpunct_char_do_truename(
3246         const numpunct_char *this, basic_string_char *ret)
3247 {
3248     TRACE("(%p)\n", this);
3249     return basic_string_char_ctor_cstr(ret, this->true_name);
3250 }
3251
3252 /* ?truename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3253 /* ?truename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3254 DEFINE_THISCALL_WRAPPER(numpunct_char_truename, 8)
3255 basic_string_char* __thiscall numpunct_char_truename(const numpunct_char *this, basic_string_char *ret)
3256 {
3257     TRACE("(%p)\n", this);
3258     return call_numpunct_char_do_truename(this, ret);
3259 }
3260
3261 /* ?id@?$numpunct@_W@std@@2V0locale@2@A */
3262 static locale_id numpunct_wchar_id = {0};
3263 /* ?id@?$numpunct@G@std@@2V0locale@2@A */
3264 locale_id numpunct_short_id = {0};
3265
3266 /* ??_7?$numpunct@_W@std@@6B@ */
3267 extern const vtable_ptr MSVCP_numpunct_wchar_vtable;
3268 /* ??_7?$numpunct@G@std@@6B@ */
3269 extern const vtable_ptr MSVCP_numpunct_short_vtable;
3270
3271 /* ?_Init@?$numpunct@_W@std@@IAEXABV_Locinfo@2@_N@Z */
3272 /* ?_Init@?$numpunct@_W@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3273 /* ?_Init@?$numpunct@G@std@@IAEXABV_Locinfo@2@_N@Z */
3274 /* ?_Init@?$numpunct@G@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3275 static void numpunct_wchar__Init(numpunct_wchar *this,
3276         const _Locinfo *locinfo, MSVCP_bool isdef)
3277 {
3278     const char *to_convert;
3279     _Cvtvec cvt;
3280     int len;
3281
3282     TRACE("(%p %p %d)\n", this, locinfo, isdef);
3283
3284     _Locinfo__Getcvt(locinfo, &cvt);
3285
3286     to_convert = _Locinfo__Getfalse(locinfo);
3287     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3288     this->false_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3289     if(this->false_name)
3290         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3291                 (wchar_t*)this->false_name, len);
3292
3293     to_convert = _Locinfo__Gettrue(locinfo);
3294     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3295     this->true_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3296     if(this->true_name)
3297         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3298                 (wchar_t*)this->true_name, len);
3299
3300     if(isdef) {
3301         this->grouping = MSVCRT_operator_new(1);
3302         if(this->grouping)
3303             *(char*)this->grouping = 0;
3304
3305         this->dp = '.';
3306         this->sep = ',';
3307     } else {
3308         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3309
3310         len = strlen(lc->grouping)+1;
3311         this->grouping = MSVCRT_operator_new(len);
3312         if(this->grouping)
3313             memcpy((char*)this->grouping, lc->grouping, len);
3314
3315         this->dp = lc->decimal_point[0];
3316         this->sep = lc->thousands_sep[0];
3317     }
3318
3319     if(!this->false_name || !this->true_name || !this->grouping) {
3320         MSVCRT_operator_delete((char*)this->grouping);
3321         MSVCRT_operator_delete((wchar_t*)this->false_name);
3322         MSVCRT_operator_delete((wchar_t*)this->true_name);
3323
3324         ERR("Out of memory\n");
3325         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3326     }
3327 }
3328
3329 /* ?_Tidy@?$numpunct@_W@std@@AAEXXZ */
3330 /* ?_Tidy@?$numpunct@_W@std@@AEAAXXZ */
3331 /* ?_Tidy@?$numpunct@G@std@@AAEXXZ */
3332 /* ?_Tidy@?$numpunct@G@std@@AEAAXXZ */
3333 static void numpunct_wchar__Tidy(numpunct_wchar *this)
3334 {
3335     TRACE("(%p)\n", this);
3336
3337     MSVCRT_operator_delete((char*)this->grouping);
3338     MSVCRT_operator_delete((wchar_t*)this->false_name);
3339     MSVCRT_operator_delete((wchar_t*)this->true_name);
3340 }
3341
3342 /* ??0?$numpunct@_W@std@@QAE@ABV_Locinfo@1@I_N@Z */
3343 /* ??0?$numpunct@_W@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3344 static numpunct_wchar* numpunct_wchar_ctor_locinfo(numpunct_wchar *this,
3345         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3346 {
3347     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3348     locale_facet_ctor_refs(&this->facet, refs);
3349     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3350     numpunct_wchar__Init(this, locinfo, usedef);
3351     return this;
3352 }
3353
3354 /* ??0?$numpunct@G@std@@QAE@ABV_Locinfo@1@I_N@Z */
3355 /* ??0?$numpunct@G@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3356 static numpunct_wchar* numpunct_short_ctor_locinfo(numpunct_wchar *this,
3357         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3358 {
3359     numpunct_wchar_ctor_locinfo(this, locinfo, refs, usedef);
3360     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3361     return this;
3362 }
3363
3364 /* ??0?$numpunct@_W@std@@IAE@PBDI_N@Z */
3365 /* ??0?$numpunct@_W@std@@IEAA@PEBD_K_N@Z */
3366 static numpunct_wchar* numpunct_wchar_ctor_name(numpunct_wchar *this,
3367         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3368 {
3369     _Locinfo locinfo;
3370
3371     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3372     locale_facet_ctor_refs(&this->facet, refs);
3373     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3374
3375     _Locinfo_ctor_cstr(&locinfo, name);
3376     numpunct_wchar__Init(this, &locinfo, usedef);
3377     _Locinfo_dtor(&locinfo);
3378     return this;
3379 }
3380
3381 /* ??0?$numpunct@G@std@@IAE@PBDI_N@Z */
3382 /* ??0?$numpunct@G@std@@IEAA@PEBD_K_N@Z */
3383 static numpunct_wchar* numpunct_short_ctor_name(numpunct_wchar *this,
3384         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3385 {
3386     numpunct_wchar_ctor_name(this, name, refs, usedef);
3387     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3388     return this;
3389 }
3390
3391 /* ??0?$numpunct@_W@std@@QAE@I@Z */
3392 /* ??0?$numpunct@_W@std@@QEAA@_K@Z */
3393 static numpunct_wchar* numpunct_wchar_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3394 {
3395     TRACE("(%p %lu)\n", this, refs);
3396     return numpunct_wchar_ctor_name(this, "C", refs, FALSE);
3397 }
3398
3399 /* ??0?$numpunct@G@std@@QAE@I@Z */
3400 /* ??0?$numpunct@G@std@@QEAA@_K@Z */
3401 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_refs, 8)
3402 numpunct_wchar* __thiscall numpunct_short_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3403 {
3404     numpunct_wchar_ctor_refs(this, refs);
3405     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3406     return this;
3407 }
3408
3409 /* ??_F?$numpunct@G@std@@QAEXXZ */
3410 /* ??_F?$numpunct@G@std@@QEAAXXZ */
3411 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor, 4)
3412 numpunct_wchar* __thiscall numpunct_short_ctor(numpunct_wchar *this)
3413 {
3414     return numpunct_short_ctor_refs(this, 0);
3415 }
3416
3417 /* ??1?$numpunct@_W@std@@MAE@XZ */
3418 /* ??1?$numpunct@_W@std@@MEAA@XZ */
3419 /* ??1?$numpunct@G@std@@MAE@XZ */
3420 /* ??1?$numpunct@G@std@@MEAA@XZ */
3421 static void numpunct_wchar_dtor(numpunct_wchar *this)
3422 {
3423     TRACE("(%p)\n", this);
3424     numpunct_wchar__Tidy(this);
3425 }
3426
3427 DEFINE_THISCALL_WRAPPER(numpunct_wchar_vector_dtor, 8)
3428 numpunct_wchar* __thiscall numpunct_wchar_vector_dtor(numpunct_wchar *this, unsigned int flags)
3429 {
3430     TRACE("(%p %x)\n", this, flags);
3431     if(flags & 2) {
3432         /* we have an array, with the number of elements stored before the first object */
3433         INT_PTR i, *ptr = (INT_PTR *)this-1;
3434
3435         for(i=*ptr-1; i>=0; i--)
3436             numpunct_wchar_dtor(this+i);
3437         MSVCRT_operator_delete(ptr);
3438     } else {
3439         numpunct_wchar_dtor(this);
3440         if(flags & 1)
3441             MSVCRT_operator_delete(this);
3442     }
3443
3444     return this;
3445 }
3446
3447 /* ?_Getcat@?$numpunct@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3448 /* ?_Getcat@?$numpunct@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3449 static MSVCP_size_t numpunct_wchar__Getcat(const locale_facet **facet, const locale *loc)
3450 {
3451     TRACE("(%p %p)\n", facet, loc);
3452
3453     if(facet && !*facet) {
3454         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3455         if(!*facet) {
3456             ERR("Out of memory\n");
3457             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3458             return 0;
3459         }
3460         numpunct_wchar_ctor_name((numpunct_wchar*)*facet,
3461                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3462     }
3463
3464     return LC_NUMERIC;
3465 }
3466
3467 static numpunct_wchar* numpunct_wchar_use_facet(const locale *loc)
3468 {
3469     static numpunct_wchar *obj = NULL;
3470
3471     _Lockit lock;
3472     const locale_facet *fac;
3473
3474     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3475     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_wchar_id));
3476     if(fac) {
3477         _Lockit_dtor(&lock);
3478         return (numpunct_wchar*)fac;
3479     }
3480
3481     if(obj) {
3482         _Lockit_dtor(&lock);
3483         return obj;
3484     }
3485
3486     numpunct_wchar__Getcat(&fac, loc);
3487     obj = (numpunct_wchar*)fac;
3488     locale_facet__Incref(&obj->facet);
3489     locale_facet_register(&obj->facet);
3490     _Lockit_dtor(&lock);
3491
3492     return obj;
3493 }
3494
3495 /* ?_Getcat@?$numpunct@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3496 /* ?_Getcat@?$numpunct@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3497 static MSVCP_size_t numpunct_short__Getcat(const locale_facet **facet, const locale *loc)
3498 {
3499     TRACE("(%p %p)\n", facet, loc);
3500
3501     if(facet && !*facet) {
3502         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3503         if(!*facet) {
3504             ERR("Out of memory\n");
3505             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3506             return 0;
3507         }
3508         numpunct_short_ctor_name((numpunct_wchar*)*facet,
3509                 basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3510     }
3511
3512     return LC_NUMERIC;
3513 }
3514
3515 static numpunct_wchar* numpunct_short_use_facet(const locale *loc)
3516 {
3517     static numpunct_wchar *obj = NULL;
3518
3519     _Lockit lock;
3520     const locale_facet *fac;
3521
3522     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3523     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_short_id));
3524     if(fac) {
3525         _Lockit_dtor(&lock);
3526         return (numpunct_wchar*)fac;
3527     }
3528
3529     if(obj) {
3530         _Lockit_dtor(&lock);
3531         return obj;
3532     }
3533
3534     numpunct_short__Getcat(&fac, loc);
3535     obj = (numpunct_wchar*)fac;
3536     locale_facet__Incref(&obj->facet);
3537     locale_facet_register(&obj->facet);
3538     _Lockit_dtor(&lock);
3539
3540     return obj;
3541 }
3542
3543 /* ?do_decimal_point@?$numpunct@_W@std@@MBE_WXZ */
3544 /* ?do_decimal_point@?$numpunct@_W@std@@MEBA_WXZ */
3545 /* ?do_decimal_point@?$numpunct@G@std@@MBEGXZ */
3546 /* ?do_decimal_point@?$numpunct@G@std@@MEBAGXZ */
3547 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_decimal_point, 4)
3548 #define call_numpunct_wchar_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3549         wchar_t, (const numpunct_wchar *this), (this))
3550 wchar_t __thiscall numpunct_wchar_do_decimal_point(const numpunct_wchar *this)
3551 {
3552     TRACE("(%p)\n", this);
3553     return this->dp;
3554 }
3555
3556 /* ?decimal_point@?$numpunct@_W@std@@QBE_WXZ */
3557 /* ?decimal_point@?$numpunct@_W@std@@QEBA_WXZ */
3558 /* ?decimal_point@?$numpunct@G@std@@QBEGXZ */
3559 /* ?decimal_point@?$numpunct@G@std@@QEBAGXZ */
3560 DEFINE_THISCALL_WRAPPER(numpunct_wchar_decimal_point, 4)
3561 wchar_t __thiscall numpunct_wchar_decimal_point(const numpunct_wchar *this)
3562 {
3563     TRACE("(%p)\n", this);
3564     return call_numpunct_wchar_do_decimal_point(this);
3565 }
3566
3567 /* ?do_thousands_sep@?$numpunct@_W@std@@MBE_WXZ */
3568 /* ?do_thousands_sep@?$numpunct@_W@std@@MEBA_WXZ */
3569 /* ?do_thousands_sep@?$numpunct@G@std@@MBEGXZ */
3570 /* ?do_thousands_sep@?$numpunct@G@std@@MEBAGXZ */
3571 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_thousands_sep, 4)
3572 #define call_numpunct_wchar_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3573         wchar_t, (const numpunct_wchar *this), (this))
3574 wchar_t __thiscall numpunct_wchar_do_thousands_sep(const numpunct_wchar *this)
3575 {
3576     TRACE("(%p)\n", this);
3577     return this->sep;
3578 }
3579
3580 /* ?thousands_sep@?$numpunct@_W@std@@QBE_WXZ */
3581 /* ?thousands_sep@?$numpunct@_W@std@@QEBA_WXZ */
3582 /* ?thousands_sep@?$numpunct@G@std@@QBEGXZ */
3583 /* ?thousands_sep@?$numpunct@G@std@@QEBAGXZ */
3584 DEFINE_THISCALL_WRAPPER(numpunct_wchar_thousands_sep, 4)
3585 wchar_t __thiscall numpunct_wchar_thousands_sep(const numpunct_wchar *this)
3586 {
3587     TRACE("(%p)\n", this);
3588     return call_numpunct_wchar_do_thousands_sep(this);
3589 }
3590
3591 /* ?do_grouping@?$numpunct@_W@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3592 /* ?do_grouping@?$numpunct@_W@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3593 /* ?do_grouping@?$numpunct@G@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3594 /* ?do_grouping@?$numpunct@G@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3595 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_grouping, 8)
3596 #define call_numpunct_wchar_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3597         basic_string_char*, (const numpunct_wchar*, basic_string_char*), (this, ret))
3598 basic_string_char* __thiscall numpunct_wchar_do_grouping(const numpunct_wchar *this, basic_string_char *ret)
3599 {
3600     TRACE("(%p)\n", this);
3601     return basic_string_char_ctor_cstr(ret, this->grouping);
3602 }
3603
3604 /* ?grouping@?$numpunct@_W@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3605 /* ?grouping@?$numpunct@_W@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3606 /* ?grouping@?$numpunct@G@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3607 /* ?grouping@?$numpunct@G@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3608 DEFINE_THISCALL_WRAPPER(numpunct_wchar_grouping, 8)
3609 basic_string_char* __thiscall numpunct_wchar_grouping(const numpunct_wchar *this, basic_string_char *ret)
3610 {
3611     TRACE("(%p)\n", this);
3612     return call_numpunct_wchar_do_grouping(this, ret);
3613 }
3614
3615 /* ?do_falsename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3616 /* ?do_falsename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3617 /* ?do_falsename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3618 /* ?do_falsename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3619 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_falsename, 8)
3620 #define call_numpunct_wchar_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3621         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3622 basic_string_wchar* __thiscall numpunct_wchar_do_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3623 {
3624     TRACE("(%p)\n", this);
3625     return basic_string_wchar_ctor_cstr(ret, this->false_name);
3626 }
3627
3628 /* ?falsename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3629 /* ?falsename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3630 /* ?falsename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3631 /* ?falsename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3632 DEFINE_THISCALL_WRAPPER(numpunct_wchar_falsename, 8)
3633 basic_string_wchar* __thiscall numpunct_wchar_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3634 {
3635     TRACE("(%p)\n", this);
3636     return call_numpunct_wchar_do_falsename(this, ret);
3637 }
3638
3639 /* ?do_truename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3640 /* ?do_truename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3641 /* ?do_truename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3642 /* ?do_truename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3643 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_truename, 8)
3644 #define call_numpunct_wchar_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3645         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3646 basic_string_wchar* __thiscall numpunct_wchar_do_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3647 {
3648     TRACE("(%p)\n", this);
3649     return basic_string_wchar_ctor_cstr(ret, this->true_name);
3650 }
3651
3652 /* ?truename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3653 /* ?truename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3654 /* ?truename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3655 /* ?truename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3656 DEFINE_THISCALL_WRAPPER(numpunct_wchar_truename, 8)
3657 basic_string_wchar* __thiscall numpunct_wchar_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3658 {
3659     TRACE("(%p)\n", this);
3660     return call_numpunct_wchar_do_truename(this, ret);
3661 }
3662
3663 double __cdecl _Stod(const char *buf, char **buf_end, LONG exp)
3664 {
3665     double ret = strtod(buf, buf_end);
3666
3667     if(exp)
3668         ret *= pow(10, exp);
3669     return ret;
3670 }
3671
3672 static double _Stodx(const char *buf, char **buf_end, LONG exp, int *err)
3673 {
3674     double ret;
3675
3676     *err = *_errno();
3677     *_errno() = 0;
3678     ret = _Stod(buf, buf_end, exp);
3679     if(*_errno()) {
3680         *err = *_errno();
3681     }else {
3682         *_errno() = *err;
3683         *err = 0;
3684     }
3685     return ret;
3686 }
3687
3688 float __cdecl _Stof(const char *buf, char **buf_end, LONG exp)
3689 {
3690     return _Stod(buf, buf_end, exp);
3691 }
3692
3693 static float _Stofx(const char *buf, char **buf_end, LONG exp, int *err)
3694 {
3695     return _Stodx(buf, buf_end, exp, err);
3696 }
3697
3698 static __int64 _Stollx(const char *buf, char **buf_end, int base, int *err)
3699 {
3700     __int64 ret;
3701
3702     *err = *_errno();
3703     *_errno() = 0;
3704     ret = _strtoi64(buf, buf_end, base);
3705     if(*_errno()) {
3706         *err = *_errno();
3707     }else {
3708         *_errno() = *err;
3709         *err = 0;
3710     }
3711     return ret;
3712 }
3713
3714 static LONG _Stolx(const char *buf, char **buf_end, int base, int *err)
3715 {
3716     __int64 i = _Stollx(buf, buf_end, base, err);
3717     if(!*err && i!=(__int64)((LONG)i))
3718         *err = ERANGE;
3719     return i;
3720 }
3721
3722 static unsigned __int64 _Stoullx(const char *buf, char **buf_end, int base, int *err)
3723 {
3724     unsigned __int64 ret;
3725
3726     *err = *_errno();
3727     *_errno() = 0;
3728     ret = _strtoui64(buf, buf_end, base);
3729     if(*_errno()) {
3730         *err = *_errno();
3731     }else {
3732         *_errno() = *err;
3733         *err = 0;
3734     }
3735     return ret;
3736 }
3737
3738 static ULONG _Stoulx(const char *buf, char **buf_end, int base, int *err)
3739 {
3740     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, err);
3741     if(!*err && i!=(unsigned __int64)((ULONG)i))
3742         *err = ERANGE;
3743     return buf[0]=='-' ? -i : i;
3744 }
3745
3746 /* ?id@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
3747 static locale_id num_get_wchar_id = {0};
3748 /* ?id@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
3749 locale_id num_get_short_id = {0};
3750
3751 /* ??_7?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
3752 extern const vtable_ptr MSVCP_num_get_wchar_vtable;
3753 /* ??_7?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
3754 extern const vtable_ptr MSVCP_num_get_short_vtable;
3755
3756 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3757 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3758 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3759 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3760 DEFINE_THISCALL_WRAPPER(num_get_wchar__Init, 8)
3761 void __thiscall num_get_wchar__Init(num_get *this, const _Locinfo *locinfo)
3762 {
3763     TRACE("(%p %p)\n", this, locinfo);
3764     _Locinfo__Getcvt(locinfo, &this->cvt);
3765 }
3766
3767 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3768 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3769 static num_get* num_get_wchar_ctor_locinfo(num_get *this,
3770         const _Locinfo *locinfo, MSVCP_size_t refs)
3771 {
3772     TRACE("(%p %p %lu)\n", this, locinfo, refs);
3773
3774     locale_facet_ctor_refs(&this->facet, refs);
3775     this->facet.vtable = &MSVCP_num_get_wchar_vtable;
3776
3777     num_get_wchar__Init(this, locinfo);
3778     return this;
3779 }
3780
3781 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3782 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3783 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_locinfo, 12)
3784 num_get* __thiscall num_get_short_ctor_locinfo(num_get *this,
3785         const _Locinfo *locinfo, MSVCP_size_t refs)
3786 {
3787     num_get_wchar_ctor_locinfo(this, locinfo, refs);
3788     this->facet.vtable = &MSVCP_num_get_short_vtable;
3789     return this;
3790 }
3791
3792 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
3793 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
3794 static num_get* num_get_wchar_ctor_refs(num_get *this, MSVCP_size_t refs)
3795 {
3796     _Locinfo locinfo;
3797
3798     TRACE("(%p %lu)\n", this, refs);
3799
3800     _Locinfo_ctor(&locinfo);
3801     num_get_wchar_ctor_locinfo(this, &locinfo, refs);
3802     _Locinfo_dtor(&locinfo);
3803     return this;
3804 }
3805
3806 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
3807 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
3808 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_refs, 8)
3809 num_get* __thiscall num_get_short_ctor_refs(num_get *this, MSVCP_size_t refs)
3810 {
3811     num_get_wchar_ctor_refs(this, refs);
3812     this->facet.vtable = &MSVCP_num_get_short_vtable;
3813     return this;
3814 }
3815
3816 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
3817 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
3818 DEFINE_THISCALL_WRAPPER(num_get_short_ctor, 4)
3819 num_get* __thiscall num_get_short_ctor(num_get *this)
3820 {
3821     return num_get_short_ctor_refs(this, 0);
3822 }
3823
3824 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
3825 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
3826 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
3827 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
3828 static void num_get_wchar_dtor(num_get *this)
3829 {
3830     TRACE("(%p)\n", this);
3831     locale_facet_dtor(&this->facet);
3832 }
3833
3834 DEFINE_THISCALL_WRAPPER(num_get_wchar_vector_dtor, 8)
3835 num_get* __thiscall num_get_wchar_vector_dtor(num_get *this, unsigned int flags)
3836 {
3837     TRACE("(%p %x)\n", this, flags);
3838     if(flags & 2) {
3839         /* we have an array, with the number of elements stored before the first object */
3840         INT_PTR i, *ptr = (INT_PTR *)this-1;
3841
3842         for(i=*ptr-1; i>=0; i--)
3843             num_get_wchar_dtor(this+i);
3844         MSVCRT_operator_delete(ptr);
3845     } else {
3846         num_get_wchar_dtor(this);
3847         if(flags & 1)
3848             MSVCRT_operator_delete(this);
3849     }
3850
3851     return this;
3852 }
3853
3854 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3855 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3856 static MSVCP_size_t num_get_wchar__Getcat(const locale_facet **facet, const locale *loc)
3857 {
3858     TRACE("(%p %p)\n", facet, loc);
3859
3860     if(facet && !*facet) {
3861         _Locinfo locinfo;
3862
3863         *facet = MSVCRT_operator_new(sizeof(num_get));
3864         if(!*facet) {
3865             ERR("Out of memory\n");
3866             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3867             return 0;
3868         }
3869
3870         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
3871         num_get_wchar_ctor_locinfo((num_get*)*facet, &locinfo, 0);
3872         _Locinfo_dtor(&locinfo);
3873     }
3874
3875     return LC_NUMERIC;
3876 }
3877
3878 static num_get* num_get_wchar_use_facet(const locale *loc)
3879 {
3880         static num_get *obj = NULL;
3881
3882         _Lockit lock;
3883         const locale_facet *fac;
3884
3885         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3886         fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_wchar_id));
3887         if(fac) {
3888             _Lockit_dtor(&lock);
3889             return (num_get*)fac;
3890         }
3891
3892         if(obj) {
3893             _Lockit_dtor(&lock);
3894             return obj;
3895         }
3896
3897         num_get_wchar__Getcat(&fac, loc);
3898         obj = (num_get*)fac;
3899         locale_facet__Incref(&obj->facet);
3900         locale_facet_register(&obj->facet);
3901         _Lockit_dtor(&lock);
3902
3903         return obj;
3904 }
3905
3906 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3907 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3908 static MSVCP_size_t num_get_short__Getcat(const locale_facet **facet, const locale *loc)
3909 {
3910     if(facet && !*facet) {
3911         num_get_wchar__Getcat(facet, loc);
3912         (*(locale_facet**)facet)->vtable = &MSVCP_num_get_short_vtable;
3913     }
3914
3915     return LC_NUMERIC;
3916 }
3917
3918 num_get* num_get_short_use_facet(const locale *loc)
3919 {
3920     static num_get *obj = NULL;
3921
3922     _Lockit lock;
3923     const locale_facet *fac;
3924
3925     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3926     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_short_id));
3927     if(fac) {
3928         _Lockit_dtor(&lock);
3929         return (num_get*)fac;
3930     }
3931
3932     if(obj) {
3933         _Lockit_dtor(&lock);
3934         return obj;
3935     }
3936
3937     num_get_short__Getcat(&fac, loc);
3938     obj = (num_get*)fac;
3939     locale_facet__Incref(&obj->facet);
3940     locale_facet_register(&obj->facet);
3941     _Lockit_dtor(&lock);
3942
3943     return obj;
3944 }
3945
3946 static inline wchar_t mb_to_wc(char ch, const _Cvtvec *cvt)
3947 {
3948     int state = 0;
3949     wchar_t ret;
3950
3951     return _Mbrtowc(&ret, &ch, 1, &state, cvt) == 1 ? ret : 0;
3952 }
3953
3954 static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
3955         istreambuf_iterator_wchar *last, const locale *loc, numpunct_wchar *numpunct)
3956 {
3957     int i, exp = 0;
3958     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
3959     wchar_t digits[11], *digits_pos;
3960     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
3961
3962     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
3963
3964     for(i=0; i<10; i++)
3965         digits[i] = mb_to_wc('0'+i, &this->cvt);
3966     digits[10] = 0;
3967
3968     istreambuf_iterator_wchar_val(first);
3969     /* get sign */
3970     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
3971         *dest++ = '-';
3972         istreambuf_iterator_wchar_inc(first);
3973     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
3974         *dest++ = '+';
3975         istreambuf_iterator_wchar_inc(first);
3976     }
3977
3978     /* read numbers before decimal */
3979     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
3980         if(!(digits_pos = wcschr(digits, first->val))) {
3981             break;
3982         }else {
3983             got_digit = TRUE; /* found a digit, zero or non-zero */
3984             /* write digit to dest if not a leading zero (to not waste dest buffer) */
3985             if(!got_nonzero && first->val == digits[0])
3986                 continue;
3987             got_nonzero = TRUE;
3988             if(dest < num_end)
3989                 *dest++ = '0'+digits_pos-digits;
3990             else
3991                 exp++; /* too many digits, just multiply by 10 */
3992         }
3993     }
3994     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
3995     if(got_digit && !got_nonzero)
3996         *dest++ = '0';
3997
3998     /* get decimal, if any */
3999     if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
4000         if(dest < num_end)
4001             *dest++ = *localeconv()->decimal_point;
4002         istreambuf_iterator_wchar_inc(first);
4003     }
4004
4005     /* read non-grouped after decimal */
4006     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4007         if(!(digits_pos = wcschr(digits, first->val)))
4008             break;
4009         else if(dest<num_end) {
4010             got_digit = TRUE;
4011             *dest++ = '0'+digits_pos-digits;
4012         }
4013     }
4014
4015     /* read exponent, if any */
4016     if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
4017         *dest++ = 'e';
4018         istreambuf_iterator_wchar_inc(first);
4019
4020         if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4021             *dest++ = '-';
4022             istreambuf_iterator_wchar_inc(first);
4023         }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4024             *dest++ = '+';
4025             istreambuf_iterator_wchar_inc(first);
4026         }
4027
4028         got_digit = got_nonzero = FALSE;
4029         error = TRUE;
4030         /* skip any leading zeroes */
4031         for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
4032             error = FALSE;
4033
4034         for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
4035             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
4036             error = FALSE;
4037             if(dest<exp_end)
4038                 *dest++ = '0'+digits_pos-digits;
4039         }
4040
4041         /* if just found zeroes for exponent, use that */
4042         if(got_digit && !got_nonzero)
4043         {
4044             error = FALSE;
4045             if(dest<exp_end)
4046                 *dest++ = '0';
4047         }
4048     }
4049
4050     if(error) {
4051         *dest_beg = '\0';
4052         return 0;
4053     }
4054     *dest++ = '\0';
4055     return exp;
4056 }
4057
4058 static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4059     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc, numpunct_wchar *numpunct)
4060 {
4061     wchar_t digits[23], *digits_pos;
4062     int i, basefield, base;
4063     char *dest_beg = dest, *dest_end = dest+24;
4064     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
4065
4066     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
4067
4068     for(i=0; i<10; i++)
4069         digits[i] = mb_to_wc('0'+i, &this->cvt);
4070     for(i=0; i<6; i++) {
4071         digits[10+i] = mb_to_wc('a'+i, &this->cvt);
4072         digits[16+i] = mb_to_wc('A'+i, &this->cvt);
4073     }
4074
4075     basefield = fmtflags & FMTFLAG_basefield;
4076     if(basefield == FMTFLAG_oct)
4077         base = 8;
4078     else if(basefield == FMTFLAG_hex)
4079         base = 22; /* equal to the size of digits buffer */
4080     else if(!basefield)
4081         base = 0;
4082     else
4083         base = 10;
4084
4085     istreambuf_iterator_wchar_val(first);
4086     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4087         *dest++ = '-';
4088         istreambuf_iterator_wchar_inc(first);
4089     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4090         *dest++ = '+';
4091         istreambuf_iterator_wchar_inc(first);
4092     }
4093
4094     if(first->strbuf && first->val==digits[0]) {
4095         found_zero = TRUE;
4096         istreambuf_iterator_wchar_inc(first);
4097         if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) {
4098             if(!base || base == 22) {
4099                 found_zero = FALSE;
4100                 istreambuf_iterator_wchar_inc(first);
4101                 base = 22;
4102             }else {
4103                 base = 10;
4104             }
4105         }else {
4106             error = FALSE;
4107             if(!base) base = 8;
4108         }
4109     }else {
4110         if(!base) base = 10;
4111     }
4112     digits[base] = 0;
4113
4114     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4115         if(!(digits_pos = wcschr(digits, first->val))) {
4116             break;
4117         }else {
4118             error = FALSE;
4119             if(dest_empty && first->val == digits[0]) {
4120                 found_zero = TRUE;
4121                 continue;
4122             }
4123             dest_empty = FALSE;
4124             /* skip digits that can't be copied to dest buffer, other
4125              * functions are responsible for detecting overflows */
4126             if(dest < dest_end)
4127                 *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits :
4128                         (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 :
4129                          'A'+digits_pos-digits-16));
4130         }
4131     }
4132
4133     if(error) {
4134         if (found_zero)
4135             *dest++ = '0';
4136         else
4137             dest = dest_beg;
4138     }else if(dest_empty)
4139         *dest++ = '0';
4140     *dest = '\0';
4141
4142     return (base==22 ? 16 : base);
4143 }
4144
4145 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HABVlocale@2@@Z */
4146 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HAEBVlocale@2@@Z */
4147 static int num_get_wchar__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4148     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4149 {
4150     return num_get__Getifld(this, dest, first, last,
4151             fmtflags, loc, numpunct_wchar_use_facet(loc));
4152 }
4153
4154 static istreambuf_iterator_wchar* num_get_do_get_void(const num_get *this,
4155         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4156         istreambuf_iterator_wchar last, ios_base *base, int *state,
4157         void **pval, numpunct_wchar *numpunct)
4158 {
4159     unsigned __int64 v;
4160     char tmp[25], *end;
4161     int err;
4162
4163     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4164
4165     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4166                 &last, FMTFLAG_hex, &base->loc, numpunct), &err);
4167     if(v!=(unsigned __int64)((INT_PTR)v))
4168         *state |= IOSTATE_failbit;
4169     else if(end!=tmp && !err)
4170         *pval = (void*)((INT_PTR)v);
4171     else
4172         *state |= IOSTATE_failbit;
4173
4174     if(!first.strbuf)
4175         *state |= IOSTATE_eofbit;
4176
4177     *ret = first;
4178     return ret;
4179 }
4180
4181 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4182 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4183 #define call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_wchar*, \
4184         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, void**), \
4185         (this, ret, first, last, base, state, pval))
4186 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_void,36)
4187 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4188     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4189 {
4190     return num_get_do_get_void(this, ret, first, last, base,
4191             state, pval, numpunct_wchar_use_facet(&base->loc));
4192 }
4193
4194 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4195 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4196 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_void,36)
4197 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4198     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4199 {
4200     return num_get_do_get_void(this, ret, first, last, base,
4201             state, pval, numpunct_short_use_facet(&base->loc));
4202 }
4203
4204 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4205 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4206 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4207 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4208 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_void,36)
4209 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4210     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4211 {
4212     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4213     return call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval);
4214 }
4215
4216 static istreambuf_iterator_wchar* num_get_do_get_double(const num_get *this,
4217         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4218         istreambuf_iterator_wchar last, ios_base *base, int *state,
4219         double *pval, numpunct_wchar *numpunct)
4220 {
4221     double v;
4222     char tmp[32], *end;
4223     int err;
4224
4225     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4226
4227     v = _Stodx(tmp, &end, num_get__Getffld(this, tmp, &first, &last, &base->loc, numpunct), &err);
4228     if(end!=tmp && !err)
4229         *pval = v;
4230     else
4231         *state |= IOSTATE_failbit;
4232
4233     if(!first.strbuf)
4234         *state |= IOSTATE_eofbit;
4235
4236     *ret = first;
4237     return ret;
4238 }
4239
4240 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4241 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4242 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4243 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4244 #define call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_wchar*, \
4245         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4246         (this, ret, first, last, base, state, pval))
4247 #define call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_wchar*, \
4248         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4249         (this, ret, first, last, base, state, pval))
4250 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_double,36)
4251 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4252     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4253 {
4254     return num_get_do_get_double(this, ret, first, last, base,
4255             state, pval, numpunct_wchar_use_facet(&base->loc));
4256 }
4257
4258 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4259 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4260 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4261 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4262 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_double,36)
4263 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4264     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4265 {
4266     return num_get_do_get_double(this, ret, first, last, base,
4267             state, pval, numpunct_short_use_facet(&base->loc));
4268 }
4269
4270 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4271 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4272 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4273 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4274 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ldouble,36)
4275 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ldouble(const num_get *this, istreambuf_iterator_wchar *ret,
4276         istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4277 {
4278     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4279     return call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval);
4280 }
4281
4282 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4283 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4284 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4285 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4286 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_double,36)
4287 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4288     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4289 {
4290     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4291     return call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval);
4292 }
4293
4294 static istreambuf_iterator_wchar* num_get_do_get_float(const num_get *this,
4295         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4296         istreambuf_iterator_wchar last, ios_base *base, int *state,
4297         float *pval, numpunct_wchar *numpunct)
4298 {
4299     float v;
4300     char tmp[32], *end;
4301     int err;
4302
4303     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4304
4305     v = _Stofx(tmp, &end, num_get__Getffld(this, tmp, &first,
4306                 &last, &base->loc, numpunct), &err);
4307     if(end!=tmp && !err)
4308         *pval = v;
4309     else
4310         *state |= IOSTATE_failbit;
4311
4312     if(!first.strbuf)
4313         *state |= IOSTATE_eofbit;
4314
4315     *ret = first;
4316     return ret;
4317 }
4318
4319 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4320 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4321 #define call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_wchar*, \
4322         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, float*), \
4323         (this, ret, first, last, base, state, pval))
4324 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_float,36)
4325 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4326     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4327 {
4328     return num_get_do_get_float(this, ret, first, last, base,
4329             state, pval, numpunct_wchar_use_facet(&base->loc));
4330 }
4331
4332 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4333 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4334 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_float,36)
4335 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4336     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4337 {
4338     return num_get_do_get_float(this, ret, first, last, base,
4339             state, pval, numpunct_short_use_facet(&base->loc));
4340 }
4341
4342 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4343 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4344 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
4345 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
4346 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_float,36)
4347 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4348     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4349 {
4350     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4351     return call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval);
4352 }
4353
4354 static istreambuf_iterator_wchar* num_get_do_get_uint64(const num_get *this,
4355         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4356         istreambuf_iterator_wchar last, ios_base *base, int *state,
4357         ULONGLONG *pval, numpunct_wchar *numpunct)
4358 {
4359     unsigned __int64 v;
4360     char tmp[25], *end;
4361     int err;
4362
4363     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4364
4365     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4366                 &last, base->fmtfl, &base->loc, numpunct), &err);
4367     if(end!=tmp && !err)
4368         *pval = v;
4369     else
4370         *state |= IOSTATE_failbit;
4371
4372     if(!first.strbuf)
4373         *state |= IOSTATE_eofbit;
4374
4375     *ret = first;
4376     return ret;
4377 }
4378
4379 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4380 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4381 #define call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_wchar*, \
4382         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONGLONG*), \
4383         (this, ret, first, last, base, state, pval))
4384 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint64,36)
4385 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4386     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4387 {
4388     return num_get_do_get_uint64(this, ret, first, last, base,
4389             state, pval, numpunct_wchar_use_facet(&base->loc));
4390 }
4391
4392 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4393 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4394 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint64,36)
4395 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4396     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4397 {
4398     return num_get_do_get_uint64(this, ret, first, last, base,
4399             state, pval, numpunct_short_use_facet(&base->loc));
4400 }
4401
4402 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4403 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4404 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
4405 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
4406 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint64,36)
4407 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4408     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4409 {
4410     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4411     return call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval);
4412 }
4413
4414 static istreambuf_iterator_wchar* num_get_do_get_int64(const num_get *this,
4415         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4416         istreambuf_iterator_wchar last, ios_base *base, int *state,
4417         LONGLONG *pval, numpunct_wchar *numpunct)
4418 {
4419     __int64 v;
4420     char tmp[25], *end;
4421     int err;
4422
4423     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4424
4425     v = _Stollx(tmp, &end, num_get__Getifld(this, tmp, &first,
4426                 &last, base->fmtfl, &base->loc, numpunct), &err);
4427     if(end!=tmp && !err)
4428         *pval = v;
4429     else
4430         *state |= IOSTATE_failbit;
4431
4432     if(!first.strbuf)
4433         *state |= IOSTATE_eofbit;
4434
4435     *ret = first;
4436     return ret;
4437 }
4438
4439 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4440 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4441 #define call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_wchar*, \
4442         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONGLONG*), \
4443         (this, ret, first, last, base, state, pval))
4444 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_int64,36)
4445 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4446     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4447 {
4448     return num_get_do_get_int64(this, ret, first, last, base,
4449             state, pval, numpunct_wchar_use_facet(&base->loc));
4450 }
4451
4452 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4453 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4454 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_int64,36)
4455 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4456     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4457 {
4458     return num_get_do_get_int64(this, ret, first, last, base,
4459             state, pval, numpunct_short_use_facet(&base->loc));
4460 }
4461
4462 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4463 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4464 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
4465 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
4466 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_int64,36)
4467 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4468     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4469 {
4470     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4471     return call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval);
4472 }
4473
4474 static istreambuf_iterator_wchar* num_get_do_get_ulong(const num_get *this,
4475         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4476         istreambuf_iterator_wchar last, ios_base *base, int *state,
4477         ULONG *pval, numpunct_wchar *numpunct)
4478 {
4479     ULONG v;
4480     char tmp[25], *end;
4481     int err;
4482
4483     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4484
4485     v = _Stoulx(tmp, &end, num_get__Getifld(this, tmp, &first,
4486                 &last, base->fmtfl, &base->loc, numpunct), &err);
4487     if(end!=tmp && !err)
4488         *pval = v;
4489     else
4490         *state |= IOSTATE_failbit;
4491
4492     if(!first.strbuf)
4493         *state |= IOSTATE_eofbit;
4494
4495     *ret = first;
4496     return ret;
4497 }
4498
4499 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4500 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4501 #define call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_wchar*, \
4502         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONG*), \
4503         (this, ret, first, last, base, state, pval))
4504 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ulong,36)
4505 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4506     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4507 {
4508     return num_get_do_get_ulong(this, ret, first, last, base,
4509             state, pval, numpunct_wchar_use_facet(&base->loc));
4510 }
4511
4512 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4513 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4514 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ulong,36)
4515 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4516     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4517 {
4518     return num_get_do_get_ulong(this, ret, first, last, base,
4519             state, pval, numpunct_short_use_facet(&base->loc));
4520 }
4521
4522 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4523 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4524 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
4525 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
4526 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ulong,36)
4527 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4528     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4529 {
4530     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4531     return call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4532 }
4533
4534 static istreambuf_iterator_wchar* num_get_do_get_long(const num_get *this,
4535         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4536         istreambuf_iterator_wchar last, ios_base *base, int *state,
4537         LONG *pval, numpunct_wchar *numpunct)
4538 {
4539     LONG v;
4540     char tmp[25], *end;
4541     int err;
4542
4543     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4544
4545     v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4546                 &last, base->fmtfl, &base->loc, numpunct), &err);
4547     if(end!=tmp && !err)
4548         *pval = v;
4549     else
4550         *state |= IOSTATE_failbit;
4551
4552     if(!first.strbuf)
4553         *state |= IOSTATE_eofbit;
4554
4555     *ret = first;
4556     return ret;
4557 }
4558
4559 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4560 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4561 #define call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_wchar*, \
4562         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONG*), \
4563         (this, ret, first, last, base, state, pval))
4564 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_long,36)
4565 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4566     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4567 {
4568     return num_get_do_get_long(this, ret, first, last, base,
4569             state, pval, numpunct_wchar_use_facet(&base->loc));
4570 }
4571
4572 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4573 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4574 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_long,36)
4575 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4576     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4577 {
4578     return num_get_do_get_long(this, ret, first, last, base,
4579         state, pval, numpunct_short_use_facet(&base->loc));
4580 }
4581
4582 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4583 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4584 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
4585 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
4586 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_long,36)
4587 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4588     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4589 {
4590     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4591     return call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval);
4592 }
4593
4594 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4595 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4596 #define call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_wchar*, \
4597         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned int*), \
4598         (this, ret, first, last, base, state, pval))
4599 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint,36)
4600 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4601     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4602 {
4603     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4604     return num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4605 }
4606
4607 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4608 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4609 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint,36)
4610 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4611     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4612 {
4613     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4614     return num_get_short_do_get_ulong(this, ret, first, last, base, state, pval);
4615 }
4616
4617 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4618 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4619 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
4620 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
4621 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint,36)
4622 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4623     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4624 {
4625     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4626     return call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval);
4627 }
4628
4629 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4630 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4631 #define call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_wchar*, \
4632         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned short*), \
4633         (this, ret, first, last, base, state, pval))
4634 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ushort,36)
4635 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4636     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4637 {
4638     ULONG v;
4639     char tmp[25], *beg, *end;
4640     int err, b;
4641
4642     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4643
4644     b = num_get_wchar__Getifld(this, tmp,
4645             &first, &last, base->fmtfl, &base->loc);
4646     beg = tmp + (tmp[0]=='-' ? 1 : 0);
4647     v = _Stoulx(beg, &end, b, &err);
4648
4649     if(v != (ULONG)((unsigned short)v))
4650         *state |= IOSTATE_failbit;
4651     else if(end!=beg && !err)
4652         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
4653     else
4654         *state |= IOSTATE_failbit;
4655
4656     if(!first.strbuf)
4657         *state |= IOSTATE_eofbit;
4658
4659     *ret = first;
4660     return ret;
4661 }
4662
4663 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4664 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4665 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ushort,36)
4666 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4667     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4668 {
4669     FIXME("(%p %p %p %p %p) stub\n", this, ret, base, state, pval);
4670     return ret;
4671 }
4672
4673 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
4674 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4675 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@ */
4676 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
4677 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ushort,36)
4678 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4679     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4680 {
4681     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4682     return call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval);
4683 }
4684
4685 static istreambuf_iterator_wchar* num_get_do_get_bool(const num_get *this,
4686         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4687         istreambuf_iterator_wchar last, ios_base *base, int *state,
4688         MSVCP_bool *pval, numpunct_wchar *numpunct)
4689 {
4690     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4691
4692     if(base->fmtfl & FMTFLAG_boolalpha) {
4693         basic_string_wchar false_bstr, true_bstr;
4694         const wchar_t *pfalse, *ptrue;
4695
4696         numpunct_wchar_falsename(numpunct, &false_bstr);
4697         numpunct_wchar_truename(numpunct, &true_bstr);
4698         pfalse = basic_string_wchar_c_str(&false_bstr);
4699         ptrue = basic_string_wchar_c_str(&true_bstr);
4700
4701         for(istreambuf_iterator_wchar_val(&first); first.strbuf;
4702                 istreambuf_iterator_wchar_inc(&first)) {
4703             if(pfalse && *pfalse && first.val!=*pfalse)
4704                 pfalse = NULL;
4705             if(ptrue && *ptrue && first.val!=*ptrue)
4706                 ptrue = NULL;
4707
4708             if(pfalse && *pfalse && ptrue && !*ptrue)
4709                 ptrue = NULL;
4710             if(ptrue && *ptrue && pfalse && !*pfalse)
4711                 pfalse = NULL;
4712
4713             if(pfalse)
4714                 pfalse++;
4715             if(ptrue)
4716                 ptrue++;
4717
4718             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
4719                 break;
4720         }
4721
4722         if(ptrue)
4723             *pval = TRUE;
4724         else if(pfalse)
4725             *pval = FALSE;
4726         else
4727             *state |= IOSTATE_failbit;
4728
4729         basic_string_wchar_dtor(&false_bstr);
4730         basic_string_wchar_dtor(&true_bstr);
4731     }else {
4732         char tmp[25], *end;
4733         int err;
4734         LONG v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4735                     &last, base->fmtfl, &base->loc, numpunct), &err);
4736
4737         if(end!=tmp && err==0 && (v==0 || v==1))
4738             *pval = v;
4739         else
4740             *state |= IOSTATE_failbit;
4741     }
4742
4743     if(!first.strbuf)
4744         *state |= IOSTATE_eofbit;
4745     memcpy(ret, &first, sizeof(first));
4746     return ret;
4747 }
4748
4749 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4750 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4751 #define call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_wchar*, \
4752         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, MSVCP_bool*), \
4753         (this, ret, first, last, base, state, pval))
4754 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_bool,36)
4755 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4756     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4757 {
4758     return num_get_do_get_bool(this, ret, first, last, base,
4759             state, pval, numpunct_wchar_use_facet(&base->loc));
4760 }
4761
4762 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4763 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4764 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_bool,36)
4765 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4766     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4767 {
4768     return num_get_do_get_bool(this, ret, first, last, base,
4769             state, pval, numpunct_short_use_facet(&base->loc));
4770 }
4771
4772 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4773 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4774 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
4775 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
4776 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_bool,36)
4777 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4778     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4779 {
4780     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4781     return call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval);
4782 }
4783
4784 /* ?id@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
4785 locale_id num_get_char_id = {0};
4786
4787 /* ??_7?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
4788 extern const vtable_ptr MSVCP_num_get_char_vtable;
4789
4790 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
4791 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
4792 DEFINE_THISCALL_WRAPPER(num_get_char__Init, 8)
4793 void __thiscall num_get_char__Init(num_get *this, const _Locinfo *locinfo)
4794 {
4795     TRACE("(%p %p)\n", this, locinfo);
4796     _Locinfo__Getcvt(locinfo, &this->cvt);
4797 }
4798
4799 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
4800 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
4801 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_locinfo, 12)
4802 num_get* __thiscall num_get_char_ctor_locinfo(num_get *this,
4803         const _Locinfo *locinfo, MSVCP_size_t refs)
4804 {
4805     TRACE("(%p %p %lu)\n", this, locinfo, refs);
4806
4807     locale_facet_ctor_refs(&this->facet, refs);
4808     this->facet.vtable = &MSVCP_num_get_char_vtable;
4809
4810     num_get_char__Init(this, locinfo);
4811     return this;
4812 }
4813
4814 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
4815 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
4816 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_refs, 8)
4817 num_get* __thiscall num_get_char_ctor_refs(num_get *this, MSVCP_size_t refs)
4818 {
4819     _Locinfo locinfo;
4820
4821     TRACE("(%p %lu)\n", this, refs);
4822
4823     _Locinfo_ctor(&locinfo);
4824     num_get_char_ctor_locinfo(this, &locinfo, refs);
4825     _Locinfo_dtor(&locinfo);
4826     return this;
4827 }
4828
4829 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
4830 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
4831 DEFINE_THISCALL_WRAPPER(num_get_char_ctor, 4)
4832 num_get* __thiscall num_get_char_ctor(num_get *this)
4833 {
4834     return num_get_char_ctor_refs(this, 0);
4835 }
4836
4837 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
4838 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
4839 static void num_get_char_dtor(num_get *this)
4840 {
4841     TRACE("(%p)\n", this);
4842     locale_facet_dtor(&this->facet);
4843 }
4844
4845 DEFINE_THISCALL_WRAPPER(num_get_char_vector_dtor, 8)
4846 num_get* __thiscall num_get_char_vector_dtor(num_get *this, unsigned int flags)
4847 {
4848     TRACE("(%p %x)\n", this, flags);
4849     if(flags & 2) {
4850         /* we have an array, with the number of elements stored before the first object */
4851         INT_PTR i, *ptr = (INT_PTR *)this-1;
4852
4853         for(i=*ptr-1; i>=0; i--)
4854             num_get_char_dtor(this+i);
4855         MSVCRT_operator_delete(ptr);
4856     } else {
4857         num_get_char_dtor(this);
4858         if(flags & 1)
4859             MSVCRT_operator_delete(this);
4860     }
4861
4862     return this;
4863 }
4864
4865 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4866 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4867 static MSVCP_size_t num_get_char__Getcat(const locale_facet **facet, const locale *loc)
4868 {
4869     TRACE("(%p %p)\n", facet, loc);
4870
4871     if(facet && !*facet) {
4872         _Locinfo locinfo;
4873
4874         *facet = MSVCRT_operator_new(sizeof(num_get));
4875         if(!*facet) {
4876             ERR("Out of memory\n");
4877             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
4878             return 0;
4879         }
4880
4881         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
4882         num_get_char_ctor_locinfo((num_get*)*facet, &locinfo, 0);
4883         _Locinfo_dtor(&locinfo);
4884     }
4885
4886     return LC_NUMERIC;
4887 }
4888
4889 num_get* num_get_char_use_facet(const locale *loc)
4890 {
4891     static num_get *obj = NULL;
4892
4893     _Lockit lock;
4894     const locale_facet *fac;
4895
4896     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4897     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_char_id));
4898     if(fac) {
4899         _Lockit_dtor(&lock);
4900         return (num_get*)fac;
4901     }
4902
4903     if(obj) {
4904         _Lockit_dtor(&lock);
4905         return obj;
4906     }
4907
4908     num_get_char__Getcat(&fac, loc);
4909     obj = (num_get*)fac;
4910     locale_facet__Incref(&obj->facet);
4911     locale_facet_register(&obj->facet);
4912     _Lockit_dtor(&lock);
4913
4914     return obj;
4915 }
4916
4917 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1ABVlocale@2@@Z */
4918 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1AEBVlocale@2@@Z */
4919 /* Copies number to dest buffer, validates grouping and skips separators.
4920  * Updates first so it points past the number, all digits are skipped.
4921  * Returns how exponent needs to changed.
4922  * Size of dest buffer is not specified, assuming it's not smaller than 32:
4923  * strlen(+0.e+) + 22(digits) + 4(expontent) + 1(nullbyte)
4924  */
4925 static int num_get_char__Getffld(const num_get *this, char *dest, istreambuf_iterator_char *first,
4926         istreambuf_iterator_char *last, const locale *loc)
4927 {
4928     numpunct_char *numpunct = numpunct_char_use_facet(loc);
4929     int exp = 0;
4930     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
4931     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
4932
4933     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
4934
4935     istreambuf_iterator_char_val(first);
4936     /* get sign */
4937     if(first->strbuf && (first->val=='-' || first->val=='+')) {
4938         *dest++ = first->val;
4939         istreambuf_iterator_char_inc(first);
4940     }
4941
4942
4943     /* read numbers before decimal */
4944     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4945         if(first->val<'0' || first->val>'9') {
4946             break;
4947         }else {
4948             got_digit = TRUE; /* found a digit, zero or non-zero */
4949             /* write digit to dest if not a leading zero (to not waste dest buffer) */
4950             if(!got_nonzero && first->val == '0')
4951                 continue;
4952             got_nonzero = TRUE;
4953             if(dest < num_end)
4954                 *dest++ = first->val;
4955             else
4956                 exp++; /* too many digits, just multiply by 10 */
4957         }
4958     }
4959     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
4960     if(got_digit && !got_nonzero)
4961         *dest++ = '0';
4962
4963     /* get decimal, if any */
4964     if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
4965         if(dest < num_end)
4966             *dest++ = *localeconv()->decimal_point;
4967         istreambuf_iterator_char_inc(first);
4968     }
4969
4970     /* read non-grouped after decimal */
4971     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4972         if(first->val<'0' || first->val>'9')
4973             break;
4974         else if(dest<num_end) {
4975             got_digit = TRUE;
4976             *dest++ = first->val;
4977         }
4978     }
4979
4980     /* read exponent, if any */
4981     if(first->strbuf && (first->val=='e' || first->val=='E')) {
4982         *dest++ = first->val;
4983         istreambuf_iterator_char_inc(first);
4984
4985         if(first->strbuf && (first->val=='-' || first->val=='+')) {
4986             *dest++ = first->val;
4987             istreambuf_iterator_char_inc(first);
4988         }
4989
4990         got_digit = got_nonzero = FALSE;
4991         error = TRUE;
4992         /* skip any leading zeroes */
4993         for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
4994             got_digit = TRUE;
4995
4996         for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
4997             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
4998             error = FALSE;
4999             if(dest<exp_end)
5000                 *dest++ = first->val;
5001         }
5002
5003         /* if just found zeroes for exponent, use that */
5004         if(got_digit && !got_nonzero)
5005         {
5006             error = FALSE;
5007             if(dest<exp_end)
5008                 *dest++ = '0';
5009         }
5010     }
5011
5012     if(error) {
5013         *dest_beg = '\0';
5014         return 0;
5015     }
5016     *dest++ = '\0';
5017     return exp;
5018 }
5019
5020 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HABVlocale@2@@Z */
5021 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HAEBVlocale@2@@Z */
5022 /* Copies number to dest buffer, validates grouping and skips separators.
5023  * Updates first so it points past the number, all digits are skipped.
5024  * Returns number base (8, 10 or 16).
5025  * Size of dest buffer is not specified, assuming it's not smaller than 25:
5026  * 22(8^22>2^64)+1(detect overflows)+1(sign)+1(nullbyte) = 25
5027  */
5028 static int num_get_char__Getifld(const num_get *this, char *dest, istreambuf_iterator_char *first,
5029         istreambuf_iterator_char *last, int fmtflags, const locale *loc)
5030 {
5031     static const char digits[] = "0123456789abcdefABCDEF";
5032
5033     int basefield, base;
5034     char *dest_beg = dest, *dest_end = dest+24;
5035     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
5036
5037     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
5038
5039     basefield = fmtflags & FMTFLAG_basefield;
5040     if(basefield == FMTFLAG_oct)
5041         base = 8;
5042     else if(basefield == FMTFLAG_hex)
5043         base = 22; /* equal to the size of digits buffer */
5044     else if(!basefield)
5045         base = 0;
5046     else
5047         base = 10;
5048
5049     istreambuf_iterator_char_val(first);
5050     if(first->strbuf && (first->val=='-' || first->val=='+')) {
5051         *dest++ = first->val;
5052         istreambuf_iterator_char_inc(first);
5053     }
5054
5055     if(first->strbuf && first->val=='0') {
5056         found_zero = TRUE;
5057         istreambuf_iterator_char_inc(first);
5058         if(first->strbuf && (first->val=='x' || first->val=='X')) {
5059             if(!base || base == 22) {
5060                 found_zero = FALSE;
5061                 istreambuf_iterator_char_inc(first);
5062                 base = 22;
5063             }else {
5064                 base = 10;
5065             }
5066         }else {
5067             error = FALSE;
5068             if(!base) base = 8;
5069         }
5070     }else {
5071         if (!base) base = 10;
5072     }
5073
5074     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5075         if(!memchr(digits, first->val, base)) {
5076             break;
5077         }else {
5078             error = FALSE;
5079             if(dest_empty && first->val == '0')
5080             {
5081                 found_zero = TRUE;
5082                 continue;
5083             }
5084             dest_empty = FALSE;
5085             /* skip digits that can't be copied to dest buffer, other
5086              * functions are responsible for detecting overflows */
5087             if(dest < dest_end)
5088                 *dest++ = first->val;
5089         }
5090     }
5091
5092     if(error) {
5093         if (found_zero)
5094             *dest++ = '0';
5095         else
5096             dest = dest_beg;
5097     }else if(dest_empty)
5098         *dest++ = '0';
5099     *dest = '\0';
5100
5101     return (base==22 ? 16 : base);
5102 }
5103
5104 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5105 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5106 #define call_num_get_char_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_char*, \
5107         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, void**), \
5108         (this, ret, first, last, base, state, pval))
5109 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_void,36)
5110 istreambuf_iterator_char *__thiscall num_get_char_do_get_void(const num_get *this, istreambuf_iterator_char *ret,
5111     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5112 {
5113     unsigned __int64 v;
5114     char tmp[25], *end;
5115     int err;
5116
5117     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5118
5119     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5120                 &first, &last, FMTFLAG_hex, &base->loc), &err);
5121     if(v!=(unsigned __int64)((INT_PTR)v))
5122         *state |= IOSTATE_failbit;
5123     else if(end!=tmp && !err)
5124         *pval = (void*)((INT_PTR)v);
5125     else
5126         *state |= IOSTATE_failbit;
5127
5128     if(!first.strbuf)
5129         *state |= IOSTATE_eofbit;
5130
5131     *ret = first;
5132     return ret;
5133 }
5134
5135 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5136 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5137 DEFINE_THISCALL_WRAPPER(num_get_char_get_void,36)
5138 istreambuf_iterator_char *__thiscall num_get_char_get_void(const num_get *this, istreambuf_iterator_char *ret,
5139     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5140 {
5141     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5142     return call_num_get_char_do_get_void(this, ret, first, last, base, state, pval);
5143 }
5144
5145 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5146 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5147 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5148 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
5149 #define call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_char*, \
5150         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5151         (this, ret, first, last, base, state, pval))
5152 #define call_num_get_char_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_char*, \
5153         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5154         (this, ret, first, last, base, state, pval))
5155 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_double,36)
5156 istreambuf_iterator_char *__thiscall num_get_char_do_get_double(const num_get *this, istreambuf_iterator_char *ret,
5157     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5158 {
5159     double v;
5160     char tmp[32], *end;
5161     int err;
5162
5163     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5164
5165     v = _Stodx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, &base->loc), &err);
5166     if(end!=tmp && !err)
5167         *pval = v;
5168     else
5169         *state |= IOSTATE_failbit;
5170
5171     if(!first.strbuf)
5172         *state |= IOSTATE_eofbit;
5173
5174     *ret = first;
5175     return ret;
5176 }
5177
5178 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5179 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5180 DEFINE_THISCALL_WRAPPER(num_get_char_get_ldouble,36)
5181 istreambuf_iterator_char *__thiscall num_get_char_get_ldouble(const num_get *this, istreambuf_iterator_char *ret,
5182         istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5183 {
5184     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5185     return call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval);
5186 }
5187
5188 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5189 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
5190 DEFINE_THISCALL_WRAPPER(num_get_char_get_double,36)
5191 istreambuf_iterator_char *__thiscall num_get_char_get_double(const num_get *this, istreambuf_iterator_char *ret,
5192     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5193 {
5194     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5195     return call_num_get_char_do_get_double(this, ret, first, last, base, state, pval);
5196 }
5197
5198 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5199 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5200 #define call_num_get_char_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_char*, \
5201         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, float*), \
5202         (this, ret, first, last, base, state, pval))
5203 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_float,36)
5204 istreambuf_iterator_char *__thiscall num_get_char_do_get_float(const num_get *this, istreambuf_iterator_char *ret,
5205     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5206 {
5207     float v;
5208     char tmp[32], *end;
5209     int err;
5210
5211     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5212
5213     v = _Stofx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, &base->loc), &err);
5214     if(end!=tmp && !err)
5215         *pval = v;
5216     else
5217         *state |= IOSTATE_failbit;
5218
5219     if(!first.strbuf)
5220         *state |= IOSTATE_eofbit;
5221
5222     *ret = first;
5223     return ret;
5224 }
5225
5226 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5227 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5228 DEFINE_THISCALL_WRAPPER(num_get_char_get_float,36)
5229 istreambuf_iterator_char *__thiscall num_get_char_get_float(const num_get *this, istreambuf_iterator_char *ret,
5230     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5231 {
5232     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5233     return call_num_get_char_do_get_float(this, ret, first, last, base, state, pval);
5234 }
5235
5236 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5237 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5238 #define call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_char*, \
5239         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONGLONG*), \
5240         (this, ret, first, last, base, state, pval))
5241 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint64,36)
5242 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5243     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5244 {
5245     unsigned __int64 v;
5246     char tmp[25], *end;
5247     int err;
5248
5249     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5250
5251     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5252                 &first, &last, base->fmtfl, &base->loc), &err);
5253     if(end!=tmp && !err)
5254         *pval = v;
5255     else
5256         *state |= IOSTATE_failbit;
5257
5258     if(!first.strbuf)
5259         *state |= IOSTATE_eofbit;
5260
5261     *ret = first;
5262     return ret;
5263 }
5264
5265 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5266 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5267 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint64,36)
5268 istreambuf_iterator_char *__thiscall num_get_char_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5269     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5270 {
5271     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5272     return call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval);
5273 }
5274
5275 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5276 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5277 #define call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_char*, \
5278         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONGLONG*), \
5279         (this, ret, first, last, base, state, pval))
5280 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_int64,36)
5281 istreambuf_iterator_char *__thiscall num_get_char_do_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5282     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5283 {
5284     __int64 v;
5285     char tmp[25], *end;
5286     int err;
5287
5288     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5289
5290     v = _Stollx(tmp, &end, num_get_char__Getifld(this, tmp,
5291                 &first, &last, base->fmtfl, &base->loc), &err);
5292     if(end!=tmp && !err)
5293         *pval = v;
5294     else
5295         *state |= IOSTATE_failbit;
5296
5297     if(!first.strbuf)
5298         *state |= IOSTATE_eofbit;
5299
5300     *ret = first;
5301     return ret;
5302 }
5303
5304 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5305 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5306 DEFINE_THISCALL_WRAPPER(num_get_char_get_int64,36)
5307 istreambuf_iterator_char *__thiscall num_get_char_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5308     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5309 {
5310     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5311     return call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval);
5312 }
5313
5314 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5315 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5316 #define call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_char*, \
5317         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONG*), \
5318         (this, ret, first, last, base, state, pval))
5319 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ulong,36)
5320 istreambuf_iterator_char *__thiscall num_get_char_do_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5321     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5322 {
5323     ULONG v;
5324     char tmp[25], *end;
5325     int err;
5326
5327     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5328
5329     v = _Stoulx(tmp, &end, num_get_char__Getifld(this, tmp,
5330                 &first, &last, base->fmtfl, &base->loc), &err);
5331     if(end!=tmp && !err)
5332         *pval = v;
5333     else
5334         *state |= IOSTATE_failbit;
5335
5336     if(!first.strbuf)
5337         *state |= IOSTATE_eofbit;
5338
5339     *ret = first;
5340     return ret;
5341 }
5342
5343 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5344 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5345 DEFINE_THISCALL_WRAPPER(num_get_char_get_ulong,36)
5346 istreambuf_iterator_char *__thiscall num_get_char_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5347     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5348 {
5349     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5350     return call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5351 }
5352
5353 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5354 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5355 #define call_num_get_char_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_char*, \
5356         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONG*), \
5357         (this, ret, first, last, base, state, pval))
5358 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_long,36)
5359 istreambuf_iterator_char *__thiscall num_get_char_do_get_long(const num_get *this, istreambuf_iterator_char *ret,
5360     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5361 {
5362     LONG v;
5363     char tmp[25], *end;
5364     int err;
5365
5366     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5367
5368     v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5369                 &first, &last, base->fmtfl, &base->loc), &err);
5370     if(end!=tmp && !err)
5371         *pval = v;
5372     else
5373         *state |= IOSTATE_failbit;
5374
5375     if(!first.strbuf)
5376         *state |= IOSTATE_eofbit;
5377
5378     *ret = first;
5379     return ret;
5380 }
5381
5382 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5383 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5384 DEFINE_THISCALL_WRAPPER(num_get_char_get_long,36)
5385 istreambuf_iterator_char *__thiscall num_get_char_get_long(const num_get *this, istreambuf_iterator_char *ret,
5386     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5387 {
5388     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5389     return call_num_get_char_do_get_long(this, ret, first, last, base, state, pval);
5390 }
5391
5392 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5393 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5394 #define call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_char*, \
5395         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned int*), \
5396         (this, ret, first, last, base, state, pval))
5397 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint,36)
5398 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5399     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5400 {
5401     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5402     return num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5403 }
5404
5405 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5406 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5407 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint,36)
5408 istreambuf_iterator_char *__thiscall num_get_char_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5409     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5410 {
5411     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5412     return call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval);
5413 }
5414
5415 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5416 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5417 #define call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_char*, \
5418         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned short*), \
5419         (this, ret, first, last, base, state, pval))
5420 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ushort,36)
5421 istreambuf_iterator_char *__thiscall num_get_char_do_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5422     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5423 {
5424     ULONG v;
5425     char tmp[25], *beg, *end;
5426     int err, b;
5427
5428     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5429
5430     b = num_get_char__Getifld(this, tmp,
5431             &first, &last, base->fmtfl, &base->loc);
5432     beg = tmp + (tmp[0]=='-' ? 1 : 0);
5433     v = _Stoulx(beg, &end, b, &err);
5434
5435     if(v != (ULONG)((unsigned short)v))
5436         *state |= IOSTATE_failbit;
5437     else if(end!=beg && !err)
5438         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
5439     else
5440         *state |= IOSTATE_failbit;
5441
5442     if(!first.strbuf)
5443         *state |= IOSTATE_eofbit;
5444
5445     *ret = first;
5446     return ret;
5447 }
5448
5449 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5450 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5451 DEFINE_THISCALL_WRAPPER(num_get_char_get_ushort,36)
5452 istreambuf_iterator_char *__thiscall num_get_char_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5453     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5454 {
5455     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5456     return call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval);
5457 }
5458
5459 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5460 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5461 #define call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_char*, \
5462         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, MSVCP_bool*), \
5463         (this, ret, first, last, base, state, pval))
5464 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_bool,36)
5465 istreambuf_iterator_char *__thiscall num_get_char_do_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5466     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5467 {
5468     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5469
5470     if(base->fmtfl & FMTFLAG_boolalpha) {
5471         numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5472         basic_string_char false_bstr, true_bstr;
5473         const char *pfalse, *ptrue;
5474
5475         numpunct_char_falsename(numpunct, &false_bstr);
5476         numpunct_char_truename(numpunct, &true_bstr);
5477         pfalse = basic_string_char_c_str(&false_bstr);
5478         ptrue = basic_string_char_c_str(&true_bstr);
5479
5480         for(istreambuf_iterator_char_val(&first); first.strbuf;
5481                 istreambuf_iterator_char_inc(&first)) {
5482             if(pfalse && *pfalse && first.val!=*pfalse)
5483                 pfalse = NULL;
5484             if(ptrue && *ptrue && first.val!=*ptrue)
5485                 ptrue = NULL;
5486
5487             if(pfalse && *pfalse && ptrue && !*ptrue)
5488                 ptrue = NULL;
5489             if(ptrue && *ptrue && pfalse && !*pfalse)
5490                 pfalse = NULL;
5491
5492             if(pfalse)
5493                 pfalse++;
5494             if(ptrue)
5495                 ptrue++;
5496
5497             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
5498                 break;
5499         }
5500
5501         if(ptrue)
5502             *pval = TRUE;
5503         else if(pfalse)
5504             *pval = FALSE;
5505         else
5506             *state |= IOSTATE_failbit;
5507
5508         basic_string_char_dtor(&false_bstr);
5509         basic_string_char_dtor(&true_bstr);
5510     }else {
5511         char tmp[25], *end;
5512         int err;
5513         LONG v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5514                     &first, &last, base->fmtfl, &base->loc), &err);
5515
5516         if(end!=tmp && err==0 && (v==0 || v==1))
5517             *pval = v;
5518         else
5519             *state |= IOSTATE_failbit;
5520     }
5521
5522     if(!first.strbuf)
5523         *state |= IOSTATE_eofbit;
5524     memcpy(ret, &first, sizeof(first));
5525     return ret;
5526 }
5527
5528 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5529 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5530 DEFINE_THISCALL_WRAPPER(num_get_char_get_bool,36)
5531 istreambuf_iterator_char *__thiscall num_get_char_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5532     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5533 {
5534     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5535     return call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval);
5536 }
5537
5538 /* ?id@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
5539 locale_id num_put_char_id = {0};
5540
5541 /* num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
5542 extern const vtable_ptr MSVCP_num_put_char_vtable;
5543
5544 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
5545 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
5546 DEFINE_THISCALL_WRAPPER(num_put_char__Init, 8)
5547 void __thiscall num_put_char__Init(num_put *this, const _Locinfo *locinfo)
5548 {
5549     TRACE("(%p %p)\n", this, locinfo);
5550     _Locinfo__Getcvt(locinfo, &this->cvt);
5551 }
5552
5553 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
5554 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
5555 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_locinfo, 12)
5556 num_put* __thiscall num_put_char_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
5557 {
5558     TRACE("(%p %p %ld)\n", this, locinfo, refs);
5559
5560     locale_facet_ctor_refs(&this->facet, refs);
5561     this->facet.vtable = &MSVCP_num_put_char_vtable;
5562
5563     num_put_char__Init(this, locinfo);
5564     return this;
5565 }
5566
5567 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
5568 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
5569 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_refs, 8)
5570 num_put* __thiscall num_put_char_ctor_refs(num_put *this, MSVCP_size_t refs)
5571 {
5572      _Locinfo locinfo;
5573
5574      TRACE("(%p %lu)\n", this, refs);
5575
5576      _Locinfo_ctor(&locinfo);
5577      num_put_char_ctor_locinfo(this, &locinfo, refs);
5578      _Locinfo_dtor(&locinfo);
5579      return this;
5580 }
5581
5582 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
5583 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
5584 DEFINE_THISCALL_WRAPPER(num_put_char_ctor, 4)
5585 num_put* __thiscall num_put_char_ctor(num_put *this)
5586 {
5587     return num_put_char_ctor_refs(this, 0);
5588 }
5589
5590 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
5591 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
5592 static void num_put_char_dtor(num_put *this)
5593 {
5594     TRACE("(%p)\n", this);
5595     locale_facet_dtor(&this->facet);
5596 }
5597
5598 DEFINE_THISCALL_WRAPPER(num_put_char_vector_dtor, 8)
5599 num_put* __thiscall num_put_char_vector_dtor(num_put *this, unsigned int flags)
5600 {
5601     TRACE("(%p %x)\n", this, flags);
5602     if(flags & 2) {
5603         /* we have an array, with the number of elements stored before the first object */
5604         INT_PTR i, *ptr = (INT_PTR *)this-1;
5605
5606         for(i=*ptr-1; i>=0; i--)
5607             num_put_char_dtor(this+i);
5608         MSVCRT_operator_delete(ptr);
5609     } else {
5610         num_put_char_dtor(this);
5611         if(flags & 1)
5612             MSVCRT_operator_delete(this);
5613     }
5614
5615     return this;
5616 }
5617
5618 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
5619 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
5620 static MSVCP_size_t num_put_char__Getcat(const locale_facet **facet, const locale *loc)
5621 {
5622     TRACE("(%p %p)\n", facet, loc);
5623
5624     if(facet && !*facet) {
5625         _Locinfo locinfo;
5626
5627         *facet = MSVCRT_operator_new(sizeof(num_put));
5628         if(!*facet) {
5629             ERR("Out of memory\n");
5630             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5631             return 0;
5632         }
5633
5634         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
5635         num_put_char_ctor_locinfo((num_put*)*facet, &locinfo, 0);
5636         _Locinfo_dtor(&locinfo);
5637     }
5638
5639     return LC_NUMERIC;
5640 }
5641
5642 num_put* num_put_char_use_facet(const locale *loc)
5643 {
5644     static num_put *obj = NULL;
5645
5646     _Lockit lock;
5647     const locale_facet *fac;
5648
5649     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
5650     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_char_id));
5651     if(fac) {
5652         _Lockit_dtor(&lock);
5653         return (num_put*)fac;
5654     }
5655
5656     if(obj) {
5657         _Lockit_dtor(&lock);
5658         return obj;
5659     }
5660
5661     num_put_char__Getcat(&fac, loc);
5662     obj = (num_put*)fac;
5663     locale_facet__Incref(&obj->facet);
5664     locale_facet_register(&obj->facet);
5665     _Lockit_dtor(&lock);
5666
5667     return obj;
5668 }
5669
5670 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PBDI@Z */
5671 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PEBD_K@Z */
5672 static ostreambuf_iterator_char* num_put_char__Putc(const num_put *this, ostreambuf_iterator_char *ret,
5673         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
5674 {
5675     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
5676
5677     for(; count>0; count--)
5678         ostreambuf_iterator_char_put(&dest, *ptr++);
5679
5680     *ret = dest;
5681     return ret;
5682 }
5683
5684 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@DI@Z */
5685 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@D_K@Z */
5686 static ostreambuf_iterator_char* num_put_char__Rep(const num_put *this, ostreambuf_iterator_char *ret,
5687         ostreambuf_iterator_char dest, char c, MSVCP_size_t count)
5688 {
5689     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
5690
5691     for(; count>0; count--)
5692         ostreambuf_iterator_char_put(&dest, c);
5693
5694     *ret = dest;
5695     return ret;
5696 }
5697
5698 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADDH@Z */
5699 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADDH@Z */
5700 static char* num_put_char__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
5701 {
5702     int type = fmtfl & FMTFLAG_floatfield;
5703     char *p = fmt;
5704
5705     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
5706
5707     *p++ = '%';
5708     if(fmtfl & FMTFLAG_showpos)
5709         *p++ = '+';
5710     if(fmtfl & FMTFLAG_showbase)
5711         *p++ = '#';
5712     *p++ = '.';
5713     *p++ = '*';
5714     if(spec)
5715         *p++ = spec;
5716
5717     if(type == FMTFLAG_fixed)
5718         *p++ = 'f';
5719     else if(type == FMTFLAG_scientific)
5720         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
5721     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
5722         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
5723     else
5724         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
5725
5726     *p++ = '\0';
5727     return fmt;
5728 }
5729
5730 /* TODO: This function should be removed when num_put_char__Fput is implemented */
5731 static ostreambuf_iterator_char* num_put_char_fput(const num_put *this, ostreambuf_iterator_char *ret,
5732         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5733 {
5734     numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5735     char *p, sep = *localeconv()->decimal_point;
5736     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5737     MSVCP_size_t pad;
5738
5739     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5740
5741     /* Change decimal point */
5742     for(p=buf; p<buf+count; p++) {
5743         if(*p == sep) {
5744             *p = numpunct_char_decimal_point(numpunct);
5745             break;
5746         }
5747     }
5748     p--;
5749
5750     /* Display number with padding */
5751     if(count >= base->wide)
5752         pad = 0;
5753     else
5754         pad = base->wide-count;
5755     base->wide = 0;
5756
5757     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5758         num_put_char__Putc(this, &dest, dest, buf, 1);
5759         buf++;
5760     }
5761     if(adjustfield != FMTFLAG_left) {
5762         num_put_char__Rep(this, ret, dest, fill, pad);
5763         pad = 0;
5764     }
5765     num_put_char__Putc(this, &dest, dest, buf, count);
5766     return num_put_char__Rep(this, ret, dest, fill, pad);
5767 }
5768
5769 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADPBDH@Z */
5770 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
5771 static char* num_put_char__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
5772 {
5773     int base = fmtfl & FMTFLAG_basefield;
5774     char *p = fmt;
5775
5776     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
5777
5778     *p++ = '%';
5779     if(fmtfl & FMTFLAG_showpos)
5780         *p++ = '+';
5781     if(fmtfl & FMTFLAG_showbase)
5782         *p++ = '#';
5783
5784     *p++ = *spec++;
5785     if(*spec == 'l')
5786         *p++ = *spec++;
5787
5788     if(base == FMTFLAG_oct)
5789         *p++ = 'o';
5790     else if(base == FMTFLAG_hex)
5791         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
5792     else
5793         *p++ = *spec;
5794
5795     *p++ = '\0';
5796     return fmt;
5797 }
5798
5799 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPADI@Z */
5800 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEAD_K@Z */
5801 static ostreambuf_iterator_char* num_put_char__Iput(const num_put *this, ostreambuf_iterator_char *ret,
5802         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5803 {
5804     numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
5805     basic_string_char grouping_bstr;
5806     const char *grouping;
5807     char *p, sep;
5808     int cur_group = 0, group_size = 0;
5809     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5810     MSVCP_size_t pad;
5811
5812     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5813
5814     /* Add separators to number */
5815     numpunct_char_grouping(numpunct, &grouping_bstr);
5816     grouping = basic_string_char_c_str(&grouping_bstr);
5817     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5818
5819     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
5820         group_size++;
5821         if(group_size == grouping[cur_group]) {
5822             group_size = 0;
5823             if(grouping[cur_group+1])
5824                 cur_group++;
5825
5826             memmove(p+1, p, buf+count-p);
5827             *p = sep;
5828             count++;
5829         }
5830     }
5831     basic_string_char_dtor(&grouping_bstr);
5832
5833     /* Display number with padding */
5834     if(count >= base->wide)
5835         pad = 0;
5836     else
5837         pad = base->wide-count;
5838     base->wide = 0;
5839
5840     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5841         num_put_char__Putc(this, &dest, dest, buf, 1);
5842         buf++;
5843     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
5844         num_put_char__Putc(this, &dest, dest, buf, 2);
5845         buf += 2;
5846     }
5847     if(adjustfield != FMTFLAG_left) {
5848         num_put_char__Rep(this, ret, dest, fill, pad);
5849         pad = 0;
5850     }
5851     num_put_char__Putc(this, &dest, dest, buf, count);
5852     return num_put_char__Rep(this, ret, dest, fill, pad);
5853 }
5854
5855 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
5856 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
5857 #define call_num_put_char_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_char*, \
5858         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, LONG), \
5859         (this, ret, dest, base, fill, v))
5860 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_long, 28)
5861 ostreambuf_iterator_char* __thiscall num_put_char_do_put_long(const num_put *this, ostreambuf_iterator_char *ret,
5862         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
5863 {
5864     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
5865     char fmt[7]; /* strlen("%+#lld")+1 */
5866
5867     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5868
5869     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
5870             sprintf(tmp, num_put_char__Ifmt(this, fmt, "ld", base->fmtfl), v));
5871 }
5872
5873 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
5874 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
5875 DEFINE_THISCALL_WRAPPER(num_put_char_put_long, 28)
5876 ostreambuf_iterator_char* __thiscall num_put_char_put_long(const num_put *this, ostreambuf_iterator_char *ret,
5877         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
5878 {
5879     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5880     return call_num_put_char_do_put_long(this, ret, dest, base, fill, v);
5881 }
5882
5883 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
5884 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
5885 #define call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_char*, \
5886         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, ULONG), \
5887         (this, ret, dest, base, fill, v))
5888 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ulong, 28)
5889 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
5890         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
5891 {
5892     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
5893     char fmt[7]; /* strlen("%+#lld")+1 */
5894
5895     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5896
5897     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
5898             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lu", base->fmtfl), v));
5899 }
5900
5901 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
5902 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
5903 DEFINE_THISCALL_WRAPPER(num_put_char_put_ulong, 28)
5904 ostreambuf_iterator_char* __thiscall num_put_char_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
5905         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
5906 {
5907     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
5908     return call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v);
5909 }
5910
5911 static inline streamsize get_precision(const ios_base *base)
5912 {
5913     return base->prec <= 0 && !(base->fmtfl & FMTFLAG_fixed) ? 6 : base->prec;
5914 }
5915
5916 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
5917 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
5918 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
5919 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
5920 #define call_num_put_char_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_char*, \
5921         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
5922         (this, ret, dest, base, fill, v))
5923 #define call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_char*, \
5924         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
5925         (this, ret, dest, base, fill, v))
5926 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_double, 32)
5927 ostreambuf_iterator_char* __thiscall num_put_char_do_put_double(const num_put *this, ostreambuf_iterator_char *ret,
5928         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5929 {
5930     char *tmp;
5931     char fmt[8]; /* strlen("%+#.*lg")+1 */
5932     int size;
5933     streamsize prec;
5934
5935     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5936
5937     num_put_char__Ffmt(this, fmt, '\0', base->fmtfl);
5938     prec = get_precision(base);
5939     size = _scprintf(fmt, prec, v);
5940
5941     /* TODO: don't use dynamic allocation */
5942     tmp = MSVCRT_operator_new(size*2);
5943     if(!tmp) {
5944         ERR("Out of memory\n");
5945         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5946     }
5947     num_put_char_fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v));
5948     MSVCRT_operator_delete(tmp);
5949     return ret;
5950 }
5951
5952 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
5953 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
5954 DEFINE_THISCALL_WRAPPER(num_put_char_put_double, 32)
5955 ostreambuf_iterator_char* __thiscall num_put_char_put_double(const num_put *this, ostreambuf_iterator_char *ret,
5956         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5957 {
5958     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5959     return call_num_put_char_do_put_double(this, ret, dest, base, fill, v);
5960 }
5961
5962 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
5963 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
5964 DEFINE_THISCALL_WRAPPER(num_put_char_put_ldouble, 32)
5965 ostreambuf_iterator_char* __thiscall num_put_char_put_ldouble(const num_put *this, ostreambuf_iterator_char *ret,
5966         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
5967 {
5968     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
5969     return call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v);
5970 }
5971
5972 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
5973 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
5974 #define call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_char*, \
5975         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, const void*), \
5976         (this, ret, dest, base, fill, v))
5977 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ptr, 28)
5978 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
5979         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
5980 {
5981     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
5982
5983     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
5984
5985     return num_put_char__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
5986 }
5987
5988 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
5989 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
5990 DEFINE_THISCALL_WRAPPER(num_put_char_put_ptr, 28)
5991 ostreambuf_iterator_char* __thiscall num_put_char_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
5992         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
5993 {
5994     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
5995     return call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v);
5996 }
5997
5998 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
5999 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
6000 #define call_num_put_char_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_char*, \
6001         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, __int64), \
6002         (this, ret, dest, base, fill, v))
6003 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_int64, 32)
6004 ostreambuf_iterator_char* __thiscall num_put_char_do_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6005         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6006 {
6007     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6008     char fmt[7]; /* strlen("%+#lld")+1 */
6009
6010     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6011
6012     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6013             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lld", base->fmtfl), v));
6014 }
6015
6016 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
6017 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
6018 DEFINE_THISCALL_WRAPPER(num_put_char_put_int64, 32)
6019 ostreambuf_iterator_char* __thiscall num_put_char_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6020         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6021 {
6022     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6023     return call_num_put_char_do_put_int64(this, ret, dest, base, fill, v);
6024 }
6025
6026 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6027 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6028 #define call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_char*, \
6029         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, unsigned __int64), \
6030         (this, ret, dest, base, fill, v))
6031 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_uint64, 32)
6032 ostreambuf_iterator_char* __thiscall num_put_char_do_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6033         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6034 {
6035     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6036     char fmt[7]; /* strlen("%+#lld")+1 */
6037
6038     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6039
6040     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6041             sprintf(tmp, num_put_char__Ifmt(this, fmt, "llu", base->fmtfl), v));
6042 }
6043
6044 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6045 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6046 DEFINE_THISCALL_WRAPPER(num_put_char_put_uint64, 32)
6047 ostreambuf_iterator_char* __thiscall num_put_char_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6048         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6049 {
6050     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6051     return call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v);
6052 }
6053
6054 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6055 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6056 #define call_num_put_char_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_char*, \
6057         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, MSVCP_bool), \
6058         (this, ret, dest, base, fill, v))
6059 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_bool, 28)
6060 ostreambuf_iterator_char* __thiscall num_put_char_do_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6061         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6062 {
6063     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6064
6065     if(base->fmtfl & FMTFLAG_boolalpha) {
6066         numpunct_char *numpunct = numpunct_char_use_facet(&base->loc);
6067         basic_string_char str;
6068         MSVCP_size_t pad, len;
6069
6070         if(v)
6071             numpunct_char_truename(numpunct, &str);
6072         else
6073             numpunct_char_falsename(numpunct, &str);
6074
6075         len = basic_string_char_length(&str);
6076         pad = (len>base->wide ? 0 : base->wide-len);
6077         base->wide = 0;
6078
6079         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6080             num_put_char__Rep(this, &dest, dest, fill, pad);
6081             pad = 0;
6082         }
6083         num_put_char__Putc(this, &dest, dest, basic_string_char_c_str(&str), len);
6084         basic_string_char_dtor(&str);
6085         return num_put_char__Rep(this, ret, dest, fill, pad);
6086     }
6087
6088     return num_put_char_put_long(this, ret, dest, base, fill, v);
6089 }
6090
6091 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6092 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6093 DEFINE_THISCALL_WRAPPER(num_put_char_put_bool, 28)
6094 ostreambuf_iterator_char* __thiscall num_put_char_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6095         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6096 {
6097     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6098     return call_num_put_char_do_put_bool(this, ret, dest, base, fill, v);
6099 }
6100
6101 /* ?id@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
6102 static locale_id num_put_wchar_id = {0};
6103 /* ?id@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
6104 locale_id num_put_short_id = {0};
6105
6106 /* num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
6107 extern const vtable_ptr MSVCP_num_put_wchar_vtable;
6108 /* num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
6109 extern const vtable_ptr MSVCP_num_put_short_vtable;
6110
6111 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
6112 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
6113 DEFINE_THISCALL_WRAPPER(num_put_wchar__Init, 8)
6114 void __thiscall num_put_wchar__Init(num_put *this, const _Locinfo *locinfo)
6115 {
6116     TRACE("(%p %p)\n", this, locinfo);
6117     _Locinfo__Getcvt(locinfo, &this->cvt);
6118 }
6119
6120 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6121 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6122 static num_put* num_put_wchar_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6123 {
6124     TRACE("(%p %p %ld)\n", this, locinfo, refs);
6125
6126     locale_facet_ctor_refs(&this->facet, refs);
6127     this->facet.vtable = &MSVCP_num_put_wchar_vtable;
6128
6129     num_put_wchar__Init(this, locinfo);
6130     return this;
6131 }
6132
6133 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6134 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6135 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_locinfo, 12)
6136 num_put* __thiscall num_put_short_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6137 {
6138     num_put_wchar_ctor_locinfo(this, locinfo, refs);
6139     this->facet.vtable = &MSVCP_num_put_short_vtable;
6140     return this;
6141 }
6142
6143 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
6144 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
6145 static num_put* num_put_wchar_ctor_refs(num_put *this, MSVCP_size_t refs)
6146 {
6147     _Locinfo locinfo;
6148
6149     TRACE("(%p %lu)\n", this, refs);
6150
6151     _Locinfo_ctor(&locinfo);
6152     num_put_wchar_ctor_locinfo(this, &locinfo, refs);
6153     _Locinfo_dtor(&locinfo);
6154     return this;
6155 }
6156
6157 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
6158 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
6159 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_refs, 8)
6160 num_put* __thiscall num_put_short_ctor_refs(num_put *this, MSVCP_size_t refs)
6161 {
6162     num_put_wchar_ctor_refs(this, refs);
6163     this->facet.vtable = &MSVCP_num_put_short_vtable;
6164     return this;
6165 }
6166
6167 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAEXXZ */
6168 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAAXXZ */
6169 DEFINE_THISCALL_WRAPPER(num_put_short_ctor, 4)
6170 num_put* __thiscall num_put_short_ctor(num_put *this)
6171 {
6172     return num_put_short_ctor_refs(this, 0);
6173 }
6174
6175 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
6176 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
6177 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
6178 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
6179 static void num_put_wchar_dtor(num_put *this)
6180 {
6181     TRACE("(%p)\n", this);
6182     locale_facet_dtor(&this->facet);
6183 }
6184
6185 DEFINE_THISCALL_WRAPPER(num_put_wchar_vector_dtor, 8)
6186 num_put* __thiscall num_put_wchar_vector_dtor(num_put *this, unsigned int flags)
6187 {
6188     TRACE("(%p %x)\n", this, flags);
6189     if(flags & 2) {
6190         /* we have an array, with the number of elements stored before the first object */
6191         INT_PTR i, *ptr = (INT_PTR *)this-1;
6192
6193         for(i=*ptr-1; i>=0; i--)
6194             num_put_wchar_dtor(this+i);
6195         MSVCRT_operator_delete(ptr);
6196     } else {
6197         num_put_wchar_dtor(this);
6198         if(flags & 1)
6199             MSVCRT_operator_delete(this);
6200     }
6201
6202     return this;
6203 }
6204
6205 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6206 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6207 static MSVCP_size_t num_put_wchar__Getcat(const locale_facet **facet, const locale *loc)
6208 {
6209     TRACE("(%p %p)\n", facet, loc);
6210
6211     if(facet && !*facet) {
6212         _Locinfo locinfo;
6213
6214         *facet = MSVCRT_operator_new(sizeof(num_put));
6215         if(!*facet) {
6216             ERR("Out of memory\n");
6217             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6218             return 0;
6219         }
6220
6221         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
6222         num_put_wchar_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6223         _Locinfo_dtor(&locinfo);
6224     }
6225
6226     return LC_NUMERIC;
6227 }
6228
6229 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6230 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6231 static MSVCP_size_t num_put_short__Getcat(const locale_facet **facet, const locale *loc)
6232 {
6233     TRACE("(%p %p)\n", facet, loc);
6234
6235     if(facet && !*facet) {
6236         _Locinfo locinfo;
6237
6238         *facet = MSVCRT_operator_new(sizeof(num_put));
6239         if(!*facet) {
6240             ERR("Out of memory\n");
6241             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6242             return 0;
6243         }
6244
6245         _Locinfo_ctor_cstr(&locinfo, basic_string_char_c_str(&loc->ptr->name));
6246         num_put_short_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6247         _Locinfo_dtor(&locinfo);
6248     }
6249
6250     return LC_NUMERIC;
6251 }
6252
6253 static num_put* num_put_wchar_use_facet(const locale *loc)
6254 {
6255     static num_put *obj = NULL;
6256
6257     _Lockit lock;
6258     const locale_facet *fac;
6259
6260     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6261     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_wchar_id));
6262     if(fac) {
6263         _Lockit_dtor(&lock);
6264         return (num_put*)fac;
6265     }
6266
6267     if(obj) {
6268         _Lockit_dtor(&lock);
6269         return obj;
6270     }
6271
6272     num_put_wchar__Getcat(&fac, loc);
6273     obj = (num_put*)fac;
6274     locale_facet__Incref(&obj->facet);
6275     locale_facet_register(&obj->facet);
6276     _Lockit_dtor(&lock);
6277
6278     return obj;
6279 }
6280
6281 num_put* num_put_short_use_facet(const locale *loc)
6282 {
6283     static num_put *obj = NULL;
6284
6285     _Lockit lock;
6286     const locale_facet *fac;
6287
6288     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6289     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_short_id));
6290     if(fac) {
6291         _Lockit_dtor(&lock);
6292         return (num_put*)fac;
6293     }
6294
6295     if(obj) {
6296         _Lockit_dtor(&lock);
6297         return obj;
6298     }
6299
6300     num_put_short__Getcat(&fac, loc);
6301     obj = (num_put*)fac;
6302     locale_facet__Incref(&obj->facet);
6303     locale_facet_register(&obj->facet);
6304     _Lockit_dtor(&lock);
6305
6306     return obj;
6307 }
6308
6309 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PB_WI@Z */
6310 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEB_W_K@Z */
6311 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBGI@Z */
6312 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBG_K@Z */
6313 static ostreambuf_iterator_wchar* num_put_wchar__Put(const num_put *this, ostreambuf_iterator_wchar *ret,
6314         ostreambuf_iterator_wchar dest, const wchar_t *ptr, MSVCP_size_t count)
6315 {
6316     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_wn(ptr, count), count);
6317
6318     for(; count>0; count--)
6319         ostreambuf_iterator_wchar_put(&dest, *ptr++);
6320
6321     *ret = dest;
6322     return ret;
6323 }
6324
6325 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PBDI@Z */
6326 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEBD_K@Z */
6327 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBDI@Z */
6328 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBD_K@Z */
6329 static ostreambuf_iterator_wchar* num_put_wchar__Putc(const num_put *this, ostreambuf_iterator_wchar *ret,
6330         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count)
6331 {
6332     int state = 0;
6333     wchar_t ch;
6334
6335     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_an(ptr, count), count);
6336
6337     for(; count>0; count--) {
6338         if(_Mbrtowc(&ch, ptr++, 1, &state, &this->cvt) == 1)
6339             ostreambuf_iterator_wchar_put(&dest, ch);
6340     }
6341
6342     *ret = dest;
6343     return ret;
6344 }
6345
6346 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_WI@Z */
6347 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_W_K@Z */
6348 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@GI@Z */
6349 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@G_K@Z */
6350 static ostreambuf_iterator_wchar* num_put_wchar__Rep(const num_put *this, ostreambuf_iterator_wchar *ret,
6351         ostreambuf_iterator_wchar dest, wchar_t c, MSVCP_size_t count)
6352 {
6353     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
6354
6355     for(; count>0; count--)
6356         ostreambuf_iterator_wchar_put(&dest, c);
6357
6358     *ret = dest;
6359     return ret;
6360 }
6361
6362 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADDH@Z */
6363 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6364 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADDH@Z */
6365 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6366 static char* num_put_wchar__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
6367 {
6368     int type = fmtfl & FMTFLAG_floatfield;
6369     char *p = fmt;
6370
6371     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
6372
6373     *p++ = '%';
6374     if(fmtfl & FMTFLAG_showpos)
6375         *p++ = '+';
6376     if(fmtfl & FMTFLAG_showbase)
6377         *p++ = '#';
6378     *p++ = '.';
6379     *p++ = '*';
6380     if(spec)
6381         *p++ = spec;
6382
6383     if(type == FMTFLAG_fixed)
6384         *p++ = 'f';
6385     else if(type == FMTFLAG_scientific)
6386         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
6387     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
6388         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
6389     else
6390         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
6391
6392     *p++ = '\0';
6393     return fmt;
6394 }
6395
6396 /* TODO: This function should be removed when num_put_wchar__Fput is implemented */
6397 static ostreambuf_iterator_wchar* num_put__fput(const num_put *this, ostreambuf_iterator_wchar *ret,
6398         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6399         MSVCP_size_t count, numpunct_wchar *numpunct)
6400 {
6401     char *p, dec_point = *localeconv()->decimal_point;
6402     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6403     MSVCP_size_t i, pad;
6404
6405     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6406
6407     for(p=buf; p<buf+count; p++) {
6408         if(*p == dec_point)
6409             break;
6410     }
6411     p--;
6412
6413     /* Display number with padding */
6414     if(count >= base->wide)
6415         pad = 0;
6416     else
6417         pad = base->wide-count;
6418     base->wide = 0;
6419
6420     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6421         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6422         buf++;
6423     }
6424     if(adjustfield != FMTFLAG_left) {
6425         num_put_wchar__Rep(this, ret, dest, fill, pad);
6426         pad = 0;
6427     }
6428
6429     for(i=0; i<count; i++) {
6430         if(buf[i] == dec_point)
6431             num_put_wchar__Rep(this, &dest, dest, numpunct_wchar_decimal_point(numpunct), 1);
6432         else
6433             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6434     }
6435
6436     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6437 }
6438
6439 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADPBDH@Z */
6440 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6441 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADPBDH@Z */
6442 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6443 static char* num_put_wchar__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
6444 {
6445     int base = fmtfl & FMTFLAG_basefield;
6446     char *p = fmt;
6447
6448     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
6449
6450     *p++ = '%';
6451     if(fmtfl & FMTFLAG_showpos)
6452         *p++ = '+';
6453     if(fmtfl & FMTFLAG_showbase)
6454         *p++ = '#';
6455
6456     *p++ = *spec++;
6457     if(*spec == 'l')
6458         *p++ = *spec++;
6459
6460     if(base == FMTFLAG_oct)
6461         *p++ = 'o';
6462     else if(base == FMTFLAG_hex)
6463         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
6464     else
6465         *p++ = *spec;
6466
6467     *p++ = '\0';
6468     return fmt;
6469 }
6470
6471 static ostreambuf_iterator_wchar* num_put__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6472         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6473         MSVCP_size_t count, numpunct_wchar *numpunct)
6474 {
6475     basic_string_char grouping_bstr;
6476     const char *grouping;
6477     char *p;
6478     wchar_t sep;
6479     int cur_group = 0, group_size = 0;
6480     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6481     MSVCP_size_t i, pad;
6482
6483     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6484
6485     /* Add separators to number */
6486     numpunct_wchar_grouping(numpunct, &grouping_bstr);
6487     grouping = basic_string_char_c_str(&grouping_bstr);
6488     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
6489
6490     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6491         group_size++;
6492         if(group_size == grouping[cur_group]) {
6493             group_size = 0;
6494             if(grouping[cur_group+1])
6495                 cur_group++;
6496
6497             memmove(p+1, p, buf+count-p);
6498             *p = '\0'; /* mark thousands separator positions */
6499             count++;
6500         }
6501     }
6502     basic_string_char_dtor(&grouping_bstr);
6503
6504     /* Display number with padding */
6505     if(count >= base->wide)
6506         pad = 0;
6507     else
6508         pad = base->wide-count;
6509     base->wide = 0;
6510
6511     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6512         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6513         buf++;
6514     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
6515         num_put_wchar__Putc(this, &dest, dest, buf, 2);
6516         buf += 2;
6517     }
6518     if(adjustfield != FMTFLAG_left) {
6519         num_put_wchar__Rep(this, ret, dest, fill, pad);
6520         pad = 0;
6521     }
6522
6523     for(i=0; i<count; i++) {
6524         if(!buf[i])
6525             num_put_wchar__Rep(this, &dest, dest, sep, 1);
6526         else
6527             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6528     }
6529
6530     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6531 }
6532
6533 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPADI@Z */
6534 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEAD_K@Z */
6535 static ostreambuf_iterator_wchar* num_put_wchar__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6536         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6537 {
6538     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_wchar_use_facet(&base->loc));
6539 }
6540
6541 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPADI@Z */
6542 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEAD_K@Z */
6543 static ostreambuf_iterator_wchar* num_put_short__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6544         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6545 {
6546     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_short_use_facet(&base->loc));
6547 }
6548
6549 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
6550 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
6551 #define call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_wchar*, \
6552         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, LONG), \
6553         (this, ret, dest, base, fill, v))
6554 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_long, 28)
6555 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6556         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6557 {
6558     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6559     char fmt[7]; /* strlen("%+#lld")+1 */
6560
6561     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6562
6563     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6564             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6565 }
6566
6567 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
6568 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
6569 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_long, 28)
6570 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6571         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6572 {
6573     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6574     char fmt[7]; /* strlen("%+#lld")+1 */
6575
6576     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6577
6578     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6579             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6580 }
6581
6582 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
6583 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
6584 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
6585 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
6586 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_long, 28)
6587 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6588         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6589 {
6590     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6591     return call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v);
6592 }
6593
6594 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
6595 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
6596 #define call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_wchar*, \
6597         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, ULONG), \
6598         (this, ret, dest, base, fill, v))
6599 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ulong, 28)
6600 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6601         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6602 {
6603     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6604     char fmt[7]; /* strlen("%+#lld")+1 */
6605
6606     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6607
6608     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6609             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6610 }
6611
6612 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
6613 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
6614 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ulong, 28)
6615 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6616         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6617 {
6618     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6619     char fmt[7]; /* strlen("%+#lld")+1 */
6620
6621     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6622
6623     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6624             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6625 }
6626
6627 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
6628 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
6629 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
6630 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
6631 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ulong, 28)
6632 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6633         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6634 {
6635     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6636     return call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v);
6637 }
6638
6639 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
6640 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
6641 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
6642 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
6643 #define call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_wchar*, \
6644         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6645         (this, ret, dest, base, fill, v))
6646 #define call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_wchar*, \
6647         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6648         (this, ret, dest, base, fill, v))
6649 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_double, 32)
6650 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6651         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6652 {
6653     char *tmp;
6654     char fmt[8]; /* strlen("%+#.*lg")+1 */
6655     int size;
6656
6657     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6658
6659     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6660     size = _scprintf(fmt, base->prec, v);
6661
6662     /* TODO: don't use dynamic allocation */
6663     tmp = MSVCRT_operator_new(size*2);
6664     if(!tmp) {
6665         ERR("Out of memory\n");
6666         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6667     }
6668     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, base->prec, v),
6669             numpunct_wchar_use_facet(&base->loc));
6670     MSVCRT_operator_delete(tmp);
6671     return ret;
6672 }
6673
6674 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
6675 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
6676 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
6677 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
6678 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_double, 32)
6679 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6680         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6681 {
6682     char *tmp;
6683     char fmt[8]; /* strlen("%+#.*lg")+1 */
6684     int size;
6685     streamsize prec;
6686
6687     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6688
6689     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6690     prec = get_precision(base);
6691     size = _scprintf(fmt, prec, v);
6692
6693     /* TODO: don't use dynamic allocation */
6694     tmp = MSVCRT_operator_new(size*2);
6695     if(!tmp) {
6696         ERR("Out of memory\n");
6697         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6698     }
6699     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v),
6700             numpunct_short_use_facet(&base->loc));
6701     MSVCRT_operator_delete(tmp);
6702     return ret;
6703 }
6704
6705 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
6706 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
6707 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
6708 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
6709 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_double, 32)
6710 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6711         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6712 {
6713     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6714     return call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v);
6715 }
6716
6717 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
6718 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
6719 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
6720 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
6721 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ldouble, 32)
6722 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ldouble(const num_put *this, ostreambuf_iterator_wchar *ret,
6723         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6724 {
6725     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6726     return call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v);
6727 }
6728
6729 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
6730 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
6731 #define call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_wchar*, \
6732         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, const void*), \
6733         (this, ret, dest, base, fill, v))
6734 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ptr, 28)
6735 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6736         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6737 {
6738     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6739
6740     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6741
6742     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6743 }
6744
6745 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
6746 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
6747 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ptr, 28)
6748 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6749         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6750 {
6751     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6752
6753     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6754
6755     return num_put_short__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6756 }
6757
6758 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
6759 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
6760 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
6761 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
6762 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ptr, 28)
6763 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6764         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6765 {
6766     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6767     return call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v);
6768 }
6769
6770 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
6771 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
6772 #define call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_wchar*, \
6773         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, __int64), \
6774         (this, ret, dest, base, fill, v))
6775 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_int64, 32)
6776 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6777         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6778 {
6779     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6780     char fmt[7]; /* strlen("%+#lld")+1 */
6781
6782     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6783
6784     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6785             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
6786 }
6787
6788 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
6789 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
6790 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_int64, 32)
6791 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6792         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6793 {
6794     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6795     char fmt[7]; /* strlen("%+#lld")+1 */
6796
6797     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6798
6799     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6800             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
6801 }
6802
6803 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
6804 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
6805 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
6806 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
6807 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_int64, 32)
6808 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
6809         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
6810 {
6811     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6812     return call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v);
6813 }
6814
6815 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
6816 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
6817 #define call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_wchar*, \
6818         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, unsigned __int64), \
6819         (this, ret, dest, base, fill, v))
6820 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_uint64, 32)
6821 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6822         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6823 {
6824     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6825     char fmt[7]; /* strlen("%+#lld")+1 */
6826
6827     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6828
6829     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6830             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
6831 }
6832
6833 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
6834 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
6835 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_uint64, 32)
6836 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6837         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6838 {
6839     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6840     char fmt[7]; /* strlen("%+#lld")+1 */
6841
6842     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6843
6844     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6845             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
6846 }
6847
6848 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
6849 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
6850 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
6851 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
6852 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_uint64, 32)
6853 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
6854         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
6855 {
6856     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6857     return call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v);
6858 }
6859
6860 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
6861 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
6862 #define call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_wchar*, \
6863         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, MSVCP_bool), \
6864         (this, ret, dest, base, fill, v))
6865 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_bool, 28)
6866 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6867         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6868 {
6869     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6870
6871     if(base->fmtfl & FMTFLAG_boolalpha) {
6872         numpunct_wchar *numpunct = numpunct_wchar_use_facet(&base->loc);
6873         basic_string_wchar str;
6874         MSVCP_size_t pad, len;
6875
6876         if(v)
6877             numpunct_wchar_truename(numpunct, &str);
6878         else
6879             numpunct_wchar_falsename(numpunct, &str);
6880
6881         len = basic_string_wchar_length(&str);
6882         pad = (len>base->wide ? 0 : base->wide-len);
6883         base->wide = 0;
6884
6885         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6886             num_put_wchar__Rep(this, &dest, dest, fill, pad);
6887             pad = 0;
6888         }
6889         num_put_wchar__Put(this, &dest, dest, basic_string_wchar_c_str(&str), len);
6890         basic_string_wchar_dtor(&str);
6891         return num_put_wchar__Rep(this, ret, dest, fill, pad);
6892     }
6893
6894     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
6895 }
6896
6897 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
6898 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
6899 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_bool, 28)
6900 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6901         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6902 {
6903     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6904
6905     if(base->fmtfl & FMTFLAG_boolalpha) {
6906         numpunct_wchar *numpunct = numpunct_short_use_facet(&base->loc);
6907         basic_string_wchar str;
6908         MSVCP_size_t pad, len;
6909
6910         if(v)
6911             numpunct_wchar_truename(numpunct, &str);
6912         else
6913             numpunct_wchar_falsename(numpunct, &str);
6914
6915         len = basic_string_wchar_length(&str);
6916         pad = (len>base->wide ? 0 : base->wide-len);
6917         base->wide = 0;
6918
6919         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6920             num_put_wchar__Rep(this, &dest, dest, fill, pad);
6921             pad = 0;
6922         }
6923         num_put_wchar__Put(this, &dest, dest, basic_string_wchar_c_str(&str), len);
6924         basic_string_wchar_dtor(&str);
6925         return num_put_wchar__Rep(this, ret, dest, fill, pad);
6926     }
6927
6928     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
6929 }
6930
6931 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
6932 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
6933 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
6934 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
6935 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_bool, 28)
6936 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
6937         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
6938 {
6939     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6940     return call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v);
6941 }
6942
6943 /* ??0_Locimp@locale@std@@AAE@_N@Z */
6944 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
6945 static locale__Locimp* locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
6946 {
6947     TRACE("(%p %d)\n", this, transparent);
6948
6949     memset(this, 0, sizeof(locale__Locimp));
6950     locale_facet_ctor_refs(&this->facet, 1);
6951     this->transparent = transparent;
6952     basic_string_char_ctor_cstr(&this->name, "*");
6953     return this;
6954 }
6955
6956 /* ??_F_Locimp@locale@std@@QAEXXZ */
6957 /* ??_F_Locimp@locale@std@@QEAAXXZ */
6958 static locale__Locimp* locale__Locimp_ctor(locale__Locimp *this)
6959 {
6960     return locale__Locimp_ctor_transparent(this, FALSE);
6961 }
6962
6963 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
6964 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
6965 static locale__Locimp* locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
6966 {
6967     _Lockit lock;
6968     MSVCP_size_t i;
6969
6970     TRACE("(%p %p)\n", this, copy);
6971
6972     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6973     memcpy(this, copy, sizeof(locale__Locimp));
6974     locale_facet_ctor_refs(&this->facet, 1);
6975     if(copy->facetvec) {
6976         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
6977         if(!this->facetvec) {
6978             _Lockit_dtor(&lock);
6979             ERR("Out of memory\n");
6980             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6981             return NULL;
6982         }
6983         for(i=0; i<this->facet_cnt; i++)
6984         {
6985             this->facetvec[i] = copy->facetvec[i];
6986             if(this->facetvec[i])
6987                 locale_facet__Incref(this->facetvec[i]);
6988         }
6989     }
6990     basic_string_char_copy_ctor(&this->name, &copy->name);
6991     _Lockit_dtor(&lock);
6992     return this;
6993 }
6994
6995 /* ??1_Locimp@locale@std@@MAE@XZ */
6996 /* ??1_Locimp@locale@std@@MEAA@XZ */
6997 static void locale__Locimp_dtor(locale__Locimp *this)
6998 {
6999     MSVCP_size_t i;
7000
7001     TRACE("(%p)\n", this);
7002
7003     locale_facet_dtor(&this->facet);
7004     for(i=0; i<this->facet_cnt; i++)
7005         if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
7006             call_locale_facet_vector_dtor(this->facetvec[i], 1);
7007
7008     MSVCRT_operator_delete(this->facetvec);
7009     basic_string_char_dtor(&this->name);
7010 }
7011
7012 DEFINE_THISCALL_WRAPPER(locale__Locimp_vector_dtor, 8)
7013 locale__Locimp* __thiscall locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
7014 {
7015     TRACE("(%p %x)\n", this, flags);
7016     if(flags & 2) {
7017         /* we have an array, with the number of elements stored before the first object */
7018         INT_PTR i, *ptr = (INT_PTR *)this-1;
7019
7020         for(i=*ptr-1; i>=0; i--)
7021             locale__Locimp_dtor(this+i);
7022         MSVCRT_operator_delete(ptr);
7023     } else {
7024         locale__Locimp_dtor(this);
7025         if(flags & 1)
7026             MSVCRT_operator_delete(this);
7027     }
7028
7029     return this;
7030 }
7031
7032 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
7033 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
7034 static void locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
7035 {
7036     _Lockit lock;
7037
7038     TRACE("(%p %p %lu)\n", locimp, facet, id);
7039
7040     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7041     if(id >= locimp->facet_cnt) {
7042         MSVCP_size_t new_size = id+1;
7043         locale_facet **new_facetvec;
7044
7045         if(new_size < locale_id__Id_cnt+1)
7046             new_size = locale_id__Id_cnt+1;
7047
7048         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
7049         if(!new_facetvec) {
7050             _Lockit_dtor(&lock);
7051             ERR("Out of memory\n");
7052             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7053             return;
7054         }
7055
7056         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
7057         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
7058         MSVCRT_operator_delete(locimp->facetvec);
7059         locimp->facetvec = new_facetvec;
7060         locimp->facet_cnt = new_size;
7061     }
7062
7063     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
7064         call_locale_facet_vector_dtor(locimp->facetvec[id], 1);
7065
7066     locimp->facetvec[id] = facet;
7067     if(facet)
7068         locale_facet__Incref(facet);
7069     _Lockit_dtor(&lock);
7070 }
7071
7072 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
7073 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
7074 static void locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
7075 {
7076     locale__Locimp__Locimp_Addfac(this, facet, id);
7077 }
7078
7079 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7080 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7081 /* List of missing facets:
7082  * num_put, collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7083  */
7084 static void locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7085 {
7086     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7087
7088     if(cat & (1<<(ctype_short__Getcat(NULL, NULL)-1))) {
7089         ctype_wchar *ctype;
7090
7091         if(loc) {
7092             ctype = ctype_short_use_facet(loc);
7093         }else {
7094             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7095             if(!ctype) {
7096                 ERR("Out of memory\n");
7097                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7098             }
7099             ctype_short_ctor_locinfo(ctype, locinfo, 0);
7100         }
7101         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_short_id));
7102     }
7103
7104     if(cat & (1<<(num_get_short__Getcat(NULL, NULL)-1))) {
7105         num_get *numget;
7106
7107         if(loc) {
7108             numget = num_get_short_use_facet(loc);
7109         }else {
7110             numget = MSVCRT_operator_new(sizeof(num_get));
7111             if(!numget) {
7112                 ERR("Out of memory\n");
7113                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7114             }
7115             num_get_short_ctor_locinfo(numget, locinfo, 0);
7116         }
7117         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_short_id));
7118     }
7119
7120     if(cat & (1<<(num_put_short__Getcat(NULL, NULL)-1))) {
7121         num_put *numput;
7122
7123         if(loc) {
7124             numput = num_put_short_use_facet(loc);
7125         }else {
7126             numput = MSVCRT_operator_new(sizeof(num_put));
7127             if(!numput) {
7128                 ERR("Out of memory\n");
7129                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7130             }
7131             num_put_short_ctor_locinfo(numput, locinfo, 0);
7132         }
7133         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_short_id));
7134     }
7135
7136     if(cat & (1<<(numpunct_short__Getcat(NULL, NULL)-1))) {
7137         numpunct_wchar *numpunct;
7138
7139         if(loc) {
7140             numpunct = numpunct_short_use_facet(loc);
7141         }else {
7142             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7143             if(!numpunct) {
7144                 ERR("Out of memory\n");
7145                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7146             }
7147             numpunct_short_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7148         }
7149         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_short_id));
7150     }
7151
7152     if(cat & (1<<(codecvt_short__Getcat(NULL, NULL)-1))) {
7153         codecvt_wchar *codecvt;
7154
7155         if(loc) {
7156             codecvt = codecvt_short_use_facet(loc);
7157         }else {
7158             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7159             if(!codecvt) {
7160                 ERR("Out of memory\n");
7161                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7162             }
7163             codecvt_short_ctor_locinfo(codecvt, locinfo, 0);
7164         }
7165         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_short_id));
7166     }
7167 }
7168
7169 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7170 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7171 /* List of missing facets:
7172  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7173  */
7174 static void locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7175 {
7176     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7177
7178     if(cat & (1<<(ctype_wchar__Getcat(NULL, NULL)-1))) {
7179         ctype_wchar *ctype;
7180
7181         if(loc) {
7182             ctype = ctype_wchar_use_facet(loc);
7183         }else {
7184             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7185             if(!ctype) {
7186                 ERR("Out of memory\n");
7187                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7188             }
7189             ctype_wchar_ctor_locinfo(ctype, locinfo, 0);
7190         }
7191         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_wchar_id));
7192     }
7193
7194     if(cat & (1<<(num_get_wchar__Getcat(NULL, NULL)-1))) {
7195         num_get *numget;
7196
7197         if(loc) {
7198             numget = num_get_wchar_use_facet(loc);
7199         }else {
7200             numget = MSVCRT_operator_new(sizeof(num_get));
7201             if(!numget) {
7202                 ERR("Out of memory\n");
7203                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7204             }
7205             num_get_wchar_ctor_locinfo(numget, locinfo, 0);
7206         }
7207         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_wchar_id));
7208     }
7209
7210     if(cat & (1<<(num_put_wchar__Getcat(NULL, NULL)-1))) {
7211         num_put *numput;
7212
7213         if(loc) {
7214             numput = num_put_wchar_use_facet(loc);
7215         }else {
7216             numput = MSVCRT_operator_new(sizeof(num_put));
7217             if(!numput) {
7218                 ERR("Out of memory\n");
7219                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7220             }
7221             num_put_wchar_ctor_locinfo(numput, locinfo, 0);
7222         }
7223         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_wchar_id));
7224     }
7225
7226     if(cat & (1<<(numpunct_wchar__Getcat(NULL, NULL)-1))) {
7227         numpunct_wchar *numpunct;
7228
7229         if(loc) {
7230             numpunct = numpunct_wchar_use_facet(loc);
7231         }else {
7232             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7233             if(!numpunct) {
7234                 ERR("Out of memory\n");
7235                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7236             }
7237             numpunct_wchar_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7238         }
7239         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_wchar_id));
7240     }
7241
7242     if(cat & (1<<(codecvt_wchar__Getcat(NULL, NULL)-1))) {
7243         codecvt_wchar *codecvt;
7244
7245         if(loc) {
7246             codecvt = codecvt_wchar_use_facet(loc);
7247         }else {
7248             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7249             if(!codecvt) {
7250                 ERR("Out of memory\n");
7251                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7252             }
7253             codecvt_wchar_ctor_locinfo(codecvt, locinfo, 0);
7254         }
7255         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_wchar_id));
7256     }
7257 }
7258
7259 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7260 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7261 /* List of missing facets:
7262  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7263  */
7264 static void locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7265 {
7266     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7267
7268     if(cat & (1<<(ctype_char__Getcat(NULL, NULL)-1))) {
7269         ctype_char *ctype;
7270
7271         if(loc) {
7272             ctype = ctype_char_use_facet(loc);
7273         }else {
7274             ctype = MSVCRT_operator_new(sizeof(ctype_char));
7275             if(!ctype) {
7276                 ERR("Out of memory\n");
7277                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7278             }
7279             ctype_char_ctor_locinfo(ctype, locinfo, 0);
7280         }
7281         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_char_id));
7282     }
7283
7284     if(cat & (1<<(num_get_char__Getcat(NULL, NULL)-1))) {
7285         num_get *numget;
7286
7287         if(loc) {
7288             numget = num_get_char_use_facet(loc);
7289         }else {
7290             numget = MSVCRT_operator_new(sizeof(num_get));
7291             if(!numget) {
7292                 ERR("Out of memory\n");
7293                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7294             }
7295             num_get_char_ctor_locinfo(numget, locinfo, 0);
7296         }
7297         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_char_id));
7298     }
7299
7300     if(cat & (1<<(num_put_char__Getcat(NULL, NULL)-1))) {
7301         num_put *numput;
7302
7303         if(loc) {
7304             numput = num_put_char_use_facet(loc);
7305         }else {
7306             numput = MSVCRT_operator_new(sizeof(num_put));
7307             if(!numput) {
7308                 ERR("Out of memory\n");
7309                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7310             }
7311             num_put_char_ctor_locinfo(numput, locinfo, 0);
7312         }
7313         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_char_id));
7314     }
7315
7316     if(cat & (1<<(numpunct_char__Getcat(NULL, NULL)-1))) {
7317         numpunct_char *numpunct;
7318
7319         if(loc) {
7320             numpunct = numpunct_char_use_facet(loc);
7321         }else {
7322             numpunct = MSVCRT_operator_new(sizeof(numpunct_char));
7323             if(!numpunct) {
7324                 ERR("Out of memory\n");
7325                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7326             }
7327             numpunct_char_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7328         }
7329         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_char_id));
7330     }
7331
7332     if(cat & (1<<(codecvt_char__Getcat(NULL, NULL)-1))) {
7333         codecvt_char *codecvt;
7334
7335         if(loc) {
7336             codecvt = codecvt_char_use_facet(loc);
7337         }else {
7338             codecvt = MSVCRT_operator_new(sizeof(codecvt_char));
7339             if(!codecvt) {
7340                 ERR("Out of memory\n");
7341                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7342             }
7343             codecvt_char_ctor_locinfo(codecvt, locinfo, 0);
7344         }
7345         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_char_id));
7346     }
7347 }
7348
7349 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
7350 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7351 static locale__Locimp* locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7352 {
7353     TRACE("(%p %d %p %p)\n", locinfo, cat, locimp, loc);
7354
7355     locale__Locimp__Makexloc(locinfo, cat, locimp, loc);
7356     locale__Locimp__Makewloc(locinfo, cat, locimp, loc);
7357     locale__Locimp__Makeushloc(locinfo, cat, locimp, loc);
7358
7359     locimp->catmask |= cat;
7360     basic_string_char_copy_ctor(&locimp->name, &locinfo->newlocname);
7361     return locimp;
7362 }
7363
7364 /* ??_7_Locimp@locale@std@@6B@ */
7365 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
7366     (vtable_ptr)THISCALL_NAME(locale__Locimp_vector_dtor)
7367 };
7368
7369 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
7370 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
7371 DEFINE_THISCALL_WRAPPER(locale_ctor_locimp, 8)
7372 locale* __thiscall locale_ctor_locimp(locale *this, locale__Locimp *locimp)
7373 {
7374     TRACE("(%p %p)\n", this, locimp);
7375     /* Don't change locimp reference counter */
7376     this->ptr = locimp;
7377     return this;
7378 }
7379
7380 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
7381 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
7382 locale__Locimp* __cdecl locale__Init(void)
7383 {
7384     _Lockit lock;
7385
7386     TRACE("\n");
7387
7388     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7389     if(global_locale) {
7390         _Lockit_dtor(&lock);
7391         return global_locale;
7392     }
7393
7394     global_locale = MSVCRT_operator_new(sizeof(locale__Locimp));
7395     if(!global_locale) {
7396         _Lockit_dtor(&lock);
7397         ERR("Out of memory\n");
7398         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7399         return NULL;
7400     }
7401
7402     locale__Locimp_ctor(global_locale);
7403     global_locale->catmask = (1<<(LC_MAX+1))-1;
7404     basic_string_char_dtor(&global_locale->name);
7405     basic_string_char_ctor_cstr(&global_locale->name, "C");
7406
7407     locale__Locimp__Clocptr = global_locale;
7408     global_locale->facet.refs++;
7409     locale_ctor_locimp(&classic_locale, locale__Locimp__Clocptr);
7410     _Lockit_dtor(&lock);
7411
7412     return global_locale;
7413 }
7414
7415 /* ??0locale@std@@QAE@ABV01@0H@Z */
7416 /* ??0locale@std@@QEAA@AEBV01@0H@Z */
7417 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_locale, 16)
7418 locale* __thiscall locale_ctor_locale_locale(locale *this, const locale *loc, const locale *other, category cat)
7419 {
7420     _Locinfo locinfo;
7421
7422     TRACE("(%p %p %p %d)\n", this, loc, other, cat);
7423
7424     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7425     if(!this->ptr) {
7426         ERR("Out of memory\n");
7427         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7428     }
7429     locale__Locimp_copy_ctor(this->ptr, loc->ptr);
7430
7431     _Locinfo_ctor_cat_cstr(&locinfo, loc->ptr->catmask, basic_string_char_c_str(&loc->ptr->name));
7432     _Locinfo__Addcats(&locinfo, cat & other->ptr->catmask, basic_string_char_c_str(&other->ptr->name));
7433     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, other);
7434     _Locinfo_dtor(&locinfo);
7435
7436     return this;
7437 }
7438
7439 /* ??0locale@std@@QAE@ABV01@@Z */
7440 /* ??0locale@std@@QEAA@AEBV01@@Z */
7441 DEFINE_THISCALL_WRAPPER(locale_copy_ctor, 8)
7442 locale* __thiscall locale_copy_ctor(locale *this, const locale *copy)
7443 {
7444     TRACE("(%p %p)\n", this, copy);
7445     this->ptr = copy->ptr;
7446     locale_facet__Incref(&this->ptr->facet);
7447     return this;
7448 }
7449
7450 /* ??0locale@std@@QAE@ABV01@PBDH@Z */
7451 /* ??0locale@std@@QEAA@AEBV01@PEBDH@Z */
7452 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_cstr, 16)
7453 locale* __thiscall locale_ctor_locale_cstr(locale *this, const locale *loc, const char *locname, category cat)
7454 {
7455     FIXME("(%p %p %s %d) stub\n", this, loc, locname, cat);
7456     return NULL;
7457 }
7458
7459 /* ??0locale@std@@QAE@PBDH@Z */
7460 /* ??0locale@std@@QEAA@PEBDH@Z */
7461 DEFINE_THISCALL_WRAPPER(locale_ctor_cstr, 12)
7462 locale* __thiscall locale_ctor_cstr(locale *this, const char *locname, category cat)
7463 {
7464     _Locinfo locinfo;
7465
7466     TRACE("(%p %s %d)\n", this, locname, cat);
7467
7468     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7469     if(!this->ptr) {
7470         ERR("Out of memory\n");
7471         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7472     }
7473     locale__Locimp_ctor(this->ptr);
7474
7475     locale__Init();
7476
7477     _Locinfo_ctor_cat_cstr(&locinfo, cat, locname);
7478     if(!memcmp(basic_string_char_c_str(&locinfo.newlocname), "*", 2)) {
7479         _Locinfo_dtor(&locinfo);
7480         MSVCRT_operator_delete(this->ptr);
7481         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
7482     }
7483
7484     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, NULL);
7485     _Locinfo_dtor(&locinfo);
7486
7487     return this;
7488 }
7489
7490 /* ??0locale@std@@QAE@W4_Uninitialized@1@@Z */
7491 /* ??0locale@std@@QEAA@W4_Uninitialized@1@@Z */
7492 DEFINE_THISCALL_WRAPPER(locale_ctor_uninitialized, 8)
7493 locale* __thiscall locale_ctor_uninitialized(locale *this, int uninitialized)
7494 {
7495     TRACE("(%p)\n", this);
7496     this->ptr = NULL;
7497     return this;
7498 }
7499
7500 /* ??0locale@std@@QAE@XZ */
7501 /* ??0locale@std@@QEAA@XZ */
7502 DEFINE_THISCALL_WRAPPER(locale_ctor, 4)
7503 locale* __thiscall locale_ctor(locale *this)
7504 {
7505     TRACE("(%p)\n", this);
7506     this->ptr = locale__Init();
7507     locale_facet__Incref(&this->ptr->facet);
7508     return this;
7509 }
7510
7511 /* ??1locale@std@@QAE@XZ */
7512 /* ??1locale@std@@QEAA@XZ */
7513 DEFINE_THISCALL_WRAPPER(locale_dtor, 4)
7514 void __thiscall locale_dtor(locale *this)
7515 {
7516     TRACE("(%p)\n", this);
7517     if(this->ptr && locale_facet__Decref(&this->ptr->facet)) {
7518         locale__Locimp_dtor(this->ptr);
7519         MSVCRT_operator_delete(this);
7520     }
7521 }
7522
7523 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
7524 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
7525 DEFINE_THISCALL_WRAPPER(locale_operator_assign, 8)
7526 locale* __thiscall locale_operator_assign(locale *this, const locale *loc)
7527 {
7528     FIXME("(%p %p) stub\n", this, loc);
7529     return NULL;
7530 }
7531
7532 /* ??8locale@std@@QBE_NABV01@@Z */
7533 /* ??8locale@std@@QEBA_NAEBV01@@Z */
7534 DEFINE_THISCALL_WRAPPER(locale_operator_equal, 8)
7535 MSVCP_bool __thiscall locale_operator_equal(const locale *this, const locale *loc)
7536 {
7537     FIXME("(%p %p) stub\n", this, loc);
7538     return 0;
7539 }
7540
7541 /* ??9locale@std@@QBE_NABV01@@Z */
7542 /* ??9locale@std@@QEBA_NAEBV01@@Z */
7543 DEFINE_THISCALL_WRAPPER(locale_operator_not_equal, 8)
7544 MSVCP_bool __thiscall locale_operator_not_equal(const locale *this, locale const *loc)
7545 {
7546     FIXME("(%p %p) stub\n", this, loc);
7547     return 0;
7548 }
7549
7550 /* ?_Addfac@locale@std@@QAEAAV12@PAVfacet@12@II@Z */
7551 /* ?_Addfac@locale@std@@QEAAAEAV12@PEAVfacet@12@_K1@Z */
7552 DEFINE_THISCALL_WRAPPER(locale__Addfac, 16)
7553 locale* __thiscall locale__Addfac(locale *this, locale_facet *facet, MSVCP_size_t id, MSVCP_size_t catmask)
7554 {
7555     TRACE("(%p %p %lu %lu)\n", this, facet, id, catmask);
7556
7557     if(this->ptr->facet.refs > 1) {
7558         locale__Locimp *new_ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7559         if(!new_ptr) {
7560             ERR("Out of memory\n");
7561             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7562             return NULL;
7563         }
7564         locale__Locimp_copy_ctor(new_ptr, this->ptr);
7565         locale_facet__Decref(&this->ptr->facet);
7566         this->ptr = new_ptr;
7567     }
7568
7569     locale__Locimp__Addfac(this->ptr, facet, id);
7570
7571     if(catmask) {
7572         basic_string_char_dtor(&this->ptr->name);
7573         basic_string_char_ctor_cstr(&this->ptr->name, "*");
7574     }
7575     return this;
7576 }
7577
7578 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
7579 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
7580 static const locale_facet* locale__Getfacet(const locale *this, MSVCP_size_t id)
7581 {
7582     locale_facet *fac;
7583
7584     TRACE("(%p %lu)\n", this, id);
7585
7586     fac = id < this->ptr->facet_cnt ? this->ptr->facetvec[id] : NULL;
7587     if(fac || !this->ptr->transparent)
7588         return fac;
7589
7590     return id < global_locale->facet_cnt ? global_locale->facetvec[id] : NULL;
7591 }
7592
7593 /* ?classic@locale@std@@SAABV12@XZ */
7594 /* ?classic@locale@std@@SAAEBV12@XZ */
7595 const locale* __cdecl locale_classic(void)
7596 {
7597     TRACE("\n");
7598     locale__Init();
7599     return &classic_locale;
7600 }
7601
7602 /* ?empty@locale@std@@SA?AV12@XZ */
7603 locale* __cdecl locale_empty(locale *ret)
7604 {
7605     TRACE("\n");
7606
7607     locale__Init();
7608
7609     ret->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7610     if(!ret->ptr) {
7611         ERR("Out of memory\n");
7612         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7613     }
7614     locale__Locimp_ctor_transparent(ret->ptr, TRUE);
7615     return ret;
7616 }
7617
7618 /* ?name@locale@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
7619 /* ?name@locale@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
7620 DEFINE_THISCALL_WRAPPER(locale_name, 8)
7621 basic_string_char* __thiscall locale_name(const locale *this, basic_string_char *ret)
7622 {
7623     TRACE( "(%p)\n", this);
7624     basic_string_char_copy_ctor(ret, &this->ptr->name);
7625     return ret;
7626 }
7627
7628 /* ?global@locale@std@@SA?AV12@ABV12@@Z */
7629 /* ?global@locale@std@@SA?AV12@AEBV12@@Z */
7630 locale* __cdecl locale_global(locale *ret, const locale *loc)
7631 {
7632     _Lockit lock;
7633     int i;
7634
7635     TRACE("(%p %p)\n", loc, ret);
7636
7637     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7638     locale_ctor(ret);
7639
7640     if(loc->ptr != global_locale) {
7641         locale_facet__Decref(&global_locale->facet);
7642         global_locale = loc->ptr;
7643         locale_facet__Incref(&global_locale->facet);
7644
7645         for(i=LC_ALL+1; i<=LC_MAX; i++) {
7646             if((global_locale->catmask & (1<<(i-1))) == 0)
7647                 continue;
7648             setlocale(i, basic_string_char_c_str(&global_locale->name));
7649         }
7650     }
7651     _Lockit_dtor(&lock);
7652     return ret;
7653 }
7654
7655 DEFINE_RTTI_DATA0(locale_facet, 0, ".?AVfacet@locale@std@@");
7656 DEFINE_RTTI_DATA1(collate_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@D@std@@");
7657 DEFINE_RTTI_DATA1(collate_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@_W@std@@");
7658 DEFINE_RTTI_DATA1(collate_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@G@std@@");
7659 DEFINE_RTTI_DATA1(ctype_base, 0, &locale_facet_rtti_base_descriptor, ".?AUctype_base@std@@");
7660 DEFINE_RTTI_DATA2(ctype_char, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@D@std@@");
7661 DEFINE_RTTI_DATA2(ctype_wchar, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@_W@std@@");
7662 DEFINE_RTTI_DATA2(ctype_short, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@G@std@@");
7663 DEFINE_RTTI_DATA1(codecvt_base, 0, &locale_facet_rtti_base_descriptor, ".?AVcodecvt_base@std@@");
7664 DEFINE_RTTI_DATA2(codecvt_char, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@DDH@std@@");
7665 DEFINE_RTTI_DATA2(codecvt_wchar, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@_WDH@std@@");
7666 DEFINE_RTTI_DATA2(codecvt_short, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@GDH@std@@");
7667 DEFINE_RTTI_DATA1(numpunct_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@D@std@@");
7668 DEFINE_RTTI_DATA1(numpunct_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@_W@std@@");
7669 DEFINE_RTTI_DATA1(numpunct_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@G@std@@");
7670 DEFINE_RTTI_DATA1(num_get_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@");
7671 DEFINE_RTTI_DATA1(num_get_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@");
7672 DEFINE_RTTI_DATA1(num_get_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@");
7673 DEFINE_RTTI_DATA1(num_put_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@");
7674 DEFINE_RTTI_DATA1(num_put_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@");
7675 DEFINE_RTTI_DATA1(num_put_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@");
7676
7677 #ifndef __GNUC__
7678 void __asm_dummy_vtables(void) {
7679 #endif
7680     __ASM_VTABLE(locale_facet,
7681             VTABLE_ADD_FUNC(locale_facet_vector_dtor));
7682     __ASM_VTABLE(collate_char,
7683             VTABLE_ADD_FUNC(collate_char_vector_dtor)
7684             VTABLE_ADD_FUNC(collate_char_do_compare)
7685             VTABLE_ADD_FUNC(collate_char_do_transform)
7686             VTABLE_ADD_FUNC(collate_char_do_hash));
7687     __ASM_VTABLE(collate_wchar,
7688             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7689             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7690             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7691             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7692     __ASM_VTABLE(collate_short,
7693             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7694             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7695             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7696             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7697     __ASM_VTABLE(ctype_base,
7698             VTABLE_ADD_FUNC(ctype_base_vector_dtor));
7699     __ASM_VTABLE(ctype_char,
7700             VTABLE_ADD_FUNC(ctype_char_vector_dtor)
7701             VTABLE_ADD_FUNC(ctype_char_do_tolower)
7702             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
7703             VTABLE_ADD_FUNC(ctype_char_do_toupper)
7704             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
7705             VTABLE_ADD_FUNC(ctype_char_do_widen)
7706             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
7707             VTABLE_ADD_FUNC(ctype_char_do_narrow)
7708             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch));
7709     __ASM_VTABLE(ctype_wchar,
7710             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7711             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7712             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7713             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7714             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7715             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7716             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7717             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7718             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7719             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7720             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7721             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7722             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7723     __ASM_VTABLE(ctype_short,
7724             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7725             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7726             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7727             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7728             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7729             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7730             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7731             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7732             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7733             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7734             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7735             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7736             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7737     __ASM_VTABLE(codecvt_base,
7738             VTABLE_ADD_FUNC(codecvt_base_vector_dtor)
7739             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7740             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7741             VTABLE_ADD_FUNC(codecvt_base_do_encoding));
7742     __ASM_VTABLE(codecvt_char,
7743             VTABLE_ADD_FUNC(codecvt_char_vector_dtor)
7744             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7745             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7746             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7747             VTABLE_ADD_FUNC(codecvt_char_do_in)
7748             VTABLE_ADD_FUNC(codecvt_char_do_out)
7749             VTABLE_ADD_FUNC(codecvt_char_do_unshift)
7750             VTABLE_ADD_FUNC(codecvt_char_do_length));
7751     __ASM_VTABLE(codecvt_wchar,
7752             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7753             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7754             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7755             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7756             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7757             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7758             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7759             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7760     __ASM_VTABLE(codecvt_short,
7761             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7762             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7763             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7764             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7765             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7766             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7767             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7768             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7769     __ASM_VTABLE(numpunct_char,
7770             VTABLE_ADD_FUNC(numpunct_char_vector_dtor)
7771             VTABLE_ADD_FUNC(numpunct_char_do_decimal_point)
7772             VTABLE_ADD_FUNC(numpunct_char_do_thousands_sep)
7773             VTABLE_ADD_FUNC(numpunct_char_do_grouping)
7774             VTABLE_ADD_FUNC(numpunct_char_do_falsename)
7775             VTABLE_ADD_FUNC(numpunct_char_do_truename));
7776     __ASM_VTABLE(numpunct_wchar,
7777             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7778             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7779             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7780             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7781             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7782             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7783     __ASM_VTABLE(numpunct_short,
7784             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7785             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7786             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7787             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7788             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7789             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7790     __ASM_VTABLE(num_get_char,
7791             VTABLE_ADD_FUNC(num_get_char_vector_dtor)
7792             VTABLE_ADD_FUNC(num_get_char_do_get_void)
7793             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7794             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7795             VTABLE_ADD_FUNC(num_get_char_do_get_float)
7796             VTABLE_ADD_FUNC(num_get_char_do_get_uint64)
7797             VTABLE_ADD_FUNC(num_get_char_do_get_int64)
7798             VTABLE_ADD_FUNC(num_get_char_do_get_ulong)
7799             VTABLE_ADD_FUNC(num_get_char_do_get_long)
7800             VTABLE_ADD_FUNC(num_get_char_do_get_uint)
7801             VTABLE_ADD_FUNC(num_get_char_do_get_ushort)
7802             VTABLE_ADD_FUNC(num_get_char_do_get_bool));
7803     __ASM_VTABLE(num_get_short,
7804             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7805             VTABLE_ADD_FUNC(num_get_short_do_get_void)
7806             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7807             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7808             VTABLE_ADD_FUNC(num_get_short_do_get_float)
7809             VTABLE_ADD_FUNC(num_get_short_do_get_uint64)
7810             VTABLE_ADD_FUNC(num_get_short_do_get_int64)
7811             VTABLE_ADD_FUNC(num_get_short_do_get_ulong)
7812             VTABLE_ADD_FUNC(num_get_short_do_get_long)
7813             VTABLE_ADD_FUNC(num_get_short_do_get_uint)
7814             VTABLE_ADD_FUNC(num_get_short_do_get_ushort)
7815             VTABLE_ADD_FUNC(num_get_short_do_get_bool));
7816     __ASM_VTABLE(num_get_wchar,
7817             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7818             VTABLE_ADD_FUNC(num_get_wchar_do_get_void)
7819             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7820             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7821             VTABLE_ADD_FUNC(num_get_wchar_do_get_float)
7822             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint64)
7823             VTABLE_ADD_FUNC(num_get_wchar_do_get_int64)
7824             VTABLE_ADD_FUNC(num_get_wchar_do_get_ulong)
7825             VTABLE_ADD_FUNC(num_get_wchar_do_get_long)
7826             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint)
7827             VTABLE_ADD_FUNC(num_get_wchar_do_get_ushort)
7828             VTABLE_ADD_FUNC(num_get_wchar_do_get_bool));
7829     __ASM_VTABLE(num_put_char,
7830             VTABLE_ADD_FUNC(num_put_char_vector_dtor)
7831             VTABLE_ADD_FUNC(num_put_char_do_put_ptr)
7832             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7833             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7834             VTABLE_ADD_FUNC(num_put_char_do_put_uint64)
7835             VTABLE_ADD_FUNC(num_put_char_do_put_int64)
7836             VTABLE_ADD_FUNC(num_put_char_do_put_ulong)
7837             VTABLE_ADD_FUNC(num_put_char_do_put_long)
7838             VTABLE_ADD_FUNC(num_put_char_do_put_bool));
7839     __ASM_VTABLE(num_put_wchar,
7840             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7841             VTABLE_ADD_FUNC(num_put_wchar_do_put_ptr)
7842             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7843             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7844             VTABLE_ADD_FUNC(num_put_wchar_do_put_uint64)
7845             VTABLE_ADD_FUNC(num_put_wchar_do_put_int64)
7846             VTABLE_ADD_FUNC(num_put_wchar_do_put_ulong)
7847             VTABLE_ADD_FUNC(num_put_wchar_do_put_long)
7848             VTABLE_ADD_FUNC(num_put_wchar_do_put_bool));
7849     __ASM_VTABLE(num_put_short,
7850             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7851             VTABLE_ADD_FUNC(num_put_short_do_put_ptr)
7852             VTABLE_ADD_FUNC(num_put_short_do_put_double)
7853             VTABLE_ADD_FUNC(num_put_short_do_put_double)
7854             VTABLE_ADD_FUNC(num_put_short_do_put_uint64)
7855             VTABLE_ADD_FUNC(num_put_short_do_put_int64)
7856             VTABLE_ADD_FUNC(num_put_short_do_put_ulong)
7857             VTABLE_ADD_FUNC(num_put_short_do_put_long)
7858             VTABLE_ADD_FUNC(num_put_short_do_put_bool));
7859 #ifndef __GNUC__
7860 }
7861 #endif
7862
7863 void init_locale(void *base)
7864 {
7865 #ifdef __x86_64__
7866     init_locale_facet_rtti(base);
7867     init_collate_char_rtti(base);
7868     init_collate_wchar_rtti(base);
7869     init_collate_short_rtti(base);
7870     init_ctype_base_rtti(base);
7871     init_ctype_char_rtti(base);
7872     init_ctype_wchar_rtti(base);
7873     init_ctype_short_rtti(base);
7874     init_codecvt_base_rtti(base);
7875     init_codecvt_char_rtti(base);
7876     init_codecvt_wchar_rtti(base);
7877     init_codecvt_short_rtti(base);
7878     init_numpunct_char_rtti(base);
7879     init_numpunct_wchar_rtti(base);
7880     init_numpunct_short_rtti(base);
7881     init_num_get_char_rtti(base);
7882     init_num_get_wchar_rtti(base);
7883     init_num_get_short_rtti(base);
7884     init_num_put_char_rtti(base);
7885     init_num_put_wchar_rtti(base);
7886     init_num_put_short_rtti(base);
7887 #endif
7888 }
7889
7890 void free_locale(void)
7891 {
7892     facets_elem *iter, *safe;
7893
7894     if(global_locale) {
7895         locale__Locimp_dtor(global_locale);
7896         locale_dtor(&classic_locale);
7897     }
7898
7899     LIST_FOR_EACH_ENTRY_SAFE(iter, safe, &lazy_facets, facets_elem, entry) {
7900         list_remove(&iter->entry);
7901         if(locale_facet__Decref(iter->fac))
7902             call_locale_facet_vector_dtor(iter->fac, 1);
7903         MSVCRT_operator_delete(iter);
7904     }
7905 }