Piotr Caban : msvcp90: Added num_get<char>::_Getffld implementation.

Alexandre Julliard julliard at winehq.org
Thu Jun 21 15:03:40 CDT 2012


Module: wine
Branch: master
Commit: 1507d715cc606437c13d8d1a1b20525370cb38a4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1507d715cc606437c13d8d1a1b20525370cb38a4

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Jun 21 12:26:20 2012 +0200

msvcp90: Added num_get<char>::_Getffld implementation.

---

 dlls/msvcp90/locale.c  |  199 +++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/msvcp90/msvcp90.h |    3 +
 2 files changed, 198 insertions(+), 4 deletions(-)

diff --git a/dlls/msvcp90/locale.c b/dlls/msvcp90/locale.c
index 103b084..c051618 100644
--- a/dlls/msvcp90/locale.c
+++ b/dlls/msvcp90/locale.c
@@ -25,6 +25,7 @@
 #include "errno.h"
 #include "limits.h"
 #include "math.h"
+#include "stdio.h"
 
 #include "wine/list.h"
 
@@ -126,6 +127,31 @@ static locale classic_locale;
 /* ?_Clocptr at _Locimp@locale at std@@0PEAV123 at EA */
 locale__Locimp *locale__Locimp__Clocptr = NULL;
 
+static char istreambuf_iterator_char_val(istreambuf_iterator_char *this)
+{
+    if(this->strbuf && !this->got) {
+        int c = basic_streambuf_char_sgetc(this->strbuf);
+        if(c == EOF)
+            this->strbuf = NULL;
+        else
+            this->val = c;
+    }
+
+    this->got = TRUE;
+    return this->val;
+}
+
+static void istreambuf_iterator_char_inc(istreambuf_iterator_char *this)
+{
+    if(!this->strbuf || basic_streambuf_char_sbumpc(this->strbuf)==EOF) {
+        this->strbuf = NULL;
+        this->got = TRUE;
+    }else {
+        this->got = FALSE;
+        istreambuf_iterator_char_val(this);
+    }
+}
+
 /* ??1facet at locale@std@@UAE at XZ */
 /* ??1facet at locale@std@@UEAA at XZ */
 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
@@ -3401,6 +3427,32 @@ MSVCP_size_t __cdecl numpunct_char__Getcat(const locale_facet **facet, const loc
     return LC_NUMERIC;
 }
 
+numpunct_char* numpunct_char_use_facet(const locale *loc)
+{
+    static numpunct_char *obj = NULL;
+
+    _Lockit lock;
+    const locale_facet *fac;
+
+    _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
+    fac = locale__Getfacet(loc, numpunct_char_id.id);
+    if(fac) {
+        _Lockit_dtor(&lock);
+        return (numpunct_char*)fac;
+    }
+
+    if(obj)
+        return obj;
+
+    numpunct_char__Getcat(&fac, loc);
+    obj = (numpunct_char*)fac;
+    locale_facet__Incref(&obj->facet);
+    locale_facet_register(&obj->facet);
+    _Lockit_dtor(&lock);
+
+    return obj;
+}
+
 /* ?do_decimal_point@?$numpunct at D@std@@MBEDXZ */
 /* ?do_decimal_point@?$numpunct at D@std@@MEBADXZ */
 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
