fix nota
This commit is contained in:
198
source/nota.h
198
source/nota.h
@@ -5,7 +5,6 @@
|
||||
#include <stdint.h>
|
||||
#include "kim.h"
|
||||
|
||||
/* Nota type nibble values */
|
||||
#define NOTA_BLOB 0x00
|
||||
#define NOTA_TEXT 0x10
|
||||
#define NOTA_ARR 0x20
|
||||
@@ -21,7 +20,6 @@
|
||||
#define NOTA_PRIVATE 0x08
|
||||
#define NOTA_SYSTEM 0x09
|
||||
|
||||
/* Some internal constants/macros (used in varint logic, etc.) */
|
||||
#define NOTA_CONT 0x80
|
||||
#define NOTA_DATA 0x7f
|
||||
#define NOTA_INT_DATA 0x07
|
||||
@@ -33,7 +31,6 @@
|
||||
#define CONTINUE(CHAR) (CHAR>>7)
|
||||
#define UTF8_DATA 0x3f
|
||||
|
||||
/* A helper to get the high-level Nota type nibble from a byte */
|
||||
static inline int nota_type(const char *nota) { return (*nota) & 0x70; }
|
||||
|
||||
char *nota_read_blob(long long *len, char **blob, char *nota);
|
||||
@@ -50,10 +47,8 @@ typedef struct NotaBuffer {
|
||||
size_t capacity; /* allocated size of data */
|
||||
} NotaBuffer;
|
||||
|
||||
/* Initialize a NotaBuffer with a given initial capacity. */
|
||||
void nota_buffer_init(NotaBuffer *nb, size_t initial_capacity);
|
||||
|
||||
/* Free the buffer's internal memory. (Does NOT free nb itself.) */
|
||||
void nota_buffer_free(NotaBuffer *nb);
|
||||
|
||||
void nota_write_blob (NotaBuffer *nb, unsigned long long nbits, const char *data);
|
||||
@@ -73,25 +68,18 @@ void nota_write_sym (NotaBuffer *nb, int sym);
|
||||
|
||||
#include "kim.h"
|
||||
|
||||
/* -------------------------------------------------------
|
||||
HELPER: skip a varint
|
||||
------------------------------------------------------- */
|
||||
static inline char *nota_skip(char *nota)
|
||||
{
|
||||
while (CONTINUE(*nota)) {
|
||||
nota++;
|
||||
}
|
||||
while (CONTINUE(*nota))
|
||||
nota++;
|
||||
return nota + 1;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------
|
||||
HELPER: read a varint
|
||||
------------------------------------------------------- */
|
||||
char *nota_read_num(long long *n, char *nota)
|
||||
{
|
||||
if (!n) {
|
||||
return nota_skip(nota);
|
||||
}
|
||||
if (!n)
|
||||
return nota_skip(nota);
|
||||
|
||||
unsigned char b = (unsigned char)*nota;
|
||||
long long result = b & NOTA_HEAD_DATA;
|
||||
nota++;
|
||||
@@ -106,7 +94,7 @@ char *nota_read_num(long long *n, char *nota)
|
||||
}
|
||||
|
||||
/* Count how many bits of varint we need to encode n,
|
||||
with sb “special bits” in the first byte. */
|
||||
with sb “special bits” in the first byte */
|
||||
static inline int nota_bits(long long n, int sb)
|
||||
{
|
||||
if (n == 0) return sb;
|
||||
@@ -116,7 +104,6 @@ static inline int nota_bits(long long n, int sb)
|
||||
return needed;
|
||||
}
|
||||
|
||||
/* Write a varint into *nota, with sb bits in the first char (which is already set). */
|
||||
static inline char *nota_continue_num(long long n, char *nota, int sb)
|
||||
{
|
||||
int bits = nota_bits(n, sb);
|
||||
@@ -272,7 +259,6 @@ void nota_buffer_free(NotaBuffer *nb)
|
||||
nb->capacity = 0;
|
||||
}
|
||||
|
||||
/* Allocate 'len' bytes in the buffer and return a pointer to them. */
|
||||
static char *nota_buffer_alloc(NotaBuffer *nb, size_t len)
|
||||
{
|
||||
nota_buffer_grow(nb, len);
|
||||
@@ -363,183 +349,11 @@ void nota_write_record(NotaBuffer *nb, unsigned long long count)
|
||||
nb->size -= (10 - used);
|
||||
}
|
||||
|
||||
void nota_write_number_str(NotaBuffer *nb, const char *str)
|
||||
{
|
||||
/* -------------------------------------------
|
||||
1) Parse sign
|
||||
------------------------------------------- */
|
||||
int negative = 0;
|
||||
if (*str == '+') {
|
||||
str++;
|
||||
}
|
||||
else if (*str == '-') {
|
||||
negative = 1;
|
||||
str++;
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
2) Parse integer part
|
||||
------------------------------------------- */
|
||||
long long coefficient = 0;
|
||||
int got_digits = 0;
|
||||
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
got_digits = 1;
|
||||
int d = (*str - '0');
|
||||
str++;
|
||||
|
||||
// Basic overflow check (very naive):
|
||||
if (coefficient <= (LLONG_MAX - d) / 10) {
|
||||
coefficient = coefficient * 10 + d;
|
||||
} else {
|
||||
// If you want to handle overflow by switching to float, do that here.
|
||||
// For simplicity, let's just keep wrapping. In production, be careful!
|
||||
coefficient = coefficient * 10 + d;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
3) Check for decimal part
|
||||
------------------------------------------- */
|
||||
int has_decimal_point = 0;
|
||||
int fraction_digits = 0;
|
||||
|
||||
if (*str == '.') {
|
||||
has_decimal_point = 1;
|
||||
str++;
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
got_digits = 1;
|
||||
int d = (*str - '0');
|
||||
str++;
|
||||
fraction_digits++;
|
||||
if (coefficient <= (LLONG_MAX - d) / 10) {
|
||||
coefficient = coefficient * 10 + d;
|
||||
} else {
|
||||
// Same naive overflow comment
|
||||
coefficient = coefficient * 10 + d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
4) Check for exponent part
|
||||
------------------------------------------- */
|
||||
int exponent_negative = 0;
|
||||
long long exponent_val = 0;
|
||||
|
||||
if (*str == 'e' || *str == 'E') {
|
||||
str++;
|
||||
if (*str == '+') {
|
||||
str++;
|
||||
}
|
||||
else if (*str == '-') {
|
||||
exponent_negative = 1;
|
||||
str++;
|
||||
}
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
int d = (*str - '0');
|
||||
str++;
|
||||
if (exponent_val <= (LLONG_MAX - d) / 10) {
|
||||
exponent_val = exponent_val * 10 + d;
|
||||
} else {
|
||||
// Again, naive overflow handling
|
||||
exponent_val = exponent_val * 10 + d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
5) If there were no valid digits at all,
|
||||
store 0 and return. (simple fallback)
|
||||
------------------------------------------- */
|
||||
if (!got_digits) {
|
||||
nota_write_int_buf(nb, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
6) Combine fraction digits into exponent
|
||||
final_exponent = exponent_val - fraction_digits
|
||||
(apply exponent sign if any)
|
||||
------------------------------------------- */
|
||||
if (exponent_negative) {
|
||||
exponent_val = -exponent_val;
|
||||
}
|
||||
long long final_exponent = exponent_val - fraction_digits;
|
||||
|
||||
/* -------------------------------------------
|
||||
7) Decide if we are storing an integer
|
||||
or a float in Nota format.
|
||||
-------------------------------------------
|
||||
Rule used here:
|
||||
- If there's no decimal point AND final_exponent == 0,
|
||||
=> integer
|
||||
- If we do have a decimal point, but fraction_digits == 0
|
||||
and exponent_val == 0, then the user typed something
|
||||
like "123." or "100.0". That is effectively an integer,
|
||||
so store it as an integer if you want a purely numeric approach.
|
||||
- Otherwise store as float.
|
||||
------------------------------------------- */
|
||||
|
||||
// If "no decimal" => definitely integer:
|
||||
// or decimal present but fraction_digits=0 & exponent_val=0 => integer
|
||||
int treat_as_integer = 0;
|
||||
if (!has_decimal_point && final_exponent == 0) {
|
||||
treat_as_integer = 1;
|
||||
}
|
||||
else if (has_decimal_point && fraction_digits == 0 && exponent_val == 0) {
|
||||
// Means "123." or "123.0"
|
||||
treat_as_integer = 1;
|
||||
}
|
||||
|
||||
if (treat_as_integer) {
|
||||
// If negative => flip the sign in the stored value
|
||||
if (negative) {
|
||||
coefficient = -coefficient;
|
||||
}
|
||||
// Write the integer in Nota format (varint with sign bit)
|
||||
nota_write_int_buf(nb, coefficient);
|
||||
return;
|
||||
}
|
||||
|
||||
/* -------------------------------------------
|
||||
8) Write as float in Nota format
|
||||
We do basically the same approach as
|
||||
nota_write_float_buf does:
|
||||
- NOTA_FLOAT nibble
|
||||
- sign bit if negative
|
||||
- exponent sign bit if final_exponent < 0
|
||||
- varint of |final_exponent|
|
||||
- varint of |coefficient|
|
||||
------------------------------------------- */
|
||||
{
|
||||
char *p = nota_buffer_alloc(nb, 21); // Up to ~21 bytes worst-case
|
||||
p[0] = NOTA_FLOAT;
|
||||
if (negative) {
|
||||
p[0] |= (1 << 3); // Mantissa sign bit
|
||||
}
|
||||
if (final_exponent < 0) {
|
||||
p[0] |= (1 << 4); // Exponent sign bit
|
||||
final_exponent = -final_exponent;
|
||||
}
|
||||
// Write exponent as varint (with 3 bits used in the first byte)
|
||||
char *c = nota_continue_num(final_exponent, p, 3);
|
||||
// Write the absolute coefficient (7 bits used in the first byte)
|
||||
char *end = nota_continue_num(coefficient, c, 7);
|
||||
|
||||
// Adjust the buffer size to the actual used length
|
||||
size_t used = (size_t)(end - p);
|
||||
nb->size -= (21 - used);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void nota_write_number(NotaBuffer *nb, double n)
|
||||
{
|
||||
nota_write_int_or_float_buf(nb, n);
|
||||
}
|
||||
|
||||
/* Write an integer in varint form (with sign bit) */
|
||||
static void nota_write_int_buf(NotaBuffer *nb, long long n)
|
||||
{
|
||||
/* up to ~10 bytes for varint */
|
||||
|
||||
@@ -146,19 +146,13 @@ static void nota_encode_value(NotaEncodeContext *enc, JSValueConst val, JSValueC
|
||||
int tag = JS_VALUE_GET_TAG(replaced);
|
||||
|
||||
switch (tag) {
|
||||
case JS_TAG_INT: {
|
||||
case JS_TAG_INT:
|
||||
case JS_TAG_FLOAT64: {
|
||||
double d;
|
||||
JS_ToFloat64(ctx, &d, replaced);
|
||||
nota_write_number(&enc->nb, d);
|
||||
break;
|
||||
}
|
||||
case JS_TAG_BIG_INT:
|
||||
case JS_TAG_FLOAT64: {
|
||||
const char *str = JS_ToCString(ctx, replaced);
|
||||
nota_write_number_str(&enc->nb, str);
|
||||
JS_FreeCString(ctx, str);
|
||||
break;
|
||||
}
|
||||
case JS_TAG_STRING: {
|
||||
const char *str = JS_ToCString(ctx, replaced);
|
||||
nota_write_text(&enc->nb, str);
|
||||
|
||||
Reference in New Issue
Block a user