From a274fb174f3a94d64466aa992a2df8fad3d0aef0 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sun, 8 Jun 2025 13:42:20 -0500 Subject: [PATCH] faster text conversion to hex; guid generation now dealt with with -u.random_fit and blob formation; mersenne twister used for -u.random functions --- meson.build | 2 +- scripts/engine.cm | 20 ++++--- scripts/math.cm | 4 -- scripts/text.cm | 50 ++---------------- source/cell.h | 6 +-- source/jsffi.c | 128 +++++++++++++++++++++++++++++---------------- source/jsffi.h | 4 +- source/qjs_blob.c | 37 ++++++++----- source/qjs_math.c | 17 ------ source/qjs_text.c | 94 +++++++++++++++++++++++++++++++++ source/qjs_text.h | 8 +++ tests/guid.ce | 14 +++++ tests/text_test.ce | 23 ++++++++ 13 files changed, 269 insertions(+), 138 deletions(-) create mode 100644 source/qjs_text.c create mode 100644 source/qjs_text.h create mode 100644 tests/guid.ce create mode 100644 tests/text_test.ce diff --git a/meson.build b/meson.build index 1fe25d95..7c7ee208 100644 --- a/meson.build +++ b/meson.build @@ -295,7 +295,7 @@ src += [ 'anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c', 'render.c','simplex.c','spline.c', 'transform.c','cell.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_nota.c', 'qjs_soloud.c', 'qjs_sdl.c', 'qjs_sdl_input.c', 'qjs_sdl_video.c', 'qjs_sdl_surface.c', 'qjs_math.c', 'qjs_geometry.c', 'qjs_transform.c', 'qjs_sprite.c', 'qjs_io.c', 'qjs_fd.c', 'qjs_os.c', 'qjs_actor.c', - 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c' + 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c', 'qjs_blob.c', 'qjs_crypto.c', 'qjs_time.c', 'qjs_http.c', 'qjs_rtree.c', 'qjs_spline.c', 'qjs_js.c', 'qjs_debug.c', 'picohttpparser.c', 'qjs_miniz.c', 'timer.c', 'qjs_socket.c', 'qjs_kim.c', 'qjs_utf8.c', 'qjs_fit.c', 'qjs_text.c' ] # quirc src src += [ diff --git a/scripts/engine.cm b/scripts/engine.cm index 7ca24d6a..ac33aff1 100644 --- a/scripts/engine.cm +++ b/scripts/engine.cm @@ -339,12 +339,16 @@ stone.p = function(object) } */ -var util = use('util') -var crypto = use('crypto') +function guid(bits = 256) +{ + var guid = new blob(bits, hidden.randi) + stone(guid) + return text(guid,'h') +} var HEADER = Symbol() -function create_actor(desc = {id:util.guid()}) { +function create_actor(desc = {id:guid()}) { var actor = {} actor[ACTORDATA] = desc return actor @@ -352,10 +356,10 @@ function create_actor(desc = {id:util.guid()}) { var $_ = create_actor() -$_.random = crypto.random +$_.random = hidden.rand $_.random[cell.DOC] = "returns a number between 0 and 1. There is a 50% chance that the result is less than 0.5." -$_.random_fit = crypto.random_fit +$_.random_fit = hidden.randi $_.clock = function(fn) { actor_mod.clock(_ => { @@ -484,7 +488,7 @@ $_.receiver[cell.DOC] = "registers a function that will receive all messages..." $_.start = function start(cb, program, ...args) { if (!program) return - var id = util.guid() + var id = guid() if (args.length === 1 && Array.isArray(args[0])) args = args[0] @@ -636,7 +640,7 @@ globalThis.send = function send(actor, message, reply) { } if (reply) { - var id = util.guid() + var id = guid() replies[id] = reply $_.delay(_ => { if (replies[id]) { @@ -654,7 +658,7 @@ globalThis.send = function send(actor, message, reply) { stone(send) -if (!cell.args.id) cell.id = util.guid() +if (!cell.args.id) cell.id = guid() else cell.id = cell.args.id $_[ACTORDATA].id = cell.id diff --git a/scripts/math.cm b/scripts/math.cm index 9ce81d48..cd01a812 100644 --- a/scripts/math.cm +++ b/scripts/math.cm @@ -22,10 +22,6 @@ math.sigma[cell.DOC] = "Compute standard deviation of an array of numbers." math.median[cell.DOC] = "Compute the median of an array of numbers." math.length[cell.DOC] = "Return the length of a vector (i.e. sqrt of sum of squares)." math.from_to[cell.DOC] = "Return an array of points from a start to an end, spaced out by a certain distance." -math.rand[cell.DOC] = "Return a random float in [0,1)." -math.randi[cell.DOC] = "Return a random 32-bit integer." -math.srand[cell.DOC] = "Seed the random number generator with the given integer, or with current time if none." - math.TAU = Math.PI * 2; math.deg2rad = function (deg) { return deg * 0.0174533; }; diff --git a/scripts/text.cm b/scripts/text.cm index b52947f4..633d3626 100644 --- a/scripts/text.cm +++ b/scripts/text.cm @@ -5,6 +5,8 @@ var blob = use('blob') var utf8 = use('utf8') +var that = this + // Convert number to string with given radix function to_radix(num, radix) { if (radix < 2 || radix > 36) return null; @@ -98,54 +100,10 @@ function text() { // Handle blob encoding styles switch (style) { case 'h': // hexadecimal - // Read 8 bits at a time for full bytes - var hex_digits = "0123456789ABCDEF"; - for (var i = 0; i < bit_length; i += 8) { - var byte_val = 0; - for (var j = 0; j < 8 && i + j < bit_length; j++) { - var bit = arg.read_logical(i + j); - if (bit) byte_val |= (1 << j); - } - result += hex_digits[(byte_val >> 4) & 0xF]; - result += hex_digits[byte_val & 0xF]; - } - return result; + return that.blob_to_hex(arg); case 't': // base32 - var b32_digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; - var bits = 0; - var value = 0; - - // Read bits from LSB to MSB within each byte - for (var byte_idx = 0; byte_idx < Math.ceil(bit_length / 8); byte_idx++) { - for (var bit_in_byte = 0; bit_in_byte < 8 && byte_idx * 8 + bit_in_byte < bit_length; bit_in_byte++) { - var bit_pos = byte_idx * 8 + bit_in_byte; - var bit = arg.read_logical(bit_pos); - - // Accumulate bits from MSB to LSB for base32 - value = (value << 1) | (bit ? 1 : 0); - bits++; - - if (bits === 5) { - result += b32_digits[value]; - bits = 0; - value = 0; - } - } - } - - // Handle remaining bits - if (bits > 0) { - value = value << (5 - bits); - result += b32_digits[value]; - } - - // Add padding to make length multiple of 8 - while (result.length % 8 !== 0) { - result += '='; - } - - return result; + return that.blob_to_base32(arg); case 'b': // binary for (var i = 0; i < bit_length; i++) { diff --git a/source/cell.h b/source/cell.h index fe9833d2..929a0d7d 100644 --- a/source/cell.h +++ b/source/cell.h @@ -21,8 +21,8 @@ typedef struct letter { }; } letter; -#define STATE_VECTOR_LENGTH 624 -#define STATE_VECTOR_M 397 +#define STATE_VECTOR_LENGTH 312 +#define STATE_VECTOR_M 156 #define ACTOR_IDLE 0 // Actor not doing anything #define ACTOR_READY 1 // Actor ready for a turn @@ -36,7 +36,7 @@ typedef JSValue (*MODULEFN)(JSContext *js); extern int tracy_profiling_enabled; typedef struct tagMTRand { - uint32_t mt[STATE_VECTOR_LENGTH]; + uint64_t mt[STATE_VECTOR_LENGTH]; int32_t index; } MTRand; diff --git a/source/jsffi.c b/source/jsffi.c index 9fcc05f0..b48ec4c1 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -56,6 +56,7 @@ #include "qjs_kim.h" #include "qjs_utf8.h" #include "qjs_fit.h" +#include "qjs_text.h" #ifndef NSTEAM #include "qjs_steam.h" #endif @@ -102,55 +103,59 @@ transform *js2transform(JSContext *js, JSValue v); //#include #endif -// Random number generation constants -#define UPPER_MASK 0x80000000 -#define LOWER_MASK 0x7fffffff -#define TEMPERING_MASK_B 0x9d2c5680 -#define TEMPERING_MASK_C 0xefc60000 +// Random number generation constants for MT19937-64 +#define NN STATE_VECTOR_LENGTH +#define MM STATE_VECTOR_M +#define MATRIX_A 0xB5026F5AA96619E9ULL +#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */ +#define LM 0x7FFFFFFFULL /* Least significant 31 bits */ // Random number generation functions -void m_seedRand(MTRand* rand, uint32_t seed) { - /* set initial seeds to mt[STATE_VECTOR_LENGTH] using the generator - * from Line 25 of Table 1 in: Donald Knuth, "The Art of Computer - * Programming," Vol. 2 (2nd Ed.) pp.102. - */ - rand->mt[0] = seed & 0xffffffff; - for(rand->index=1; rand->indexindex++) { - rand->mt[rand->index] = (6069 * rand->mt[rand->index-1]) & 0xffffffff; +void m_seedRand(MTRand* rand, uint64_t seed) { + rand->mt[0] = seed; + for(rand->index = 1; rand->index < NN; rand->index++) { + rand->mt[rand->index] = (6364136223846793005ULL * (rand->mt[rand->index-1] ^ (rand->mt[rand->index-1] >> 62)) + rand->index); } } -uint32_t genRandLong(MTRand* rand) { - uint32_t y; - static uint32_t mag[2] = {0x0, 0x9908b0df}; /* mag[x] = x * 0x9908b0df for x = 0,1 */ - if(rand->index >= STATE_VECTOR_LENGTH || rand->index < 0) { - /* generate STATE_VECTOR_LENGTH words at a time */ - int32_t kk; - if(rand->index >= STATE_VECTOR_LENGTH+1 || rand->index < 0) { - m_seedRand(rand, 4357); +int64_t genRandLong(MTRand* rand) { + int i; + uint64_t x; + static uint64_t mag01[2] = {0ULL, MATRIX_A}; + + if (rand->index >= NN) { /* generate NN words at one time */ + /* if init_genrand64() has not been called, */ + /* a default initial seed is used */ + if (rand->index == NN+1) + m_seedRand(rand, 5489ULL); + + for (i = 0; i < NN-MM; i++) { + x = (rand->mt[i] & UM) | (rand->mt[i+1] & LM); + rand->mt[i] = rand->mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; } - for(kk=0; kkmt[kk] & UPPER_MASK) | (rand->mt[kk+1] & LOWER_MASK); - rand->mt[kk] = rand->mt[kk+STATE_VECTOR_M] ^ (y >> 1) ^ mag[y & 0x1]; + for (; i < NN-1; i++) { + x = (rand->mt[i] & UM) | (rand->mt[i+1] & LM); + rand->mt[i] = rand->mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; } - for(; kkmt[kk] & UPPER_MASK) | (rand->mt[kk+1] & LOWER_MASK); - rand->mt[kk] = rand->mt[kk+(STATE_VECTOR_M-STATE_VECTOR_LENGTH)] ^ (y >> 1) ^ mag[y & 0x1]; - } - y = (rand->mt[STATE_VECTOR_LENGTH-1] & UPPER_MASK) | (rand->mt[0] & LOWER_MASK); - rand->mt[STATE_VECTOR_LENGTH-1] = rand->mt[STATE_VECTOR_M-1] ^ (y >> 1) ^ mag[y & 0x1]; + x = (rand->mt[NN-1] & UM) | (rand->mt[0] & LM); + rand->mt[NN-1] = rand->mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)]; + rand->index = 0; } - y = rand->mt[rand->index++]; - y ^= (y >> 11); - y ^= (y << 7) & TEMPERING_MASK_B; - y ^= (y << 15) & TEMPERING_MASK_C; - y ^= (y >> 18); - return y; + + x = rand->mt[rand->index++]; + + x ^= (x >> 29) & 0x5555555555555555ULL; + x ^= (x << 17) & 0x71D67FFFEDA60000ULL; + x ^= (x << 37) & 0xFFF7EEE000000000ULL; + x ^= (x >> 43); + + return (int64_t)(x & 0x000FFFFFFFFFFFFFULL); /* return 52-bit value safe for JS */ } double genRand(MTRand* rand) { - return((double)genRandLong(rand) / (uint32_t)0xffffffff); + /* generates a random number on [0,1)-real-interval */ + return (genRandLong(rand) >> 11) * (1.0/9007199254740992.0); } double rand_range(JSContext *js, double min, double max) @@ -947,15 +952,31 @@ static const JSCFunctionListEntry js_number_funcs[] = { PROTO_FUNC_DEF(number, lerp, 2), }; +static uint32_t rng_state = 123456789; +static uint32_t xorshift32(){ + uint32_t x = rng_state; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return rng_state = x; +} + JSC_CCALL(os_guid, - SDL_GUID guid; - randombytes(guid.data, 16); + uint8_t data[16]; + for(int i = 0; i < 4; i++){ + uint32_t v = xorshift32(); + memcpy(&data[i*4], &v, 4); + } + + static const char hex[] = "0123456789abcdef"; + char buf[32]; + for(int i = 0; i < 16; i++){ + uint8_t b = data[i]; + buf[i*2 ] = hex[b >> 4]; + buf[i*2 + 1] = hex[b & 0x0f]; + } - char guid_str[33]; - - SDL_GUIDToString(guid, guid_str, 33); - - return JS_NewString(js,guid_str); + return JS_NewStringLen(js, buf, 32); ) JSC_SCALL(console_print, printf("%s", str); ) @@ -1197,6 +1218,21 @@ JSC_CCALL(os_make_font, JSC_SCALL(os_system, ret = number2js(js,system(str)); ) +JSC_CCALL(os_rand, + MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; + return number2js(js, genRand(mrand)); +) + +JSC_CCALL(os_randi, + MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; + return JS_NewInt64(js, genRandLong(mrand)); +) + +JSC_CCALL(os_srand, + MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; + m_seedRand(mrand, js2number(js,argv[0])); +) + JSValue make_color_buffer(JSContext *js, colorf c, int verts) { HMM_Vec4 *colordata = malloc(sizeof(*colordata)*verts); @@ -1561,6 +1597,7 @@ void ffi_load(JSContext *js) arrput(rt->module_registry, MISTLINE(kim)); arrput(rt->module_registry, MISTLINE(utf8)); arrput(rt->module_registry, MISTLINE(fit)); + arrput(rt->module_registry, MISTLINE(text)); arrput(rt->module_registry, MISTLINE(wota)); arrput(rt->module_registry, MISTLINE(nota)); @@ -1623,6 +1660,9 @@ void ffi_load(JSContext *js) // Add functions that should only be accessible to engine.js JS_SetPropertyStr(js, hidden_fn, "use_dyn", JS_NewCFunction(js, js_os_use_dyn, "use_dyn", 1)); JS_SetPropertyStr(js, hidden_fn, "use_embed", JS_NewCFunction(js, js_os_use_embed, "use_embed", 1)); + JS_SetPropertyStr(js, hidden_fn, "rand", JS_NewCFunction(js, js_os_rand, "rand", 0)); + JS_SetPropertyStr(js, hidden_fn, "randi", JS_NewCFunction(js, js_os_randi, "randi", 0)); + JS_SetPropertyStr(js, hidden_fn, "srand", JS_NewCFunction(js, js_os_srand, "srand", 1)); const char actorsym_script[] = "var sym = Symbol(`actordata`); sym;"; diff --git a/source/jsffi.h b/source/jsffi.h index 8255e310..5ff80669 100644 --- a/source/jsffi.h +++ b/source/jsffi.h @@ -42,8 +42,8 @@ typedef struct tagMTRand MTRand; // Random number generation functions double genRand(MTRand *mrand); -uint32_t genRandLong(MTRand *mrand); -void m_seedRand(MTRand *mrand, uint32_t seed); +int64_t genRandLong(MTRand *mrand); +void m_seedRand(MTRand *mrand, uint64_t seed); double rand_range(JSContext *js, double min, double max); // Common data structures diff --git a/source/qjs_blob.c b/source/qjs_blob.c index d8334261..ed302c08 100644 --- a/source/qjs_blob.c +++ b/source/qjs_blob.c @@ -50,32 +50,43 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target, int is_one = JS_ToBool(ctx, argv[1]); bd = blob_new_with_fill((size_t)length_bits, is_one); } else if (JS_IsFunction(ctx, argv[1])) { - /* Random function provided – call it for each bit */ + /* Random function provided – call it and use up to 56 bits at a time */ size_t bytes = (length_bits + 7) / 8; bd = blob_new((size_t)length_bits); if (bd) { bd->length = length_bits; /* Ensure the backing storage starts out zeroed */ memset(bd->data, 0, bytes); - for (size_t i = 0; i < length_bits; i++) { + + size_t bits_written = 0; + while (bits_written < length_bits) { JSValue randval = JS_Call(ctx, argv[1], JS_UNDEFINED, 0, NULL); if (JS_IsException(randval)) { blob_destroy(bd); return JS_EXCEPTION; } - int32_t fitval; - JS_ToInt32(ctx, &fitval, randval); + int64_t fitval; + JS_ToInt64(ctx, &fitval, randval); JS_FreeValue(ctx, randval); - - /* Compute which byte and which bit within that byte to set/clear */ - size_t byte_idx = i / 8; - size_t bit_idx = i % 8; - - if (fitval & 1) - bd->data[byte_idx] |= (uint8_t)(1 << bit_idx); - else - bd->data[byte_idx] &= (uint8_t)~(1 << bit_idx); + + /* Extract up to 56 bits from the random value */ + size_t bits_to_use = length_bits - bits_written; + if (bits_to_use > 52) bits_to_use = 52; + + /* Write bits from the random value */ + for (size_t j = 0; j < bits_to_use; j++) { + size_t bit_pos = bits_written + j; + size_t byte_idx = bit_pos / 8; + size_t bit_idx = bit_pos % 8; + + if (fitval & (1LL << j)) + bd->data[byte_idx] |= (uint8_t)(1 << bit_idx); + else + bd->data[byte_idx] &= (uint8_t)~(1 << bit_idx); + } + + bits_written += bits_to_use; } } } else { diff --git a/source/qjs_math.c b/source/qjs_math.c index b201bbed..c071806c 100644 --- a/source/qjs_math.c +++ b/source/qjs_math.c @@ -231,20 +231,6 @@ JSC_CCALL(math_from_to, return jsarr; ) -JSC_CCALL(math_rand, - MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; - return number2js(js, genRand(mrand)); -) - -JSC_CCALL(math_randi, - MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; - return number2js(js, genRandLong(mrand)); -) - -JSC_CCALL(math_srand, - MTRand *mrand = &((cell_rt*)JS_GetContextOpaque(js))->mrand; - m_seedRand(mrand, js2number(js,argv[0])); -) JSC_CCALL(math_dot, size_t alen, blen; @@ -497,9 +483,6 @@ static const JSCFunctionListEntry js_math_funcs[] = { MIST_FUNC_DEF(math, median, 1), MIST_FUNC_DEF(math, length, 1), MIST_FUNC_DEF(math, from_to, 5), - MIST_FUNC_DEF(math, rand, 0), - MIST_FUNC_DEF(math, randi, 0), - MIST_FUNC_DEF(math, srand,0), }; JSValue js_math_use(JSContext *js) { diff --git a/source/qjs_text.c b/source/qjs_text.c new file mode 100644 index 00000000..e1e317ba --- /dev/null +++ b/source/qjs_text.c @@ -0,0 +1,94 @@ +#include "qjs_text.h" +#include "qjs_blob.h" +#include "blob.h" +#include "jsffi.h" +#include +#include + +JSC_CCALL(text_blob_to_hex, + size_t blob_len; + void *blob_data = js_get_blob_data(js, &blob_len, argv[0]); + if (!blob_data) return JS_ThrowTypeError(js, "Expected stone blob"); + + uint8_t *bytes = (uint8_t *)blob_data; + + // Hex encoding: each byte becomes 2 hex characters + size_t hex_len = blob_len * 2; + char *hex_str = malloc(hex_len + 1); + + static const char hex_digits[] = "0123456789ABCDEF"; + + for (size_t i = 0; i < blob_len; i++) { + hex_str[i * 2] = hex_digits[(bytes[i] >> 4) & 0xF]; + hex_str[i * 2 + 1] = hex_digits[bytes[i] & 0xF]; + } + + hex_str[hex_len] = '\0'; + ret = JS_NewString(js, hex_str); + free(hex_str); +) + +JSC_CCALL(text_blob_to_base32, + size_t blob_len; + void *blob_data = js_get_blob_data(js, &blob_len, argv[0]); + if (!blob_data) return JS_ThrowTypeError(js, "Expected stone blob"); + + uint8_t *bytes = (uint8_t *)blob_data; + + static const char b32_digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + + // Calculate output length: each 5 bytes becomes 8 base32 chars + size_t groups = (blob_len + 4) / 5; + size_t b32_len = groups * 8; + char *b32_str = malloc(b32_len + 1); + + size_t in_idx = 0; + size_t out_idx = 0; + + while (in_idx < blob_len) { + // Process 5 bytes (40 bits) at a time to produce 8 base32 chars + uint64_t buf = 0; + int bytes_read = 0; + + // Read up to 5 bytes into buffer + for (int i = 0; i < 5 && in_idx < blob_len; i++) { + buf = (buf << 8) | bytes[in_idx++]; + bytes_read++; + } + + // Pad with zeros if we read fewer than 5 bytes + buf = buf << (8 * (5 - bytes_read)); + + // Extract 8 groups of 5 bits from the 40-bit buffer + for (int i = 7; i >= 0; i--) { + b32_str[out_idx + i] = b32_digits[buf & 0x1F]; + buf >>= 5; + } + out_idx += 8; + } + + // Replace trailing chars with padding if needed + int padding = (5 - (blob_len % 5)) % 5; + if (padding > 0) { + static const int pad_chars[] = {0, 6, 4, 3, 1}; + for (int i = 0; i < pad_chars[padding]; i++) { + b32_str[b32_len - 1 - i] = '='; + } + } + + b32_str[b32_len] = '\0'; + ret = JS_NewString(js, b32_str); + free(b32_str); +) + +static const JSCFunctionListEntry js_text_funcs[] = { + MIST_FUNC_DEF(text, blob_to_hex, 1), + MIST_FUNC_DEF(text, blob_to_base32, 1), +}; + +JSValue js_text_use(JSContext *js) +{ + JSValue mod = JS_NewObject(js); + JS_SetPropertyFunctionList(js, mod, js_text_funcs, countof(js_text_funcs)); + return mod; +} diff --git a/source/qjs_text.h b/source/qjs_text.h new file mode 100644 index 00000000..ee59e7e0 --- /dev/null +++ b/source/qjs_text.h @@ -0,0 +1,8 @@ +#ifndef QJS_TEXT_H +#define QJS_TEXT_H + +#include + +JSValue js_text_use(JSContext *js); + +#endif diff --git a/tests/guid.ce b/tests/guid.ce new file mode 100644 index 00000000..b0cd4c1c --- /dev/null +++ b/tests/guid.ce @@ -0,0 +1,14 @@ +var blob = use('blob') +var time = use('time') + +var st = time.number() +var guid = new blob(256, $_.random_fit) +stone(guid) +var btime = time.number()-st +st = time.number() +guid = text(guid,'h') +st = time.number()-st +log.console(`took ${btime*1000000} us to make blob; took ${st*1000000} us to make it text`) +log.console(guid.toLowerCase()) +log.console(guid.length) +$_.stop() \ No newline at end of file diff --git a/tests/text_test.ce b/tests/text_test.ce new file mode 100644 index 00000000..bd813df3 --- /dev/null +++ b/tests/text_test.ce @@ -0,0 +1,23 @@ +// Test text module +var text = use('text') +var blob = use('blob') + +// Create a test blob with some data +var b = new blob() +b.write_text("Hello") +b.stone() + +log.console("Original blob content (as text):", text(b)) +log.console("Hex encoding:", text(b, 'h')) +log.console("Base32 encoding:", text(b, 't')) + +// Test with binary data +var b2 = new blob() +b2.write_fit(255, 8) +b2.write_fit(170, 8) // 10101010 in binary +b2.write_fit(15, 8) // 00001111 in binary +b2.stone() + +log.console("\nBinary data tests:") +log.console("Hex encoding:", text(b2, 'h')) +log.console("Base32 encoding:", text(b2, 't')) \ No newline at end of file