static Variant HHVM_METHOD(NumberFormatter, parse, const String& value, int64_t type, VRefParam position) { NUMFMT_GET(obj, this_, false); UErrorCode error = U_ZERO_ERROR; icu::UnicodeString val(u16(value, error)); NUMFMT_CHECK(obj, error, false); Variant ret; int32_t pos = position.toInt64(); error = U_ZERO_ERROR; switch (type) { case UNUM(TYPE_INT32): ret = unum_parse(obj->formatter(), val.getBuffer(), val.length(), &pos, &error); break; case UNUM(TYPE_INT64): ret = unum_parseInt64(obj->formatter(), val.getBuffer(), val.length(), &pos, &error); break; case UNUM(TYPE_DOUBLE): ret = unum_parseDouble(obj->formatter(), val.getBuffer(), val.length(), &pos, &error); break; default: obj->setError(U_UNSUPPORTED_ERROR); return false; } NUMFMT_CHECK(obj, error, false); position = pos; return ret; }
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; }