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