]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/io/ufmt_cmn.c
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / io / ufmt_cmn.c
index 855f1475b7e4970b503332c02f27b0b51c017245..e4e09033911bfe1947c895909ff5d074a58242ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1998-2004, International Business Machines
+*   Copyright (C) 1998-2006, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -39,7 +39,7 @@ ufmt_digitvalue(UChar c)
         ((c>=LOWERCASE_A)&&(c<=LOWERCASE_Z)) ||
         ((c>=UPPERCASE_A)&&(c<=UPPERCASE_Z))  )
     {
-      return c - 0x0030 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0);
+      return c - DIGIT_0 - (c >= 0x0041 ? (c >= 0x0061 ? 39 : 7) : 0);
     }
     else
     {
@@ -56,8 +56,8 @@ ufmt_isdigit(UChar     c,
     return (UBool)(digitVal < radix && digitVal >= 0);
 }
 
-#define TO_UC_DIGIT(a) a <= 9 ? (0x0030 + a) : (0x0037 + a)
-#define TO_LC_DIGIT(a) a <= 9 ? (0x0030 + a) : (0x0057 + a)
+#define TO_UC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0037 + a)
+#define TO_LC_DIGIT(a) a <= 9 ? (DIGIT_0 + a) : (0x0057 + a)
 
 void 
 ufmt_64tou(UChar     *buffer, 
@@ -81,7 +81,7 @@ ufmt_64tou(UChar     *buffer,
     /* pad with zeroes to make it minDigits long */
     if(minDigits != -1 && length < minDigits) {
         while(length < minDigits && length < *len)
-            buffer[length++] = 0x0030;  /*zero padding */
+            buffer[length++] = DIGIT_0;  /*zero padding */
     }
 
     /* reverse the buffer */
@@ -158,37 +158,64 @@ ufmt_uto64(const UChar     *buffer,
     return result;
 }
 
+#define NIBBLE_PER_BYTE 2
 void *
 ufmt_utop(const UChar     *buffer,
           int32_t     *len)
 {
-    /*
-    TODO: Fix this code so that it will work with pointers that are 2<=sizeof(void*)<=16
-    */
-    const UChar *limit;
-    int32_t     count;
-    int64_t     result;
+    int32_t count, resultIdx, incVal, offset;
+    /* This union allows the pointer to be written as an array. */
+    union {
+        void *ptr;
+        uint8_t bytes[sizeof(void*)];
+    } result;
     
-    
-    /* intialize parameters */
-    limit     = buffer + *len;
-    count     = 0;
-    result    = 0;
-    
-    /* iterate through buffer */
-    /* limit to sixteen iterations since that is the max that an int64_t can contain for pointer work */
-    while(ufmt_isdigit(*buffer, 16) && buffer < limit) {
-        
-        /* read the next digit */
-        result *= 16;
-        result += ufmt_digitvalue(*buffer++);
-        
-        /* increment our count */
+    /* intialize variables */
+    count      = 0;
+    offset     = 0;
+    result.ptr = NULL;
+
+    /* Skip the leading zeros */
+    while(buffer[count] == DIGIT_0 || u_isspace(buffer[count])) {
+        count++;
+        offset++;
+    }
+
+    /* iterate through buffer, stop when you hit the end */
+    while(ufmt_isdigit(buffer[count], 16) && count < *len) {
+        /* increment the count consumed */
         ++count;
     }
+
+    /* detect overflow */
+    if (count - offset > (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE)) {
+        offset = count - (int32_t)(sizeof(void*)*NIBBLE_PER_BYTE);
+    }
     
+    /* Initialize the direction of the input */
+#if U_IS_BIG_ENDIAN
+    incVal = -1;
+    resultIdx = (int32_t)(sizeof(void*) - 1);
+#else
+    incVal = 1;
+    resultIdx = 0;
+#endif
+    /* Write how much was consumed. */
     *len = count;
-    return (void *)result;
+    while(--count >= offset) {
+        /* Get the first nibble of the byte */
+        uint8_t byte = (uint8_t)ufmt_digitvalue(buffer[count]);
+
+        if (count > offset) {
+            /* Get the second nibble of the byte when available */
+            byte = (uint8_t)(byte + (ufmt_digitvalue(buffer[--count]) << 4));
+        }
+        /* Write the byte into the array */
+        result.bytes[resultIdx] = byte;
+        resultIdx += incVal;
+    }
+
+    return result.ptr;
 }
 
 UChar*