stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r367462 - /incubator/stdcxx/trunk/src/collate.cpp
Date Tue, 10 Jan 2006 02:11:00 GMT
Author: sebor
Date: Mon Jan  9 18:10:57 2006
New Revision: 367462

URL: http://svn.apache.org/viewcvs?rev=367462&view=rev
Log:
2006-01-09  Martin Sebor  <sebor@roguewave.com>

	STDCXX-104
	* collate.cpp (wsccoll, wcsxfrm, wcstombs): Declared when the functions
	are known to be defined in the libc binary but not declared in the libc
	headers.
	(__rw_wcsxfrm): New. Just like wcsxfrm but implemented in terms of
	mbstowcs and strxfrm when wcxfrm is not implemented by the system's
	libc.
	(_RWSTD_WCSXFRM): New macro expands to wcsxfrm or __rw_wcsxfrm.
	(__rw_wcsnxfrm): Used _RWSTD_WCSXFRM.
	[_RWSTD_NO_WCSCOLL] (collate_byname::do_compare): Implemented in terms
	of do_transform when there is no support for wcscoll in libc.

Modified:
    incubator/stdcxx/trunk/src/collate.cpp

Modified: incubator/stdcxx/trunk/src/collate.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/src/collate.cpp?rev=367462&r1=367461&r2=367462&view=diff
==============================================================================
--- incubator/stdcxx/trunk/src/collate.cpp (original)
+++ incubator/stdcxx/trunk/src/collate.cpp Mon Jan  9 18:10:57 2006
@@ -38,8 +38,12 @@
 #include <limits>     // for numeric_limits
 
 #include <limits.h>
+#include <stdlib.h>   // for wcstombs()
 #include <string.h>   // for memchr(), memcpy()
-#include <wchar.h>    // for wcsxfrm(), wmemcmp()
+
+#ifndef _RWSTD_NO_WCHAR_H
+#  include <wchar.h>    // for wcscoll(), wcsxfrm(), wmemcmp()
+#endif   // _RWSTD_NO_WCHAR_H
 
 #include <loc/_collate.h>
 #include <loc/_locale.h>
@@ -50,6 +54,55 @@
 #include "setlocale.h"
 
 
+#if defined (_RWSTD_NO_WCSCOLL) && !defined (_RWSTD_NO_WCSCOLL_IN_LIBC)
+
+extern "C" {
+
+// declare if not declared in the system header(s)
+int wcscoll (const wchar_t*, const wchar_t*) _LIBC_THROWS ();
+
+#  undef _RWSTD_NO_WCSCOLL
+
+}   // extern "C"
+
+#endif   // _RWSTD_NO_WCSCOLL && !_RWSTD_NO_WCSCOLL_IN_LIBC
+
+
+#ifdef _RWSTD_NO_WCSXFRM
+#  ifndef _RWSTD_NO_WCSXFRM_IN_LIBC
+
+extern "C" {
+
+// declare if not declared in the system header(s)
+_RWSTD_SIZE_T wcsxfrm (wchar_t*, const wchar_t*, _RWSTD_SIZE_T) _LIBC_THROWS ();
+
+#    define _RWSTD_WCSXFRM   wcsxfrm
+#    undef _RWSTD_NO_WCSXFRM
+
+}   // extern "C"
+
+#  else
+#    define _RWSTD_WCSXFRM   _RW::__rw_wcsxfrm
+#  endif   // _RWSTD_NO_WCSXFRM_IN_LIBC
+#else
+#    define _RWSTD_WCSXFRM   wcsxfrm
+#endif   // _RWSTD_NO_WCSXFRM
+
+
+#if defined (_RWSTD_NO_WCSTOMBS) && !defined (_RWSTD_NO_WCSTOMBS_IN_LIBC)
+
+extern "C" {
+
+// declare if not declared in the system header(s)
+_RWSTD_SIZE_T wcstombs (char*, const wchar_t*, _RWSTD_SIZE_T) _LIBC_THROWS ();
+
+#  undef _RWSTD_NO_WCSTOMBS
+
+}   // extern "C"
+
+#endif   // _RWSTD_NO_WCSTOMBS && !_RWSTD_NO_WCSTOMBS_IN_LIBC
+
+
 // for convenience
 typedef unsigned char UChar;
 
@@ -498,6 +551,99 @@
 
 #ifndef _RWSTD_NO_WCHAR_T
 
