nota leaks fixed
This commit is contained in:
@@ -19,7 +19,6 @@ HMM_Vec2 mouse_delta = {0, 0};
|
||||
|
||||
struct joystick {
|
||||
int id;
|
||||
//GLFWgamepadstate state;
|
||||
};
|
||||
|
||||
static int *downkeys = NULL;
|
||||
|
||||
@@ -162,8 +162,8 @@ JSValue js_getpropidx(JSValue v, uint32_t i)
|
||||
|
||||
static inline cpBody *js2body(JSValue v) { return js2gameobject(v)->body; }
|
||||
|
||||
uint64_t js2uint64(JSValue v) {
|
||||
uint64_t i;
|
||||
int64_t js2int64(JSValue v) {
|
||||
int64_t i;
|
||||
JS_ToInt64(js, &i, v);
|
||||
return i;
|
||||
}
|
||||
@@ -247,6 +247,8 @@ char *js_nota_decode(JSValue *tmp, char *nota)
|
||||
case NOTA_TEXT:
|
||||
nota = nota_read_text(&str, nota);
|
||||
*tmp = str2js(str);
|
||||
/* TODO: Avoid malloc and free here */
|
||||
free(str);
|
||||
break;
|
||||
case NOTA_ARR:
|
||||
nota = nota_read_array(&n, nota);
|
||||
@@ -258,14 +260,12 @@ char *js_nota_decode(JSValue *tmp, char *nota)
|
||||
break;
|
||||
case NOTA_REC:
|
||||
nota = nota_read_record(&n, nota);
|
||||
printf("nota object with %d elements\n", n);
|
||||
*tmp = JS_NewObject(js);
|
||||
for (int i = 0; i < n; i++) {
|
||||
|
||||
nota = nota_read_text(&str, nota);
|
||||
printf("looking at property %d named %s\n", i, str);
|
||||
nota = js_nota_decode(&ret2, nota);
|
||||
JS_SetPropertyStr(js, *tmp, str, ret2);
|
||||
free(str);
|
||||
}
|
||||
break;
|
||||
case NOTA_INT:
|
||||
@@ -273,8 +273,10 @@ char *js_nota_decode(JSValue *tmp, char *nota)
|
||||
*tmp = int2js(n);
|
||||
break;
|
||||
case NOTA_SYM:
|
||||
nota = nota_read_bool(&b, nota);
|
||||
*tmp = bool2js(b);
|
||||
nota = nota_read_sym(&b, nota);
|
||||
if (b == NOTA_NULL) *tmp = JS_UNDEFINED;
|
||||
else
|
||||
*tmp = bool2js(b);
|
||||
break;
|
||||
default:
|
||||
case NOTA_FLOAT:
|
||||
@@ -297,42 +299,44 @@ char *js_nota_encode(JSValue v, char *nota)
|
||||
|
||||
switch(tag) {
|
||||
case JS_TAG_FLOAT64:
|
||||
// printf("encode float\n");
|
||||
return nota_write_float(JS_VALUE_GET_FLOAT64(v), nota);
|
||||
case JS_TAG_INT:
|
||||
// printf("encode int\n");
|
||||
return nota_write_int(JS_VALUE_GET_INT(v), nota);
|
||||
case JS_TAG_STRING:
|
||||
// printf("encode string\n");
|
||||
str = js2str(v);
|
||||
nota = nota_write_text(str, nota);
|
||||
JS_FreeCString(js, str);
|
||||
return nota;
|
||||
case JS_TAG_BOOL:
|
||||
// printf("encode bool\n");
|
||||
return nota_write_bool(JS_VALUE_GET_BOOL(v), nota);
|
||||
return nota_write_sym(JS_VALUE_GET_BOOL(v), nota);
|
||||
case JS_TAG_UNDEFINED:
|
||||
return nota_write_sym(NOTA_NULL, nota);
|
||||
case JS_TAG_NULL:
|
||||
return nota_write_sym(NOTA_NULL, nota);
|
||||
case JS_TAG_OBJECT:
|
||||
if (JS_IsArray(js, v)) {
|
||||
// printf("encode array\n");
|
||||
int n = js_arrlen(v);
|
||||
nota = nota_write_array(n, nota);
|
||||
for (int i = 0; i < js_arrlen(v); i++)
|
||||
for (int i = 0; i < n; i++)
|
||||
nota = js_nota_encode(js_arridx(v, i), nota);
|
||||
return nota;
|
||||
}
|
||||
// printf("encode object\n");
|
||||
|
||||
n = JS_GetOwnPropertyNames(js, &ptab, &plen, v, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK);
|
||||
nota = nota_write_record(plen, nota);
|
||||
|
||||
for (int i = 0; i < plen; i++) {
|
||||
val = JS_GetProperty(js,v,ptab[i].atom);
|
||||
if (JS_IsUndefined(val) || JS_IsNull(val)) continue;
|
||||
/* todo: slower than atomtocstring */
|
||||
str = JS_AtomToCString(js, ptab[i].atom);
|
||||
// printf("encoding object entry %s\n", str);
|
||||
JS_FreeAtom(js, ptab[i].atom);
|
||||
|
||||
nota = nota_write_text(str, nota);
|
||||
nota = js_nota_encode(JS_GetProperty(js, v, ptab[i].atom), nota);
|
||||
JS_FreeCString(js, str);
|
||||
|
||||
nota = js_nota_encode(val, nota);
|
||||
JS_FreeValue(js,val);
|
||||
}
|
||||
|
||||
js_free(js, ptab);
|
||||
return nota;
|
||||
}
|
||||
}
|
||||
@@ -666,6 +670,7 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
int *intids = NULL;
|
||||
gameobject *go = NULL;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
size_t plen = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case 0:
|
||||
@@ -807,9 +812,9 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
break;
|
||||
|
||||
case 39:
|
||||
str = JS_ToCString(js, argv[1]);
|
||||
str = JS_ToCStringLen(js, &plen, argv[1]);
|
||||
str2 = JS_ToCString(js, argv[2]);
|
||||
ret = JS_NewInt64(js, slurp_write(str, str2));
|
||||
ret = JS_NewInt64(js, slurp_write(str, str2, plen));
|
||||
break;
|
||||
|
||||
case 40:
|
||||
@@ -883,6 +888,10 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
break;
|
||||
|
||||
case 60:
|
||||
str = JS_GetArrayBuffer(js, &plen, argv[1]);
|
||||
str2 = JS_ToCString(js, argv[2]);
|
||||
ret = JS_NewInt64(js, slurp_write(str, str2, plen));
|
||||
str = NULL;
|
||||
break;
|
||||
|
||||
case 61:
|
||||
@@ -961,6 +970,12 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
arrfree(ids);
|
||||
break;
|
||||
|
||||
case 81:
|
||||
str = JS_ToCString(js, argv[1]);
|
||||
d1 = slurp_file(str, &plen);
|
||||
ret = JS_NewArrayBufferCopy(js, d1, plen);
|
||||
break;
|
||||
|
||||
case 82:
|
||||
gameobject_draw_debug(js2gameobject(argv[1]));
|
||||
break;
|
||||
@@ -1101,15 +1116,15 @@ JSValue duk_cmd(JSContext *js, JSValueConst this, int argc, JSValueConst *argv)
|
||||
break;
|
||||
|
||||
case 128:
|
||||
ret = JS_NewFloat64(js, stm_ns(js2uint64(argv[1])));
|
||||
ret = JS_NewFloat64(js, stm_ns(js2int64(argv[1])));
|
||||
break;
|
||||
|
||||
case 129:
|
||||
ret = JS_NewFloat64(js, stm_us(js2uint64(argv[1])));
|
||||
ret = JS_NewFloat64(js, stm_us(js2int64(argv[1])));
|
||||
break;
|
||||
|
||||
case 130:
|
||||
ret = JS_NewFloat64(js, stm_ms(js2uint64(argv[1])));
|
||||
ret = JS_NewFloat64(js, stm_ms(js2int64(argv[1])));
|
||||
break;
|
||||
|
||||
case 131:
|
||||
@@ -2041,7 +2056,7 @@ JSValue nota_encode(JSContext *js, JSValueConst this, int argc, JSValueConst *ar
|
||||
if (argc < 1) return JS_UNDEFINED;
|
||||
|
||||
JSValue obj = argv[0];
|
||||
char nota[100000];
|
||||
char nota[1024*1024]; // 1MB
|
||||
char *e = js_nota_encode(obj, nota);
|
||||
|
||||
return JS_NewArrayBufferCopy(js, nota, e-nota);
|
||||
@@ -2107,6 +2122,7 @@ void ffi_load() {
|
||||
sound_proto = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, sound_proto, js_sound_funcs, countof(js_sound_funcs));
|
||||
JS_SetPrototype(js, sound_proto, dsp_node_proto);
|
||||
JS_FreeValue(js, sound_proto);
|
||||
|
||||
QJSCLASSPREP_FUNCS(emitter);
|
||||
QJSCLASSPREP_FUNCS(warp_gravity);
|
||||
|
||||
@@ -1,2 +1,101 @@
|
||||
#include "kim.h"
|
||||
|
||||
#define KIM_CONT 0x80
|
||||
#define KIM_DATA 0x7f
|
||||
#define CONTINUE(CHAR) (CHAR>>7)
|
||||
|
||||
int utf8_bytes(char *s)
|
||||
{
|
||||
int bytes = __builtin_clz(~(*s));
|
||||
if (!bytes) return 1;
|
||||
return bytes-24;
|
||||
}
|
||||
|
||||
int utf8_count(char *s)
|
||||
{
|
||||
int count = 0;
|
||||
char *p = s;
|
||||
|
||||
while(*s) {
|
||||
count++;
|
||||
s += utf8_bytes(s);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* decode and advance s, returning the character cde */
|
||||
int decode_utf8(char **s) {
|
||||
int k = **s ? __builtin_clz(~(**s << 24)) : 0; // Count # of leading 1 bits.
|
||||
int mask = (1 << (8 - k)) - 1; // All 1's with k leading 0's.
|
||||
int value = **s & mask;
|
||||
for (++(*s), --k; k > 0 && **s; --k, ++(*s)) { // Note that k = #total bytes, or 0.
|
||||
value <<= 6;
|
||||
value += (**s & 0x3F);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Write and advance s with code in utf-8 */
|
||||
void encode_utf8(char **s, int code) {
|
||||
char val[4];
|
||||
int lead_byte_max = 0x7F;
|
||||
int val_index = 0;
|
||||
while (code > lead_byte_max) {
|
||||
val[val_index++] = (code & 0x3F) | 0x80;
|
||||
code >>= 6;
|
||||
lead_byte_max >>= (val_index == 1 ? 2 : 1);
|
||||
}
|
||||
val[val_index++] = (code & lead_byte_max) | (~lead_byte_max << 1);
|
||||
while (val_index--) {
|
||||
**s = val[val_index];
|
||||
(*s)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* write and advance s with code in kim */
|
||||
void encode_kim(char **s, int code)
|
||||
{
|
||||
if (code < KIM_CONT) {
|
||||
**s = 0 | (KIM_DATA & code);
|
||||
(*s)++;
|
||||
return;
|
||||
}
|
||||
|
||||
int bits = ((32 - __builtin_clz(code) + 6) / 7) * 7;
|
||||
|
||||
while (bits > 7) {
|
||||
bits -= 7;
|
||||
**s = KIM_CONT | KIM_DATA & (code >> bits);
|
||||
(*s)++;
|
||||
}
|
||||
**s = KIM_DATA & code;
|
||||
(*s)++;
|
||||
}
|
||||
|
||||
/* decode and advance s, returning the character code */
|
||||
int decode_kim(char **s)
|
||||
{
|
||||
int rune = **s & KIM_DATA;
|
||||
while (CONTINUE(**s)) {
|
||||
rune <<= 7;
|
||||
(*s)++;
|
||||
rune |= **s & KIM_DATA;
|
||||
}
|
||||
(*s)++;
|
||||
return rune;
|
||||
}
|
||||
|
||||
/* write a null-terminated utf8 stream into a kim string */
|
||||
void utf8_to_kim(char **utf, char **kim)
|
||||
{
|
||||
while (**utf)
|
||||
encode_kim(kim, decode_utf8(utf));
|
||||
}
|
||||
|
||||
/* write number of runes from a kim stream int a utf8 stream */
|
||||
void kim_to_utf8(char **kim, char **utf, int runes)
|
||||
{
|
||||
for (int i = 0; i < runes; i++)
|
||||
encode_utf8(utf, decode_kim(kim));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#ifndef KIM_H
|
||||
#define KIM_H
|
||||
|
||||
void write_kim_char(char c, char *into);
|
||||
int utf8_bytes(char *s);
|
||||
int utf8_count(char *s);
|
||||
int decode_utf8(char **s);
|
||||
void encode_utf8(char **s, int code);
|
||||
void encode_kim(char **s, int code);
|
||||
int decode_kim(char **s);
|
||||
void utf8_to_kim(char **utf, char **kim);
|
||||
void kim_to_utf8(char **kim, char **utf, int runes);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "string.h"
|
||||
#include "stdlib.h"
|
||||
#include "limits.h"
|
||||
#include "kim.h"
|
||||
|
||||
#define NOTA_CONT 0x80
|
||||
#define NOTA_DATA 0x7f
|
||||
@@ -15,13 +16,11 @@
|
||||
#define NOTA_HEAD_DATA 0x0f
|
||||
#define CONTINUE(CHAR) (CHAR>>7)
|
||||
|
||||
#define NOTA_FALSE 0x00
|
||||
#define NOTA_TRUE 0x01
|
||||
#define NOTA_PRIVATE 0x08
|
||||
#define NOTA_SYSTEM 0x09
|
||||
|
||||
#define UTF8_DATA 0x3f
|
||||
|
||||
/* define this to use native string instead of kim. Bytes are encoded instead of runes */
|
||||
#define NOTA_UTF8
|
||||
|
||||
int nota_type(char *nota) { return *nota & NOTA_TYPE; }
|
||||
|
||||
char *nota_skip(char *nota)
|
||||
@@ -240,136 +239,52 @@ char *nota_write_record(unsigned long long n, char *nota)
|
||||
return nota_continue_num(n, nota, 4);
|
||||
}
|
||||
|
||||
/* kim is 7, 14, then 21 */
|
||||
|
||||
int utf8_bytes(char *s)
|
||||
char *nota_write_sym(int sym, char *nota)
|
||||
{
|
||||
int bytes = __builtin_clz(~(*s));
|
||||
if (!bytes) return 1;
|
||||
return bytes-24;
|
||||
*nota = NOTA_SYM | sym;
|
||||
return nota+1;
|
||||
}
|
||||
|
||||
int utf8_count(char *s)
|
||||
char *nota_read_sym(int *sym, char *nota)
|
||||
{
|
||||
int count = 0;
|
||||
char *p = s;
|
||||
|
||||
while(*s) {
|
||||
count++;
|
||||
s += utf8_bytes(s);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int decode_utf8(char **s) {
|
||||
int k = **s ? __builtin_clz(~(**s << 24)) : 0; // Count # of leading 1 bits.
|
||||
int mask = (1 << (8 - k)) - 1; // All 1's with k leading 0's.
|
||||
int value = **s & mask;
|
||||
for (++(*s), --k; k > 0 && **s; --k, ++(*s)) { // Note that k = #total bytes, or 0.
|
||||
value <<= 6;
|
||||
value += (**s & 0x3F);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void encode_utf8(char **s, char *end, int code) {
|
||||
if (code < 255) {
|
||||
**s = code;
|
||||
(*s)++;
|
||||
return;
|
||||
}
|
||||
|
||||
char val[4];
|
||||
int lead_byte_max = 0x7F;
|
||||
int val_index = 0;
|
||||
while (code > lead_byte_max) {
|
||||
val[val_index++] = (code & 0x3F) | 0x80;
|
||||
code >>= 6;
|
||||
lead_byte_max >>= (val_index == 1 ? 2 : 1);
|
||||
}
|
||||
val[val_index++] = (code & lead_byte_max) | (~lead_byte_max << 1);
|
||||
while (val_index-- && *s < end) {
|
||||
**s = val[val_index];
|
||||
(*s)++;
|
||||
}
|
||||
}
|
||||
|
||||
void encode_kim(char **s, char *end, int code)
|
||||
{
|
||||
if (code < 255) {
|
||||
**s = 0 | (NOTA_DATA & code);
|
||||
(*s)++;
|
||||
return;
|
||||
}
|
||||
|
||||
int bits = ((32 - __builtin_clz(code) + 6) / 7) * 7;
|
||||
|
||||
while (bits > 7) {
|
||||
bits -= 7;
|
||||
**s = NOTA_CONT | NOTA_DATA & (code >> bits);
|
||||
(*s)++;
|
||||
}
|
||||
**s = NOTA_DATA & code;
|
||||
(*s)++;
|
||||
}
|
||||
|
||||
int decode_kim(char **s)
|
||||
{
|
||||
int rune = **s & NOTA_DATA;
|
||||
while (CONTINUE(**s)) {
|
||||
rune <<= 7;
|
||||
(*s)++;
|
||||
rune |= **s & NOTA_DATA;
|
||||
}
|
||||
(*s)++;
|
||||
return rune;
|
||||
}
|
||||
|
||||
char *utf8_to_kim(char *utf, char *kim)
|
||||
{
|
||||
while (*utf)
|
||||
encode_kim(&kim, NULL, decode_utf8(&utf));
|
||||
|
||||
return kim;
|
||||
}
|
||||
|
||||
void kim_to_utf8(char *kim, char *utf, int runes)
|
||||
{
|
||||
for (int i = 0; i < runes; i++)
|
||||
encode_utf8(&utf, utf+4, decode_kim(&kim));
|
||||
|
||||
*utf = 0;
|
||||
if (*sym) *sym = (*nota) & 0x0f;
|
||||
return nota+1;
|
||||
}
|
||||
|
||||
char *nota_read_text(char **text, char *nota)
|
||||
{
|
||||
long long chars;
|
||||
nota = nota_read_num(&chars, nota);
|
||||
|
||||
#ifdef NOTA_UTF8
|
||||
*text = calloc(chars+1,1);
|
||||
memcpy(*text, nota, chars);
|
||||
nota += chars;
|
||||
#else
|
||||
char utf[chars*4];
|
||||
kim_to_utf8(nota, utf, chars);
|
||||
*text = strdup(utf);
|
||||
char *pp = utf;
|
||||
kim_to_utf8(¬a, &pp, chars);
|
||||
*pp = 0;
|
||||
*text = strdup(utf);
|
||||
#endif
|
||||
|
||||
return nota;
|
||||
}
|
||||
|
||||
char *nota_write_bool(int b, char *nota)
|
||||
{
|
||||
*nota = NOTA_SYM | (b ? NOTA_TRUE : NOTA_FALSE);
|
||||
return nota+1;
|
||||
}
|
||||
|
||||
char *nota_read_bool(int *b, char *nota)
|
||||
{
|
||||
if (b) *b = (*nota) & 0x0f;
|
||||
return nota+1;
|
||||
}
|
||||
|
||||
char *nota_write_text(char *s, char *nota)
|
||||
{
|
||||
char *start = nota;
|
||||
nota[0] = NOTA_TEXT;
|
||||
long long n = utf8_count(s);
|
||||
|
||||
#ifdef NOTA_UTF8
|
||||
long long n = strlen(s);
|
||||
nota = nota_continue_num(n,nota,4);
|
||||
return utf8_to_kim(s, nota);
|
||||
memcpy(nota, s, n);
|
||||
return nota+n;
|
||||
#else
|
||||
long long n = utf8_count(s);
|
||||
nota = nota_continue_num(n,nota,4);
|
||||
utf8_to_kim(&s, ¬a);
|
||||
return nota;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
#define NOTA_INT 0x60
|
||||
#define NOTA_SYM 0x70
|
||||
|
||||
#define NOTA_FALSE 0x00
|
||||
#define NOTA_TRUE 0x01
|
||||
#define NOTA_PRIVATE 0x08
|
||||
#define NOTA_SYSTEM 0x09
|
||||
#define NOTA_NULL 0x02
|
||||
|
||||
typedef struct NOTA {
|
||||
char *head;
|
||||
} NOTA;
|
||||
@@ -21,7 +27,7 @@ char *nota_read_array(long long *len, char *nota);
|
||||
char *nota_read_record(long long *len, char *nota);
|
||||
char *nota_read_float(double *d, char *nota);
|
||||
char *nota_read_int(long long *l, char *nota);
|
||||
char *nota_read_bool(int *b, char *nota);
|
||||
char *nota_read_sym(int *sym, char *nota);
|
||||
|
||||
void print_nota_hex(char *nota);
|
||||
|
||||
@@ -31,6 +37,6 @@ char *nota_write_array(unsigned long long n, char *nota);
|
||||
char *nota_write_record(unsigned long long n, char *nota);
|
||||
char *nota_write_float(double n, char *nota);
|
||||
char *nota_write_int(long long n, char *nota);
|
||||
char *nota_write_bool(int b, char *nota);
|
||||
char *nota_write_sym(int sym, char *nota);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -291,11 +291,12 @@ FILE *fopen_mkdir(const char *path, const char *mode) {
|
||||
return fopen(path,mode);
|
||||
}
|
||||
|
||||
int slurp_write(const char *txt, const char *filename) {
|
||||
int slurp_write(const char *txt, const char *filename, size_t len) {
|
||||
FILE *f = fopen_mkdir(filename, "w");
|
||||
if (!f) return 1;
|
||||
|
||||
fputs(txt, f);
|
||||
if (len < 0) len = strlen(txt);
|
||||
fwrite(txt, len, 1, f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ char *dirname(const char *path);
|
||||
|
||||
void *slurp_file(const char *filename, size_t *size);
|
||||
char *slurp_text(const char *filename, size_t *size);
|
||||
int slurp_write(const char *txt, const char *filename);
|
||||
int slurp_write(const char *txt, const char *filename, size_t len);
|
||||
|
||||
char *seprint(char *fmt, ...);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user