qr_reader-native 0.0.1

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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-mruby.txt +22 -0
  3. data/LICENSE-spinel.txt +19 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +61 -0
  6. data/ext/qr_reader_native/SPINEL_VERSION +1 -0
  7. data/ext/qr_reader_native/extconf.rb +8 -0
  8. data/ext/qr_reader_native/mruby/error.h +13 -0
  9. data/ext/qr_reader_native/mruby/internal.h +145 -0
  10. data/ext/qr_reader_native/mruby/string.h +22 -0
  11. data/ext/qr_reader_native/mruby.h +93 -0
  12. data/ext/qr_reader_native/mruby_shim.h +118 -0
  13. data/ext/qr_reader_native/qr_reader_native.c +13513 -0
  14. data/ext/qr_reader_native/qr_reader_native.h +29 -0
  15. data/ext/qr_reader_native/qr_reader_native_ext.c +598 -0
  16. data/ext/qr_reader_native/re_cased.h +71 -0
  17. data/ext/qr_reader_native/re_compile.c +5784 -0
  18. data/ext/qr_reader_native/re_ctype.h +3540 -0
  19. data/ext/qr_reader_native/re_exec.c +2190 -0
  20. data/ext/qr_reader_native/re_internal.h +671 -0
  21. data/ext/qr_reader_native/re_prop.h +4629 -0
  22. data/ext/qr_reader_native/re_spinel.c +363 -0
  23. data/ext/qr_reader_native/re_spinel.h +22 -0
  24. data/ext/qr_reader_native/re_spinel_utf8.inc +97 -0
  25. data/ext/qr_reader_native/re_utf8.c +156 -0
  26. data/ext/qr_reader_native/sp_alloc.c +1447 -0
  27. data/ext/qr_reader_native/sp_alloc.h +1196 -0
  28. data/ext/qr_reader_native/sp_argf.h +33 -0
  29. data/ext/qr_reader_native/sp_array.c +1052 -0
  30. data/ext/qr_reader_native/sp_array.h +456 -0
  31. data/ext/qr_reader_native/sp_bigint.c +5826 -0
  32. data/ext/qr_reader_native/sp_bigint.h +117 -0
  33. data/ext/qr_reader_native/sp_cold.c +5259 -0
  34. data/ext/qr_reader_native/sp_compat.h +402 -0
  35. data/ext/qr_reader_native/sp_core.c +818 -0
  36. data/ext/qr_reader_native/sp_core.h +56 -0
  37. data/ext/qr_reader_native/sp_crypto.c +877 -0
  38. data/ext/qr_reader_native/sp_crypto.h +169 -0
  39. data/ext/qr_reader_native/sp_dtoa.c +1533 -0
  40. data/ext/qr_reader_native/sp_dtoa.h +29 -0
  41. data/ext/qr_reader_native/sp_encoding_names.h +172 -0
  42. data/ext/qr_reader_native/sp_enum.h +86 -0
  43. data/ext/qr_reader_native/sp_exc.c +1185 -0
  44. data/ext/qr_reader_native/sp_exc.h +186 -0
  45. data/ext/qr_reader_native/sp_exc_ctx.h +56 -0
  46. data/ext/qr_reader_native/sp_fiber.c +889 -0
  47. data/ext/qr_reader_native/sp_fiber.h +162 -0
  48. data/ext/qr_reader_native/sp_fiber_ctx.h +84 -0
  49. data/ext/qr_reader_native/sp_format.c +695 -0
  50. data/ext/qr_reader_native/sp_format.h +83 -0
  51. data/ext/qr_reader_native/sp_gc.c +1793 -0
  52. data/ext/qr_reader_native/sp_gc.h +762 -0
  53. data/ext/qr_reader_native/sp_hash.c +131 -0
  54. data/ext/qr_reader_native/sp_hash.h +131 -0
  55. data/ext/qr_reader_native/sp_inspect.c +215 -0
  56. data/ext/qr_reader_native/sp_inspect.h +128 -0
  57. data/ext/qr_reader_native/sp_io.c +1676 -0
  58. data/ext/qr_reader_native/sp_io.h +272 -0
  59. data/ext/qr_reader_native/sp_iobuffer.c +1014 -0
  60. data/ext/qr_reader_native/sp_iobuffer.h +167 -0
  61. data/ext/qr_reader_native/sp_marshal.c +487 -0
  62. data/ext/qr_reader_native/sp_marshal.h +60 -0
  63. data/ext/qr_reader_native/sp_net.c +1029 -0
  64. data/ext/qr_reader_native/sp_net.h +205 -0
  65. data/ext/qr_reader_native/sp_pack.c +1254 -0
  66. data/ext/qr_reader_native/sp_poly_cold.c +1220 -0
  67. data/ext/qr_reader_native/sp_proc.c +410 -0
  68. data/ext/qr_reader_native/sp_proc.h +327 -0
  69. data/ext/qr_reader_native/sp_process.c +547 -0
  70. data/ext/qr_reader_native/sp_process_status.c +211 -0
  71. data/ext/qr_reader_native/sp_process_status.h +66 -0
  72. data/ext/qr_reader_native/sp_random.c +287 -0
  73. data/ext/qr_reader_native/sp_random.h +52 -0
  74. data/ext/qr_reader_native/sp_range.h +144 -0
  75. data/ext/qr_reader_native/sp_re.c +1379 -0
  76. data/ext/qr_reader_native/sp_re.h +186 -0
  77. data/ext/qr_reader_native/sp_re_names.h +59 -0
  78. data/ext/qr_reader_native/sp_sched.c +4044 -0
  79. data/ext/qr_reader_native/sp_sched.h +295 -0
  80. data/ext/qr_reader_native/sp_slab.c +1507 -0
  81. data/ext/qr_reader_native/sp_str.c +1462 -0
  82. data/ext/qr_reader_native/sp_str.h +306 -0
  83. data/ext/qr_reader_native/sp_str_crypt.c +23 -0
  84. data/ext/qr_reader_native/sp_string.c +92 -0
  85. data/ext/qr_reader_native/sp_string.h +253 -0
  86. data/ext/qr_reader_native/sp_system.c +78 -0
  87. data/ext/qr_reader_native/sp_system.h +18 -0
  88. data/ext/qr_reader_native/sp_time.c +860 -0
  89. data/ext/qr_reader_native/sp_time.h +100 -0
  90. data/ext/qr_reader_native/sp_types.h +292 -0
  91. data/ext/qr_reader_native/spinel_rt.h +19017 -0
  92. data/ext/qr_reader_native/unicase.c +399 -0
  93. data/ext/qr_reader_native/unicase.h +901 -0
  94. data/lib/qr_reader/native.rb +6 -0
  95. metadata +153 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 302d0fa96881495731eb70720ef57850577cd6abccdce2037be53640ad961fa2
