[libcxx] r182026 - Glen: This patch gets the string conversion functions working on Windows. It also refactors repetitive code in string.cpp do greatly reduce the repetitiveness, increasing maintainability.

Howard Hinnant hhinnant at apple.com
Thu May 16 10:13:40 PDT 2013


Author: hhinnant
Date: Thu May 16 12:13:40 2013
New Revision: 182026

URL: http://llvm.org/viewvc/llvm-project?rev=182026&view=rev
Log:
Glen:  This patch gets the string conversion functions working on Windows.  It also refactors repetitive code in string.cpp do greatly reduce the repetitiveness, increasing maintainability.

Modified:
    libcxx/trunk/include/support/win32/support.h
    libcxx/trunk/src/string.cpp
    libcxx/trunk/src/support/win32/locale_win32.cpp
    libcxx/trunk/src/support/win32/support.cpp

Modified: libcxx/trunk/include/support/win32/support.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/win32/support.h?rev=182026&r1=182025&r2=182026&view=diff
==============================================================================
--- libcxx/trunk/include/support/win32/support.h (original)
+++ libcxx/trunk/include/support/win32/support.h Thu May 16 12:13:40 2013
@@ -15,26 +15,23 @@
    Functions and constants used in libc++ that are missing from the Windows C library.
   */
 
-#include <__config>
-#include <wchar.h>  // mbstate_t
-#include <stdio.h> // _snwprintf
+#include <cwchar>  // mbstate_t
+#include <cstdarg> // va_ macros
 #define swprintf _snwprintf
 #define vswprintf _vsnwprintf
-#define vfscnaf fscanf
 
-int vasprintf( char **sptr, const char *__restrict fmt , va_list ap );
-int asprintf( char **sptr, const char *__restrict fmt, ...);
-//int vfscanf( FILE *__restrict stream, const char *__restrict format,
-//             va_list arg);
+extern "C" {
 
+int vasprintf( char **sptr, const char *__restrict fmt, va_list ap );
+int asprintf( char **sptr, const char *__restrict fmt, ...);
 size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src,
                    size_t nmc, size_t len, mbstate_t *__restrict ps );
 size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src,
                    size_t nwc, size_t len, mbstate_t *__restrict ps );
+}
 
 #if defined(_MSC_VER)
 #define snprintf _snprintf
-
 #include <xlocinfo.h>
 #define atoll _atoi64
 #define strtoll _strtoi64
@@ -85,9 +82,11 @@ _LIBCPP_ALWAYS_INLINE int __builtin_ctz(
    _BitScanReverse(&r, x);
    return static_cast<int>(r);
 }
+
 // sizeof(long) == sizeof(int) on Windows
 _LIBCPP_ALWAYS_INLINE int __builtin_ctzl( unsigned long x )
 { return __builtin_ctz( static_cast<int>(x) ); }
