static CborError value_to_json()

in encoding/tinycbor/src/cbortojson.c [490:645]


static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status)
{
    CborError err;
    status->flags = 0;

    switch (type) {
    case CborArrayType:
    case CborMapType: {
        /* recursive type */
        CborValue recursed;
        err = cbor_value_enter_container(it, &recursed);
        if (err) {
            it->offset = recursed.offset;
            return err;       /* parse error */
        }
        if (fputc(type == CborArrayType ? '[' : '{', out) < 0)
            return CborErrorIO;

        err = (type == CborArrayType) ?
                  array_to_json(out, &recursed, flags, status) :
                  map_to_json(out, &recursed, flags, status);
        if (err) {
            it->offset = recursed.offset;
            return err;       /* parse error */
        }

        if (fputc(type == CborArrayType ? ']' : '}', out) < 0)
            return CborErrorIO;
        err = cbor_value_leave_container(it, &recursed);
        if (err)
            return err;       /* parse error */

        status->flags = 0;    /* reset, there are never conversion errors for us */
        return CborNoError;
    }

    case CborIntegerType: {
        double num;     /* JS numbers are IEEE double precision */
        uint64_t val;
        cbor_value_get_raw_integer(it, &val);    /* can't fail */
        num = (double)val;

        if (cbor_value_is_negative_integer(it)) {
            num = -num - 1;                     /* convert to negative */
            if ((uint64_t)(-num - 1) != val) {
                status->flags = NumberPrecisionWasLost | NumberWasNegative;
                status->originalNumber = val;
            }
        } else {
            if ((uint64_t)num != val) {
                status->flags = NumberPrecisionWasLost;
                status->originalNumber = val;
            }
        }
        if (fprintf(out, "%.0f", num) < 0)  /* this number has no fraction, so no decimal points please */
            return CborErrorIO;
        break;
    }

    case CborByteStringType:
    case CborTextStringType: {
        char *str;
        if (type == CborByteStringType) {
            err = dump_bytestring_base64url(&str, it);
            status->flags = TypeWasNotNative;
        } else {
            size_t n = 0;
            err = cbor_value_dup_text_string(it, &str, &n, it);
        }
        if (err)
            return err;
        err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError;
        free(str);
        return err;
    }

    case CborTagType:
        return tagged_value_to_json(out, it, flags, status);

    case CborSimpleType: {
        uint8_t simple_type;
        cbor_value_get_simple_type(it, &simple_type);  /* can't fail */
        status->flags = TypeWasNotNative;
        status->originalNumber = simple_type;
        if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0)
            return CborErrorIO;
        break;
    }

    case CborNullType:
        if (fprintf(out, "null") < 0)
            return CborErrorIO;
        break;

    case CborUndefinedType:
        status->flags = TypeWasNotNative;
        if (fprintf(out, "\"undefined\"") < 0)
            return CborErrorIO;
        break;

    case CborBooleanType: {
        bool val;
        cbor_value_get_boolean(it, &val);       /* can't fail */
        if (fprintf(out, val ? "true" : "false") < 0)
            return CborErrorIO;
        break;
    }
#if FLOAT_SUPPORT
    case CborDoubleType: {
        double val;
        if (false) {
            float f;
    case CborFloatType:
            status->flags = TypeWasNotNative;
            cbor_value_get_float(it, &f);
            val = f;
        } else if (false) {
            uint16_t f16;
    case CborHalfFloatType:
            status->flags = TypeWasNotNative;
            cbor_value_get_half_float(it, &f16);
            val = decode_half(f16);
        } else {
            cbor_value_get_double(it, &val);
        }

        int r = fpclassify(val);
        if (r == FP_NAN || r == FP_INFINITE) {
            if (fprintf(out, "null") < 0)
                return CborErrorIO;
            status->flags |= r == FP_NAN ? NumberWasNaN :
                                           NumberWasInfinite | (val < 0 ? NumberWasNegative : 0);
        } else {
            uint64_t ival = (uint64_t)fabs(val);
            if ((double)ival == fabs(val)) {
                /* print as integer so we get the full precision */
                r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival);
                status->flags |= TypeWasNotNative;   /* mark this integer number as a double */
            } else {
                /* this number is definitely not a 64-bit integer */
                r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val);
            }
            if (r < 0)
                return CborErrorIO;
        }
        break;
    }
#endif

    case CborInvalidType:
    default:
        return CborErrorUnknownType;
    }

    return cbor_value_advance_fixed(it);
}