+#  ifdef _RWSTD_NO_WCSXFRM
+
+// implements wcsxfrm() using wcstombs() and strxfrm() on platforms
+// such as some versions of BSD where the function isn't defined in
+// the C Standard Library
+static _RWSTD_SIZE_T
+__rw_wcsxfrm (wchar_t *dst, const wchar_t *src, _RWSTD_SIZE_T dstsize)
+{
+    // src must be non-null
+    _RWSTD_ASSERT (0 != src);
+
+    // dst is permitted to be null only when (dstsize == 0)
+    _RWSTD_ASSERT (0 == dstsize || dst);
+
+#    ifndef _RWSTD_NO_WCSTOMBS
+
+    // convert wide string to a multibyte string before tranforming it
+    // using strxfrm() and widening the result into the destination buffer
+
+    const _RWSTD_SIZE_T srclen = _RWSTD_WCSLEN (src);
+
+    // compute the size of the temporary nearrow buffer where to narrow
+    // the source wide string to
+    const _RWSTD_SIZE_T needbytes =
+        (dstsize ? dstsize : srclen) * MB_LEN_MAX;
+
+    char narrow_buf [256];
+    char* const nbuf =
+        sizeof narrow_buf < needbytes ? new char [needbytes + 1] : narrow_buf;
+
+    _RWSTD_SIZE_T result;
+
+    const _RWSTD_SIZE_T nmbchars = wcstombs (nbuf, src, needbytes);
+
+    if (_RWSTD_SIZE_MAX == nmbchars)
+        result = _RWSTD_SIZE_MAX;
+    else {
+        // allocate a small buffer 8 times the size of the multibyte
+        // buffer (where 8 is a guess at the maximum number of bytes
+        // needed to transform the longest multibyte character)
+        char xfrm_buf [sizeof narrow_buf * 8];
+        const _RWSTD_SIZE_T xbufsize = sizeof xfrm_buf;
+        const _RWSTD_SIZE_T xbufneed = needbytes * 8;
+
+        // allocate a larger buffer if the small statically buffer
+        // isn't big enough
+        char* const xbuf =
+            xbufsize < xbufneed ? new char [xbufneed + 1] : xfrm_buf;
+
+        // transform the multibyte character string into the narrow
+        // buffer, storing the returned value
+        result = strxfrm (xbuf, nbuf, xbufneed);
+
+        if (_RWSTD_SIZE_MAX != result && dstsize) {
+            // widen the bytes (not characters) of the transformed string
+            // if the transformation was successful and the size of the
+            // destination buffer is non-zero
+
+            if (result < dstsize)
+                dstsize = result;
+
+            for (_RWSTD_SIZE_T i = 0; i != dstsize; ++i)
+                dst [i] = wchar_t (UChar (xbuf [i]));
+        }
+
+        // free the transformation buffer if dynamically allocated
+        if (xbuf != xfrm_buf)
+            delete[] xbuf;
+    }
+
+    // free the multibyte buffer if dynamically allocated
+    if (nbuf != narrow_buf)
+        delete[] nbuf;
+
+    return result;
+
+#    else   // if defined (_RWSTD_NO_WCSTOMBS)
+
+    _RWSTD_UNUSED (dst);
+    _RWSTD_UNUSED (src);
+    _RWSTD_UNUSED (dstsize);
+
+    // fail when there is no way to convert a wchar_t array
+    // to a multibyte string
+    return _RWSTD_SIZE_MAX;
+
+#    endif   // _RWSTD_NO_WCSTOMBS
+
+}
+
+#  endif   // _RWSTD_NO_WCSXFRM
+
+
 // same as wcsxfrm() except that it takes the number of characters
 // in an array that may contain embedded NULs; these are inserted
 // into the transformed string
