Add core functionality

This commit is contained in:
Gregory Lirent 2022-08-26 10:09:26 +03:00
parent eebedd557f
commit d1f9622cd2
5 changed files with 391 additions and 0 deletions

56
src/buffer.c Normal file
View 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
View 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
View 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
View 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
View 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);
}