nota leaks fixed
This commit is contained in:
parent
46b86a8e92
commit
262cd50e1a
|
@ -91,14 +91,14 @@
|
|||
*/
|
||||
//#define DUMP_BYTECODE (1)
|
||||
/* dump the occurence of the automatic GC */
|
||||
//#define DUMP_GC
|
||||
#define DUMP_GC
|
||||
/* dump objects freed by the garbage collector */
|
||||
//#define DUMP_GC_FREE
|
||||
/* dump objects leaking when freeing the runtime */
|
||||
//#define DUMP_LEAKS 1
|
||||
#define DUMP_LEAKS 1
|
||||
/* dump memory usage before running the garbage collector */
|
||||
//#define DUMP_MEM
|
||||
//#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
|
||||
#define DUMP_MEM
|
||||
#define DUMP_OBJECTS /* dump objects in JS_FreeContext */
|
||||
//#define DUMP_ATOMS /* dump atoms in JS_FreeContext */
|
||||
//#define DUMP_SHAPES /* dump shapes in JS_FreeContext */
|
||||
//#define DUMP_MODULE_RESOLVE
|
||||
|
|
|
@ -562,7 +562,7 @@ var editor = {
|
|||
} else {
|
||||
var path = sub.replaceAll('.', '/') + ".json";
|
||||
var saveobj = obj.json_obj();
|
||||
IO.slurpwrite(JSON.stringify(saveobj,null,1), path);
|
||||
IO.slurpwrite(path, JSON.stringify(saveobj,null,1));
|
||||
|
||||
if (obj === editor.edit_level) {
|
||||
if (obj === editor.desktop) {
|
||||
|
@ -841,7 +841,7 @@ editor.inputs['C-s'] = function() {
|
|||
if (savejs.objects) saveobj.__proto__.objects = savejs.objects;
|
||||
var path = prototypes.ur_stem(saveobj.ur.toString()) + ".json";
|
||||
|
||||
IO.slurpwrite(JSON.stringify(saveobj.__proto__,null,1), path);
|
||||
IO.slurpwrite(path, JSON.stringify(saveobj.__proto__,null,1));
|
||||
Log.warn(`Wrote to file ${path}`);
|
||||
|
||||
Object.values(saveobj.objects).forEach(function(x) { x.check_dirty(); });
|
||||
|
|
|
@ -760,7 +760,6 @@ gameobject.doc = {
|
|||
var prototypes = {};
|
||||
prototypes.ur_ext = ".jso";
|
||||
prototypes.ur = {};
|
||||
prototypes.save_gameobjects = function() { slurpwrite(JSON.stringify(gameobjects,null,2), "proto.json"); };
|
||||
|
||||
/* Makes a new ur-type from disk. If the ur doesn't exist, it searches on the disk to create it. */
|
||||
prototypes.from_file = function(file)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
var Sound = {
|
||||
bus: {},
|
||||
samplerate() { return cmd(198); },
|
||||
|
@ -108,9 +107,10 @@ Object.mixin(cmd(180).__proto__, {
|
|||
set volume(x) { this.gain = x; },
|
||||
});
|
||||
|
||||
Object.mixin(DSP.source().__proto__, {
|
||||
/*Object.mixin(DSP.source().__proto__, {
|
||||
frames() { return cmd(197,this); },
|
||||
length() { return this.frames()/Sound.samplerate(); },
|
||||
time() { return this.frame/Sound.samplerate(); },
|
||||
pct() { return this.time()/this.length(); },
|
||||
});
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,12 @@ function compile_env(str, env, file)
|
|||
|
||||
function fcompile_env(file, env) { return compile_env(IO.slurp(file), env, file); }
|
||||
|
||||
function buf2hex(buffer) { // buffer is an ArrayBuffer
|
||||
return [...new Uint8Array(buffer)]
|
||||
.map(x => x.toString(16).padStart(2, '0'))
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
var OS = {};
|
||||
OS.cwd = function() { return cmd(144); }
|
||||
OS.exec = function(s) { cmd(143, s); }
|
||||
|
@ -140,7 +146,15 @@ var IO = {
|
|||
else
|
||||
throw new Error(`File ${file} does not exist; can't slurp`);
|
||||
},
|
||||
slurpwrite(str, file) { return cmd(39, str, file); },
|
||||
slurpbytes(file) {
|
||||
return cmd(81, file);
|
||||
},
|
||||
slurpwrite(file, data) {
|
||||
if (data.byteLength)
|
||||
cmd(60, data, file);
|
||||
else
|
||||
return cmd(39, data, file);
|
||||
},
|
||||
extensions(ext) {
|
||||
var paths = IO.ls();
|
||||
paths = paths.filter(function(str) { return str.ext() === ext; });
|
||||
|
@ -312,7 +326,6 @@ Cmdline.register_cmd("cjson", function(json) {
|
|||
}
|
||||
|
||||
Log.say(j);
|
||||
// IO.slurpwrite(JSON.stringify(j,undefined,2), f);
|
||||
|
||||
STD.exit(0);
|
||||
}, "Clean up a jso file.");
|
||||
|
|
|
@ -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, ...);
|
||||
|
||||
|
|
Loading…
Reference in a new issue