4
+ data.tar.gz: 9b16290e8a14b8f8d9852e5306553bf7dc266b34a32d6e6c90b5f2fab7e02533
5
+ SHA512:
6
+ metadata.gz: b80a5b426ca64035ed32c7f03ddb4a38bf7f784e6fc96ffd1c1bae5112ea530230ddac1aaaa053b80017e45b6798b5c3d5a47e0c82d3a44285dfe38b7615c49b
7
+ data.tar.gz: 4712f8478d40c573807b3d65552910e6dc1ee583b4b51c93e36cbceac92dfd7a33f4eca90788e8082e2f577e958d5ecacbeaa1738749afa870e0dff970b75f49
data/LICENSE-mruby.txt ADDED
@@ -0,0 +1,22 @@
1
+ Parts of the Spinel runtime under ext/qr_reader_native (marked "See Copyright
2
+ Notice in mruby.h") are derived from mruby:
3
+
4
+ Copyright (c) 2010- mruby developers
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a
7
+ copy of this software and associated documentation files (the "Software"),
8
+ to deal in the Software without restriction, including without limitation
9
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ and/or sell copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
+ DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2024- Yukihiro Matsumoto (matz@ruby.or.jp)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation
6
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
+ and/or sell copies of the Software, and to permit persons to whom the
8
+ Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19
+ DEALINGS IN THE SOFTWARE.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Andi Idogawa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # qr_reader-native
2
+
3
+ Optional native speed-up for [qr_reader](https://github.com/largo/qr_reader).
4
+
5
+ qr_reader is pure Ruby. Its hot loops (image decoding, binarization, pattern
6
+ scanning) are written as plain-Ruby "kernels" in a subset of Ruby that the
7
+ [Spinel](https://github.com/matz/spinel) AOT compiler understands. This gem is
8
+ those very kernels compiled to C by Spinel: install it next to qr_reader and
9
+ qr_reader uses them automatically.
10
+
11
+ ```ruby
12
+ # Gemfile
13
+ gem "qr_reader"
14
+ gem "qr_reader-native" # optional; needs a C compiler at install time
15
+ ```
16
+
17
+ ```ruby
18
+ require "qr_reader"
19
+ QrReader.native? # => true when the native kernels are in use
20
+ ```
21
+
22
+ - Same results: the native kernels are compiled from the same source as the
23
+ Ruby ones and are tested against them.
24
+ - Safe to omit: without this gem, or on Rubies without C extensions (JRuby,
25
+ ruby.wasm, ...), qr_reader runs the same code as Ruby.
26
+ - Version-locked: it depends on the identical qr_reader version and is only
27
+ used when its kernel digest matches the installed qr_reader.
28
+ - `QR_READER_NATIVE=0` disables it at runtime.
29
+
30
+ ## Which kernels run natively
31
+
32
+ Each kernel is used natively only where that was measured to be faster
33
+ (`QrReader::NativeKernels::ALWAYS`/`WITHOUT_YJIT`/`NEVER`):
34
+
35
+ | kernel | with YJIT | without YJIT |
36
+ |---|---|---|
37
+ | hybrid binarization | 2.6x faster | 8.9x faster |
38
+ | finder-pattern scan | 9.6x faster | 6.3x faster |
39
+ | downscale | ~same | 8x faster |
40
+ | CCITT G3/G4 | ~same | 3.6x faster |
41
+ | JPEG IDCT rendering | 4-20x faster | 4-20x faster |
42
+ | PNG / pixel conversion | slower -> Ruby | 3x faster |
43
+ | JPEG entropy decoding | not used | not used |
44
+
45
+ JPEG entropy decoding compiled by the current Spinel (see
46
+ ext/qr_reader_native/SPINEL_VERSION) is 2x faster on small images but slows
47
+ down superlinearly with image size (32 ms at 640x480, 3 s at 2560x1920, versus
48
+ 83 ms in Ruby), so it stays Ruby until that is fixed in Spinel. The usual
49
+ suspects (`byteindex`, `byteslice`, `getbyte` on strings passed from CRuby,
50
+ appends, Strings held in Arrays) are all linear in isolation (see
51
+ bench/spinel/ in the qr_reader repository).
52
+
53
+ Installing compiles about 4 MB of generated C (Spinel's runtime included);
54
+ Spinel itself is not needed.
55
+
56
+ ## Licenses
57
+
58
+ MIT (see LICENSE.txt). `ext/qr_reader_native` contains code generated by
59
+ Spinel and the Spinel runtime (MIT, Copyright (c) 2024- Yukihiro Matsumoto,
60
+ see LICENSE-spinel.txt), parts of which derive from mruby (MIT, see
61
+ LICENSE-mruby.txt).
@@ -0,0 +1 @@
1
+ spinel 2026.09.12+7228 (84f5b5020) [gcc 15.2.0 (cc)]
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+
5
+ # The sources are generated by Spinel (script/native_generate.rb) and include
6
+ # Spinel's runtime; they only need a C compiler.
7
+ $INCFLAGS << " -I$(srcdir)"
8
+ create_makefile("qr_reader_native/qr_reader_native")
@@ -0,0 +1,13 @@
1
+ /* shim/mruby/error.h - see shim/mruby.h */
2
+ #ifndef SP_RE_SHIM_MRUBY_ERROR_H
3
+ #define SP_RE_SHIM_MRUBY_ERROR_H
4
+ #include "../mruby.h"
5
+
6
+ struct RClass;
7
+ struct RClass *mrb_exc_get_id(mrb_state *mrb, mrb_sym name);
8
+ mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass *c, mrb_value str);
9
+ /* the one exception the engine raises is a RegexpError, and it hands the
10
+ message to spinel's handler (sp_re_set_error_handler), which does not
11
+ return */
12
+ __attribute__((noreturn)) void mrb_exc_raise(mrb_state *mrb, mrb_value exc);
13
+ #endif
@@ -0,0 +1,145 @@
1
+ /* shim/mruby/internal.h - see shim/mruby.h. The UTF-8 scan and the case
2
+ declarations below are mruby's include/mruby/internal.h as it spells them. */
3
+ #ifndef SP_RE_SHIM_MRUBY_INTERNAL_H
4
+ #define SP_RE_SHIM_MRUBY_INTERNAL_H
5
+ #include "../mruby.h"
6
+
7
+ #define MRB_ENC_MULTIBYTE_P 1
8
+
9
+ /* a buffer that lives until the compile ends (re_spinel.c) */
10
+ void *mrb_temp_alloc(mrb_state *mrb, size_t size);
11
+
12
+ mrb_int mrb_utf8_to_buf(char *buf, mrb_int cp);
13
+
14
+ #define MRB_UTF8_MALFORMED (-1)
15
+ #define MRB_UTF8_TRUNCATED (-2)
16
+ #define MRB_UTF8_REDUNDANT (-3)
17
+ #define MRB_UTF8_EXCLUDED (-4)
18
+ #define MRB_UTF8_LONG (-5)
19
+
20
+ static inline mrb_int
21
+ mrb_utf8_scan(const char *p, const char *e, uint32_t *uv, const uint8_t bounds[][2])
22
+ {
23
+ /* the byte length a lead byte claims, by its top five bits; the last entry
24
+ folds 0xF8-0xFF together and they are told apart below. The table lives
25
+ in the function, as the lookup tables of boxing_word.h do, so that a
26
+ translation unit that never reads through the scan emits neither, at
27
+ any optimization level. */
28
+ static const uint8_t lead[32] = {
29
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
30
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0
31
+ };
32
+ const unsigned char *q = (const unsigned char*)p;
33
+ unsigned char c = q[0];
34
+ mrb_int n = lead[c >> 3];
35
+
36
+ if (n <= 1) {
37
+ if (n == 1) {
38
+ if (uv) *uv = c;
39
+ return 1;
40
+ }
41
+ /* a continuation byte leads nothing; 0xF8-0xFD claim five or six,
42
+ the lengths RFC 3629 withdrew, which a reader that wants them reads
43
+ for itself */
44
+ return (c < 0xF8 || c >= 0xFE) ? MRB_UTF8_MALFORMED : MRB_UTF8_LONG;
45
+ }
46
+ if (n > e - p) return MRB_UTF8_TRUNCATED;
47
+
48
+ /* Each byte after the lead has to continue it. A second byte inside its
49
+ bounds has, since the table admits nothing else, so only one outside
50
+ them walks the sequence to tell a malformed one from a bounded one. The
51
+ later checks nest in the order the bytes come, so a length costs the
52
+ compares up to its own and none past it. Read as a signed char, a
53
+ continuation byte is one below -0x40, a single compare where the mask
54
+ takes three. A caller that wants the form alone passes no `uv`, and the
55
+ value is dead code the compiler drops. */
56
+ const uint8_t *b = bounds[c - 0xC0];
57
+ if (q[1] < b[0] || q[1] > b[1]) {
58
+ for (mrb_int i = 1; i < n; i++) {
59
+ if ((signed char)q[i] >= -0x40) return MRB_UTF8_MALFORMED;
60
+ }
61
+ return q[1] < b[0] ? MRB_UTF8_REDUNDANT : MRB_UTF8_EXCLUDED;
62
+ }
63
+ uint32_t v = ((c & (0x7F >> n)) << 6) | (q[1] & 0x3F);
64
+ if (n > 2) {
65
+ if ((signed char)q[2] >= -0x40) return MRB_UTF8_MALFORMED;
66
+ v = (v << 6) | (q[2] & 0x3F);
67
+ if (n > 3) {
68
+ if ((signed char)q[3] >= -0x40) return MRB_UTF8_MALFORMED;
69
+ v = (v << 6) | (q[3] & 0x3F);
70
+ }
71
+ }
72
+ if (uv) *uv = v;
73
+ return n;
74
+ }
75
+
76
+ mrb_int mrb_utf8len(const char *str, const char *end);
77
+ const char *mrb_utf8_char_head(const char *beg, const char *p, const char *end);
78
+ uint32_t mrb_utf8_decode(const char *p, const char *e, mrb_int *lenp);
79
+
80
+ static inline mrb_int
81
+ mrb_enc_charlen(const char *p, const char *e)
82
+ {
83
+ return mrb_utf8len(p, e);
84
+ }
85
+
86
+ static inline const char *
87
+ mrb_enc_char_head(const char *beg, const char *p, const char *end)
88
+ {
89
+ return mrb_utf8_char_head(beg, p, end);
90
+ }
91
+
92
+ static inline uint32_t
93
+ mrb_enc_decode(const char *p, const char *e, mrb_int *lenp)
94
+ {
95
+ return mrb_utf8_decode(p, e, lenp);
96
+ }
97
+
98
+ enum mrb_case_kind {
99
+ MRB_CASE_KIND_LOWER,
100
+ MRB_CASE_KIND_UPPER,
101
+ MRB_CASE_KIND_TITLE,
102
+ MRB_CASE_KIND_SWAP,
103
+ MRB_CASE_KIND_FOLD
104
+ };
105
+
106
+ /* The buffer mrb_uni_case_map() writes into. A mapping may spell several
107
+ characters, so this is wider than one of them; unicase.c asserts that the
108
+ table it carries fits. */
109
+ #define MRB_UNI_CASE_MAX_BYTES 8
110
+
111
+ /* The `kind` mapping of `cp`, written into `buf` as UTF-8, answering how many
112
+ bytes it took, or 0 for a character that maps to itself. */
113
+ mrb_int mrb_uni_case_map(enum mrb_case_kind kind, uint32_t cp, char *buf);
114
+
115
+ #ifdef HAVE_MRUBY_REGEXP_GEM
116
+ /* The four below are the foldings /i reads off the same table, in the two
117
+ directions a pattern needs them. A build without mruby-regexp has nothing
118
+ that reads them, so a caller reaching for one there is a compile error
119
+ rather than a link one. */
120
+
121
+ /* Simple case folding: the folded codepoint, or cp itself when it folds to
122
+ nothing else. A codepoint whose folding spells several characters (U+FB00
123
+ to "ff") folds to itself here, which is what makes this the simple folding
124
+ rather than the full one mrb_uni_case_map() answers with. */
125
+ uint32_t mrb_uni_case_fold(uint32_t cp);
126
+
127
+ /* At most this many codepoints share one folded form. */
128
+ #define MRB_UNI_MAX_UNFOLD 4
129
+
130
+ /* Write every other codepoint sharing cp's folded form into out, at most max
131
+ of them, and answer how many were written. */
132
+ int mrb_uni_case_unfold(uint32_t cp, uint32_t *out, int max);
133
+
134
+ /* The same two directions over a span rather than one codepoint, reporting
135
+ what they find by calling add() with each span of it: fold_range the folds
136
+ of the sources in [lo, hi], unfold_range the sources of the folds in
137
+ [lo, hi]. Spans may repeat or overlap what the caller already holds; the
138
+ caller merges. */
139
+ void mrb_uni_case_fold_range(uint32_t lo, uint32_t hi,
140
+ void (*add)(void *, uint32_t, uint32_t), void *user);
141
+ void mrb_uni_case_unfold_range(uint32_t lo, uint32_t hi,
142
+ void (*add)(void *, uint32_t, uint32_t), void *user);
143
+ #endif /* HAVE_MRUBY_REGEXP_GEM */
144
+
145
+ #endif /* SP_RE_SHIM_MRUBY_INTERNAL_H */
@@ -0,0 +1,22 @@
1
+ /* shim/mruby/string.h - see shim/mruby.h */
2
+ #ifndef SP_RE_SHIM_MRUBY_STRING_H
3
+ #define SP_RE_SHIM_MRUBY_STRING_H
4
+ #include "../mruby.h"
5
+
6
+ struct sp_re_str {
7
+ char *ptr;
8
+ mrb_int len;
9
+ mrb_int capa;
10
+ struct sp_re_str *next; /* the compile's list of strings to release */
11
+ };
12
+ #define RSTRING_PTR(s) ((s)->ptr)
13
+ #define RSTRING_LEN(s) ((s)->len)
14
+
15
+ mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len);
16
+ mrb_value mrb_str_new_cstr(mrb_state *mrb, const char *p);
17
+ mrb_value mrb_str_cat(mrb_state *mrb, mrb_value str, const char *p, size_t len);
18
+ mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len);
19
+ /* mruby's format: %l takes a pointer and a size_t length, %v a String, %c a
20
+ char; the engine uses no other directive */
21
+ mrb_value mrb_format(mrb_state *mrb, const char *fmt, ...);
22
+ #endif
@@ -0,0 +1,93 @@
1
+ /*
2
+ ** shim/mruby.h - the slice of mruby's API the regexp engine reads
3
+ **
4
+ ** lib/regexp holds mruby-regexp's engine as mruby carries it (re_compile.c,
5
+ ** re_exec.c, re_utf8.c, re_internal.h, re_ctype.h, re_cased.h) together
6
+ ** with mruby's case tables (unicase.c, unicase.h), so that a later change
7
+ ** there is taken by copying the files again. The engine is written against
8
+ ** mruby's API; spinel has no mruby VM, and these headers answer the calls
9
+ ** the engine makes with the C library. re_spinel.c defines the functions
10
+ ** declared here and gives the engine the entry points spinel calls.
11
+ */
12
+ #ifndef SP_RE_SHIM_MRUBY_H
13
+ #define SP_RE_SHIM_MRUBY_H
14
+
15
+ #include "sp_re_names.h"
16
+
17
+ #include <stdint.h>
18
+ #include <stddef.h>
19
+ #include <stdlib.h>
20
+ #include <string.h>
21
+ #include <assert.h>
22
+
23
+ /* the build the engine reads a string as: UTF-8, with the Unicode tables
24
+ (RE_UNICODE_CASE, and re_ctype.h above ASCII) unless a -DMRB_USE_ASCII_CTYPE
25
+ build leaves them out */
26
+ #ifndef MRB_UTF8_STRING
27
+ # define MRB_UTF8_STRING
28
+ #endif
29
+ #ifndef HAVE_MRUBY_REGEXP_GEM
30
+ # define HAVE_MRUBY_REGEXP_GEM
31
+ #endif
32
+ /* spinel's switches for a build without the Unicode tables: mruby has the
33
+ one, which leaves out the case foldings and the classes above ASCII
34
+ together */
35
+ #if (defined(RE_NO_UNICODE_CASE) || defined(RE_NO_UNICODE_CTYPE)) && !defined(MRB_USE_ASCII_CTYPE)
36
+ # define MRB_USE_ASCII_CTYPE
37
+ #endif
38
+
39
+ #ifdef __cplusplus
40
+ # define MRB_BEGIN_DECL extern "C" {
41
+ # define MRB_END_DECL }
42
+ #else
43
+ # define MRB_BEGIN_DECL
44
+ # define MRB_END_DECL
45
+ #endif
46
+
47
+ /* The backtracking engine's ceiling, as spinel's engine had it before this
48
+ one: mruby's default of 2048 entries refuses a subject spinel matched
49
+ (a backreference to a run of 20000, test/regexp_backtrack_heap_stack.rb),
50
+ and a limit is not lowered because what it counts moved. */
51
+ #ifndef MRB_REGEXP_STACK_LIMIT
52
+ # define MRB_REGEXP_STACK_LIMIT 32768
53
+ #endif
54
+
55
+ typedef int64_t mrb_int;
56
+ typedef uint8_t mrb_bool;
57
+ #ifndef TRUE
58
+ # define TRUE 1
59
+ #endif
60
+ #ifndef FALSE
61
+ # define FALSE 0
62
+ #endif
63
+ #define MRB_INT_MAX INT64_MAX
64
+
65
+ /* The engine threads an mrb_state through every call it makes; nothing
66
+ reads it here. */
67
+ typedef struct mrb_state { int unused; } mrb_state;
68
+
69
+ /* A String, as the engine uses one: a growable buffer it builds a message or
70
+ a table in. Every one made during a compile is released when the compile
71
+ ends (re_spinel.c), as mruby's GC would release it. */
72
+ typedef struct sp_re_str *mrb_value;
73
+ static inline mrb_value mrb_nil_value(void) { return NULL; }
74
+ static inline mrb_bool mrb_nil_p(mrb_value v) { return v == NULL; }
75
+
76
+ typedef int mrb_sym;
77
+ #define MRB_SYM(name) 0
78
+
79
+ #ifdef MRB_DEBUG
80
+ # define mrb_assert(p) assert(p)
81
+ #else
82
+ # define mrb_assert(p) ((void)0)
83
+ #endif
84
+ #define mrb_static_assert(...) _Static_assert(__VA_ARGS__)
85
+
86
+ void *mrb_malloc(mrb_state *mrb, size_t len);
87
+ void *mrb_malloc_simple(mrb_state *mrb, size_t len);
88
+ void *mrb_calloc(mrb_state *mrb, size_t nelem, size_t len);
89
+ void *mrb_realloc(mrb_state *mrb, void *p, size_t len);
90
+ void *mrb_realloc_simple(mrb_state *mrb, void *p, size_t len);
91
+ void mrb_free(mrb_state *mrb, void *p);
92
+
93
+ #endif /* SP_RE_SHIM_MRUBY_H */
@@ -0,0 +1,118 @@
1
+ /*
2
+ * Minimal shim to compile mruby-bigint without the full mruby runtime.
3
+ * Provides just enough types and macros for bigint.c to compile standalone.
4
+ */
5
+ #ifndef MRUBY_SHIM_H
6
+ #define MRUBY_SHIM_H
7
+
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <stdint.h>
11
+ #include <string.h>
12
+ #include <assert.h>
13
+
14
+ /* GCC < 10 doesn't predefine __has_builtin, so #if expressions like
15
+ `defined(__GNUC__) || __has_builtin(...)` choke on the bare token.
16
+ Provide a no-op fallback so the || short-circuits cleanly on the
17
+ left when the compiler doesn't support __has_builtin (issue #55). */
18
+ #ifndef __has_builtin
19
+ #define __has_builtin(x) 0
20
+ #endif
21
+
22
+ /* Basic mruby types */
23
+ typedef int64_t mrb_int;
24
+ typedef uint64_t mrb_uint;
25
+ typedef double mrb_float;
26
+ typedef int mrb_bool;
27
+ #define TRUE 1
28
+ #define FALSE 0
29
+ #define MRB_INT_MAX INT64_MAX
30
+ #define MRB_INT_MIN INT64_MIN
31
+ #define MRB_INT_BIT 64
32
+
33
+ /* mrb_state stub */
34
+ typedef struct mrb_state {
35
+ int dummy;
36
+ } mrb_state;
37
+
38
+ /* Memory allocation */
39
+ #define mrb_malloc(mrb, sz) malloc(sz)
40
+ #define mrb_realloc(mrb, p, sz) realloc(p, sz)
41
+ #define mrb_free(mrb, p) free(p)
42
+ #define mrb_malloc_simple(mrb, sz) malloc(sz)
43
+
44
+ /* Error handling — sp_bigint.c is compiled as a separate TU and
45
+ would otherwise hard-exit on internal errors (mini-gmp's zero-
46
+ divisor check, allocation overflow, etc.). The mrb_raise macro
47
+ now dispatches on the symbolic class enum: ZeroDivisionError is
48
+ routed through sp_bigint_raise_zerodiv (defined non-static in
49
+ spinel_rt.h, linked from gen.c) so it reaches spinel's longjmp
50
+ rescue net and is catchable by `rescue ZeroDivisionError`.
51
+ Other classes still hard-exit — they're internal invariants
52
+ (allocation overflow) where graceful handling buys little. */
53
+ extern void sp_bigint_raise_zerodiv(const char *msg);
54
+ #define E_RANGE_ERROR 1
55
+ #define E_RUNTIME_ERROR 2
56
+ #define E_ARGUMENT_ERROR 3
57
+ #define E_TYPE_ERROR 4
58
+ #define E_ZERODIV_ERROR 5
59
+ #define mrb_raise(mrb, cls, msg) do { \
60
+ if ((cls) == E_ZERODIV_ERROR) { sp_bigint_raise_zerodiv(msg); } \
61
+ else { fprintf(stderr, "%s\n", msg); exit(1); } \
62
+ } while(0)
63
+ #define mrb_int_zerodiv(mrb) sp_bigint_raise_zerodiv("divided by 0")
64
+
65
+ /* mrb_value stub - tagged union */
66
+ typedef struct mrb_value {
67
+ union {
68
+ mrb_int i;
69
+ mrb_float f;
70
+ void *p;
71
+ } value;
72
+ int tt;
73
+ } mrb_value;
74
+
75
+ enum mrb_vtype {
76
+ MRB_TT_FALSE = 0,
77
+ MRB_TT_TRUE,
78
+ MRB_TT_INTEGER,
79
+ MRB_TT_FLOAT,
80
+ MRB_TT_STRING,
81
+ MRB_TT_BIGINT,
82
+ };
83
+
84
+ #define mrb_integer(v) ((v).value.i)
85
+ #define mrb_float(v) ((v).value.f)
86
+ #define mrb_ptr(v) ((v).value.p)
87
+ #define mrb_type(v) ((v).tt)
88
+ #define mrb_integer_p(v) ((v).tt == MRB_TT_INTEGER)
89
+ #define mrb_float_p(v) ((v).tt == MRB_TT_FLOAT)
90
+ #define mrb_bigint_p(v) ((v).tt == MRB_TT_BIGINT)
91
+ #define mrb_fixnum_value(i) ((mrb_value){{.i=(i)}, MRB_TT_INTEGER})
92
+ #define mrb_int_value(mrb, i) mrb_fixnum_value(i)
93
+
94
+ /* Object header stub */
95
+ #define MRB_OBJECT_HEADER uint32_t flags; uint32_t _pad
96
+ #define mrb_obj_ptr(v) ((struct RBasic*)mrb_ptr(v))
97
+ #define mrb_static_assert_object_size(t) /* nop */
98
+ #define mrb_assert(x) assert(x)
99
+
100
+ /* String */
101
+ #define RSTRING_PTR(s) ((const char*)mrb_ptr(s))
102
+ #define RSTRING_LEN(s) ((mrb_int)strlen(RSTRING_PTR(s)))
103
+
104
+ /* nil value */
105
+ static inline mrb_value mrb_nil_value(void) {
106
+ mrb_value v; v.tt = MRB_TT_FALSE; v.value.i = 0; return v;
107
+ }
108
+
109
+ /* MRB_ENSURE stub - execute body, no exception handling */
110
+ #define MRB_ENSURE(mrb, exc, body, data) \
111
+ { mrb_value exc = body(mrb, data); (void)exc; } if(0)
112
+
113
+ /* Bigint object creation */
114
+ struct RBasic {
115
+ MRB_OBJECT_HEADER;
116
+ };
117
+
118
+ #endif /* MRUBY_SHIM_H */