Current section

Files

Jump to
jaxon c_src decoder.h
Raw

c_src/decoder.h

#include <stddef.h>
#include <stdint.h>
typedef enum {
UNDEFINED,
START_OBJECT,
END_OBJECT,
START_ARRAY,
END_ARRAY,
KEY,
COLON,
COMMA,
STRING,
INTEGER,
DECIMAL,
BOOLEAN,
NIL,
SYNTAX_ERROR,
INCOMPLETE,
INCOMPLETE_INTEGER,
INCOMPLETE_DECIMAL,
END
} json_event_type_t;
typedef struct {
const uint8_t* buffer;
size_t size;
size_t escapes;
} string_t;
typedef struct {
json_event_type_t expected[5];
unsigned char* context;
} syntax_error_t;
typedef union {
string_t string;
long int integer;
double decimal;
short boolean;
syntax_error_t syntax_error;
} json_event_value_t;
typedef struct {
json_event_type_t type;
json_event_value_t value;
json_event_value_t secondary_value;
} json_event_t;
typedef struct {
const uint8_t* buffer;
const uint8_t* cursor;
const uint8_t* last_token;
size_t buffer_length;
} decoder_t;
void make_decoder(decoder_t* d);
void update_decoder_buffer(decoder_t* d, unsigned char* buf, size_t length);
void decode(decoder_t* d, json_event_t* e);
const uint8_t* unescape_unicode(const uint8_t*, uint8_t*, const uint8_t*);
static inline const char* event_type_to_string(json_event_type_t type) {
switch (type) {
case STRING:
return "string";
case INTEGER:
return "integer";
case DECIMAL:
return "decimal";
case BOOLEAN:
return "boolean";
case NIL:
return "null";
case START_OBJECT:
return "start_object";
case START_ARRAY:
return "start_array";
case END_OBJECT:
return "end_object";
case END_ARRAY:
return "end_array";
case KEY:
return "key";
case UNDEFINED:
return "undefined";
case INCOMPLETE:
return "incomplete";
case INCOMPLETE_DECIMAL:
return "incomplete decimal";
case INCOMPLETE_INTEGER:
return "incomplete integer";
case END:
return "end";
case SYNTAX_ERROR:
return "syntax_error";
case COMMA:
return "comma";
case COLON:
return ":";
}
}
static inline const int32_t hex_byte_to_i32(const char in) {
int8_t c = -1;
if(in <= '9') {
c = (in - '0');
} else if (in >= 'A' && in <= 'F') {
c = (in - 'A') + 10;
} else if (in >= 'a' && in <= 'f') {
c = (in - 'a') + 10;
}
return (int32_t)c;
}
static inline const size_t u32_size(const uint32_t in) {
size_t num = 1;
if(in >= 0x10000) {
num = 4;
} else if(in >= 0x800) {
num = 3;
} else if(in >= 0x80) {
num = 2;
}
return num;
}
#define is_utf8(c) (((c) > 0x7f))
static inline const size_t u32_to_utf8(uint32_t in, uint8_t *out) {
const size_t num = u32_size(in);
out[0] = (in >> ((num - 1)*6));
out[0] |= (0xff << (8 - num) & 0xff) * is_utf8(in);
for(size_t i = 1; i < num; ++i) {
out[i] = 0x80 + ((in >> ((num-i-1)*6)) & 0x3f);
}
return num;
}