]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/string: support a fixed locale for "%f" output
authorVMware, Inc <>
Tue, 29 Mar 2011 18:53:55 +0000 (11:53 -0700)
committerMarcelo Vanzin <mvanzin@vmware.com>
Tue, 29 Mar 2011 18:53:55 +0000 (11:53 -0700)
Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/bsd_output.h
open-vm-tools/lib/include/str.h
open-vm-tools/lib/string/bsd_vsnprintf.c
open-vm-tools/lib/string/str.c

index 238c0e67d0e1f4b1d90fcf3670ddb6e4581a941e..060ed1b6c487f5700c024baa80bc201832941ad2 100644 (file)
@@ -47,6 +47,10 @@ int
 bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0,
               va_list ap);
 
+int
+bsd_vsnprintf_c_locale(char **outbuf, size_t bufSize, const char *fmt0,
+                       va_list ap);
+
 int
 bsd_vsnwprintf(wchar_t **outbuf, size_t bufSize, const wchar_t *fmt0,
                va_list ap);
index 2a0fc14760d11833456a4a50800f4c7f3ba219c8..c5904e921bef93b4f6b33ad9dd63008cf8e39519 100644 (file)
  * strings of "wchar_t" units, regardless of platform.
  */
 
+#ifdef HAS_BSD_PRINTF
+EXTERN int Str_Sprintf_C_Locale(char *buf, size_t max,
+                                const char *fmt, ...) PRINTF_DECL(3, 4);
+#endif
+
 EXTERN int Str_Sprintf(char *buf, size_t max,
                        const char *fmt, ...) PRINTF_DECL(3, 4);
 EXTERN int Str_Snprintf(char *buf, size_t len,
index 7ffb4502c23ffd69a28abb86a411505d1bf3e9a3..91d1011dc0edd5bdc3accfc770f46bd4ce821b50 100644 (file)
@@ -402,7 +402,13 @@ BSDFmt_WCharToUTF8(wchar_t *wcsarg, int prec)
 
 
 int
-bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap)
+bsd_vsnprintf_core(char **outbuf,
+                   char *grouping,
+                   char thousands_sep,
+                   char *decimal_point,
+                   size_t bufSize,
+                   const char *fmt0,
+                   va_list ap)
 {
    char *fmt;      /* format string */
    int ch;         /* character from fmt */
@@ -414,8 +420,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap)
    int width;      /* width from format (%8d), or 0 */
    int prec;      /* precision from format; <0 for N/A */
    char sign;      /* sign prefix (' ', '+', '-', or \0) */
-   char thousands_sep;   /* locale specific thousands separator */
-   const char *grouping;   /* locale specific numeric grouping rules */
 
 #ifndef NO_FLOATING_POINT
    /*
@@ -432,10 +436,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap)
     * D:   expchar holds this character; '\0' if no exponent, e.g. %f
     * F:   at least two digits for decimal, at least one digit for hex
     */
-   char *decimal_point;   /* locale specific decimal point */
-#if defined __ANDROID__
-   static const char dp = '.';
-#endif
    int signflag;      /* true if float is negative */
    union {         /* floating point arguments %[aAeEfFgG] */
       double dbl;
@@ -585,20 +585,9 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap)
 
    xdigs = xdigs_lower;
    thousands_sep = '\0';
-   grouping = NULL;
    convbuf = NULL;
 #ifndef NO_FLOATING_POINT
    dtoaresult = NULL;
-#if defined(__ANDROID__)
-   /*
-    * Struct lconv is not working! For decimal_point,
-    * using '.' instead is a workaround.
-    */
-   NOT_TESTED();
-   decimal_point = &dp;
-#else
-   decimal_point = localeconv()->decimal_point;
-#endif
 #endif
 
    fmt = (char *)fmt0;
@@ -714,16 +703,6 @@ bsd_vsnprintf(char **outbuf, size_t bufSize, const char *fmt0, va_list ap)
          goto rflag;
       case '\'':
          flags |= GROUPING;
-#if defined(__ANDROID__)
-         /*
-          * Struct lconv is not working! The code below is a workaround.
-          */
-         NOT_TESTED();
-         thousands_sep = ',';
-#else
-         thousands_sep = *(localeconv()->thousands_sep);
-         grouping = localeconv()->grouping;
-#endif
         /*
          * Grouping should not begin with 0, but it nevertheless
          * does (see bug 281072) and makes the formatting code
@@ -1303,12 +1282,65 @@ error:
 #undef FIND_ARGUMENTS
 }
 
+int
+bsd_vsnprintf_c_locale(char **outbuf,
+                       size_t bufSize,
+                       const char *fmt0,
+                       va_list ap)
+{
+   char thousands_sep;
+   char *decimal_point;
+   static char dp = '.';
+
+   /*
+    * Perform a "%f" conversion always using the locale associated
+    * with the C locale - "," for thousands, '.' for decimal point.
+    */
+
+   thousands_sep = ',';
+   decimal_point = &dp;
+
+   return bsd_vsnprintf_core(outbuf, NULL, thousands_sep, decimal_point,
+                             bufSize, fmt0, ap);
+}
+
+int
+bsd_vsnprintf(char **outbuf,
+              size_t bufSize,
+              const char *fmt0,
+              va_list ap)
+{
+   char *grouping;
+   char thousands_sep;
+   char *decimal_point;
+
+#if defined(__ANDROID__)
+   static char dp = '.';
+
+   /*
+    * Struct lconv is not working! The code below is a workaround.
+    */
+   NOT_TESTED();
+   grouping = NULL;
+   thousands_sep = ',';
+   decimal_point = &dp;
+#else
+   grouping =        localeconv()->grouping;
+   thousands_sep = *(localeconv()->thousands_sep);
+   decimal_point =   localeconv()->decimal_point;
+#endif
+
+   return bsd_vsnprintf_core(outbuf, grouping, thousands_sep, decimal_point,
+                             bufSize, fmt0, ap);
+}
+
 /*
  * Find all arguments when a positional parameter is encountered.  Returns a
  * table, indexed by argument number, of pointers to each arguments.  The
  * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
  * It will be replaces with a malloc-ed one if it overflows.
  */
+
 static void
 __find_arguments (const char *fmt0, va_list ap, union arg **argtable)
 {
index 72cf25ce630856b378e3ef1a5158f5e09def9f90..50102950e30bf63c6d5989a1a10d2a3ae96995b7 100644 (file)
@@ -131,10 +131,13 @@ Str_Vsnprintf(char *str,          // OUT
     * those cases.
     */
 
-   if ((retval < 0 || retval >= size) && size > 0) {
-      /* Find UTF-8 code point boundary and place NUL termination there */
-      int trunc = CodeSet_Utf8FindCodePointBoundary(str, size - 1);
-      str[trunc] = '\0';
+   if ((retval < 0) || (retval >= size)) {
+      if (size > 0) {
+         /* Find UTF-8 code point boundary and place NUL termination there */
+         int trunc = CodeSet_Utf8FindCodePointBoundary(str, size - 1);
+
+         str[trunc] = '\0';
+      }
    }
    if (retval >= size) {
       return -1;
@@ -143,6 +146,58 @@ Str_Vsnprintf(char *str,          // OUT
 }
 
 
+#ifdef HAS_BSD_PRINTF
+/*
+ *----------------------------------------------------------------------
+ *
+ * Str_Sprintf_C_Locale --
+ *
+ *      sprintf wrapper that fails on overflow. Enforces numeric C locale.
+ *
+ * Results:
+ *      Returns the number of bytes stored in 'buf'.
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Str_Sprintf_C_Locale(char *buf,        // OUT:
+                     size_t maxSize,   // IN:
+                     const char *fmt,  // IN:
+                     ...)              // IN:
+{
+   uint32 *stack = (uint32*) &buf;
+   va_list args;
+   int retval;
+
+   ASSERT(buf);
+   ASSERT(fmt);
+   
+   va_start(args, fmt);
+   retval = bsd_vsnprintf_c_locale(&buf, maxSize, fmt, args);
+   va_end(args);
+
+   if ((retval < 0) || (retval >= maxSize)) {
+      if (maxSize > 0) {
+         /* Find UTF-8 code point boundary and place NUL termination there */
+         int trunc = CodeSet_Utf8FindCodePointBoundary(buf, maxSize - 1);
+
+         buf[trunc] = '\0';
+      }
+   }
+
+   if (retval >= maxSize) {
+      Panic("%s:%d Buffer too small 0x%x\n", __FILE__, __LINE__, stack[-1]);
+   }
+
+   return retval;
+}
+#endif
+
+
 /*
  *----------------------------------------------------------------------
  *