/*
*******************************************************************************
*
-* Copyright (C) 1998-2004, International Business Machines
+* Copyright (C) 1998-2011, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
} u_scanf_info;
#define USCANF_NUM_FMT_HANDLERS 108
+#define USCANF_SYMBOL_BUFFER_SIZE 8
/* We do not use handlers for 0-0x1f */
#define USCANF_BASE_FMT_HANDLERS 0x20
return count;
}
+/* TODO: Is always skipping the prefix symbol as a positive sign a good idea in all locales? */
+static int32_t
+u_scanf_skip_leading_positive_sign(UFILE *input,
+ UNumberFormat *format,
+ UErrorCode *status)
+{
+ UChar c;
+ int32_t count = 0;
+ UBool isNotEOF;
+ UChar plusSymbol[USCANF_SYMBOL_BUFFER_SIZE];
+ int32_t symbolLen;
+ UErrorCode localStatus = U_ZERO_ERROR;
+
+ if (U_SUCCESS(*status)) {
+ symbolLen = unum_getSymbol(format,
+ UNUM_PLUS_SIGN_SYMBOL,
+ plusSymbol,
+ sizeof(plusSymbol)/sizeof(*plusSymbol),
+ &localStatus);
+
+ if (U_SUCCESS(localStatus)) {
+ /* skip all leading ws in the input */
+ while( (isNotEOF = ufile_getch(input, &c)) && (count < symbolLen && c == plusSymbol[count]) )
+ {
+ count++;
+ }
+
+ /* put the final character back on the input */
+ if(isNotEOF) {
+ u_fungetc(c, input);
+ }
+ }
+ }
+
+ return count;
+}
+
static int32_t
u_scanf_simple_percent_handler(UFILE *input,
u_scanf_spec_info *info,
else
*(int32_t*)(args[0].ptrValue) = (int32_t)(UINT32_MAX & info->fWidth);
}
+ *argConverted = 0;
/* we converted 0 args */
return 0;
double num;
UNumberFormat *format;
int32_t parsePos = 0;
+ int32_t skipped;
UErrorCode status = U_ZERO_ERROR;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(format == 0)
return 0;
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ skipped += u_scanf_skip_leading_positive_sign(input, format, &status);
+
/* parse the number */
num = unum_parseDouble(format, input->str.fPos, len, &parsePos, &status);
if (!info->fSkipArg) {
- *(double*)(args[0].ptrValue) = num;
+ if (info->fIsLong)
+ *(double*)(args[0].ptrValue) = num;
+ else if (info->fIsLongDouble)
+ *(long double*)(args[0].ptrValue) = num;
+ else
+ *(float*)(args[0].ptrValue) = (float)num;
}
/* mask off any necessary bits */
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return parsePos;
+ return parsePos + skipped;
}
+#define UPRINTF_SYMBOL_BUFFER_SIZE 8
+
static int32_t
u_scanf_scientific_handler(UFILE *input,
u_scanf_spec_info *info,
double num;
UNumberFormat *format;
int32_t parsePos = 0;
+ int32_t skipped;
UErrorCode status = U_ZERO_ERROR;
+ UChar srcExpBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
+ int32_t srcLen, expLen;
+ UChar expBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(format == 0)
return 0;
+ /* set the appropriate flags on the formatter */
+
+ srcLen = unum_getSymbol(format,
+ UNUM_EXPONENTIAL_SYMBOL,
+ srcExpBuf,
+ sizeof(srcExpBuf),
+ &status);
+
+ /* Upper/lower case the e */
+ if (info->fSpec == (UChar)0x65 /* e */) {
+ expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf),
+ srcExpBuf, srcLen,
+ input->str.fBundle.fLocale,
+ &status);
+ }
+ else {
+ expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf),
+ srcExpBuf, srcLen,
+ input->str.fBundle.fLocale,
+ &status);
+ }
+
+ unum_setSymbol(format,
+ UNUM_EXPONENTIAL_SYMBOL,
+ expBuf,
+ expLen,
+ &status);
+
+
+
+
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ skipped += u_scanf_skip_leading_positive_sign(input, format, &status);
+
/* parse the number */
num = unum_parseDouble(format, input->str.fPos, len, &parsePos, &status);
if (!info->fSkipArg) {
- *(double*)(args[0].ptrValue) = num;
+ if (info->fIsLong)
+ *(double*)(args[0].ptrValue) = num;
+ else if (info->fIsLongDouble)
+ *(long double*)(args[0].ptrValue) = num;
+ else
+ *(float*)(args[0].ptrValue) = (float)num;
}
/* mask off any necessary bits */
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return parsePos;
+ return parsePos + skipped;
}
static int32_t
int32_t *fmtConsumed,
int32_t *argConverted)
{
- int32_t len;
+ int32_t len;
double num;
UNumberFormat *scientificFormat, *genericFormat;
/*int32_t scientificResult, genericResult;*/
double scientificResult, genericResult;
int32_t scientificParsePos = 0, genericParsePos = 0, parsePos = 0;
+ int32_t skipped;
UErrorCode scientificStatus = U_ZERO_ERROR;
UErrorCode genericStatus = U_ZERO_ERROR;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(scientificFormat == 0 || genericFormat == 0)
return 0;
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ skipped += u_scanf_skip_leading_positive_sign(input, genericFormat, &genericStatus);
+
/* parse the number using each format*/
scientificResult = unum_parseDouble(scientificFormat, input->str.fPos, len,
input->str.fPos += parsePos;
if (!info->fSkipArg) {
- *(double*)(args[0].ptrValue) = num;
+ if (info->fIsLong)
+ *(double*)(args[0].ptrValue) = num;
+ else if (info->fIsLongDouble)
+ *(long double*)(args[0].ptrValue) = num;
+ else
+ *(float*)(args[0].ptrValue) = (float)num;
}
/* mask off any necessary bits */
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return parsePos;
+ return parsePos + skipped;
}
static int32_t
void *num = (void*) (args[0].ptrValue);
UNumberFormat *format;
int32_t parsePos = 0;
+ int32_t skipped;
UErrorCode status = U_ZERO_ERROR;
int64_t result;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(format == 0)
return 0;
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ skipped += u_scanf_skip_leading_positive_sign(input, format, &status);
+
/* parse the number */
result = unum_parseInt64(format, input->str.fPos, len, &parsePos, &status);
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return parsePos;
+ return parsePos + skipped;
}
static int32_t
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(format == 0)
return 0;
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ u_scanf_skip_leading_positive_sign(input, format, &status);
+
/* parse the number */
num = unum_parseDouble(format, input->str.fPos, len, &parsePos, &status);
char *limit;
UErrorCode status = U_ZERO_ERROR;
int32_t count;
+ int32_t skipped = 0;
UChar c;
UBool isNotEOF = FALSE;
/* skip all ws in the input */
if (info->fIsString) {
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
}
/* get the string one character at a time, truncating to the width */
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return count;
+ return count + skipped;
}
static int32_t
UChar *arg = (UChar*)(args[0].ptrValue);
UChar *alias = arg;
int32_t count;
+ int32_t skipped = 0;
UChar c;
UBool isNotEOF = FALSE;
/* skip all ws in the input */
if (info->fIsString) {
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
}
/* get the string one character at a time, truncating to the width */
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return count;
+ return count + skipped;
}
static int32_t
double num;
UNumberFormat *format;
int32_t parsePos = 0;
+ int32_t skipped;
UErrorCode status = U_ZERO_ERROR;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
if(format == 0)
return 0;
+ /* Skip the positive prefix. ICU normally can't handle this due to strict parsing. */
+ /* This is not applicable to RBNF. */
+ /*skipped += u_scanf_skip_leading_positive_sign(input, format, &status);*/
+
/* parse the number */
num = unum_parseDouble(format, input->str.fPos, len, &parsePos, &status);
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return parsePos;
+ return parsePos + skipped;
}
static int32_t
int32_t *argConverted)
{
int32_t len;
+ int32_t skipped;
void *num = (void*) (args[0].ptrValue);
int64_t result;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return len;
+ return len + skipped;
}
static int32_t
int32_t *fmtConsumed,
int32_t *argConverted)
{
- int32_t len;
- void *num = (void*) (args[0].ptrValue);
- int64_t result;
+ int32_t len;
+ int32_t skipped;
+ void *num = (void*) (args[0].ptrValue);
+ int64_t result;
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1)
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return len;
+ return len + skipped;
}
static int32_t
int32_t *argConverted)
{
int32_t len;
+ int32_t skipped;
void *result;
void **p = (void**)(args[0].ptrValue);
/* skip all ws in the input */
- u_scanf_skip_leading_ws(input, info->fPadChar);
+ skipped = u_scanf_skip_leading_ws(input, info->fPadChar);
/* fill the input's internal buffer */
ufile_fill_uchar_buffer(input);
/* determine the size of the input's buffer */
- len = input->str.fLimit - input->str.fPos;
+ len = (int32_t)(input->str.fLimit - input->str.fPos);
/* truncate to the width, if specified */
if(info->fWidth != -1) {
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);
*p = result;
}
-#endif
-
/* update the input's position to reflect consumed data */
input->str.fPos += len;
/* we converted 1 arg */
*argConverted = !info->fSkipArg;
- return len;
+ return len + skipped;
}
static int32_t