ConversionResultFlags jstr_to_i64(raw_buffer *str, int64_t *result) { ConversionResultFlags conv_result; CHECK_POINTER_RETURN_VALUE(str->m_str, CONV_BAD_ARGS); CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); conv_result = parseJSONNumber(str, result, NULL, NULL, NULL); if (CONV_HAS_POSITIVE_OVERFLOW(conv_result)) *result = INT64_MAX; else if (CONV_HAS_NEGATIVE_OVERFLOW(conv_result)) *result = INT64_MIN; return conv_result; }
static const char *jvalue_tostring_internal_layer2 (jvalue_ref val, JSchemaInfoRef schemainfo, bool schemaNecessary) { SANITY_CHECK_POINTER(val); CHECK_POINTER_RETURN_VALUE(val, "null"); if (!val->m_toString) { if (schemaNecessary && !jvalue_check_schema(val, schemainfo)) { return NULL; } bool parseok = false; StreamStatus error; JStreamRef generating = jstreamInternal(TOP_None); if (generating == NULL) { return NULL; } parseok = jvalue_to_string_append (val, generating); val->m_toString = generating->finish (generating, &error); val->m_toStringDealloc = free; assert (val->m_toString != NULL); if(!parseok) { return NULL; } } return val->m_toString; }
int dom_number(JSAXContextRef ctxt, const char *number, size_t numberLen) { DomInfo *data = getDOMContext(ctxt); jvalue_ref jnum; CHECK_CONDITION_RETURN_VALUE(data == NULL, 0, "number encountered without any context"); CHECK_CONDITION_RETURN_VALUE(data->m_prev == NULL, 0, "unexpected state - how is this possible?"); CHECK_POINTER_RETURN_VALUE(number, 0); CHECK_CONDITION_RETURN_VALUE(numberLen == 0, 0, "unexpected - numeric string doesn't actually contain a number"); jnum = createOptimalNumber(data->m_optInformation, number, numberLen); if (data->m_value == NULL) { if (UNLIKELY(!jis_array(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_ARR_MISPLACED_NUM", 1, PMLOGKS("NUM", number), "Improper place for number"); j_release(&jnum); return 0; } jarray_append(data->m_prev->m_value, jnum); } else if (jis_string(data->m_value)) { if (UNLIKELY(!jis_object(data->m_prev->m_value))) { PJ_LOG_ERR("PBNJSON_OBJ_MISPLACED_NUM", 1, PMLOGKS("NUM", number), "Improper place for number"); j_release(&jnum); return 0; } jobject_put(data->m_prev->m_value, data->m_value, jnum); data->m_value = NULL; } else { PJ_LOG_ERR("PBNJSON_NUM_VALUE_WO_KEY", 1, PMLOGKS("NUM", number), "value portion of key-value pair without a key"); return 0; } return 1; }
ConversionResultFlags jdouble_to_i32(double value, int32_t *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); if (isnan(value) != 0) { PJ_LOG_WARN("PBNJSON_NAN_TO_INT_WARN", 0, "attempting to convert nan to int"); *result = 0; return CONV_NOT_A_NUM; } switch (isinf(value)) { case 0: break; case 1: PJ_LOG_WARN("PBNJSON_+INF_TO_INT_WARN", 0, "attempting to convert +infinity to int"); *result = PJSON_MAX_INT; return CONV_POSITIVE_INFINITY; case -1: PJ_LOG_WARN("PBNJSON_-INF_TO_INT_WARN", 0, "attempting to convert -infinity to int"); *result = PJSON_MIN_INT; return CONV_NEGATIVE_INFINITY; default: PJ_LOG_ERR("PBNJSON_ISINF_ERR", 1, PMLOGKFV("VALUE", "%lf", value), "unknown result from isinf for %lf", value); return CONV_GENERIC_ERROR; } if (value > PJSON_MAX_INT) { PJ_LOG_WARN("PBNJSON_DBL_OO_INT_RANGE", 1, PMLOGKFV("VALUE", "%lf", value), "attempting to convert double %lf outside of int range", value); *result = PJSON_MAX_INT; return CONV_POSITIVE_OVERFLOW; } if (value < PJSON_MIN_INT) { PJ_LOG_WARN("PBNJSON_DBL_OO_INT_RANGE", 1, PMLOGKFV("VALUE", "%lf", value), "attempting to convert double %lf outside of int range", value); *result = PJSON_MIN_INT; return CONV_NEGATIVE_OVERFLOW; } #if 0 // unnecessary for 32-bits because they will always fit in a double // with no precision loss if (value > PJSON_MAX_INT_IN_DBL || value < PJSON_MIN_INT_IN_DBL) { PJ_LOG_WARN("PBNJSON_DBL_TO_INT_CONV_WARN", 1, PMLOGKFV("VALUE", "%lf", value), "conversion of double %lf to integer potentially has precision loss", value); *result = (int64_t)value; return CONV_PRECISION_LOSS; } #endif *result = (int32_t) value; if (*result != value) { PJ_LOG_WARN("PBNJSON_DBL_TO_INT_CONV_LOSS", 1, PMLOGKFV("VALUE", "%lf", value), "conversion of double %lf results in integer with different value", value); return CONV_PRECISION_LOSS; } return CONV_OK; }
ConversionResultFlags ji64_to_double(int64_t value, double *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); if (value > PJSON_MAX_INT_IN_DBL || value < PJSON_MIN_INT_IN_DBL) { PJ_LOG_WARN("PBNJSON_INT_TO_DBL_CONV_WARN", 1, PMLOGKFV("VALUE", "%"PRId64, value), "conversion of integer %"PRId64 " to a double will result in precision loss when doing reverse", value); *result = (double)value; return CONV_PRECISION_LOSS; } *result = (double)value; return CONV_OK; }
ConversionResultFlags jstr_to_double(raw_buffer *str, double *result) { ConversionResultFlags conv_result; int64_t wholeComponent = 0; int64_t fraction = 0; int64_t fractionLeadingZeros = 0; int64_t exponent = 0; CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); conv_result = parseJSONNumber(str, &wholeComponent, &exponent, &fraction, &fractionLeadingZeros); if (UNLIKELY(CONV_IS_BAD_ARGS(conv_result) || CONV_IS_GENERIC_ERROR(conv_result))) { PJ_LOG_ERR("PBNJSON_STR_TO_NUM_ERR", 1, PMLOGKS("STRING", str->m_str), "Some weird problem converting %.*s to a number: %x", (int)str->m_len, str->m_str, conv_result); assert(false); *result = DBL_QUIET_NAN; } else if (UNLIKELY(CONV_HAS_POSITIVE_INFINITY(conv_result))) { *result = HUGE_VAL; } else if (UNLIKELY(CONV_HAS_NEGATIVE_INFINITY(conv_result))) { *result = -HUGE_VAL; } else { if (CONV_HAS_OVERFLOW(conv_result)) { // overflow that isn't infinity is precision loss assert (CONV_HAS_PRECISION_LOSS(conv_result)); } double calculatedWhole = expBase10(wholeComponent, exponent); double calculatedFraction = copysign(expBase10(fraction, exponent - fractionLeadingZeros), calculatedWhole); *result = calculatedWhole + calculatedFraction; if (isinf(*result)) conv_result |= CONV_POSITIVE_OVERFLOW; else if (-isinf(*result)) conv_result |= CONV_NEGATIVE_OVERFLOW; else if (*result == 0 && fraction != 0) conv_result |= CONV_PRECISION_LOSS; } return conv_result; }
ConversionResultFlags ji32_to_double(int32_t value, double *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); *result = value; return CONV_OK; }
static ConversionResult jdouble_noop(double value, double *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); *result = value; return CONV_OK; }
static ConversionResult ji64_noop(int64_t value, int64_t *result) { CHECK_POINTER_RETURN_VALUE(result, CONV_BAD_ARGS); *result = value; return CONV_OK; }