static int32_t u_scanf_integer_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { int32_t len; 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 */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) len = ufmt_min(len, info->fWidth); /* get the formatter */ format = u_locbund_getNumberFormat(&input->str.fBundle, UNUM_DECIMAL); /* handle error */ 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); /* mask off any necessary bits */ if (!info->fSkipArg) { if (info->fIsShort) *(int16_t*)num = (int16_t)(UINT16_MAX & result); else if (info->fIsLongLong) *(int64_t*)num = result; else *(int32_t*)num = (int32_t)(UINT32_MAX & result); } /* update the input's position to reflect consumed data */ input->str.fPos += parsePos; /* we converted 1 arg */ *argConverted = !info->fSkipArg; return parsePos + skipped; }
/* copies the minimum number of code units of (count or output->available) */ static int32_t u_minstrncpy(u_localized_string *output, const UChar *str, int32_t count) { int32_t size = ufmt_min(count, output->available); u_strncpy(output->str + (output->len - output->available), str, size); output->available -= size; return size; }
static int32_t u_scanf_spellout_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { int32_t len; double num; UNumberFormat *format; int32_t parsePos = 0; int32_t skipped; UErrorCode status = U_ZERO_ERROR; /* skip all ws in the input */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) len = ufmt_min(len, info->fWidth); /* get the formatter */ format = u_locbund_getNumberFormat(&input->str.fBundle, UNUM_SPELLOUT); /* handle error */ 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); if (!info->fSkipArg) { *(double*)(args[0].ptrValue) = num; } /* mask off any necessary bits */ /* if(! info->fIsLong_double) num &= DBL_MAX;*/ /* update the input's position to reflect consumed data */ input->str.fPos += parsePos; /* we converted 1 arg */ *argConverted = !info->fSkipArg; return parsePos + skipped; }
static int32_t u_scanf_hex_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { int32_t len; int32_t skipped; void *num = (void*) (args[0].ptrValue); int64_t result; /* skip all ws in the input */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) len = ufmt_min(len, info->fWidth); /* check for alternate form */ if( *(input->str.fPos) == 0x0030 && (*(input->str.fPos + 1) == 0x0078 || *(input->str.fPos + 1) == 0x0058) ) { /* skip the '0' and 'x' or 'X' if present */ input->str.fPos += 2; len -= 2; } /* parse the number */ result = ufmt_uto64(input->str.fPos, &len, 16); /* update the input's position to reflect consumed data */ input->str.fPos += len; /* mask off any necessary bits */ if (!info->fSkipArg) { if (info->fIsShort) *(int16_t*)num = (int16_t)(UINT16_MAX & result); else if (info->fIsLongLong) *(int64_t*)num = result; else *(int32_t*)num = (int32_t)(UINT32_MAX & result); } /* we converted 1 arg */ *argConverted = !info->fSkipArg; return len + skipped; }
/* u_minstrncpy copies the minimum number of code units of (count or output->available) */ static int32_t u_sprintf_write(void *context, const UChar *str, int32_t count) { u_localized_print_string *output = (u_localized_print_string *)context; int32_t size = ufmt_min(count, output->available); u_strncpy(output->str + (output->len - output->available), str, size); output->available -= size; return size; }
static int32_t u_sprintf_pad_and_justify(void *context, const u_printf_spec_info *info, const UChar *result, int32_t resultLen) { u_localized_print_string *output = (u_localized_print_string *)context; int32_t written = 0; int32_t lengthOfResult = resultLen; resultLen = ufmt_min(resultLen, output->available); /* pad and justify, if needed */ if(info->fWidth != -1 && resultLen < info->fWidth) { int32_t paddingLeft = info->fWidth - resultLen; int32_t outputPos = output->len - output->available; if (paddingLeft + resultLen > output->available) { paddingLeft = output->available - resultLen; if (paddingLeft < 0) { paddingLeft = 0; } /* paddingLeft = output->available - resultLen;*/ } written += paddingLeft; /* left justify */ if(info->fLeft) { written += u_sprintf_write(output, result, resultLen); u_memset(&output->str[outputPos + resultLen], info->fPadChar, paddingLeft); output->available -= paddingLeft; } /* right justify */ else { u_memset(&output->str[outputPos], info->fPadChar, paddingLeft); output->available -= paddingLeft; written += u_sprintf_write(output, result, resultLen); } } /* just write the formatted output */ else { written = u_sprintf_write(output, result, resultLen); } if (written >= 0 && lengthOfResult > written) { return lengthOfResult; } return written; }
static int32_t u_scanf_pointer_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { int32_t len; int32_t skipped; void *result; void **p = (void**)(args[0].ptrValue); /* skip all ws in the input */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) { len = ufmt_min(len, info->fWidth); } /* Make sure that we don't consume too much */ if (len > (int32_t)(sizeof(void*)*2)) { len = (int32_t)(sizeof(void*)*2); } /* parse the pointer - assign to temporary value */ result = ufmt_utop(input->str.fPos, &len); if (!info->fSkipArg) { *p = result; } /* update the input's position to reflect consumed data */ input->str.fPos += len; /* we converted 1 arg */ *argConverted = !info->fSkipArg; return len + skipped; }
/* private function used for buffering input */ void ufile_fill_uchar_buffer(UFILE *f) { UErrorCode status; const char *mySource; const char *mySourceEnd; UChar *myTarget; int32_t bufferSize; int32_t maxCPBytes; int32_t bytesRead; int32_t availLength; int32_t dataSize; /* shift the buffer if it isn't empty */ dataSize = (int32_t)(f->fUCLimit - f->fUCPos); if(dataSize != 0) { memmove(f->fUCBuffer, f->fUCPos, dataSize * sizeof(UChar)); } /* record how much buffer space is available */ availLength = UFILE_UCHARBUFFER_SIZE - dataSize; /* Determine the # of codepage bytes needed to fill our UChar buffer */ /* weiv: if converter is NULL, we use invariant converter with charwidth = 1)*/ maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1); /* Read in the data to convert */ bytesRead = (int32_t)fread(f->fCharBuffer, sizeof(char), ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile); /* Set up conversion parameters */ status = U_ZERO_ERROR; mySource = f->fCharBuffer; mySourceEnd = f->fCharBuffer + bytesRead; myTarget = f->fUCBuffer + dataSize; bufferSize = UFILE_UCHARBUFFER_SIZE; if(f->fConverter != NULL) { /* We have a valid converter */ /* Perform the conversion */ ucnv_toUnicode(f->fConverter, &myTarget, f->fUCBuffer + bufferSize, &mySource, mySourceEnd, NULL, (UBool)(feof(f->fFile) != 0), &status); } else { /*weiv: do the invariant conversion */ u_charsToUChars(mySource, myTarget, bytesRead); myTarget += bytesRead; } /* update the pointers into our array */ f->fUCPos = f->fUCBuffer; f->fUCLimit = myTarget; }
/* private function used for buffering input */ void ufile_fill_uchar_buffer(UFILE *f) { UErrorCode status; const char *mySource; const char *mySourceEnd; UChar *myTarget; int32_t bufferSize; int32_t maxCPBytes; int32_t bytesRead; int32_t availLength; int32_t dataSize; char charBuffer[UFILE_CHARBUFFER_SIZE]; u_localized_string *str; if (f->fFile == NULL) { /* There is nothing to do. It's a string. */ return; } str = &f->str; dataSize = (int32_t)(str->fLimit - str->fPos); if (f->fFileno == 0 && dataSize > 0) { /* Don't read from stdin too many times. There is still some data. */ return; } /* shift the buffer if it isn't empty */ if(dataSize != 0) { uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar)); } /* record how much buffer space is available */ availLength = UFILE_UCHARBUFFER_SIZE - dataSize; /* Determine the # of codepage bytes needed to fill our UChar buffer */ /* weiv: if converter is NULL, we use invariant converter with charwidth = 1)*/ maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1); /* Read in the data to convert */ if (f->fFileno == 0) { /* Special case. Read from stdin one line at a time. */ char *retStr = fgets(charBuffer, ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile); bytesRead = (int32_t)(retStr ? uprv_strlen(charBuffer) : 0); } else { /* A normal file */ bytesRead = (int32_t)fread(charBuffer, sizeof(char), ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile); } /* Set up conversion parameters */ status = U_ZERO_ERROR; mySource = charBuffer; mySourceEnd = charBuffer + bytesRead; myTarget = f->fUCBuffer + dataSize; bufferSize = UFILE_UCHARBUFFER_SIZE; if(f->fConverter != NULL) { /* We have a valid converter */ /* Perform the conversion */ ucnv_toUnicode(f->fConverter, &myTarget, f->fUCBuffer + bufferSize, &mySource, mySourceEnd, NULL, (UBool)(feof(f->fFile) != 0), &status); } else { /*weiv: do the invariant conversion */ u_charsToUChars(mySource, myTarget, bytesRead); myTarget += bytesRead; } /* update the pointers into our array */ str->fPos = str->fBuffer; str->fLimit = myTarget; }
U_CFUNC int32_t U_EXPORT2 u_file_write_flush(const UChar *chars, int32_t count, UFILE *f, UBool flushIO, UBool flushTranslit) { /* Set up conversion parameters */ UErrorCode status = U_ZERO_ERROR; const UChar *mySource = chars; const UChar *mySourceBegin; const UChar *mySourceEnd; char charBuffer[UFILE_CHARBUFFER_SIZE]; char *myTarget = charBuffer; int32_t written = 0; int32_t numConverted = 0; if (count < 0) { count = u_strlen(chars); } #if !UCONFIG_NO_TRANSLITERATION if((f->fTranslit) && (f->fTranslit->translit)) { /* Do the transliteration */ mySource = u_file_translit(f, chars, &count, flushTranslit); } #endif /* Write to a string. */ if (!f->fFile) { int32_t charsLeft = (int32_t)(f->str.fLimit - f->str.fPos); if (flushIO && charsLeft > count) { count++; } written = ufmt_min(count, charsLeft); u_strncpy(f->str.fPos, mySource, written); f->str.fPos += written; return written; } mySourceEnd = mySource + count; /* Perform the conversion in a loop */ do { mySourceBegin = mySource; /* beginning location for this loop */ status = U_ZERO_ERROR; if(f->fConverter != NULL) { /* We have a valid converter */ ucnv_fromUnicode(f->fConverter, &myTarget, charBuffer + UFILE_CHARBUFFER_SIZE, &mySource, mySourceEnd, NULL, flushIO, &status); } else { /*weiv: do the invariant conversion */ int32_t convertChars = (int32_t) (mySourceEnd - mySource); if (convertChars > UFILE_CHARBUFFER_SIZE) { convertChars = UFILE_CHARBUFFER_SIZE; status = U_BUFFER_OVERFLOW_ERROR; } u_UCharsToChars(mySource, myTarget, convertChars); mySource += convertChars; myTarget += convertChars; } numConverted = (int32_t)(myTarget - charBuffer); if (numConverted > 0) { /* write the converted bytes */ fwrite(charBuffer, sizeof(char), numConverted, f->fFile); written += (int32_t) (mySource - mySourceBegin); } myTarget = charBuffer; } while(status == U_BUFFER_OVERFLOW_ERROR); /* return # of chars written */ return written; }
static int32_t u_scanf_scidbl_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { 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; /* since we can't determine by scanning the characters whether */ /* a number was formatted in the 'f' or 'g' styles, parse the */ /* string with both formatters, and assume whichever one */ /* parsed the most is the correct formatter to use */ /* skip all ws in the input */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) len = ufmt_min(len, info->fWidth); /* get the formatters */ scientificFormat = u_locbund_getNumberFormat(&input->str.fBundle, UNUM_SCIENTIFIC); genericFormat = u_locbund_getNumberFormat(&input->str.fBundle, UNUM_DECIMAL); /* handle error */ 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, &scientificParsePos, &scientificStatus); genericResult = unum_parseDouble(genericFormat, input->str.fPos, len, &genericParsePos, &genericStatus); /* determine which parse made it farther */ if(scientificParsePos > genericParsePos) { /* stash the result in num */ num = scientificResult; /* update the input's position to reflect consumed data */ parsePos += scientificParsePos; } else { /* stash the result in num */ num = genericResult; /* update the input's position to reflect consumed data */ parsePos += genericParsePos; } input->str.fPos += parsePos; if (!info->fSkipArg) { 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 */ /* if(! info->fIsLong_double) num &= DBL_MAX;*/ /* we converted 1 arg */ *argConverted = !info->fSkipArg; return parsePos + skipped; }
static int32_t u_scanf_scientific_handler(UFILE *input, u_scanf_spec_info *info, ufmt_args *args, const UChar *fmt, int32_t *fmtConsumed, int32_t *argConverted) { int32_t len; 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 */ 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 = (int32_t)(input->str.fLimit - input->str.fPos); /* truncate to the width, if specified */ if(info->fWidth != -1) len = ufmt_min(len, info->fWidth); /* get the formatter */ format = u_locbund_getNumberFormat(&input->str.fBundle, UNUM_SCIENTIFIC); /* handle error */ 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) { 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 */ /* if(! info->fIsLong_double) num &= DBL_MAX;*/ /* update the input's position to reflect consumed data */ input->str.fPos += parsePos; /* we converted 1 arg */ *argConverted = !info->fSkipArg; return parsePos + skipped; }