Skip to content

Commit 66d9ec8

Browse files
Update jellyfish.c
1 parent 90d2cd3 commit 66d9ec8

File tree

1 file changed

+159
-28
lines changed

1 file changed

+159
-28
lines changed

code/logic/jellyfish.c

Lines changed: 159 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -168,64 +168,195 @@ void fossil_jellyfish_dump(const fossil_jellyfish_chain *chain) {
168168
}
169169
}
170170

171+
static bool match_key(const char **ptr, const char *key) {
172+
while (**ptr && (**ptr == ' ' || **ptr == '\n' || **ptr == '\r' || **ptr == '\t')) (*ptr)++;
173+
size_t len = strlen(key);
174+
if (strncmp(*ptr, key, len) == 0) {
175+
*ptr += len;
176+
return true;
177+
}
178+
return false;
179+
}
180+
181+
static void skip_whitespace(const char **ptr) {
182+
while (**ptr && (**ptr == ' ' || **ptr == '\n' || **ptr == '\r' || **ptr == '\t')) (*ptr)++;
183+
}
184+
185+
static bool parse_string(const char **ptr, char *out, size_t maxlen) {
186+
skip_whitespace(ptr);
187+
if (**ptr != '\"') return false;
188+
(*ptr)++;
189+
size_t i = 0;
190+
while (**ptr && **ptr != '\"' && i < maxlen - 1) {
191+
out[i++] = *(*ptr)++;
192+
}
193+
if (**ptr != '\"') return false;
194+
(*ptr)++;
195+
out[i] = '\0';
196+
return true;
197+
}
198+
199+
static bool parse_number(const char **ptr, double *out_double, long *out_long) {
200+
skip_whitespace(ptr);
201+
char buffer[64];
202+
size_t i = 0;
203+
while ((**ptr >= '0' && **ptr <= '9') || **ptr == '.' || **ptr == '-') {
204+
if (i < sizeof(buffer) - 1)
205+
buffer[i++] = *(*ptr)++;
206+
else
207+
return false;
208+
}
209+
buffer[i] = '\0';
210+
211+
if (strchr(buffer, '.')) {
212+
if (out_double) *out_double = atof(buffer);
213+
} else {
214+
if (out_long) *out_long = atol(buffer);
215+
}
216+
217+
return true;
218+
}
219+
171220
int fossil_jellyfish_load(fossil_jellyfish_chain *chain, const char *filepath) {
172221
FILE *fp = fopen(filepath, "rb");
173222
if (!fp) return 0;
174223

175-
// Optional: check file signature
176-
char sig[4];
177-
if (fread(sig, sizeof(char), 4, fp) != 4) {
224+
fseek(fp, 0, SEEK_END);
225+
long fsize = ftell(fp);
226+
fseek(fp, 0, SEEK_SET);
227+
228+
char *data = malloc(fsize + 1);
229+
if (!data) {
178230
fclose(fp);
179231
return 0;
180232
}
181-
if (sig[0] != 'J' || sig[1] != 'F' || sig[2] != 'S' || sig[3] != '1') {
182-
fclose(fp);
233+
234+
fread(data, 1, fsize, fp);
235+
fclose(fp);
236+
data[fsize] = '\0';
237+
238+
const char *ptr = data;
239+
skip_whitespace(&ptr);
240+
241+
// Look for signature
242+
if (!match_key(&ptr, "{\"signature\":")) {
243+
free(data);
183244
return 0;
184245
}
185246

186-
size_t count = 0;
187-
if (fread(&count, sizeof(size_t), 1, fp) != 1) {
188-
fclose(fp);
247+
char sig[8];
248+
if (!parse_string(&ptr, sig, sizeof(sig)) || strcmp(sig, "JFS1") != 0) {
249+
free(data);
189250
return 0;
190251
}
191252

192-
if (count > FOSSIL_JELLYFISH_MAX_MEM) {
193-
fclose(fp);
253+
if (!match_key(&ptr, ",\"blocks\":[")) {
254+
free(data);
194255
return 0;
195256
}
196257

197-
if (fread(chain->memory, sizeof(fossil_jellyfish_block), count, fp) != count) {
198-
fclose(fp);
199-
return 0;
258+
size_t count = 0;
259+
while (*ptr && *ptr != ']') {
260+
if (count >= FOSSIL_JELLYFISH_MAX_MEM) break;
261+
262+
if (!match_key(&ptr, "{")) {
263+
free(data);
264+
return 0;
265+
}
266+
267+
fossil_jellyfish_block *block = &chain->memory[count];
268+
memset(block, 0, sizeof(*block));
269+
270+
if (!match_key(&ptr, "\"input\":")) {
271+
free(data);
272+
return 0;
273+
}
274+
if (!parse_string(&ptr, block->input, sizeof(block->input))) {
275+
free(data);
276+
return 0;
277+
}
278+
279+
if (!match_key(&ptr, ",\"output\":")) {
280+
free(data);
281+
return 0;
282+
}
283+
if (!parse_string(&ptr, block->output, sizeof(block->output))) {
284+
free(data);
285+
return 0;
286+
}
287+
288+
if (!match_key(&ptr, ",\"timestamp\":")) {
289+
free(data);
290+
return 0;
291+
}
292+
if (!parse_number(&ptr, NULL, &block->timestamp)) {
293+
free(data);
294+
return 0;
295+
}
296+
297+
if (!match_key(&ptr, ",\"confidence\":")) {
298+
free(data);
299+
return 0;
300+
}
301+
if (!parse_number(&ptr, &block->confidence, NULL)) {
302+
free(data);
303+
return 0;
304+
}
305+
306+
if (!match_key(&ptr, "}")) {
307+
free(data);
308+
return 0;
309+
}
310+
311+
count++;
312+
313+
skip_whitespace(&ptr);
314+
if (*ptr == ',') ptr++;
200315
}
201316

202317
chain->count = count;
203-
fclose(fp);
318+
free(data);
204319
return 1;
205320
}
206321

207322
int fossil_jellyfish_save(const fossil_jellyfish_chain *chain, const char *filepath) {
208323
FILE *fp = fopen(filepath, "wb");
209324
if (!fp) return 0;
210325

211-
// Optional: write file signature
212-
const char sig[4] = { 'J', 'F', 'S', '1' };
213-
if (fwrite(sig, sizeof(char), 4, fp) != 4) {
214-
fclose(fp);
215-
return 0;
216-
}
326+
fprintf(fp, "{\n");
327+
fprintf(fp, " \"signature\": \"JFS1\",\n");
328+
fprintf(fp, " \"blocks\": [\n");
217329

218-
if (fwrite(&chain->count, sizeof(size_t), 1, fp) != 1) {
219-
fclose(fp);
220-
return 0;
221-
}
330+
for (size_t i = 0; i < chain->count; ++i) {
331+
const fossil_jellyfish_block *block = &chain->memory[i];
332+
333+
// Escape JSON strings (only for quote and backslash for simplicity)
334+
char input_escaped[512] = {0}, output_escaped[512] = {0};
335+
char *dst = input_escaped;
336+
for (const char *src = block->input; *src && (dst - input_escaped) < sizeof(input_escaped) - 2; ++src) {
337+
if (*src == '"' || *src == '\\') *dst++ = '\\';
338+
*dst++ = *src;
339+
}
340+
*dst = '\0';
222341

223-
if (fwrite(chain->memory, sizeof(fossil_jellyfish_block), chain->count, fp) != chain->count) {
224-
fclose(fp);
225-
return 0;
342+
dst = output_escaped;
343+
for (const char *src = block->output; *src && (dst - output_escaped) < sizeof(output_escaped) - 2; ++src) {
344+
if (*src == '"' || *src == '\\') *dst++ = '\\';
345+
*dst++ = *src;
346+
}
347+
*dst = '\0';
348+
349+
fprintf(fp, " {\n");
350+
fprintf(fp, " \"input\": \"%s\",\n", input_escaped);
351+
fprintf(fp, " \"output\": \"%s\",\n", output_escaped);
352+
fprintf(fp, " \"timestamp\": %ld,\n", block->timestamp);
353+
fprintf(fp, " \"confidence\": %.6f\n", block->confidence);
354+
fprintf(fp, " }%s\n", (i < chain->count - 1) ? "," : "");
226355
}
227356

228-
fflush(fp);
357+
fprintf(fp, " ]\n");
358+
fprintf(fp, "}\n");
359+
229360
fclose(fp);
230361
return 1;
231362
}

0 commit comments

Comments
 (0)