teptris 0.3.23.0 → 0.3.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ /* Unicode property ranges for the schema regex \p{...}. Generated. */
2
+ #ifndef TEPTRIS_SCHEMA_UNICODE_PROPS_H
3
+ #define TEPTRIS_SCHEMA_UNICODE_PROPS_H
4
+
5
+ #include <stdint.h>
6
+
7
+ typedef struct {
8
+ uint32_t lo, hi;
9
+ } teptris_uc_range;
10
+
11
+ typedef struct {
12
+ const char *name;
13
+ const teptris_uc_range *ranges;
14
+ int n;
15
+ } teptris_uc_prop;
16
+
17
+ extern const teptris_uc_prop teptris_unicode_props[];
18
+ extern const int teptris_n_unicode_props;
19
+
20
+ #endif
@@ -41,6 +41,13 @@ typedef struct {
41
41
  size_t n_keys, cap_keys;
42
42
  size_t *idx;
43
43
  size_t n_idx, cap_idx;
44
+ /* stamp-validated open-addressing indexes: a slot holds the
45
+ * entry's position when inserted, so a trial's truncate
46
+ * (n_keys rewind) self-invalidates without a rebuild */
47
+ struct { const char *key; size_t stamp; } *khash;
48
+ size_t khash_cap; /* power of two, 0 = absent */
49
+ struct { size_t val; size_t stamp; } *ihash;
50
+ size_t ihash_cap;
44
51
  } *frames;
45
52
  int n_frames, cap_frames;
46
53
  /* dynamic-scope stack for $dynamicRef / $recursiveRef: one frame
@@ -206,6 +213,9 @@ static bool frame_grow(vctx *vc) {
206
213
  return true;
207
214
  }
208
215
 
216
+ static void frame_khash_insert(struct eval_frame *f, const char *key);
217
+ static void frame_ihash_insert(struct eval_frame *f, size_t idx);
218
+
209
219
  static bool frame_push(vctx *vc, const sch_svalue *v) {
210
220
  if (!frame_grow(vc)) return false;
211
221
  struct eval_frame *f = &vc->frames[vc->n_frames++];
@@ -233,6 +243,9 @@ static void frame_merge_up(vctx *vc) {
233
243
  }
234
244
  memcpy(p->keys + p->n_keys, f->keys, f->n_keys * sizeof(*f->keys));
235
245
  p->n_keys += f->n_keys;
246
+ for (size_t i = p->n_keys - f->n_keys; i < p->n_keys; i++) {
247
+ frame_khash_insert(p, p->keys[i]);
248
+ }
236
249
  }
237
250
  if (f->n_idx > 0) {
238
251
  if (p->n_idx + f->n_idx > p->cap_idx) {
@@ -245,6 +258,9 @@ static void frame_merge_up(vctx *vc) {
245
258
  }
246
259
  memcpy(p->idx + p->n_idx, f->idx, f->n_idx * sizeof(*f->idx));
247
260
  p->n_idx += f->n_idx;
261
+ for (size_t i = p->n_idx - f->n_idx; i < p->n_idx; i++) {
262
+ frame_ihash_insert(p, p->idx[i]);
263
+ }
248
264
  }
249
265
  }
250
266
 
@@ -256,23 +272,111 @@ static void frame_pop(vctx *vc) {
256
272
  struct eval_frame *f = &vc->frames[vc->n_frames - 1];
257
273
  free(f->keys);
258
274
  free(f->idx);
275
+ free(f->khash);
276
+ free(f->ihash);
259
277
  vc->n_frames--;
260
278
  }
261
279
 
262
- static bool frame_key_seen(const struct eval_frame *f, const char *key) {
280
+ static uint64_t frame_mix(uint64_t x) {
281
+ x ^= x >> 33;
282
+ x *= 0xff51afd7ed558ccdULL;
283
+ x ^= x >> 33;
284
+ x *= 0xc4ceb9fe1a85ec53ULL;
285
+ x ^= x >> 33;
286
+ return x;
287
+ }
288
+
289
+ static uint64_t frame_str_hash(const char *s) {
290
+ uint64_t h = 1469598103934665603ULL;
291
+ for (; *s != '\0'; s++) {
292
+ h ^= (unsigned char)*s;
293
+ h *= 1099511628211ULL;
294
+ }
295
+ return h;
296
+ }
297
+
298
+ /* rebuild a key index from the frame's valid entries */
299
+ static void frame_khash_build(struct eval_frame *f) {
300
+ size_t cap = 16;
301
+ while (cap * 7 / 10 < f->n_keys + 1) cap *= 2;
302
+ void *nh = realloc(f->khash, cap * sizeof(*f->khash));
303
+ if (nh == NULL) return;
304
+ f->khash = nh;
305
+ f->khash_cap = cap;
306
+ for (size_t i = 0; i < cap; i++) f->khash[i].stamp = (size_t)-1;
263
307
  for (size_t i = 0; i < f->n_keys; i++) {
264
- if (strcmp(f->keys[i], key) == 0) return true;
308
+ size_t slot = frame_mix(frame_str_hash(f->keys[i])) & (cap - 1);
309
+ while (f->khash[slot].stamp != (size_t)-1) {
310
+ slot = (slot + 1) & (cap - 1);
311
+ }
312
+ f->khash[slot].key = f->keys[i];
313
+ f->khash[slot].stamp = i;
314
+ }
315
+ }
316
+
317
+ static bool frame_key_seen(const struct eval_frame *f, const char *key) {
318
+ if (f->khash_cap == 0) return false;
319
+ size_t slot = frame_mix(frame_str_hash(key)) & (f->khash_cap - 1);
320
+ while (f->khash[slot].stamp != (size_t)-1) {
321
+ if (f->khash[slot].stamp < f->n_keys &&
322
+ strcmp(f->khash[slot].key, key) == 0) {
323
+ return true;
324
+ }
325
+ slot = (slot + 1) & (f->khash_cap - 1);
265
326
  }
266
327
  return false;
267
328
  }
