Add core functionality
This commit is contained in:
parent
eebedd557f
commit
d1f9622cd2
56
src/buffer.c
Normal file
56
src/buffer.c
Normal file
@ -0,0 +1,56 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
static inline void libcjsonp_builtin_write8(buffer_t* x, unsigned char s) {
|
||||
*(x->ptr++) = s;
|
||||
--x->c;
|
||||
}
|
||||
|
||||
static inline void libcjsonp_builtin_wrap8_8(buffer_t* x, unsigned char s) {
|
||||
*(x->ptr++) = '\\';
|
||||
*(x->ptr++) = s;
|
||||
x->c -= 2;
|
||||
}
|
||||
|
||||
static inline void libcjsonp_builtin_wrap8_e16(buffer_t* x, unsigned char s) {
|
||||
*(x->ptr++) = '\\';
|
||||
*(x->ptr++) = 'u';
|
||||
*(x->ptr++) = '0';
|
||||
*(x->ptr++) = '0';
|
||||
|
||||
if ((s&0xf0) < 0xa0) {
|
||||
*(x->ptr++) = 0x30 + (s>>4);
|
||||
} else *(x->ptr++) = 0x57 + (s>>4);
|
||||
|
||||
if ((s&0x0f) < 0x0a) {
|
||||
*(x->ptr++) = 0x30 + (s&0x0f);
|
||||
} else *(x->ptr++) = 0x57 + (s&0x0f);
|
||||
|
||||
x->c -= 6;
|
||||
}
|
||||
|
||||
void libcjsonp_builtin_buffer_write_and_wrap(buffer_t* x, const char* s) {
|
||||
unsigned char* v = (void*)s;
|
||||
|
||||
buffer_check_size(x, 7);
|
||||
libcjsonp_builtin_write8(x, '"');
|
||||
|
||||
while (*v) {
|
||||
if (*v < 0x20 || *v == 0x7f) switch (*v) {
|
||||
case 0x09: libcjsonp_builtin_wrap8_8 (x, 't'); break;
|
||||
case 0x0a: libcjsonp_builtin_wrap8_8 (x, 'n'); break;
|
||||
case 0x0d: libcjsonp_builtin_wrap8_8 (x, 'r'); break;
|
||||
default: libcjsonp_builtin_wrap8_e16(x, *v); break;
|
||||
} else if (*v == '\\') libcjsonp_builtin_wrap8_8(x, '\\');
|
||||
else if (*v == '"') libcjsonp_builtin_wrap8_8(x, '"');
|
||||
else libcjsonp_builtin_write8 (x, *v);
|
||||
|
||||
++v;
|
||||
|
||||
buffer_check_size(x, 6);
|
||||
}
|
||||
|
||||
buffer_write_char(x, '"');
|
||||
}
|
71
src/buffer.h
Normal file
71
src/buffer.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "include.h"
|
||||
|
||||
#ifndef LIBCJSONP_SRC_BUFFER_H
|
||||
#define LIBCJSONP_SRC_BUFFER_H
|
||||
|
||||
#define buffer_block 1024
|
||||
|
||||
typedef struct {
|
||||
char* mem;
|
||||
char* ptr;
|
||||
size_t n;
|
||||
size_t c;
|
||||
} buffer_t;
|
||||
|
||||
static_assert(offsetof(vtype_string, buffer) == offsetof(buffer_t, mem), "Implementation assert");
|
||||
|
||||
#define buffer_write_and_wrap libcjsonp_builtin_buffer_write_and_wrap
|
||||
#define buffer_check_size libcjsonp_builtin_buffer_check_size
|
||||
#define buffer_write_indent libcjsonp_builtin_buffer_write_indent
|
||||
#define buffer_write_char libcjsonp_builtin_buffer_write_char
|
||||
#define buffer_write libcjsonp_builtin_buffer_write
|
||||
|
||||
extern void libcjsonp_builtin_buffer_write_and_wrap(buffer_t* x, const char* s);
|
||||
inline void libcjsonp_builtin_buffer_check_size (buffer_t* x, size_t need) Always_inline__;
|
||||
inline void libcjsonp_builtin_buffer_write_indent (buffer_t* x, indent_t* indent, size_t level) Always_inline__;
|
||||
inline void libcjsonp_builtin_buffer_write_char (buffer_t* x, char c) Always_inline__;
|
||||
inline void libcjsonp_builtin_buffer_write (buffer_t* x, const char* v) Always_inline__;
|
||||
|
||||
inline void libcjsonp_builtin_buffer_check_size(buffer_t* x, size_t need) {
|
||||
while (x->c < need) {
|
||||
x->mem = libcdsb_realloc(x->mem, x->n + buffer_block);
|
||||
x->ptr = x->mem + (x->n - x->c);
|
||||
x->n += buffer_block;
|
||||
x->c += buffer_block;
|
||||
}
|
||||
}
|
||||
|
||||
inline void libcjsonp_builtin_buffer_write_char(buffer_t* x, char c) {
|
||||
|
||||
buffer_check_size(x, 1);
|
||||
|
||||
*(x->ptr++) = c;
|
||||
--x->c;
|
||||
}
|
||||
|
||||
inline void libcjsonp_builtin_buffer_write(buffer_t* x, const char* v) {
|
||||
size_t n = libcdsb_strlen(v);
|
||||
|
||||
buffer_check_size(x, n);
|
||||
|
||||
x->ptr = memcpy(x->ptr, v, n) + n;
|
||||
x->c -= n;
|
||||
}
|
||||
|
||||
inline void libcjsonp_builtin_buffer_write_indent(buffer_t* x, indent_t* indent, size_t level) {
|
||||
|
||||
libcjsonp_builtin_buffer_check_size(x, indent->nmemb * level);
|
||||
|
||||
while (level--) {
|
||||
memcpy(x->ptr, indent->indent, indent->nmemb);
|
||||
x->ptr += indent->nmemb;
|
||||
x->c -= indent->nmemb;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LIBCJSONP_SRC_BUFFER_H */
|
43
src/include.h
Normal file
43
src/include.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../include/jsonp.h"
|
||||
#include "../include/bits/string.h"
|
||||
|
||||
#ifndef LIBCJSONP_SRC_INCLUDE_H
|
||||
#define LIBCJSONP_SRC_INCLUDE_H
|
||||
|
||||
typedef struct {
|
||||
char* indent;
|
||||
size_t nmemb;
|
||||
} indent_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
vtype_bool b;
|
||||
vtype_int8 s8;
|
||||
vtype_int16 s16;
|
||||
vtype_int32 s32;
|
||||
vtype_int64 s64;
|
||||
vtype_uint8 u8;
|
||||
vtype_uint16 u16;
|
||||
vtype_uint32 u32;
|
||||
vtype_uint64 u64;
|
||||
vtype_ldouble ldbl;
|
||||
vtype_map map;
|
||||
vtype_list list;
|
||||
vtype_string str;
|
||||
vtype_pointer ptr;
|
||||
} value[1];
|
||||
|
||||
vtype type;
|
||||
} value_t;
|
||||
|
||||
extern indent_t LIBCJSONP_BUILTIN_WITHOUT_INDENT[1];
|
||||
|
||||
extern const char* libcjsonp_builtin_fetch_number(value_t* x, const char *s, bool is_float);
|
||||
|
||||
|
||||
#endif /* LIBCJSONP_SRC_INCLUDE_H */
|
43
src/memory.c
Normal file
43
src/memory.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "include.h"
|
||||
|
||||
extern const size_t *LIBCDSB_BUILTIN_VTYPE_SIZES;
|
||||
|
||||
indent_t LIBCJSONP_BUILTIN_WITHOUT_INDENT[1] = {{ .indent = 0, .nmemb = 0 }};
|
||||
|
||||
void libcjsonp_json_init(json_t* x, void* v, vtype t, bool attach) {
|
||||
value_t value;
|
||||
|
||||
if (!attach) {
|
||||
switch (t) {
|
||||
default: break;
|
||||
case VTYPE_STRING: string_copy_init((void*)value.value, v); v = value.value; break;
|
||||
case VTYPE_MAP: map_copy_init((void*)value.value, v); v = value.value; break;
|
||||
case VTYPE_ARRAY: array_copy_init((void*)value.value, v); v = value.value; break;
|
||||
case VTYPE_LIST: list_copy_init((void*)value.value, v); v = value.value; break;
|
||||
case VTYPE_SET: vset_copy_init((void*)value.value, v); v = value.value; break;
|
||||
case VTYPE_DICT: dict_copy_init((void*)value.value, v); v = value.value; break;
|
||||
}
|
||||
}
|
||||
|
||||
x->data = libcdsb_memndup(v, LIBCDSB_BUILTIN_VTYPE_SIZES[t]);
|
||||
x->type = t;
|
||||
}
|
||||
|
||||
|
||||
void json_free(json_t* x) {
|
||||
switch (x->type) {
|
||||
default: break;
|
||||
case VTYPE_STRING: string_free(x->data); break;
|
||||
case VTYPE_MAP: map_free(x->data); break;
|
||||
case VTYPE_ARRAY: array_free(x->data); break;
|
||||
case VTYPE_LIST: list_free(x->data); break;
|
||||
case VTYPE_SET: vset_free(x->data); break;
|
||||
case VTYPE_DICT: dict_free(x->data); break;
|
||||
}
|
||||
|
||||
libcdsb_free(x->data);
|
||||
memset(x, 0, sizeof(*x));
|
||||
}
|
178
src/string.c
Normal file
178
src/string.c
Normal file
@ -0,0 +1,178 @@
|
||||
/* This software is licensed by the MIT License, see LICENSE file */
|
||||
/* Copyright © 2022 Gregory Lirent */
|
||||
|
||||
#include "../modules/libcdsb/modules/libunic/include.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define unescape8 libcjsonp_builtin_unescape8
|
||||
#define unescape16 libcjsonp_builtin_unescape32
|
||||
#define unescape32 libcjsonp_builtin_unescape16
|
||||
|
||||
static bool libcjsonp_builtin_unescape8(unsigned char* x, const char* s) {
|
||||
unsigned char c[2];
|
||||
|
||||
if (*s > 0x39) {
|
||||
c[0] = (*s|0x20);
|
||||
|
||||
if (c[0] < 0x61 || c[0] > 0x66)
|
||||
return false;
|
||||
|
||||
c[0] -= 0x57;
|
||||
} else if (*s >= 0x30) {
|
||||
c[0] = *s&0x0f;
|
||||
} else return false;
|
||||
|
||||
if (*++s > 0x39) {
|
||||
c[1] = (*s|0x20);
|
||||
|
||||
if (c[1] < 0x61 || c[1] > 0x66)
|
||||
return false;
|
||||
|
||||
c[1] -= 0x57;
|
||||
} else if (*s >= 0x30) {
|
||||
c[1] |= *s&0x0f;
|
||||
} else return false;
|
||||
|
||||
*x = (c[0]<<4) | c[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void libcjsonp_builtin_unescape32(char** x, char** s) {
|
||||
|
||||
vtype_uint32 uc;
|
||||
size_t n;
|
||||
bool f;
|
||||
char* p;
|
||||
|
||||
n = 4;
|
||||
uc = 0;
|
||||
f = 0;
|
||||
p = *s;
|
||||
|
||||
while (n--) {
|
||||
unsigned char c;
|
||||
|
||||
f |= !libcjsonp_builtin_unescape8(&c, p);
|
||||
uc = c | uc >> 8;
|
||||
|
||||
p += 2;
|
||||
}
|
||||
|
||||
if (!f) {
|
||||
*s = p;
|
||||
if (!f && (p = tochar_unicode(*x, uc)))
|
||||
*x = p;
|
||||
} else --*s;
|
||||
}
|
||||
|
||||
static void libcjsonp_builtin_unescape16(char** x, char** s) {
|
||||
|
||||
vtype_uint32 uc;
|
||||
char* p;
|
||||
bool f;
|
||||
unsigned char c[2];
|
||||
|
||||
f = 0;
|
||||
p = *s;
|
||||
|
||||
f |= !libcjsonp_builtin_unescape8(c, p);
|
||||
f |= !libcjsonp_builtin_unescape8(c + 1, p += 2);
|
||||
|
||||
p += 2;
|
||||
|
||||
if (f) goto bad_;
|
||||
|
||||
if (*c < 0xd8 || *c >= 0xdc) {
|
||||
uc = *c << 8 | c[1];
|
||||
goto end_;
|
||||
}
|
||||
|
||||
if ((p)[0] != '\\' || (p)[1] != 'u')
|
||||
return;
|
||||
|
||||
p += 2;
|
||||
|
||||
uc = (c[0]&0x03) << 18;
|
||||
uc |= c[1] << 10;
|
||||
|
||||
f |= !libcjsonp_builtin_unescape8(c, p);
|
||||
f |= !libcjsonp_builtin_unescape8(c + 1, p += 2);
|
||||
|
||||
p += 2;
|
||||
|
||||
if (!f) {
|
||||
if (*c < 0xdc || *c > 0xdf)
|
||||
goto bad_;
|
||||
|
||||
uc |= (c[0]&0x03)<<8;
|
||||
uc |= c[1];
|
||||
uc += 0x010000;
|
||||
|
||||
end_: *s = p;
|
||||
if ((p = tochar_unicode(*x, uc)))
|
||||
*x = p;
|
||||
} else bad_: --*s;
|
||||
}
|
||||
|
||||
/*#####################################################################################################################*/
|
||||
|
||||
void libcjsonp_string_unescape(vtype_string* x) {
|
||||
|
||||
char *p, *c;
|
||||
|
||||
if (!x->buffer || !*x->buffer)
|
||||
return;
|
||||
|
||||
p = c = x->buffer;
|
||||
|
||||
while (*p) {
|
||||
|
||||
if (*p == '\\') {
|
||||
switch (*(++p)) {
|
||||
default : *(c++) = *p; break;
|
||||
case 'n': *(c++) = '\n'; break;
|
||||
case 'r': *(c++) = '\r'; break;
|
||||
case 'e': *(c++) = '\e'; break;
|
||||
case 'v': *(c++) = '\v'; break;
|
||||
case 't': *(c++) = '\t'; break;
|
||||
case 'a': *(c++) = '\a'; break;
|
||||
|
||||
case 'x': if (unescape8((void*)c, p + 1)) {
|
||||
++c;
|
||||
p += 3;
|
||||
} goto end_loop_;
|
||||
case 'U': ++p; unescape32(&c, &p); goto end_loop_;
|
||||
case 'u': ++p; unescape16(&c, &p); goto end_loop_;
|
||||
}
|
||||
|
||||
} else if (p != c) {
|
||||
*(c++) = *p;
|
||||
} else ++c;
|
||||
|
||||
++p;
|
||||
|
||||
end_loop_:{}
|
||||
}
|
||||
|
||||
*c = 0;
|
||||
}
|
||||
|
||||
|
||||
void libcjsonp_string_escape(vtype_string* s) {
|
||||
buffer_t x;
|
||||
|
||||
if (!s->buffer || !*s->buffer)
|
||||
return;
|
||||
|
||||
memset(&x, 0, sizeof(x));
|
||||
|
||||
buffer_write_and_wrap(&x, s->buffer);
|
||||
|
||||
x.n = (x.ptr - x.mem) - 1;
|
||||
s->buffer = libcdsb_realloc(s->buffer, x.n);
|
||||
x.ptr[-1] = 0;
|
||||
|
||||
memcpy(s->buffer, x.mem + 1, x.n);
|
||||
libcdsb_free(x.mem);
|
||||
}
|
Loading…
Reference in New Issue
Block a user