+
 _LIBCPP_ALWAYS_INLINE int __builtin_ctzll( unsigned long long x )
 {
     DWORD r = 0;

Modified: libcxx/trunk/src/string.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/string.cpp?rev=182026&r1=182025&r2=182026&view=diff
==============================================================================
--- libcxx/trunk/src/string.cpp (original)
+++ libcxx/trunk/src/string.cpp Thu May 16 12:13:40 2013
@@ -11,6 +11,8 @@
 #include "cstdlib"
 #include "cwchar"
 #include "cerrno"
+#include "limits"
+#include "stdexcept"
 #ifdef _WIN32
 #include "support/win32/support.h"
 #endif // _WIN32
@@ -26,662 +28,499 @@ template
     string
     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
 
-int
-stoi(const string& str, size_t* idx, int base)
+namespace
+{
+
+template<typename T>
+inline
+void throw_helper( const string& msg )
+{
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    throw T( msg );
+#else
+    abort();
+#endif
+}
+
+inline
+void throw_from_string_out_of_range( const string& func )
+{
+    throw_helper<out_of_range>(func + ": out of range");
+}
+
+inline
+void throw_from_string_invalid_arg( const string& func )
+{
+    throw_helper<invalid_argument>(func + ": no conversion");
+}
+
+// as_integer
+
+template<typename V, typename S, typename F>
+inline
+V
+as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
 {
-    char* ptr;
-    const char* const p = str.c_str();
+    typename S::value_type* ptr;
+    const typename S::value_type* const p = str.c_str();
     typename remove_reference<decltype(errno)>::type errno_save = errno;
     errno = 0;
-    long r = strtol(p, &ptr, base);
+    V r = f(p, &ptr, base);
     swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
-                                numeric_limits<int>::max() < r)
-        throw out_of_range("stoi: out of range");
+    if (errno_save == ERANGE)
+        throw_from_string_out_of_range(func);
     if (ptr == p)
-        throw invalid_argument("stoi: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
+        throw_from_string_invalid_arg(func);
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
+    return r;
+}
+
+template<typename V, typename S>
+inline
+V
+as_integer(const string& func, const S& s, size_t* idx, int base);
+
+// string
+template<>
+inline
+int
+as_integer(const string& func, const string& s, size_t* idx, int base )
+{
+    // Use long as no Stantard string to integer exists.
+    long r = as_integer_helper<long>( func, s, idx, base, strtol );
+    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
+        throw_from_string_out_of_range(func);
     return static_cast<int>(r);
 }
 
+template<>
+inline
+long
+as_integer(const string& func, const string& s, size_t* idx, int base )
+{
+    return as_integer_helper<long>( func, s, idx, base, strtol );
+}
+
+template<>
+inline
+unsigned long
+as_integer( const string& func, const string& s, size_t* idx, int base )
+{
+    return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
+}
+
+template<>
+inline
+long long
+as_integer( const string& func, const string& s, size_t* idx, int base )
+{
+    return as_integer_helper<long long>( func, s, idx, base, strtoll );
+}
+
+template<>
+inline
+unsigned long long
+as_integer( const string& func, const string& s, size_t* idx, int base )
+{
+    return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
+}
+
+// wstring
+template<>
+inline
 int
-stoi(const wstring& str, size_t* idx, int base)
+as_integer( const string& func, const wstring& s, size_t* idx, int base )
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long r = wcstol(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE || r < numeric_limits<int>::min() ||
-                                numeric_limits<int>::max() < r)
-        throw out_of_range("stoi: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoi: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
+    // Use long as no Stantard string to integer exists.
+    long r = as_integer_helper<long>( func, s, idx, base, wcstol );
+    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
+        throw_from_string_out_of_range(func);
     return static_cast<int>(r);
 }
 
+template<>
+inline
 long
-stol(const string& str, size_t* idx, int base)
+as_integer( const string& func, const wstring& s, size_t* idx, int base )
+{
+    return as_integer_helper<long>( func, s, idx, base, wcstol );
+}
+
+template<>
+inline
+unsigned long
+as_integer( const string& func, const wstring& s, size_t* idx, int base )
+{
+    return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
+}
+
+template<>
+inline
+long long
+as_integer( const string& func, const wstring& s, size_t* idx, int base )
+{
+    return as_integer_helper<long long>( func, s, idx, base, wcstoll );
+}
+
+template<>
+inline
+unsigned long long
+as_integer( const string& func, const wstring& s, size_t* idx, int base )
+{
+    return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
+}
+
+// as_float
+
+template<typename V, typename S, typename F> 
+inline
+V
+as_float_helper(const string& func, const S& str, size_t* idx, F f )
 {
-    char* ptr;
-    const char* const p = str.c_str();
+    typename S::value_type* ptr;
+    const typename S::value_type* const p = str.c_str();
     typename remove_reference<decltype(errno)>::type errno_save = errno;
     errno = 0;
-    long r = strtol(p, &ptr, base);
+    V r = f(p, &ptr);
     swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
     if (errno_save == ERANGE)
-        throw out_of_range("stol: out of range");
+        throw_from_string_out_of_range(func);
     if (ptr == p)
-        throw invalid_argument("stol: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
+        throw_from_string_invalid_arg(func);
     if (idx)
         *idx = static_cast<size_t>(ptr - p);
     return r;
 }
 
+template<typename V, typename S>
+inline
+V as_float( const string& func, const S& s, size_t* idx = nullptr );
+
+template<>
+inline
+float
+as_float( const string& func, const string& s, size_t* idx )
+{
+    return as_float_helper<float>( func, s, idx, strtof );
+}
+
+template<>
+inline
+double
+as_float(const string& func, const string& s, size_t* idx )
+{
+    return as_float_helper<double>( func, s, idx, strtod );
+}
+
+template<>
+inline
+long double
+as_float( const string& func, const string& s, size_t* idx )
+{
+    return as_float_helper<long double>( func, s, idx, strtold );
+}
+
+template<>
+inline
+float
+as_float( const string& func, const wstring& s, size_t* idx )
+{
+    return as_float_helper<float>( func, s, idx, wcstof );
+}
+
+template<>
+inline
+double
+as_float( const string& func, const wstring& s, size_t* idx )
+{
+    return as_float_helper<double>( func, s, idx, wcstod );
+}
+
+template<>
+inline
+long double
+as_float( const string& func, const wstring& s, size_t* idx )
+{
+    return as_float_helper<long double>( func, s, idx, wcstold );
+}
+
+}  // unnamed namespace
+
+int
+stoi(const string& str, size_t* idx, int base)
+{
+    return as_integer<int>( "stoi", str, idx, base );
+}
+
+int
+stoi(const wstring& str, size_t* idx, int base)
+{
+    return as_integer<int>( "stoi", str, idx, base );
+}
+
+long
+stol(const string& str, size_t* idx, int base)
+{
+    return as_integer<long>( "stol", str, idx, base );
+}
+
 long
 stol(const wstring& str, size_t* idx, int base)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long r = wcstol(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stol: out of range");
-    if (ptr == p)
-        throw invalid_argument("stol: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<long>( "stol", str, idx, base );
 }
 
 unsigned long
 stoul(const string& str, size_t* idx, int base)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    unsigned long r = strtoul(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoul: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoul: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<unsigned long>( "stoul", str, idx, base );
 }
 
 unsigned long
 stoul(const wstring& str, size_t* idx, int base)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    unsigned long r = wcstoul(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoul: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoul: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<unsigned long>( "stoul", str, idx, base );
 }
 
 long long
 stoll(const string& str, size_t* idx, int base)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long long r = strtoll(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoll: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoll: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<long long>( "stoll", str, idx, base );
 }
 
 long long
 stoll(const wstring& str, size_t* idx, int base)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long long r = wcstoll(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoll: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoll: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<long long>( "stoll", str, idx, base );
 }
 
 unsigned long long
 stoull(const string& str, size_t* idx, int base)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    unsigned long long r = strtoull(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoull: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoull: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<unsigned long long>( "stoull", str, idx, base );
 }
 
 unsigned long long
 stoull(const wstring& str, size_t* idx, int base)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    unsigned long long r = wcstoull(p, &ptr, base);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stoull: out of range");
-    if (ptr == p)
-        throw invalid_argument("stoull: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_integer<unsigned long long>( "stoull", str, idx, base );
 }
 
 float
 stof(const string& str, size_t* idx)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    float r = strtof(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stof: out of range");
-    if (ptr == p)
-        throw invalid_argument("stof: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<float>( "stof", str, idx );
 }
 
 float
 stof(const wstring& str, size_t* idx)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    float r = wcstof(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stof: out of range");
-    if (ptr == p)
-        throw invalid_argument("stof: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<float>( "stof", str, idx );
 }
 
 double
 stod(const string& str, size_t* idx)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    double r = strtod(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stod: out of range");
-    if (ptr == p)
-        throw invalid_argument("stod: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<double>( "stod", str, idx );
 }
 
 double
 stod(const wstring& str, size_t* idx)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    double r = wcstod(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stod: out of range");
-    if (ptr == p)
-        throw invalid_argument("stod: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<double>( "stod", str, idx );
 }
 
 long double
 stold(const string& str, size_t* idx)
 {
-    char* ptr;
-    const char* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long double r = strtold(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stold: out of range");
-    if (ptr == p)
-        throw invalid_argument("stold: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<long double>( "stold", str, idx );
 }
 
 long double
 stold(const wstring& str, size_t* idx)
 {
-    wchar_t* ptr;
-    const wchar_t* const p = str.c_str();
-    typename remove_reference<decltype(errno)>::type errno_save = errno;
-    errno = 0;
-    long double r = wcstold(p, &ptr);
-    swap(errno, errno_save);
-#ifndef _LIBCPP_NO_EXCEPTIONS
-    if (errno_save == ERANGE)
-        throw out_of_range("stold: out of range");
-    if (ptr == p)
-        throw invalid_argument("stold: no conversion");
-#endif  // _LIBCPP_NO_EXCEPTIONS
-    if (idx)
-        *idx = static_cast<size_t>(ptr - p);
-    return r;
+    return as_float<long double>( "stold", str, idx );
 }
 
-string to_string(int val)
+// to_string
+
+namespace
+{
+
+// as_string
+
+template<typename S, typename P, typename V >
+inline
+S
+as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
 {
-    string s;
-    s.resize(s.capacity());
+    typedef typename S::size_type size_type;
+    size_type available = s.size();
     while (true)
     {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%d", val));
-        if (n2 <= s.size())
+        int status = sprintf_like(&s[0], available + 1, fmt, a);
+        if ( status >= 0 )
         {
-            s.resize(n2);
-            break;
+            size_type used = static_cast<size_type>(status);
+            if ( used <= available )
+            {
+                s.resize( used );
+                break;
+            }
+            available = used; // Assume this is advice of how much space we need.
         }
-        s.resize(n2);
+        else
+            available = available * 2 + 1;
+        s.resize(available);
     }
     return s;
 }
 
-string to_string(unsigned val)
+template <class S, class V, bool = is_floating_point<V>::value>
+struct initial_string;
+
+template <class V, bool b>
+struct initial_string<string, V, b>
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
+    string
+    operator()() const
     {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%u", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
+        string s;
+        s.resize(s.capacity());
+        return s;
     }
-    return s;
-}
+};
 
-string to_string(long val)
+template <class V>
+struct initial_string<wstring, V, false>
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
+    wstring
+    operator()() const
     {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%ld", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
+        const size_t n = (numeric_limits<unsigned long long>::digits / 3)
+          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
+          + 1;
+        wstring s(n, wchar_t());
+        s.resize(s.capacity());
+        return s;
     }
-    return s;
-}
+};
 
-string to_string(unsigned long val)
+template <class V>
+struct initial_string<wstring, V, true>
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
+    wstring
+    operator()() const
     {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%lu", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
+        wstring s(20, wchar_t());
+        s.resize(s.capacity());
+        return s;
     }
-    return s;
+};
+
+typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
+
+inline
+wide_printf
+get_swprintf()
+{
+#ifndef _WIN32
+    return swprintf;
+#else
+    return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(swprintf);
+#endif
+}
+
+}  // unnamed namespace
+
+string to_string(int val)
+{
+    return as_string(snprintf, initial_string<string, int>()(), "%d", val);
+}
+
+string to_string(unsigned val)
+{
+    return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
+}
+
+string to_string(long val)
+{
+    return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
+}
+
+string to_string(unsigned long val)
+{
+    return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
 }
 
 string to_string(long long val)
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
-    {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%lld", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
-    }
-    return s;
+    return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
 }
 
 string to_string(unsigned long long val)
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
-    {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%llu", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
-    }
-    return s;
+    return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
 }
 
 string to_string(float val)
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
-    {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%f", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
-    }
-    return s;
+    return as_string(snprintf, initial_string<string, float>()(), "%f", val);
 }
 
 string to_string(double val)
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
-    {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%f", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
-    }
-    return s;
+    return as_string(snprintf, initial_string<string, double>()(), "%f", val);
 }
 
 string to_string(long double val)
 {
-    string s;
-    s.resize(s.capacity());
-    while (true)
-    {
-        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%Lf", val));
-        if (n2 <= s.size())
-        {
-            s.resize(n2);
-            break;
-        }
-        s.resize(n2);
-    }
-    return s;
+    return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
 }
 
 wstring to_wstring(int val)
 {
-    const size_t n = (numeric_limits<int>::digits / 3)
-          + ((numeric_limits<int>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%d", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
 }
 
 wstring to_wstring(unsigned val)
 {
-    const size_t n = (numeric_limits<unsigned>::digits / 3)
-          + ((numeric_limits<unsigned>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%u", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
 }
 
 wstring to_wstring(long val)
 {
-    const size_t n = (numeric_limits<long>::digits / 3)
-          + ((numeric_limits<long>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%ld", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
 }
 
 wstring to_wstring(unsigned long val)
 {
-    const size_t n = (numeric_limits<unsigned long>::digits / 3)
-          + ((numeric_limits<unsigned long>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%lu", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
 }
 
 wstring to_wstring(long long val)
 {
-    const size_t n = (numeric_limits<long long>::digits / 3)
-          + ((numeric_limits<long long>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%lld", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
 }
 
 wstring to_wstring(unsigned long long val)
 {
-    const size_t n = (numeric_limits<unsigned long long>::digits / 3)
-          + ((numeric_limits<unsigned long long>::digits % 3) != 0)
-          + 1;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%llu", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
 }
 
 wstring to_wstring(float val)
 {
-    const size_t n = 20;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%f", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
 }
 
 wstring to_wstring(double val)
 {
-    const size_t n = 20;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%f", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
 }
 
 wstring to_wstring(long double val)
 {
-    const size_t n = 20;
-    wstring s(n, wchar_t());
-    s.resize(s.capacity());
-    while (true)
-    {
-        int n2 = swprintf(&s[0], s.size()+1, L"%Lf", val);
-        if (n2 > 0)
-        {
-            s.resize(static_cast<size_t>(n2));
-            break;
-        }
-        s.resize(2*s.size());
-        s.resize(s.capacity());
-    }
-    return s;
+    return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
 }
-
 _LIBCPP_END_NAMESPACE_STD

Modified: libcxx/trunk/src/support/win32/locale_win32.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/support/win32/locale_win32.cpp?rev=182026&r1=182025&r2=182026&view=diff
==============================================================================
--- libcxx/trunk/src/support/win32/locale_win32.cpp (original)
+++ libcxx/trunk/src/support/win32/locale_win32.cpp Thu May 16 12:13:40 2013
@@ -9,8 +9,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "support/win32/locale_win32.h"
-
-#include <stdarg.h> // va_start, va_end
+#include <cstdarg> // va_start, va_end
+#include <cwchar>  // mbstate_t
 
 // FIXME: base currently unused. Needs manual work to construct the new locale
 locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )

Modified: libcxx/trunk/src/support/win32/support.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/support/win32/support.cpp?rev=182026&r1=182025&r2=182026&view=diff
==============================================================================
--- libcxx/trunk/src/support/win32/support.cpp (original)
+++ libcxx/trunk/src/support/win32/support.cpp Thu May 16 12:13:40 2013
@@ -8,38 +8,55 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <support/win32/support.h>
-#include <stdarg.h> // va_start, va_end
-#include <stddef.h> // size_t
-#include <stdlib.h> // malloc
-#include <stdio.h>  // vsprintf, vsnprintf
-#include <string.h> // strcpy, wcsncpy
+#include <cstdarg> // va_start, va_end
+#include <cstddef> // size_t
+#include <cstdlib> // malloc
+#include <cstdio>  // vsprintf, vsnprintf
+#include <cstring> // strcpy, wcsncpy
+#include <cwchar>  // mbstate_t
+#include <memory> // unique_ptr
+
+namespace { // Private
+
+	struct free_deleter { 
+		inline void operator()(char* p) { free(p); } 
+	}; 
+}
+// Some of these functions aren't standard or if they conform, the name does not.
 
-int asprintf(char **sptr, const char *__restrict fmt, ...)
+int asprintf(char **sptr, const char *__restrict format, ...)
 {
     va_list ap;
-    va_start(ap, fmt);
-    int result = vasprintf(sptr, fmt, ap);
+    va_start(ap, format);
+    int result;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+        result = vasprintf(sptr, format, ap);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch( ... ) {
+        va_end(ap);
+        throw;
+    }
+#endif
     va_end(ap);
     return result;
 }
 
 // Like sprintf, but when return value >= 0 it returns a pointer to a malloc'd string in *sptr.
 // If return >= 0, use free to delete *sptr.
-int vasprintf( char **sptr, const char *__restrict fmt, va_list ap )
+int vasprintf( char **sptr, const char *__restrict format, va_list ap )
 {
     *sptr = NULL;
-    int count = vsnprintf( NULL, 0, fmt, ap ); // Query the buffer size required.
+    int count = _vsnprintf( NULL, 0, format, ap ); // Query the buffer size required.
     if( count >= 0 ) {
-        char* p = static_cast<char*>(malloc(count+1)); // Allocate memory for it and the terminator.
-        if ( p == NULL )
+        std::unique_ptr<char, free_deleter> p( static_cast<char*>(malloc(count+1)) );
+        if ( ! p )
             return -1;
-        if ( vsnprintf( p, count+1, fmt, ap ) == count ) // We should have used exactly what was required.
-            *sptr = p;
-        else { // Otherwise something is wrong, likely a bug in vsnprintf. If so free the memory and report the error.
-            free(p);
-            return -1;
-        }
+        if ( vsnprintf( p.get(), count+1, format, ap ) == count ) // We should have used exactly what was required.
+            *sptr = p.release();
+        else // Otherwise something is wrong, likely a bug in vsnprintf. If so free the memory and report the error.
+            return -1; // Pointer will get automaticlaly deleted.
     }
 
     return count;
@@ -120,7 +137,7 @@ size_t wcsnrtombs( char *__restrict dst,
         if ( dst )
             result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps);
         else
-            result = wcrtomb_s( &char_size, NULL, 0, c, ps); 
+            result = wcrtomb_s( &char_size, NULL, 0, c, ps);
         // If result is zero there is no error and char_size contains the size of the multi-byte-sequence converted.
         // Otherwise result indicates an errno type error.
         if ( result == no_error ) {





More information about the cfe-commits mailing list