268
329
 
269
- static bool frame_idx_seen(const struct eval_frame *f, size_t idx) {
330
+ static void frame_khash_insert(struct eval_frame *f, const char *key) {
331
+ if (f->n_keys + 1 > f->khash_cap * 7 / 10) frame_khash_build(f);
332
+ size_t slot = frame_mix(frame_str_hash(key)) & (f->khash_cap - 1);
333
+ while (f->khash[slot].stamp != (size_t)-1) {
334
+ slot = (slot + 1) & (f->khash_cap - 1);
335
+ }
336
+ f->khash[slot].key = key;
337
+ f->khash[slot].stamp = f->n_keys - 1;
338
+ }
339
+
340
+ static void frame_ihash_build(struct eval_frame *f) {
341
+ size_t cap = 16;
342
+ while (cap * 7 / 10 < f->n_idx + 1) cap *= 2;
343
+ void *nh = realloc(f->ihash, cap * sizeof(*f->ihash));
344
+ if (nh == NULL) return;
345
+ f->ihash = nh;
346
+ f->ihash_cap = cap;
347
+ for (size_t i = 0; i < cap; i++) f->ihash[i].stamp = (size_t)-1;
270
348
  for (size_t i = 0; i < f->n_idx; i++) {
271
- if (f->idx[i] == idx) return true;
349
+ size_t slot = frame_mix((uint64_t)f->idx[i]) & (cap - 1);
350
+ while (f->ihash[slot].stamp != (size_t)-1) {
351
+ slot = (slot + 1) & (cap - 1);
352
+ }
353
+ f->ihash[slot].val = f->idx[i];
354
+ f->ihash[slot].stamp = i;
355
+ }
356
+ }
357
+
358
+ static bool frame_idx_seen(const struct eval_frame *f, size_t idx) {
359
+ if (f->ihash_cap == 0) return false;
360
+ size_t slot = frame_mix((uint64_t)idx) & (f->ihash_cap - 1);
361
+ while (f->ihash[slot].stamp != (size_t)-1) {
362
+ if (f->ihash[slot].stamp < f->n_idx && f->ihash[slot].val == idx) {
363
+ return true;
364
+ }
365
+ slot = (slot + 1) & (f->ihash_cap - 1);
272
366
  }
273
367
  return false;
274
368
  }
275
369
 
370
+ static void frame_ihash_insert(struct eval_frame *f, size_t idx) {
371
+ if (f->n_idx + 1 > f->ihash_cap * 7 / 10) frame_ihash_build(f);
372
+ size_t slot = frame_mix((uint64_t)idx) & (f->ihash_cap - 1);
373
+ while (f->ihash[slot].stamp != (size_t)-1) {
374
+ slot = (slot + 1) & (f->ihash_cap - 1);
375
+ }
376
+ f->ihash[slot].val = idx;
377
+ f->ihash[slot].stamp = f->n_idx - 1;
378
+ }
379
+
276
380
  static void frame_add_key(vctx *vc, const char *key) {
277
381
  if (vc->n_frames == 0) return;
278
382
  struct eval_frame *f = &vc->frames[vc->n_frames - 1];
@@ -284,6 +388,7 @@ static void frame_add_key(vctx *vc, const char *key) {
284
388
  f->keys = nk;
285
389
  }
286
390
  f->keys[f->n_keys++] = key;
391
+ frame_khash_insert(f, key);
287
392
  }
288
393
 
289
394
  static void frame_add_idx(vctx *vc, size_t idx) {
@@ -297,6 +402,7 @@ static void frame_add_idx(vctx *vc, size_t idx) {
297
402
  f->idx = ni;
298
403
  }
299
404
  f->idx[f->n_idx++] = idx;
405
+ frame_ihash_insert(f, idx);
300
406
  }
301
407
 
302
408
  /* drop the annotations a trial contributed to its merge target (the
@@ -313,6 +419,8 @@ static void frames_free(vctx *vc) {
313
419
  for (int i = 0; i < vc->n_frames; i++) {
314
420
  free(vc->frames[i].keys);
315
421
  free(vc->frames[i].idx);
422
+ free(vc->frames[i].khash);
423
+ free(vc->frames[i].ihash);
316
424
  }
317
425
  free(vc->frames);
318
426
  }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Teptris
4
- VERSION = "0.3.23.0"
4
+ VERSION = "0.3.24.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teptris
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.23.0
4
+ version: 0.3.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - teptris contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-11-03 00:00:00.000000000 Z
11
+ date: 2026-11-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A native C extension over libteptris, a C99 TOML 1.1 parser/emitter.
14
14
  API shape mirrors the tomlib gem.
@@ -64,6 +64,8 @@ files:
64
64
  - ext/teptris_ext/engine/src/teptris/schema/regex.h
65
65
  - ext/teptris_ext/engine/src/teptris/schema/schema.c
66
66
  - ext/teptris_ext/engine/src/teptris/schema/schema_internal.h
67
+ - ext/teptris_ext/engine/src/teptris/schema/unicode_props.c
68
+ - ext/teptris_ext/engine/src/teptris/schema/unicode_props.h
67
69
  - ext/teptris_ext/engine/src/teptris/schema/validate.c
68
70
  - ext/teptris_ext/engine/src/teptris/version.c
69
71
  - ext/teptris_ext/extconf.rb