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