stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/valcmp.cpp
changeset 31 ce057bb09d0b
child 45 4b03adbd26ca
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/valcmp.cpp	Fri Jun 04 16:20:51 2010 +0100
@@ -0,0 +1,928 @@
+
+
+/************************************************************************
+ *
+ * valcmp.cpp - definitions of the rw_valcmp() family of helper functions
+ *
+ * $Id: valcmp.cpp 332687 2005-11-12 00:47:57Z sebor $
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License");  you may  not use this file except  in compliance with the
+ * License.    You    may   obtain   a   copy   of    the   License    at
+ * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
+ * applicable law  or agreed to  in writing,  software  distributed under
+ * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
+ * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
+ * for the specific language governing permissions  and limitations under
+ * the License.
+ * 
+ **************************************************************************/
+
+// expand _TEST_EXPORT macros
+#define _RWSTD_TEST_SRC
+
+#include <cfloat>
+#include <valcmp.h>
+
+#include <stdio.h>    // for fprintf, stderr
+#include <stdlib.h>   // for abort
+#include <string.h>   // for memcmp
+
+/**************************************************************************/
+
+typedef unsigned char UChar;
+
+
+static const UChar
+_rw_upper [] = {
+
+#if 'A' == 0x41
+
+    // basic ASCII:
+    //          .0  .1  .2  .3  .4  .5  .6  .7  .8  .9  .a  .b  .c  .d  .e  .f
+    //         --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
+    //         NUL SOH STX ETX EOT ENQ ACK BEL BS  TAB  LF  VT  FF  CR  SO  SI
+    /* 0. */ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+    //         DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN  EM SUB ESC  FS  GS  RS  US
+    /* 1. */ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+    //         SPC   !   "   #   $   %   '   '   (   )   *   +   ,   -   .   /
+    /* 2. */ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+    //           0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
+    /* 3. */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+    //               A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
+    /* 4. */ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+    //           P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
+    /* 5. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+    //           `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
+    /* 6. */ "\x60\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+    //           p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ DEL
+    /* 7. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x7b\x7c\x7d\x7e\x7f"
+
+    // extended ASCII:
+    /* 8. */ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+    /* 9. */ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+    /* a. */ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+    /* b. */ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+    /* c. */ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+    /* d. */ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+    /* e. */ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+    /* f. */ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+#elif 'A' == 0xc1
+
+    // EBCDIC:
+    //          .0  .1  .2  .3  .4  .5  .6  .7  .8  .9  .a  .b  .c  .d  .e  .f
+    //         --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
+    //         NUL SOH STX ETX  PF  HT  LC DEL         SMM  VT  FF  CR  SO  SI
+    /* 0. */ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+    //         DLE DC1 DC2  TM RES  NL  BS  IL CAN  EM  CC CU1 IFS IGS IRS IUS
+    /* 1. */ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+    //          DS SOS  FS     BYP  LF ETB ESC          SM CU2     ENQ ACK BEL
+    /* 2. */ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+    //                 SYN      PN  RS  UC EOT             CU3 DC4 NAK     SUB
+    /* 3. */ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+    //          SP                                     ct.  .   <   (   +   |
+    /* 4. */ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+    //          &                                       !   $   *   )   ;   ~
+    /* 5. */ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"
+    //          -   /                                       ,   %   _   >   ?
+    /* 6. */ "\x60\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"
+    //                                                  :   #   @   '   =   "
+    /* 7. */ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+    //              a   b   c   d   e   f   g   h   i
+    /* 8. */ "\x80\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\x8a\x8b\x8c\x8d\x8e\x8f"
+    //              j   k   l   m   n   o   p   q   r
+    /* 9. */ "\x90\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\x9a\x9b\x9c\x9d\x9e\x9f"
+    //                  s   t   u   v   w   x   y   z
+    /* a. */ "\xa0\xa1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xaa\xab\xac\xad\xae\xaf"
+    //                                            `
+    /* b. */ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+    //              A   B   C   D   E   F   G   H   I
+    /* c. */ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+    //              J   K   L   M   N   O   P   Q   R
+    /* d. */ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+    //                  S   T   U   V   W   X   Y   Z
+    /* e. */ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+    //          0   1   2   3   4   5   6   7   8   9
+    /* f. */ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+#else   // 'A' != 0x41 && 'A' != 0xc1
+#  error unknown character set (neither ASCII nor EBCDIC)
+#endif   // ASCII or EBCDIC
+
+};
+
+
+// returns 1 iff all size bytes of the object pointed to by buf are 0
+static int
+_rw_iszero (const void *buf, _RWSTD_SIZE_T size)
+{
+    for (_RWSTD_SIZE_T i = 0; i != size; ++i)
+        if (_RWSTD_STATIC_CAST (const UChar*, buf)[i])
+            return 0;
+
+    return 1;
+}
+
+
+// compares two objects of equal size
+static int
+_rw_cmpx (const void *buf1,
+          const void *buf2,
+          _RWSTD_SIZE_T nelems,
+          _RWSTD_SIZE_T size,
+          int           flags = 0)
+{
+    const UChar *p1 = _RWSTD_STATIC_CAST (const UChar*, buf1);
+    const UChar *p2 = _RWSTD_STATIC_CAST (const UChar*, buf2);
+
+    int ret = 0;
+
+    for ( ; nelems; p1 += size, p2 += size, --nelems) {
+
+        ret = memcmp (p1, p2, size);
+
+        if (flags & CMP_NULTERM) {
+
+            const int zero1 = _rw_iszero (p1, size);
+            const int zero2 = _rw_iszero (p2, size);
+
+            if (zero1 || zero2) {
+                ret = zero1 - zero2;
+                break;
+            }
+        }
+
+        if (ret && (flags & CMP_NOCASE)) {
+            // FIXME: implement
+            fprintf (stderr,
+                     "%s:%d: case insensitive comparison not implemented\n",
+                     __FILE__, __LINE__);
+            abort ();
+        }
+    }
+
+    if (flags & CMP_RETOFF) {
+        // FIXME: implement
+        fprintf (stderr,
+                 "%s:%d: returning offset not implemented\n",
+                 __FILE__, __LINE__);
+        abort ();
+    }
+
+    return ret < 0 ? -1 : ret ? +1 : 0;
+}
+
+
+// compares two byte arrays
+static int
+_rw_cmp1 (const void *buf1,
+          const void *buf2,
+          _RWSTD_SIZE_T nelems,
+          int           flags = 0)
+{
+#ifdef _RWSTD_UINT8_T
+
+    typedef _RWSTD_UINT8_T UI8T;
+
+    if (0 == flags) {
+        const int ret = memcmp (buf1, buf2, nelems);
+        return ret < 0 ? -1 : ret ? +1 : 0;
+    }
+
+    if (CMP_NULTERM == flags) {
+        const int ret =
+            strncmp (_RWSTD_STATIC_CAST (const char*, buf1),
+                     _RWSTD_STATIC_CAST (const char*, buf2),
+                     nelems);
+        return ret < 0 ? -1 : ret ? +1 : 0;
+    }
+
+    int ret = 0;
+    int inx = 0;
+
+    const UI8T *pi1 = _RWSTD_STATIC_CAST (const UI8T*, buf1);
+    const UI8T *pi2 = _RWSTD_STATIC_CAST (const UI8T*, buf2);
+
+    for (; nelems; ++pi1, ++pi2, --nelems, ++inx) {
+
+        const UI8T ui1 = *pi1;
+        const UI8T ui2 = *pi2;
+
+        if (flags & CMP_NULTERM) {
+
+            if (0 == ui1) {
+                ret = ui2 ? -1 : 0;
+                break;
+            }
+
+            if (0 == ui2) {
+                ret = +1;
+                break;
+            }
+        }
+
+        if (ui1 != ui2) {
+            if (flags & CMP_NOCASE) {
+                if (_rw_upper [ui1] != _rw_upper [ui2]) {
+                    ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
+                    break;
+                }
+            }
+            else {
+                ret = ui1 < ui2 ? -1 : +1;
+                break;
+            }
+        }
+    }
+
+    if (CMP_RETOFF & flags) {
+        ret = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < nelems ? inx : -1;
+    }
+            
+    return ret;
+
+#else // if !defined (_RWSTD_UINT8_T)
+#  error _RWSTD_UINT8_T not #defined (configuration problem?)
+#endif   // _RWSTD_UINT8_T
+
+}
+
+
+// compares two arrays of objects each 16 bits in size
+static int
+_rw_cmp2 (const void *buf1,
+          const void *buf2,
+          _RWSTD_SIZE_T nelems,
+          int           flags = 0)
+{
+#ifdef _RWSTD_UINT16_T
+
+    typedef _RWSTD_UINT16_T UI16T;
+
+    int ret = 0;
+    int inx = 0;
+
+    const UI16T *pi1 = _RWSTD_STATIC_CAST (const UI16T*, buf1);
+    const UI16T *pi2 = _RWSTD_STATIC_CAST (const UI16T*, buf2);
+
+    for (; nelems; ++pi1, ++pi2, --nelems) {
+
+        const UI16T ui1 = *pi1;
+        const UI16T ui2 = *pi2;
+
+        if (flags & CMP_NULTERM) {
+
+            if (0 == ui1) {
+                ret = ui2 ? -1 : 0;
+                break;
+            }
+
+            if (0 == ui2) {
+                ret = +1;
+                break;
+            }
+        }
+
+        if (ui1 != ui2) {
+            if (flags & CMP_NOCASE) {
+                if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
+                    ret = ui1 < ui2 ? -1 : +1;
+                    break;
+                }
+                else if (_rw_upper [ui1] != _rw_upper [ui2]) {
+                    ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
+                    break;
+                }
+            }
+            else {
+                ret = ui1 < ui2 ? -1 : +1;
+                break;
+            }
+        }
+    }
+
+    if (CMP_RETOFF & flags) {
+        ret = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < nelems ? inx : -1;
+    }
+            
+    return ret;
+
+#else   // if !defined (_RWSTD_UINT16_T)
+
+    return _rw_cmpx (buf1, buf2, nelems, 2, flags);
+
+#endif   // _RWSTD_UINT16_T
+}
+
+
+// compares two arrays of objects each 32 bits in size
+static int
+_rw_cmp4 (const void *buf1,
+          const void *buf2,
+          _RWSTD_SIZE_T nelems,
+          int           flags = 0)
+{
+#ifdef _RWSTD_UINT32_T
+
+    typedef _RWSTD_UINT32_T UI32T;
+
+    int ret = 0;
+    int inx = 0;
+
+    const UI32T *pi1 = _RWSTD_STATIC_CAST (const UI32T*, buf1);
+    const UI32T *pi2 = _RWSTD_STATIC_CAST (const UI32T*, buf2);
+
+    for (; nelems; ++pi1, ++pi2, --nelems) {
+
+        const UI32T ui1 = *pi1;
+        const UI32T ui2 = *pi2;
+
+        if (flags & CMP_NULTERM) {
+
+            if (0 == ui1) {
+                ret = ui2 ? -1 : 0;
+                break;
+            }
+
+            if (0 == ui2) {
+                ret = +1;
+                break;
+            }
+        }
+
+        if (ui1 != ui2) {
+            if (flags & CMP_NOCASE) {
+                if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
+                    ret = ui1 < ui2 ? -1 : +1;
+                    break;
+                }
+                else if (_rw_upper [ui1] != _rw_upper [ui2]) {
+                    ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
+                    break;
+                }
+            }
+            else {
+                ret = ui1 < ui2 ? -1 : +1;
+                break;
+            }
+        }
+    }
+
+    if (CMP_RETOFF & flags) {
+        ret = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < nelems ? inx : -1;
+    }
+            
+    return ret;
+
+#else   // if !defined (_RWSTD_UINT32_T)
+
+    return _rw_cmpx (buf1, buf2, nelems, 4, flags);
+
+#endif   // _RWSTD_UINT32_T
+}
+
+
+// compares two arrays of objects each 64 bits in size
+static int
+_rw_cmp8 (const void *buf1,
+          const void *buf2,
+          _RWSTD_SIZE_T nelems,
+          int           flags = 0)
+{
+#ifdef _RWSTD_UINT64_T
+
+    typedef _RWSTD_UINT64_T UI64T;
+
+    int ret = 0;
+    int inx = 0;
+
+    const UI64T *pi1 = _RWSTD_STATIC_CAST (const UI64T*, buf1);
+    const UI64T *pi2 = _RWSTD_STATIC_CAST (const UI64T*, buf2);
+
+    for (; nelems; ++pi1, ++pi2, --nelems) {
+
+        const UI64T ui1 = *pi1;
+        const UI64T ui2 = *pi2;
+
+        if (flags & CMP_NULTERM) {
+
+            if (0 == ui1) {
+                ret = ui2 ? -1 : 0;
+                break;
+            }
+
+            if (0 == ui2) {
+                ret = +1;
+                break;
+            }
+        }
+
+        if (ui1 != ui2) {
+            if (flags & CMP_NOCASE) {
+                if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
+                    ret = ui1 < ui2 ? -1 : +1;
+                    break;
+                }
+                else if (_rw_upper [ui1] != _rw_upper [ui2]) {
+                    ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
+                    break;
+                }
+            }
+            else {
+                ret = ui1 < ui2 ? -1 : +1;
+                break;
+            }
+        }
+    }
+
+    if (CMP_RETOFF & flags) {
+        ret = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < nelems ? inx : -1;
+    }
+            
+    return ret;
+
+#else   // if !defined (_RWSTD_UINT64_T)
+
+    return _rw_cmpx (buf1, buf2, nelems, 8, flags);
+
+#endif   // _RWSTD_UINT64_T
+}
+
+
+// compares two arrays of objects of unequal size
+static int
+_rw_cmpxx (const void*   buf1,
+           const void*   buf2,
+           _RWSTD_SIZE_T nelems,
+           _RWSTD_SIZE_T size1,
+           _RWSTD_SIZE_T size2,
+           int           flags)
+{
+    int ret = 0;
+    int inx = 0;
+
+    for (; nelems; --nelems, ++inx) {
+
+#ifdef _RWSTD_UINT64_T
+
+        _RWSTD_UINT64_T ui1;
+        _RWSTD_UINT64_T ui2;
+
+#else   // if !defined (_RWSTD_UINT64_T)
+
+        _RWSTD_SIZE_T ui1;
+        _RWSTD_SIZE_T ui2;
+
+#endif   // _RWSTD_UINT64_T
+
+        switch (size1) {
+
+#ifdef _RWSTD_UINT8_T
+
+        case 1: {
+            const _RWSTD_UINT8_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT8_T*, buf1);
+            ui1 = *ptr++;
+            buf1 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT8_T
+
+#ifdef _RWSTD_UINT16_T
+
+        case 2: {
+            const _RWSTD_UINT16_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT16_T*, buf1);
+            ui1 = *ptr++;
+            buf1 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT16_T
+
+#ifdef _RWSTD_UINT32_T
+
+        case 4: {
+            const _RWSTD_UINT32_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT32_T*, buf1);
+            ui1 = *ptr++;
+            buf1 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT32_T
+
+#ifdef _RWSTD_UINT64_T
+
+        case 8: {
+            const _RWSTD_UINT64_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT64_T*, buf1);
+            ui1 = *ptr++;
+            buf1 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT64_T
+
+        default:
+            fprintf (stderr,
+                     "%s:%d: comparison of objects %u and %u bytes in size "
+                     "not implemented\n", __FILE__, __LINE__,
+                     unsigned (size1), unsigned (size2));
+            abort ();
+        }
+
+        switch (size2) {
+
+#ifdef _RWSTD_UINT8_T
+
+        case 1: {
+            const _RWSTD_UINT8_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT8_T*, buf2);
+            ui2 = *ptr++;
+            buf2 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT8_T
+
+#ifdef _RWSTD_UINT16_T
+
+        case 2: {
+            const _RWSTD_UINT16_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT16_T*, buf2);
+            ui2 = *ptr++;
+            buf2 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT16_T
+
+#ifdef _RWSTD_UINT32_T
+
+        case 4: {
+            const _RWSTD_UINT32_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT32_T*, buf2);
+            ui2 = *ptr++;
+            buf2 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT32_T
+
+#ifdef _RWSTD_UINT64_T
+
+        case 8: {
+            const _RWSTD_UINT64_T* ptr =
+                _RWSTD_STATIC_CAST (const _RWSTD_UINT64_T*, buf2);
+            ui2 = *ptr++;
+            buf2 = ptr;
+            break;
+        }
+
+#endif   // _RWSTD_UINT64_T
+
+        default:
+            fprintf (stderr,
+                     "%s:%d: comparison of objects %u and %u bytes in size "
+                     "not implemented\n", __FILE__, __LINE__,
+                     unsigned (size1), unsigned (size2));
+            abort ();
+        }
+
+        if (flags & CMP_NULTERM) {
+
+            if (0 == ui1) {
+                ret = ui2 ? -1 : 0;
+                break;
+            }
+
+            if (0 == ui2) {
+                ret = +1;
+                break;
+            }
+        }
+
+        if (ui1 != ui2) {
+            if (flags & CMP_NOCASE) {
+                if (_RWSTD_UCHAR_MAX < ui1 || _RWSTD_UCHAR_MAX < ui2) {
+                    ret = ui1 < ui2 ? -1 : +1;
+                    break;
+                }
+                else if (_rw_upper [ui1] != _rw_upper [ui2]) {
+                    ret = _rw_upper [ui1] < _rw_upper [ui2] ? -1 : +1;
+                    break;
+                }
+            }
+            else {
+                ret = ui1 < ui2 ? -1 : +1;
+                break;
+            }
+        }
+    }
+
+    if (CMP_RETOFF & flags) {
+        ret = _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, inx) < nelems ? inx : -1;
+    }
+
+    return ret;
+}
+
+
+_TEST_EXPORT int
+rw_valcmp (const void*   buf1,
+           const void*   buf2,
+           _RWSTD_SIZE_T nelems,
+           _RWSTD_SIZE_T size1,
+           _RWSTD_SIZE_T size2,
+           int           flags /* = 0 */)
+{
+    if (size1 == size2) {
+
+        switch (size1) {
+        case 1: return _rw_cmp1 (buf1, buf2, nelems, flags);
+        case 2: return _rw_cmp2 (buf1, buf2, nelems, flags);
+        case 4: return _rw_cmp4 (buf1, buf2, nelems, flags);
+        case 8: return _rw_cmp8 (buf1, buf2, nelems, flags);
+        }
+
+        return _rw_cmpx (buf1, buf2, nelems, size1, flags);
+    }
+
+    return _rw_cmpxx (buf1, buf2, nelems, size1, size2, flags);
+}
+
+
+_TEST_EXPORT int
+rw_strncmp (const char*   str1,
+            const char*   str2,
+            _RWSTD_SIZE_T nelems /* = _RWSTD_SIZE_MAX */,
+           int            flags /* = CMP_NULTERM */)
+{
+    return rw_valcmp (str1, str2, nelems, 1, 1, flags);
+}
+
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+_TEST_EXPORT int
+rw_strncmp (const char*    str1,
+            const wchar_t* str2,
+            _RWSTD_SIZE_T  nelems /* = _RWSTD_SIZE_MAX */,
+           int             flags /* = CMP_NULTERM */)
+{
+    return rw_valcmp (str1, str2, nelems, 1, sizeof (wchar_t), flags);
+}
+
+
+_TEST_EXPORT int
+rw_strncmp (const wchar_t* str1,
+            const char*    str2,
+            _RWSTD_SIZE_T  nelems /* = _RWSTD_SIZE_MAX */,
+            int             flags /* = CMP_NULTERM */)
+{
+    return rw_valcmp (str1, str2, nelems, sizeof (wchar_t), 1, flags);
+}
+
+
+_TEST_EXPORT int
+rw_strncmp (const wchar_t* str1,
+            const wchar_t* str2,
+            _RWSTD_SIZE_T  nelems /* = _RWSTD_SIZE_MAX */,
+           int             flags /* = CMP_NULTERM */)
+{
+    return rw_valcmp (str1, str2, nelems,
+                      sizeof (wchar_t), sizeof (wchar_t), flags);
+}
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+
+// floating point comparison helpers based on
+// http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
+
+_TEST_EXPORT int
+rw_fltcmp (float x, float y)
+{
+#if _RWSTD_SHRT_SIZE == _RWSTD_INT_SIZE
+    typedef short IntT;
+    #ifdef __ARMCC__
+    #pragma diag_suppress 68
+    #endif
+    const IntT imin = _RWSTD_SHRT_MIN;
+    
+#elif _RWSTD_FLT_SIZE == _RWSTD_INT_SIZE
+    typedef int IntT;
+    const IntT imin = _RWSTD_INT_MIN;
+#elif _RWSTD_FLT_SIZE == _RWSTD_LONG_SIZE
+    typedef long IntT;
+    const IntT imin = _RWSTD_LONG_MIN;
+#elif _RWSTD_FLT_SIZE == _RWSTD_LLONG_SIZE
+    typedef _RWSTD_LONG_LONG IntT;
+    const IntT imin = _RWSTD_LLONG_MIN;
+#else
+    // ???
+#  error no integral type of the same size as float exists
+#endif
+
+    if (x == y)
+        return 0;
+
+    // make both arguments lexicographically ordered as twos-complement ints
+    IntT x_int = *(IntT*)&x;
+    if (x_int < 0)
+        x_int = imin - x_int;
+
+    IntT y_int = *(IntT*)&y;
+    if (y_int < 0)
+        y_int = imin - y_int;
+
+    const IntT int_diff = x_int - y_int;
+
+    return int_diff;
+}
+
+
+#define Abs(x) ((x) < 0 ? -(x) : (x))
+
+
+_TEST_EXPORT int
+rw_dblcmp (double x, double y)
+{
+#if _RWSTD_DBL_SIZE == _RWSTD_INT_SIZE
+    typedef int IntT;
+    const IntT imin = _RWSTD_INT_MIN;
+#elif _RWSTD_DBL_SIZE == _RWSTD_LONG_SIZE
+    typedef long IntT;
+    const IntT imin = _RWSTD_LONG_MIN;
+#elif _RWSTD_DBL_SIZE == _RWSTD_LLONG_SIZE
+    typedef _RWSTD_LONG_LONG IntT;
+    const IntT imin = _RWSTD_LLONG_MIN;
+#endif
+
+#if _RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE
+
+    if (x == y)
+        return 0;
+
+    // FIXME: use integer math as in the functions above
+
+    const double diff = x - y;
+
+    // check absolute error
+    if (Abs (diff) < _RWSTD_DBL_EPSILON)
+        return 0;
+
+    // check relative error
+    const double relerr =
+        Abs (x) < Abs (y) ? Abs (diff / y) : Abs (diff / x);
+
+    if (relerr <= 0.0000001)
+        return 0;
+
+    return x < y ? -1 : +1;
+
+#else   // if !(_RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE)
+
+    if (x == y)
+        return 0;
+
+    IntT x_int = *(IntT*)&x;
+    if (x_int < 0)
+        x_int = imin - x_int;
+
+    IntT y_int = *(IntT*)&y;
+    if (y_int < 0)
+        y_int = imin - y_int;
+
+    const IntT int_diff = x_int - y_int;
+
+    return int_diff;
+
+#endif   // _RWSTD_LLONG_SIZE < _RWSTD_DBL_SIZE
+
+}
+
+
+#ifndef _RWSTD_NO_LONG_DOUBLE
+_TEST_EXPORT int
+rw_ldblcmp (long double x, long double y)
+{
+    if (sizeof (long double) == sizeof (double))
+        return rw_dblcmp (double (x), double (y));
+
+    #ifdef __ARMCC__
+    #pragma diag_suppress 111
+    #endif
+    if (x == y)
+        return 0;
+    
+    
+
+    // FIXME: use integer math as in the functions above
+
+    const long double diff = x - y;
+
+    // check absolute error
+    if (Abs (diff) < _RWSTD_LDBL_EPSILON)
+        return 0;
+
+    // check relative error
+    const long double relerr =
+        Abs (x) < Abs (y) ? Abs (diff / y) : Abs (diff / x);
+
+    if (relerr <= 0.0000001L)
+        return 0;
+
+    return x < y ? -1 : +1;
+}
+
+#endif   // _RWSTD_NO_LONG_DOUBLE
+
+#ifdef __SYMBIAN32__
+_TEST_EXPORT int 
+ rw_strcmp (std::basic_string<char>& x ,/*std::basic_string<char> */ long double  y)
+ {
+   const char * c= x.c_str(); 
+   
+   /*if(x.compare(y)==0)
+       return 0;
+   else
+     return x.compare(y)<0?-1:+1;	      */
+   float z=atof(c);
+   
+   if ((long double)z == y)
+        return 0;
+
+    // FIXME: use integer math as in the functions above
+
+    const long double diff =((long double)z) - y;
+
+    // check absolute error
+    if (Abs (diff) < _RWSTD_LDBL_EPSILON)
+        return 0;
+
+    // check relative error
+    const long double relerr =
+        Abs ((long double)z) < Abs (y) ? Abs (diff / y) : Abs (diff /(long double)z);
+
+    if (relerr <= 0.0000001L)
+        return 0;
+
+    return z < y ? -1 : +1;
+     
+ }
+ 
+_TEST_EXPORT int 
+ rw_strcmp (std::basic_string<wchar_t>& x ,long double y)
+{
+ /*  if(x.compare(y)==0)
+       return 0;
+   else
+     return x.compare(y)<0?-1:+1;	      */
+  
+ int len=x.length();
+ const wchar_t *w=x.c_str();
+ char c[128];
+ WCtoC(w,len,c);
+ 
+  float z=atof(c);
+   
+   if ((long double)z == y)
+        return 0;
+
+    // FIXME: use integer math as in the functions above
+
+    const long double diff =((long double)z) - y;
+
+    // check absolute error
+    if (Abs (diff) < _RWSTD_LDBL_EPSILON)
+        return 0;
+
+    // check relative error
+    const long double relerr =
+        Abs ((long double)z) < Abs (y) ? Abs (diff / y) : Abs (diff /(long double)z);
+
+    if (relerr <= 0.0000001L)
+        return 0;
+
+    return z < y ? -1 : +1;      
+     
+ }   
+_TEST_EXPORT
+ void WCtoC(const wchar_t *wstr, int len, char* str)
+{
+
+	int i = 0;
+	for (;i<len;i++)
+		str[i] = wstr[i]; 
+
+}
+
+
+ #endif