ICU-5092 Replace the temporary pointer parsing hack with a permanent platform independent parsing function.

X-SVN-Rev: 19451
This commit is contained in:
George Rhoten 2006-03-27 06:49:03 +00:00
parent 406830baf5
commit 722f647186
2 changed files with 54 additions and 60 deletions

View 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*

View File

@ -1031,37 +1031,6 @@ u_scanf_pointer_handler(UFILE *input,
len = ufmt_min(len, info->fWidth);
}
#ifdef OS400
/* TODO: Fix this code so that it will work on all platforms */
{
int64_t result[2];
int32_t lenOrig = len;
/* Make sure that we don't consume too much */
if (len > (int32_t)(sizeof(int64_t)*2)) {
len = (int32_t)(sizeof(int64_t)*2);
}
/* parse the pointer - set first half of big endian pointer */
result[0] = (int64_t)ufmt_utop(input->str.fPos, &len);
/* update the input's position to reflect consumed data */
input->str.fPos += len;
len = lenOrig - len;
/* Make sure that we don't consume too much */
if (len > (int32_t)(sizeof(int64_t)*2)) {
len = (int32_t)(sizeof(int64_t)*2);
}
/* parse the pointer - set second half of big endian pointer */
result[1] = (int64_t)ufmt_utop(input->str.fPos, &len);
if (!info->fSkipArg) {
p = *((void **)result);
}
}
#else
/* Make sure that we don't consume too much */
if (len > (int32_t)(sizeof(void*)*2)) {
len = (int32_t)(sizeof(void*)*2);
@ -1074,8 +1043,6 @@ u_scanf_pointer_handler(UFILE *input,
*p = result;
}
#endif
/* update the input's position to reflect consumed data */
input->str.fPos += len;