#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "config.h"
#include "buf.h"
#include "ktable.h"
#include "capture.h"
#include "json.h"
#define UNUSED(x) (void)(x)
static const char *char2escape[256] = {
"\\u0000", "\\u0001", "\\u0002", "\\u0003",
"\\u0004", "\\u0005", "\\u0006", "\\u0007",
"\\b", "\\t", "\\n", "\\u000b",
"\\f", "\\r", "\\u000e", "\\u000f",
"\\u0010", "\\u0011", "\\u0012", "\\u0013",
"\\u0014", "\\u0015", "\\u0016", "\\u0017",
"\\u0018", "\\u0019", "\\u001a", "\\u001b",
"\\u001c", "\\u001d", "\\u001e", "\\u001f",
NULL, NULL, "\\\"", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "\\\\", NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\u007f",
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int addlstring_json(Buffer *buf, const char *string, size_t len)
{
assert( sizeof(char2escape) == 256 * sizeof(char *) );
static const char dquote = '\"';
const char *escstr;
size_t esclen;
char c;
size_t i;
buf_prepsize(buf, 2 + 6*len);
buf_addchar_UNSAFE(buf, dquote);
for (i = 0; i < len; i++) {
c = string[i];
if ((c=='\"') || (c=='\\') || (c>0 && c<32) || (c==127)) {
escstr = char2escape[(unsigned char)c];
esclen = strlen(escstr);
buf_addlstring_UNSAFE(buf, escstr, esclen);
}
else buf_addchar_UNSAFE(buf, c);
}
buf_addchar(buf, dquote);
return MATCH_OK;
}
static void json_encode_pos(size_t pos, Buffer *buf) {
char nb[MAXNUMBER2STR];
size_t len;
len = r_inttostring(nb, (int) pos);
buf_addlstring(buf, nb, len);
}
static void json_encode_ktable_element(CapState *cs, Buffer *buf) {
size_t len;
const char *name = ktable_element_name(cs->kt, capidx(cs->cap), &len);
buf_addlstring(buf, name, len);
}
int json_Close(CapState *cs, Buffer *buf, int count, const char *start) {
size_t e;
UNUSED(count);
if (isopencap(cs->cap)) return MATCH_CLOSE_ERROR;
e = cs->cap->s - cs->s + 1;
if (!isopencap(cs->cap-1)) buf_addstring(buf, "]");
buf_addstring(buf, END_LABEL);
json_encode_pos(e, buf);
if (capkind(cs->cap) == Ccloseconst) {
buf_addstring(buf, DATA_LABEL);
buf_addstring(buf, "\"");
json_encode_ktable_element(cs, buf);
buf_addstring(buf, "\"");
} else {
assert(start);
buf_addstring(buf, DATA_LABEL);
int err = addlstring_json(buf, start, cs->cap->s - start);
if (err != MATCH_OK) return err;
}
buf_addstring(buf, "}");
return MATCH_OK;
}
int json_Open(CapState *cs, Buffer *buf, int count) {
size_t s;
if (!acceptable_capture(capkind(cs->cap))) {
printf("%s:%d: capkind is %d\n", __FILE__, __LINE__, capkind(cs->cap));
return MATCH_OPEN_ERROR;
}
if (count) buf_addstring(buf, ",");
buf_addstring(buf, TYPE_LABEL);
json_encode_ktable_element(cs, buf);
buf_addstring(buf, "\"");
s = cs->cap->s - cs->s + 1;
buf_addstring(buf, START_LABEL);
json_encode_pos(s, buf);
if (isopencap(cs->cap+1)) buf_addstring(buf, COMPONENT_LABEL);
return MATCH_OK;
}