DMS-Parser-XS
view release on metacpan or search on metacpan
/* Post-process exponent. */
char out[64];
int oi = 0;
int has_dot_or_e = 0;
for (int i = 0; i < chosen_n; i++) {
char c = buf[i];
if (c == '.') has_dot_or_e = 1;
if (c == 'e' || c == 'E') {
has_dot_or_e = 1;
out[oi++] = c;
i++;
int sign = 1;
if (i < chosen_n && buf[i] == '+') { i++; }
else if (i < chosen_n && buf[i] == '-') { sign = -1; i++; }
/* skip leading zeros */
while (i < chosen_n && buf[i] == '0') i++;
if (i >= chosen_n || buf[i] < '0' || buf[i] > '9') {
/* exponent collapsed to zero â drop it */
/* Pop the 'e' we already wrote. */
oi--;
continue;
}
if (sign < 0) out[oi++] = '-';
while (i < chosen_n) out[oi++] = buf[i++];
break;
}
out[oi++] = c;
}
if (!has_dot_or_e) {
out[oi++] = '.';
out[oi++] = '0';
}
jbuf_puts(j, out, (size_t)oi);
}
static void emit_value(jbuf *j, const dms_value *v, int indent);
/* Emit a tagged scalar:
* {
* "type": "<t>",
* "value": "<v>"
* }
* with the same indentation rules as encoder.pl. */
static void emit_tagged(jbuf *j, const char *type, int indent,
void (*write_value)(jbuf *, const dms_value *),
const dms_value *v) {
jbuf_puts(j, "{\n", 2);
jbuf_indent(j, indent + 1);
jbuf_puts(j, "\"type\": \"", 9);
jbuf_putcstr(j, type);
jbuf_puts(j, "\",\n", 3);
jbuf_indent(j, indent + 1);
jbuf_puts(j, "\"value\": \"", 10);
write_value(j, v);
jbuf_puts(j, "\"\n", 2);
jbuf_indent(j, indent);
jbuf_putc(j, '}');
}
/* write_value callbacks â write the inner string of a tagged scalar
* (no surrounding quotes; the caller already wrote them). */
static void wv_bool(jbuf *j, const dms_value *v) {
jbuf_putcstr(j, v->u.b ? "true" : "false");
}
static void wv_int(jbuf *j, const dms_value *v) {
jbuf_int64(j, v->u.i);
}
static void wv_float(jbuf *j, const dms_value *v) {
jbuf_float(j, v->u.f);
}
/* Datetime values: stored as a UTF-8 NUL-terminated string in v->u.s.
* No JSON escaping is needed (datetime/date/time strings are ASCII), but
* for safety we run them through the same escape code as other strings. */
static void wv_str_escape(jbuf *j, const dms_value *v) {
const char *s = v->u.s ? v->u.s : "";
for (const char *p = s; *p; p++) {
unsigned char c = (unsigned char)*p;
switch (c) {
case '"': jbuf_puts(j, "\\\"", 2); break;
case '\\': jbuf_puts(j, "\\\\", 2); break;
case '\n': jbuf_puts(j, "\\n", 2); break;
case '\r': jbuf_puts(j, "\\r", 2); break;
case '\t': jbuf_puts(j, "\\t", 2); break;
case '\b': jbuf_puts(j, "\\b", 2); break;
case '\f': jbuf_puts(j, "\\f", 2); break;
default:
if (c < 0x20) {
char tmp[8];
int k = snprintf(tmp, sizeof(tmp), "\\u%04x", c);
jbuf_puts(j, tmp, (size_t)k);
} else {
jbuf_putc(j, (char)c);
}
}
}
}
static void emit_value(jbuf *j, const dms_value *v, int indent) {
switch (v->type) {
case DMS_BOOL:
emit_tagged(j, "bool", indent, wv_bool, v); return;
case DMS_INTEGER:
emit_tagged(j, "integer", indent, wv_int, v); return;
case DMS_FLOAT:
emit_tagged(j, "float", indent, wv_float, v); return;
case DMS_STRING:
emit_tagged(j, "string", indent, wv_str_escape, v); return;
case DMS_OFFSET_DT:
emit_tagged(j, "offset-datetime", indent, wv_str_escape, v); return;
case DMS_LOCAL_DT:
emit_tagged(j, "local-datetime", indent, wv_str_escape, v); return;
case DMS_LOCAL_DATE:
emit_tagged(j, "local-date", indent, wv_str_escape, v); return;
case DMS_LOCAL_TIME:
emit_tagged(j, "local-time", indent, wv_str_escape, v); return;
case DMS_TABLE: {
if (v->u.t.len == 0) { jbuf_puts(j, "{}", 2); return; }
( run in 0.555 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )