int spb_read_header(binstream_t *stream, geom_blob_header_t *spb, errorstream_t *error) {
    uint8_t start;
    if (binstream_read_u8(stream, &start) != SQLITE_OK) {
        return SQLITE_IOERR;
    }

    if (start != 0x00) {
        if (error) {
            error_append(error, "Incorrect SPB START value [expected: 00, actual:%x]", start);
        }
        return SQLITE_IOERR;
    }

    uint8_t endian;
    if (binstream_read_u8(stream, &endian)) {
        return SQLITE_IOERR;
    }

    if (endian != SPB_BIG_ENDIAN && endian != SPB_LITTLE_ENDIAN) {
        if (error) {
            error_append(error, "Incorrect SPB ENDIAN value [expected: 00 or 01, actual:%x]", endian);
        }
        return SQLITE_IOERR;
    }

    binstream_set_endianness(stream, endian == SPB_BIG_ENDIAN ? BIG : LITTLE);
    if (binstream_read_i32(stream, &spb->srid) != SQLITE_OK) {
        return SQLITE_IOERR;
    }

    spb->envelope.has_env_x = 1;
    spb->envelope.has_env_y = 1;
    spb->envelope.has_env_z = 0;
    spb->envelope.has_env_m = 0;
    if (binstream_read_double(stream, &spb->envelope.min_x)) {
        return SQLITE_IOERR;
    }
    if (binstream_read_double(stream, &spb->envelope.min_y)) {
        return SQLITE_IOERR;
    }
    if (binstream_read_double(stream, &spb->envelope.max_x)) {
        return SQLITE_IOERR;
    }
    if (binstream_read_double(stream, &spb->envelope.max_y)) {
        return SQLITE_IOERR;
    }

    spb->empty = fp_isnan(spb->envelope.min_x) && fp_isnan(spb->envelope.max_x) && fp_isnan(spb->envelope.min_y) && fp_isnan(spb->envelope.max_y);

    CHECK_ENV(spb, error)

    return SQLITE_OK;
}
Beispiel #2
0
int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) {

    char *s = buf;

    if (buf_size <= FPMIN_BUF_SIZE) {
        // FPMIN_BUF_SIZE is the minimum size needed to store any FP number.
        // If the buffer does not have enough room for this (plus null terminator)
        // then don't try to format the float.

        if (buf_size >= 2) {
            *s++ = '?';
        }
        if (buf_size >= 1) {
            *s++ = '\0';
        }
        return buf_size >= 2;
    }
    if (fp_signbit(f)) {
        *s++ = '-';
        f = -f;
    } else {
        if (sign) {
            *s++ = sign;
        }
    }

    // buf_remaining contains bytes available for digits and exponent.
    // It is buf_size minus room for the sign and null byte.
    int buf_remaining = buf_size - 1 - (s - buf);

    if (fp_isspecial(f)) {
        char uc = fmt & 0x20;
        if (fp_isinf(f)) {
            *s++ = 'I' ^ uc;
            *s++ = 'N' ^ uc;
            *s++ = 'F' ^ uc;
            goto ret;
        } else if (fp_isnan(f)) {
            *s++ = 'N' ^ uc;
            *s++ = 'A' ^ uc;
            *s++ = 'N' ^ uc;
        ret:
            *s = '\0';
            return s - buf;
        }
    }

    if (prec < 0) {
        prec = 6;
    }
    char e_char = 'E' | (fmt & 0x20);   // e_char will match case of fmt
    fmt |= 0x20; // Force fmt to be lowercase
    char org_fmt = fmt;
    if (fmt == 'g' && prec == 0) {
        prec = 1;
    }
    int e, e1; 
    int dec = 0;
    char e_sign = '\0';
    int num_digits = 0;
    const FPTYPE *pos_pow = g_pos_pow;
    const FPTYPE *neg_pow = g_neg_pow;

    if (fp_iszero(f)) {
        e = 0;
        if (fmt == 'f') {
            // Truncate precision to prevent buffer overflow
            if (prec + 2 > buf_remaining) {
                prec = buf_remaining - 2;
            }
            num_digits = prec + 1;
        } else {
            // Truncate precision to prevent buffer overflow
            if (prec + 6 > buf_remaining) {
                prec = buf_remaining - 6;
            }
            if (fmt == 'e') {
                e_sign = '+';
            }
        }
    } else if (fp_isless1(f)) {
        // We need to figure out what an integer digit will be used
        // in case 'f' is used (or we revert other format to it below).
        // As we just tested number to be <1, this is obviously 0,
        // but we can round it up to 1 below.
        char first_dig = '0';
        if (f >= FPROUND_TO_ONE) {
            first_dig = '1';
        }

        // Build negative exponent
        for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {
            if (*neg_pow > f) {
                e += e1;
                f *= *pos_pow;
            }
        }
        char e_sign_char = '-';
        if (fp_isless1(f) && f >= FPROUND_TO_ONE) {
            f = FPCONST(1.0);
            if (e == 0) {
                e_sign_char = '+';
            }
        } else if (fp_isless1(f)) {
            e++; 
            f *= FPCONST(10.0);
        }

        // If the user specified 'g' format, and e is <= 4, then we'll switch
        // to the fixed format ('f')

        if (fmt == 'f' || (fmt == 'g' && e <= 4)) {
            fmt = 'f';
            dec = -1;
            *s++ = first_dig;

            if (org_fmt == 'g') {
                prec += (e - 1);
            }

            // truncate precision to prevent buffer overflow
            if (prec + 2 > buf_remaining) {
                prec = buf_remaining - 2;
            }

            num_digits = prec;
            if (num_digits) {
                *s++ = '.'; 
                while (--e && num_digits) {
                    *s++ = '0';
                    num_digits--;
                }
            }
        } else {
            // For e & g formats, we'll be printing the exponent, so set the
            // sign.
            e_sign = e_sign_char;
            dec = 0;

            if (prec > (buf_remaining - FPMIN_BUF_SIZE)) {
                prec = buf_remaining - FPMIN_BUF_SIZE;
                if (fmt == 'g') {
                    prec++;
                }
            }
        }
    } else {
        // Build positive exponent
        for (e = 0, e1 = FPDECEXP; e1; e1 >>= 1, pos_pow++, neg_pow++) {