diff --git a/source/nota.h b/source/nota.h index 9d235ec2..db654c80 100755 --- a/source/nota.h +++ b/source/nota.h @@ -77,16 +77,24 @@ char *nota_skip(char *nota) char *nota_read_num(long long *n, char *nota) { - if (!n) - return nota_skip(nota); - - *n = 0; - *n |= (*nota) & NOTA_HEAD_DATA; - - while (CONTINUE(*(nota++))) - *n = (((*n<<7) | *nota) & NOTA_DATA); + if (!n) { + return nota_skip(nota); + } - return nota; + // Start by reading the first byte + unsigned char b = *nota; + int result = b & NOTA_HEAD_DATA; // lower bits + nota++; + + // While the top bit is set, read more 7-bit chunks + while (CONTINUE(b)) { + b = *nota; + nota++; + result = (result << 7) | (b & NOTA_DATA); + } + + *n = result; + return nota; } // Given a number n, and bits used in the first char sb, how many bits are needed diff --git a/source/qjs_nota.c b/source/qjs_nota.c index a71c3621..5b157d30 100755 --- a/source/qjs_nota.c +++ b/source/qjs_nota.c @@ -117,13 +117,21 @@ char *js_do_nota_encode(JSContext *js, JSValue v, char *nota) return nota_write_blob(bloblen*8, blob, nota); if (JS_IsArray(js, v)) { + JSValue lengthVal = JS_GetPropertyStr(js, v, "length"); int n; - JS_ToInt32(js, &n, JS_GetPropertyStr(js, v, "length")); + JS_ToInt32(js, &n, lengthVal); + JS_FreeValue(js, lengthVal); + nota = nota_write_array(n, nota); - for (int i = 0; i < n; i++) - nota = js_do_nota_encode(js, JS_GetPropertyUint32(js, v, i), nota); + + for (int i = 0; i < n; i++) { + JSValue elemVal = JS_GetPropertyUint32(js, v, i); + nota = js_do_nota_encode(js, elemVal, nota); + JS_FreeValue(js, elemVal); + } return nota; } + JS_GetOwnPropertyNames(js, &ptab, &plen, v, JS_GPN_ENUM_ONLY | JS_GPN_STRING_MASK); nota = nota_write_record(plen, nota); diff --git a/tests/nota.js b/tests/nota.js index a403995e..98b4bda1 100644 --- a/tests/nota.js +++ b/tests/nota.js @@ -96,6 +96,13 @@ function deepCompare(expected, actual, path = '') { } // Extended test cases covering all Nota types from documentation +var testarr = [] +var hex = "a374" +for (var i = 0; i < 500; i++) { + testarr.push(1) + hex += "61" +} + var testCases = [ // Integer tests { input: 0, expectedHex: "60" }, @@ -130,6 +137,8 @@ var testCases = [ { input: new Uint8Array([0b11110000, 0b11100011, 0b00100000, 0b10000000]).buffer, expectedHex: "8019f0e32080" }, // 25 bits example padded to 32 bits + { input: testarr, expectedHex: hex }, + // Array tests { input: [], expectedHex: "20" }, { input: [1, 2, 3], expectedHex: "23616263" }, @@ -156,6 +165,13 @@ var testCases = [ { input: { system: { msg: "hello" } }, expectedHex: "3179216d73671568656c6c6f" }, + { input: [ { system: {msg: "hello" } }, { + num: 42, + arr: [1, -1, 2.5], + str: "test", + obj: { x: true } + } ], expectedHex: "223179216d73671568656c6c6f34216e756d622a2173747214746573742161727223616965235840216f626a21117873" }, + // Additional edge cases { input: new Uint8Array([]).buffer, expectedHex: "00" }, // Empty blob { input: [[]], expectedHex: "2120" }, // Nested empty array