@@ -506,8 +652,6 @@
 {
     _STD::wstring res;
 
-#ifndef _RWSTD_NO_WCSXFRM
-
     wchar_t buf [256];
     wchar_t *pbuf = buf;
 
@@ -553,10 +697,12 @@
         // it's buggy (such as MSVC's) and tries to write to
         // the buffer even if it's 0
         wchar_t just_in_case_buf [8];
-        const _RWSTD_SIZE_T dst_size = wcsxfrm (just_in_case_buf, psrc, 0);
+
+        const _RWSTD_SIZE_T dst_size =
+            _RWSTD_WCSXFRM (just_in_case_buf, psrc, 0);
 
         // check for wcsxfrm() errors
-        if (0 == (dst_size << 1))
+        if (_RWSTD_SIZE_MAX == dst_size)
             return _STD::wstring ();
 
         _RWSTD_SIZE_T res_size = res.size ();
@@ -568,14 +714,14 @@
 
         // transfor the source string up to the terminating NUL
         _RWSTD_SIZE_T xfrm_size =
-            wcsxfrm (&res [0] + res_size, psrc, dst_size + 1);
+            _RWSTD_WCSXFRM (&res [0] + res_size, psrc, dst_size + 1);
 
-#if defined _MSC_VER && _MSC_VER < 1400
+#  if defined _MSC_VER && _MSC_VER < 1400
         // compute the correct value that should have been returned from
         // strxfrm() after the transformation has completed (MSVC strxfrm()
         // returns a bogus result; see PR #29935)
         xfrm_size = Traits::length (&res [0] + res_size);
-#endif   // MSVC < 8.0
+#  endif   // MSVC < 8.0
 
         // increment the size of the result string by the number
         // of transformed characters excluding the terminating NUL
@@ -588,8 +734,6 @@
     if (pbuf != buf)
         delete[] pbuf;
 
-#endif   // _RWSTD_NO_WCSXFRM
-
     return res;
 }
 
@@ -880,40 +1024,55 @@
         const string_type s1 = do_transform (low1, high1);
         const string_type s2 = do_transform (low2, high2);
 
-        // FIXME: not optomized,
+        // FIXME: optimize
         return s1.compare (s2);
     }
-    else {
-        _RW::__rw_setlocale clocale (this->_C_name, _RWSTD_LC_COLLATE);
+
+#ifndef _RWSTD_NO_WCSCOLL
+
+    // use the system C library to compare the strings
+
+    _RW::__rw_setlocale clocale (this->_C_name, _RWSTD_LC_COLLATE);
     
-        const _RWSTD_SIZE_T len1 = high1 - low1;
-        const _RWSTD_SIZE_T len2 = high2 - low2;
-        const _RWSTD_SIZE_T len  = len1 + len2;
+    const _RWSTD_SIZE_T len1 = high1 - low1;
+    const _RWSTD_SIZE_T len2 = high2 - low2;
+    const _RWSTD_SIZE_T len  = len1 + len2;
 
-        // small local buffer
-        wchar_t buffer [256];
+    // small local buffer
+    wchar_t local_buffer [256];
+    const _RWSTD_SIZE_T bufsize = sizeof local_buffer / sizeof *local_buffer;
 
-        // allocate only if local buffer is too small
-        wchar_t *buf = len + 2 >= sizeof buffer 
-            ? new wchar_t [len + 2] : buffer;
+    // allocate only if local buffer is too small
+    wchar_t* const wbuf =
+        len + 2 >= bufsize ? new wchar_t [len + 2] : local_buffer;
 
-        // copy and null-terminate first sequence
-        char_traits<wchar_t>::copy (buf, low1, len1);
-        buf [len1] = '\0';
+    // copy and null-terminate first sequence
+    char_traits<wchar_t>::copy (wbuf, low1, len1);
+    wbuf [len1] = '\0';
 
-        // append and null-terminate first sequence
-        char_traits<wchar_t>::copy (buf + len1 + 1, low2, len2);
-        buf [len1 + 1 + len2] = '\0';
+    // append and null-terminate first sequence
+    char_traits<wchar_t>::copy (wbuf + len1 + 1, low2, len2);
+    wbuf [len1 + 1 + len2] = '\0';
 
-        // compare sequences
-        int result = wcscoll (buf, buf + len1 + 1);
+    // compare sequences using wcscoll()
+    const int result = wcscoll (wbuf, wbuf + len1 + 1);
 
-        // deallocate only if allocated
-        if (buf != buffer)
-            delete[] buf;
+    // deallocate only if allocated
+    if (wbuf != local_buffer)
+        delete[] wbuf;
+
+    return result ? result > 0 ? 1 : -1 : 0;
+
+#else   // if defined (_RWSTD_NO_WCSCOLL)
+
+    // transform strings first and compare the transformed results
+    const string_type s1 = do_transform (low1, high1);
+    const string_type s2 = do_transform (low2, high2);
+
+    return s1.compare (s2);
+
+#endif   // _RWSTD_NO_WCSCOLL
 
-        return result ? result > 0 ? 1 : -1 : 0;
-    }
 }
 
 



Mime
View raw message