@@ -4509,11 +4561,150 @@ MSVCP_size_t __cdecl num_get_char__Getcat(const locale_facet **facet, const loca
 
 /* ?_Getffld@?$num_get at DV?$istreambuf_iterator at DU?$char_traits at D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator at DU?$char_traits at D@std@@@2 at 1ABVlocale@2@@Z */
 /* ?_Getffld@?$num_get at DV?$istreambuf_iterator at DU?$char_traits at D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator at DU?$char_traits at D@std@@@2 at 1AEBVlocale@2@@Z */
-int __cdecl num_get_char__Getffld(num_get *this, char *dest, istreambuf_iterator_char *first,
-    istreambuf_iterator_char *last, const locale *loc)
+/* Copies number to dest buffer, validates grouping and skips separators.
+ * Updates first so it points past the number, all digits are skipped.
+ * Returns how exponent needs to changed.
+ * Size of dest buffer is not specified, assuming it's not smaller then 32:
+ * strlen(+0.e+) + 22(digits) + 4(expontent) + 1(nullbyte)
+ */
+int __cdecl num_get_char__Getffld(const num_get *this, char *dest, istreambuf_iterator_char *first,
+        istreambuf_iterator_char *last, const locale *loc)
 {
-    FIXME("(%p %p %p %p) stub\n", dest, first, last, loc);
-    return -1;
+    numpunct_char *numpunct = numpunct_char_use_facet(loc);
+    basic_string_char grouping_bstr;
+    int groups_no = 0, cur_group = 0, exp = 0;
+    char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, *groups = NULL, sep;
+    const char *grouping;
+    BOOL error = TRUE, dest_empty = TRUE;
+
+    TRACE("(%p %p %p %p)\n", dest, first, last, loc);
+
+    numpunct_char_grouping(numpunct, &grouping_bstr);
+    grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
+    sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
+
+    istreambuf_iterator_char_val(first);
+    if(first->strbuf && (first->val=='-' || first->val=='+')) {
+        *dest++ = first->val;
+        istreambuf_iterator_char_inc(first);
+    }
+
+    if(sep) {
+        groups_no = strlen(grouping)+2;
+        groups = calloc(groups_no, sizeof(char));
+    }
+
+    for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
+        if(first->val<'0' || first->val>'9') {
+            if(sep && first->val==sep) {
+                if(cur_group == groups_no+1) {
+                    if(groups[1] != groups[2]) {
+                        error = TRUE;
+                        break;
+                    }else {
+                        memmove(groups+1, groups+2, groups_no);
+                        groups[cur_group] = 0;
+                    }
+                }else {
+                    cur_group++;
+                }
+            }else {
+                break;
+            }
+        }else {
+            error = FALSE;
+            if(dest_empty && first->val == '0')
+                continue;
+            dest_empty = FALSE;
+            if(dest < num_end)
+                *dest++ = first->val;
+            else
+                exp++;
+            if(sep && groups[cur_group]<CHAR_MAX)
+                groups[cur_group]++;
+        }
+    }
+
+    if(cur_group && !groups[cur_group])
+        error = TRUE;
+    else if(!cur_group)
+        cur_group--;
+
+    for(; cur_group>=0 && !error; cur_group--) {
+        if(*grouping == CHAR_MAX) {
+            if(cur_group)
+                error = TRUE;
+            break;
+        }else if((cur_group && *grouping!=groups[cur_group])
+                || (!cur_group && *grouping<groups[cur_group])) {
+            error = TRUE;
+            break;
+        }else if(grouping[1]) {
+            grouping++;
+        }
+    }
+    MSVCP_basic_string_char_dtor(&grouping_bstr);
+    free(groups);
+
+    if(error) {
+        *dest_beg = '\0';
+        return 0;
+    }else if(dest_empty) {
+        *dest++ = '0';
+    }
+
+    if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
+        if(dest < num_end)
+            *dest++ = *localeconv()->decimal_point;
+        istreambuf_iterator_char_inc(first);
+
+        if(dest_empty) {
+            for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
+                exp--;
+
+            if(!first->strbuf || first->val<'1' || first->val>'9')
+                dest--;
+        }
+    }
+
+    for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
+        if(first->val<'0' || first->val>'9')
+            break;
+        else if(dest<num_end)
+            *dest++ = first->val;
+        else
+            exp--;
+    }
+
+    if(first->strbuf && (first->val=='e' || first->val=='E')) {
+        *dest++ = first->val;
+        istreambuf_iterator_char_inc(first);
+
+        if(first->strbuf && (first->val=='-' || first->val=='+')) {
+            *dest++ = first->val;
+            istreambuf_iterator_char_inc(first);
+        }
+
+        error = dest_empty = TRUE;
+        for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
+            error = FALSE;
+
+        for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
+            error = dest_empty = FALSE;
+            if(dest<exp_end)
+                *dest++ = first->val;
+        }
+
+        if(error) {
+            *dest_beg = '\0';
+            return 0;
+        }else if(dest_empty) {
+            *dest++ = '0';
+        }
+    }
+
+    *dest++ = '\0';
+    return exp;
 }
 
 /* ?_Getffldx@?$num_get at DV?$istreambuf_iterator at DU?$char_traits at D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator at DU?$char_traits at D@std@@@2 at 1AAVios_base@2 at PAH@Z */
diff --git a/dlls/msvcp90/msvcp90.h b/dlls/msvcp90/msvcp90.h
index e6cffc7..6ac7c08 100644
--- a/dlls/msvcp90/msvcp90.h
+++ b/dlls/msvcp90/msvcp90.h
@@ -503,6 +503,9 @@ typedef struct {
     locale *loc;
 } basic_streambuf_char;
 
+int __thiscall basic_streambuf_char_sgetc(basic_streambuf_char*);
+int __thiscall basic_streambuf_char_sbumpc(basic_streambuf_char*);
+
 /* class basic_streambuf<wchar> */
 typedef struct {
     const vtable_ptr *vtable;




More information about the wine-cvs mailing list