@delali/narsil-react-native 0.3.1-next.155 → 0.3.1-next.156

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 (253) hide show
  1. package/NOTICE +144 -0
  2. package/NarsilReactNative.podspec +2 -2
  3. package/android/CMakeLists.txt +1 -1
  4. package/cpp/HybridNarsilCoreAnalysis.cpp +277 -0
  5. package/cpp/HybridNarsilCoreImpl.hpp +43 -0
  6. package/cpp/HybridNarsilCoreKeyword.cpp +253 -0
  7. package/cpp/HybridNarsilCoreMath.cpp +47 -0
  8. package/cpp/core/include/narsil_analysis.h +86 -0
  9. package/cpp/core/include/narsil_core.h +1 -1
  10. package/cpp/core/include/narsil_keyword.h +110 -0
  11. package/cpp/core/include/narsil_math.h +36 -0
  12. package/cpp/core/src/analysis/analyse.c +281 -0
  13. package/cpp/core/src/analysis/analyser.h +49 -0
  14. package/cpp/core/src/analysis/languages.c +79 -0
  15. package/cpp/core/src/analysis/languages.h +42 -0
  16. package/cpp/core/src/analysis/normalise.c +242 -0
  17. package/cpp/core/src/analysis/normalise.h +28 -0
  18. package/cpp/core/src/analysis/split.c +183 -0
  19. package/cpp/core/src/analysis/split.h +27 -0
  20. package/cpp/core/src/analysis/stop_words.c +82 -0
  21. package/cpp/core/src/analysis/stop_words.h +19 -0
  22. package/cpp/core/src/analysis/term_cache.c +88 -0
  23. package/cpp/core/src/analysis/term_cache.h +36 -0
  24. package/cpp/core/src/analysis/text.c +161 -0
  25. package/cpp/core/src/analysis/text.h +45 -0
  26. package/cpp/core/src/analysis/transform.c +103 -0
  27. package/cpp/core/src/analysis/unicode.c +252 -0
  28. package/cpp/core/src/analysis/unicode.h +54 -0
  29. package/cpp/core/src/internal.h +4 -0
  30. package/cpp/core/src/keyword/pass.h +117 -0
  31. package/cpp/core/src/keyword/prune.c +324 -0
  32. package/cpp/core/src/keyword/request.c +179 -0
  33. package/cpp/core/src/keyword/rows.c +83 -0
  34. package/cpp/core/src/keyword/rows.h +18 -0
  35. package/cpp/core/src/keyword/score.c +257 -0
  36. package/cpp/core/src/keyword/score.h +17 -0
  37. package/cpp/core/src/keyword/scratch.c +226 -0
  38. package/cpp/core/src/keyword/scratch.h +55 -0
  39. package/cpp/core/src/keyword/select.c +155 -0
  40. package/cpp/core/src/keyword/select.h +17 -0
  41. package/cpp/core/src/languages/bulgarian_stemmer.c +114 -0
  42. package/cpp/core/src/languages/data/albanian.c +54 -0
  43. package/cpp/core/src/languages/data/amharic.c +93 -0
  44. package/cpp/core/src/languages/data/arabic.c +146 -0
  45. package/cpp/core/src/languages/data/armenian.c +46 -0
  46. package/cpp/core/src/languages/data/azerbaijani.c +68 -0
  47. package/cpp/core/src/languages/data/bambara.c +48 -0
  48. package/cpp/core/src/languages/data/basque.c +62 -0
  49. package/cpp/core/src/languages/data/belarusian.c +56 -0
  50. package/cpp/core/src/languages/data/bengali.c +63 -0
  51. package/cpp/core/src/languages/data/bosnian.c +73 -0
  52. package/cpp/core/src/languages/data/breton.c +52 -0
  53. package/cpp/core/src/languages/data/bulgarian.c +144 -0
  54. package/cpp/core/src/languages/data/burmese.c +48 -0
  55. package/cpp/core/src/languages/data/catalan.c +84 -0
  56. package/cpp/core/src/languages/data/chinese.c +70 -0
  57. package/cpp/core/src/languages/data/croatian.c +72 -0
  58. package/cpp/core/src/languages/data/czech.c +72 -0
  59. package/cpp/core/src/languages/data/dagbani.c +88 -0
  60. package/cpp/core/src/languages/data/danish.c +56 -0
  61. package/cpp/core/src/languages/data/declarations.h +114 -0
  62. package/cpp/core/src/languages/data/dutch.c +58 -0
  63. package/cpp/core/src/languages/data/english.c +172 -0
  64. package/cpp/core/src/languages/data/esperanto.c +71 -0
  65. package/cpp/core/src/languages/data/estonian.c +417 -0
  66. package/cpp/core/src/languages/data/ewe.c +89 -0
  67. package/cpp/core/src/languages/data/faroese.c +54 -0
  68. package/cpp/core/src/languages/data/fijian.c +44 -0
  69. package/cpp/core/src/languages/data/finnish.c +100 -0
  70. package/cpp/core/src/languages/data/french.c +74 -0
  71. package/cpp/core/src/languages/data/ga.c +83 -0
  72. package/cpp/core/src/languages/data/galician.c +70 -0
  73. package/cpp/core/src/languages/data/georgian.c +57 -0
  74. package/cpp/core/src/languages/data/german.c +96 -0
  75. package/cpp/core/src/languages/data/greek.c +202 -0
  76. package/cpp/core/src/languages/data/guarani.c +110 -0
  77. package/cpp/core/src/languages/data/gujarati.c +90 -0
  78. package/cpp/core/src/languages/data/haitian-creole.c +54 -0
  79. package/cpp/core/src/languages/data/hausa.c +85 -0
  80. package/cpp/core/src/languages/data/hawaiian.c +50 -0
  81. package/cpp/core/src/languages/data/hebrew.c +85 -0
  82. package/cpp/core/src/languages/data/hindi.c +91 -0
  83. package/cpp/core/src/languages/data/hungarian.c +98 -0
  84. package/cpp/core/src/languages/data/icelandic.c +73 -0
  85. package/cpp/core/src/languages/data/igbo.c +90 -0
  86. package/cpp/core/src/languages/data/indonesian.c +296 -0
  87. package/cpp/core/src/languages/data/irish.c +60 -0
  88. package/cpp/core/src/languages/data/italian.c +107 -0
  89. package/cpp/core/src/languages/data/japanese.c +52 -0
  90. package/cpp/core/src/languages/data/kannada.c +60 -0
  91. package/cpp/core/src/languages/data/kazakh.c +57 -0
  92. package/cpp/core/src/languages/data/khmer.c +71 -0
  93. package/cpp/core/src/languages/data/kinyarwanda.c +54 -0
  94. package/cpp/core/src/languages/data/kirundi.c +53 -0
  95. package/cpp/core/src/languages/data/korean.c +74 -0
  96. package/cpp/core/src/languages/data/kurmanji.c +43 -0
  97. package/cpp/core/src/languages/data/kyrgyz.c +65 -0
  98. package/cpp/core/src/languages/data/lao.c +46 -0
  99. package/cpp/core/src/languages/data/latin.c +46 -0
  100. package/cpp/core/src/languages/data/latvian.c +75 -0
  101. package/cpp/core/src/languages/data/lingala.c +88 -0
  102. package/cpp/core/src/languages/data/lithuanian.c +65 -0
  103. package/cpp/core/src/languages/data/luxembourgish.c +80 -0
  104. package/cpp/core/src/languages/data/macedonian.c +286 -0
  105. package/cpp/core/src/languages/data/malagasy.c +51 -0
  106. package/cpp/core/src/languages/data/malay.c +184 -0
  107. package/cpp/core/src/languages/data/malayalam.c +64 -0
  108. package/cpp/core/src/languages/data/maltese.c +102 -0
  109. package/cpp/core/src/languages/data/maori.c +52 -0
  110. package/cpp/core/src/languages/data/marathi.c +62 -0
  111. package/cpp/core/src/languages/data/nepali.c +72 -0
  112. package/cpp/core/src/languages/data/norwegian.c +74 -0
  113. package/cpp/core/src/languages/data/oromo.c +51 -0
  114. package/cpp/core/src/languages/data/persian.c +150 -0
  115. package/cpp/core/src/languages/data/polish.c +111 -0
  116. package/cpp/core/src/languages/data/portuguese.c +91 -0
  117. package/cpp/core/src/languages/data/punjabi.c +80 -0
  118. package/cpp/core/src/languages/data/registry.c +116 -0
  119. package/cpp/core/src/languages/data/romanian.c +93 -0
  120. package/cpp/core/src/languages/data/russian.c +76 -0
  121. package/cpp/core/src/languages/data/samoan.c +47 -0
  122. package/cpp/core/src/languages/data/sanskrit.c +53 -0
  123. package/cpp/core/src/languages/data/scottish-gaelic.c +119 -0
  124. package/cpp/core/src/languages/data/serbian.c +84 -0
  125. package/cpp/core/src/languages/data/shona.c +55 -0
  126. package/cpp/core/src/languages/data/sinhala.c +78 -0
  127. package/cpp/core/src/languages/data/slovak.c +135 -0
  128. package/cpp/core/src/languages/data/slovenian.c +139 -0
  129. package/cpp/core/src/languages/data/sorani.c +55 -0
  130. package/cpp/core/src/languages/data/spanish.c +84 -0
  131. package/cpp/core/src/languages/data/swahili.c +59 -0
  132. package/cpp/core/src/languages/data/swedish.c +60 -0
  133. package/cpp/core/src/languages/data/tagalog.c +75 -0
  134. package/cpp/core/src/languages/data/tamil.c +69 -0
  135. package/cpp/core/src/languages/data/tatar.c +548 -0
  136. package/cpp/core/src/languages/data/telugu.c +54 -0
  137. package/cpp/core/src/languages/data/thai.c +46 -0
  138. package/cpp/core/src/languages/data/tibetan.c +55 -0
  139. package/cpp/core/src/languages/data/tigrinya.c +73 -0
  140. package/cpp/core/src/languages/data/tongan.c +47 -0
  141. package/cpp/core/src/languages/data/turkish.c +100 -0
  142. package/cpp/core/src/languages/data/twi.c +88 -0
  143. package/cpp/core/src/languages/data/ukrainian.c +99 -0
  144. package/cpp/core/src/languages/data/urdu.c +174 -0
  145. package/cpp/core/src/languages/data/vietnamese.c +88 -0
  146. package/cpp/core/src/languages/data/welsh.c +143 -0
  147. package/cpp/core/src/languages/data/wolof.c +51 -0
  148. package/cpp/core/src/languages/data/xhosa.c +56 -0
  149. package/cpp/core/src/languages/data/yoruba.c +93 -0
  150. package/cpp/core/src/languages/data/zulu.c +58 -0
  151. package/cpp/core/src/languages/marks.c +64 -0
  152. package/cpp/core/src/languages/rules.c +63 -0
  153. package/cpp/core/src/languages/rules.h +68 -0
  154. package/cpp/core/src/languages/sanskrit_stemmer.c +50 -0
  155. package/cpp/core/src/languages/scripts.c +143 -0
  156. package/cpp/core/src/languages/slovenian_stemmer.c +46 -0
  157. package/cpp/core/src/languages/snowball/api.c +52 -0
  158. package/cpp/core/src/languages/snowball/api.h +43 -0
  159. package/cpp/core/src/languages/snowball/arabic_stemmer.c +1506 -0
  160. package/cpp/core/src/languages/snowball/arabic_stemmer.h +24 -0
  161. package/cpp/core/src/languages/snowball/armenian_stemmer.c +523 -0
  162. package/cpp/core/src/languages/snowball/armenian_stemmer.h +24 -0
  163. package/cpp/core/src/languages/snowball/basque_stemmer.c +1089 -0
  164. package/cpp/core/src/languages/snowball/basque_stemmer.h +24 -0
  165. package/cpp/core/src/languages/snowball/catalan_stemmer.c +1380 -0
  166. package/cpp/core/src/languages/snowball/catalan_stemmer.h +24 -0
  167. package/cpp/core/src/languages/snowball/czech_stemmer.c +582 -0
  168. package/cpp/core/src/languages/snowball/czech_stemmer.h +24 -0
  169. package/cpp/core/src/languages/snowball/danish_stemmer.c +352 -0
  170. package/cpp/core/src/languages/snowball/danish_stemmer.h +24 -0
  171. package/cpp/core/src/languages/snowball/dutch_stemmer.c +1657 -0
  172. package/cpp/core/src/languages/snowball/dutch_stemmer.h +24 -0
  173. package/cpp/core/src/languages/snowball/english_stemmer.c +1019 -0
  174. package/cpp/core/src/languages/snowball/english_stemmer.h +24 -0
  175. package/cpp/core/src/languages/snowball/esperanto_stemmer.c +716 -0
  176. package/cpp/core/src/languages/snowball/esperanto_stemmer.h +24 -0
  177. package/cpp/core/src/languages/snowball/estonian_stemmer.c +1361 -0
  178. package/cpp/core/src/languages/snowball/estonian_stemmer.h +24 -0
  179. package/cpp/core/src/languages/snowball/finnish_stemmer.c +800 -0
  180. package/cpp/core/src/languages/snowball/finnish_stemmer.h +24 -0
  181. package/cpp/core/src/languages/snowball/french_stemmer.c +1217 -0
  182. package/cpp/core/src/languages/snowball/french_stemmer.h +24 -0
  183. package/cpp/core/src/languages/snowball/german_stemmer.c +567 -0
  184. package/cpp/core/src/languages/snowball/german_stemmer.h +24 -0
  185. package/cpp/core/src/languages/snowball/greek_stemmer.c +3450 -0
  186. package/cpp/core/src/languages/snowball/greek_stemmer.h +24 -0
  187. package/cpp/core/src/languages/snowball/hindi_stemmer.c +325 -0
  188. package/cpp/core/src/languages/snowball/hindi_stemmer.h +24 -0
  189. package/cpp/core/src/languages/snowball/hungarian_stemmer.c +742 -0
  190. package/cpp/core/src/languages/snowball/hungarian_stemmer.h +24 -0
  191. package/cpp/core/src/languages/snowball/indonesian_stemmer.c +443 -0
  192. package/cpp/core/src/languages/snowball/indonesian_stemmer.h +24 -0
  193. package/cpp/core/src/languages/snowball/irish_stemmer.c +428 -0
  194. package/cpp/core/src/languages/snowball/irish_stemmer.h +24 -0
  195. package/cpp/core/src/languages/snowball/italian_stemmer.c +983 -0
  196. package/cpp/core/src/languages/snowball/italian_stemmer.h +24 -0
  197. package/cpp/core/src/languages/snowball/lithuanian_stemmer.c +794 -0
  198. package/cpp/core/src/languages/snowball/lithuanian_stemmer.h +24 -0
  199. package/cpp/core/src/languages/snowball/nepali_stemmer.c +361 -0
  200. package/cpp/core/src/languages/snowball/nepali_stemmer.h +24 -0
  201. package/cpp/core/src/languages/snowball/norwegian_stemmer.c +332 -0
  202. package/cpp/core/src/languages/snowball/norwegian_stemmer.h +24 -0
  203. package/cpp/core/src/languages/snowball/persian_stemmer.c +538 -0
  204. package/cpp/core/src/languages/snowball/persian_stemmer.h +24 -0
  205. package/cpp/core/src/languages/snowball/polish_stemmer.c +501 -0
  206. package/cpp/core/src/languages/snowball/polish_stemmer.h +24 -0
  207. package/cpp/core/src/languages/snowball/portuguese_stemmer.c +866 -0
  208. package/cpp/core/src/languages/snowball/portuguese_stemmer.h +24 -0
  209. package/cpp/core/src/languages/snowball/romanian_stemmer.c +940 -0
  210. package/cpp/core/src/languages/snowball/romanian_stemmer.h +24 -0
  211. package/cpp/core/src/languages/snowball/russian_stemmer.c +598 -0
  212. package/cpp/core/src/languages/snowball/russian_stemmer.h +24 -0
  213. package/cpp/core/src/languages/snowball/serbian_stemmer.c +6765 -0
  214. package/cpp/core/src/languages/snowball/serbian_stemmer.h +24 -0
  215. package/cpp/core/src/languages/snowball/snowball_runtime.h +122 -0
  216. package/cpp/core/src/languages/snowball/spanish_stemmer.c +955 -0
  217. package/cpp/core/src/languages/snowball/spanish_stemmer.h +24 -0
  218. package/cpp/core/src/languages/snowball/swedish_stemmer.c +364 -0
  219. package/cpp/core/src/languages/snowball/swedish_stemmer.h +24 -0
  220. package/cpp/core/src/languages/snowball/tamil_stemmer.c +1305 -0
  221. package/cpp/core/src/languages/snowball/tamil_stemmer.h +24 -0
  222. package/cpp/core/src/languages/snowball/turkish_stemmer.c +1700 -0
  223. package/cpp/core/src/languages/snowball/turkish_stemmer.h +24 -0
  224. package/cpp/core/src/languages/snowball/utilities.c +716 -0
  225. package/cpp/core/src/languages/substitutions.c +131 -0
  226. package/cpp/core/src/languages/swahili_stemmer.c +85 -0
  227. package/cpp/core/src/languages/ukrainian_stemmer.c +168 -0
  228. package/cpp/core/src/locks.c +2 -15
  229. package/cpp/core/src/math/apply.c +44 -0
  230. package/cpp/core/src/math/fdlibm.h +16 -0
  231. package/cpp/core/src/math/inverse.c +242 -0
  232. package/cpp/core/src/math/log.c +90 -0
  233. package/cpp/core/src/math/reduce.c +325 -0
  234. package/cpp/core/src/math/trig.c +188 -0
  235. package/cpp/core/src/math/words.h +45 -0
  236. package/cpp/core/src/thread_yield.h +18 -0
  237. package/cpp/core/src/unicode/decompositions.c +310 -0
  238. package/cpp/core/src/unicode/lowercase.c +172 -0
  239. package/cpp/core/src/unicode/properties.c +214 -0
  240. package/cpp/core/src/workspace.c +5 -1
  241. package/lib/engine/analysis.d.ts +3 -0
  242. package/lib/engine/analysis.js +76 -0
  243. package/lib/engine/core.js +5 -0
  244. package/lib/engine/keyword.d.ts +3 -0
  245. package/lib/engine/keyword.js +25 -0
  246. package/lib/specs/core.nitro.d.ts +1 -0
  247. package/nitrogen/generated/shared/c++/HybridNarsilCoreSpec.cpp +1 -0
  248. package/nitrogen/generated/shared/c++/HybridNarsilCoreSpec.hpp +1 -0
  249. package/package.json +4 -3
  250. package/src/engine/analysis.ts +87 -0
  251. package/src/engine/core.ts +6 -0
  252. package/src/engine/keyword.ts +26 -0
  253. package/src/specs/core.nitro.ts +1 -0
package/NOTICE ADDED
@@ -0,0 +1,144 @@
1
+ narsil
2
+ Copyright 2026 Delali (https://sondelali.com)
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ --------------------------------------------------------------------------------
17
+
18
+ This product includes software from the Snowball project
19
+ (https://snowballstem.org/).
20
+
21
+ The search core's C sources under cpp/core/ in this package hold stemmers that
22
+ the Snowball compiler generated as C from the algorithms in that project,
23
+ together with the project's C runtime. The licence below covers both.
24
+
25
+ Copyright (c) 2001, Dr Martin Porter
26
+ Copyright (c) 2002, Richard Boulton
27
+ Copyright (c) 2004,2005, Richard Boulton
28
+ Copyright (c) 2013, Yoshiki Shibukawa
29
+ Copyright (c) 2006-2025, Olly Betts
30
+ All rights reserved.
31
+
32
+ Redistribution and use in source and binary forms, with or without
33
+ modification, are permitted provided that the following conditions
34
+ are met:
35
+
36
+ 1. Redistributions of source code must retain the above copyright notice,
37
+ this list of conditions and the following disclaimer.
38
+ 2. Redistributions in binary form must reproduce the above copyright notice,
39
+ this list of conditions and the following disclaimer in the documentation
40
+ and/or other materials provided with the distribution.
41
+ 3. Neither the name of the Snowball project nor the names of its contributors
42
+ may be used to endorse or promote products derived from this software
43
+ without specific prior written permission.
44
+
45
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
46
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
49
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
52
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
53
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
54
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55
+
56
+ --------------------------------------------------------------------------------
57
+
58
+ This product includes software derived from fdlibm
59
+ (http://www.netlib.org/fdlibm/), through the copy in the V8 project's
60
+ src/base/ieee754.cc.
61
+
62
+ The search core's C sources under cpp/core/ in this package hold a port of its
63
+ logarithm and trigonometric functions to C. The two notices below cover the
64
+ port.
65
+
66
+ Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
67
+
68
+ Developed at SunSoft, a Sun Microsystems, Inc. business.
69
+ Permission to use, copy, modify, and distribute this
70
+ software is freely granted, provided that this notice
71
+ is preserved.
72
+
73
+ Copyright 2016 the V8 project authors. All rights reserved.
74
+
75
+ Redistribution and use in source and binary forms, with or without
76
+ modification, are permitted provided that the following conditions are
77
+ met:
78
+
79
+ * Redistributions of source code must retain the above copyright
80
+ notice, this list of conditions and the following disclaimer.
81
+ * Redistributions in binary form must reproduce the above
82
+ copyright notice, this list of conditions and the following
83
+ disclaimer in the documentation and/or other materials provided
84
+ with the distribution.
85
+ * Neither the name of Google Inc. nor the names of its
86
+ contributors may be used to endorse or promote products derived
87
+ from this software without specific prior written permission.
88
+
89
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
90
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
91
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
92
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
93
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
94
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
95
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
96
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
97
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
98
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
99
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
100
+
101
+ --------------------------------------------------------------------------------
102
+
103
+ This product includes data from the Unicode Character Database
104
+ (https://www.unicode.org/).
105
+
106
+ UNICODE LICENSE V3
107
+
108
+ COPYRIGHT AND PERMISSION NOTICE
109
+
110
+ Copyright © 1991-2026 Unicode, Inc.
111
+
112
+ NOTICE TO USER: Carefully read the following legal agreement. BY
113
+ DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
114
+ SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
115
+ TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
116
+ DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
117
+
118
+ Permission is hereby granted, free of charge, to any person obtaining a
119
+ copy of data files and any associated documentation (the "Data Files") or
120
+ software and any associated documentation (the "Software") to deal in the
121
+ Data Files or Software without restriction, including without limitation
122
+ the rights to use, copy, modify, merge, publish, distribute, and/or sell
123
+ copies of the Data Files or Software, and to permit persons to whom the
124
+ Data Files or Software are furnished to do so, provided that either (a)
125
+ this copyright and permission notice appear with all copies of the Data
126
+ Files or Software, or (b) this copyright and permission notice appear in
127
+ associated Documentation.
128
+
129
+ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
130
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
131
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
132
+ THIRD PARTY RIGHTS.
133
+
134
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
135
+ BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
136
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
137
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
138
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
139
+ FILES OR SOFTWARE.
140
+
141
+ Except as contained in this notice, the name of a copyright holder shall
142
+ not be used in advertising or otherwise to promote the sale, use or other
143
+ dealings in these Data Files or Software without prior written
144
+ authorization of the copyright holder.
@@ -30,10 +30,10 @@ Pod::Spec.new do |s|
30
30
 
31
31
  s.source_files = [
32
32
  "cpp/*.{hpp,cpp}",
33
- "cpp/core/src/*.{c,h}",
33
+ "cpp/core/src/**/*.{c,h}",
34
34
  "cpp/core/include/*.h",
35
35
  ]
36
- s.private_header_files = ["cpp/*.hpp", "cpp/core/src/*.h", "cpp/core/include/*.h"]
36
+ s.private_header_files = ["cpp/*.hpp", "cpp/core/src/**/*.h", "cpp/core/include/*.h"]
37
37
 
38
38
  header_search_paths = "$(inherited) \"$(PODS_TARGET_SRCROOT)/cpp/core/include\""
39
39
  header_search_paths += " \"$(PODS_ROOT)/Headers/Public/RNWorklets\"" if links_worklets
@@ -9,7 +9,7 @@ if(NOT EXISTS ${CORE_DIRECTORY}/include/narsil_core.h)
9
9
  message(FATAL_ERROR "The package has no copy of the search core in cpp/core. Run `node scripts/copy-core.mjs` in the package directory first.")
10
10
  endif()
11
11
 
12
- file(GLOB CORE_SOURCES ${CORE_DIRECTORY}/src/*.c)
12
+ file(GLOB_RECURSE CORE_SOURCES ${CORE_DIRECTORY}/src/*.c)
13
13
  file(GLOB BINDING_SOURCES ${CMAKE_SOURCE_DIR}/../cpp/*.cpp)
14
14
 
15
15
  add_library(${PACKAGE_NAME} SHARED
@@ -0,0 +1,277 @@
1
+ #include "HostMemory.hpp"
2
+ #include "HybridNarsilCoreImpl.hpp"
3
+
4
+ #include <cerrno>
5
+ #include <cmath>
6
+ #include <cstdint>
7
+ #include <cstring>
8
+ #include <memory>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ namespace margelo::nitro::narsil {
13
+
14
+ namespace {
15
+
16
+ enum AnalyseArgument : size_t {
17
+ ANALYSE_LANGUAGE,
18
+ ANALYSE_FLAGS,
19
+ ANALYSE_TEXT,
20
+ ANALYSE_STOP_WORDS,
21
+ ANALYSE_RECORD_BUFFER,
22
+ ANALYSE_RECORD_BYTE_OFFSET,
23
+ ANALYSE_RECORD_LENGTH,
24
+ ANALYSE_ARGUMENT_COUNT
25
+ };
26
+
27
+ enum TransformArgument : size_t { TRANSFORM_LANGUAGE, TRANSFORM_FLAGS, TRANSFORM_TEXT, TRANSFORM_ARGUMENT_COUNT };
28
+
29
+ enum TokenRecord : size_t {
30
+ RECORD_POSITION,
31
+ RECORD_TERM_OFFSET,
32
+ RECORD_TERM_LENGTH,
33
+ RECORD_SURFACE_OFFSET,
34
+ RECORD_SURFACE_LENGTH,
35
+ RECORD_ORIGINAL_OFFSET,
36
+ RECORD_ORIGINAL_LENGTH,
37
+ RECORD_TERM_SLOT,
38
+ TOKEN_RECORD_WORDS
39
+ };
40
+
41
+ const uint16_t NO_UNITS[1] = {0};
42
+
43
+ class StopWordSetState final : public jsi::NativeState {
44
+ public:
45
+ StopWordSetState() = default;
46
+ ~StopWordSetState() override { narsil_stop_word_set_destroy(set); }
47
+ StopWordSetState(const StopWordSetState&) = delete;
48
+ StopWordSetState& operator=(const StopWordSetState&) = delete;
49
+ narsil_stop_word_set* set = nullptr;
50
+ };
51
+
52
+ uint32_t wholeArgument(const jsi::Value* arguments, size_t count, size_t index, const char* what) {
53
+ if (index >= count || !arguments[index].isNumber()) throwInvalid(std::string(what) + " must be a number");
54
+ double value = arguments[index].getNumber();
55
+ if (!std::isfinite(value) || value < 0 || value > UINT32_MAX || std::floor(value) != value) {
56
+ throwInvalid(std::string(what) + " must be a whole number from 0 to 4294967295");
57
+ }
58
+ return static_cast<uint32_t>(value);
59
+ }
60
+
61
+ uint32_t languageArgument(const jsi::Value* arguments, size_t count, size_t index) {
62
+ uint32_t language = wholeArgument(arguments, count, index, "The language index");
63
+ if (language >= narsil_language_count()) throwInvalid("The language index names no language module of the core");
64
+ return language;
65
+ }
66
+
67
+ void appendUnits(jsi::Runtime& runtime, const jsi::String& text, std::vector<uint16_t>& units, size_t limit) {
68
+ bool tooLong = false;
69
+ auto collect = [&units, &tooLong, limit](bool ascii, const void* data, size_t length) {
70
+ if (tooLong || length > limit - units.size()) {
71
+ tooLong = true;
72
+ return;
73
+ }
74
+ size_t start = units.size();
75
+ units.resize(start + length);
76
+ if (ascii) {
77
+ const auto* characters = static_cast<const unsigned char*>(data);
78
+ for (size_t index = 0; index < length; index++) units[start + index] = characters[index];
79
+ } else if (length > 0) {
80
+ std::memcpy(units.data() + start, data, length * sizeof(uint16_t));
81
+ }
82
+ };
83
+ text.getStringData(runtime, collect);
84
+ if (tooLong) throwInvalid("The text holds more code units than the core analyses at once");
85
+ }
86
+
87
+ const narsil_stop_word_set* stopWordsArgument(jsi::Runtime& runtime, const jsi::Value& value) {
88
+ if (value.isNull()) return nullptr;
89
+ if (value.isObject()) {
90
+ jsi::Object handle = value.getObject(runtime);
91
+ if (handle.hasNativeState<StopWordSetState>(runtime)) return handle.getNativeState<StopWordSetState>(runtime)->set;
92
+ }
93
+ throwInvalid("The stop words must be a set from createStopWordSet, or null");
94
+ }
95
+
96
+ uint32_t* recordsArgument(jsi::Runtime& runtime, const jsi::Value* arguments, size_t count, size_t* capacity) {
97
+ uint32_t byteOffset = wholeArgument(arguments, count, ANALYSE_RECORD_BYTE_OFFSET, "The record byte offset");
98
+ uint32_t length = wholeArgument(arguments, count, ANALYSE_RECORD_LENGTH, "The record length");
99
+ const jsi::Value& value = arguments[ANALYSE_RECORD_BUFFER];
100
+ if (!value.isObject()) throwInvalid("The records must be a Uint32Array");
101
+ jsi::Object object = value.getObject(runtime);
102
+ if (!object.isArrayBuffer(runtime)) throwInvalid("The records must be a Uint32Array");
103
+ jsi::ArrayBuffer buffer = object.getArrayBuffer(runtime);
104
+ size_t held = buffer.size(runtime);
105
+ if (length == 0 || byteOffset > held || static_cast<size_t>(length) > (held - byteOffset) / sizeof(uint32_t)) {
106
+ throwInvalid("The records reach past the end of their buffer, or hold no entry");
107
+ }
108
+ uint8_t* bytes = buffer.data(runtime) + byteOffset;
109
+ if (reinterpret_cast<uintptr_t>(bytes) % alignof(uint32_t) != 0) throwInvalid("The records are misaligned");
110
+ *capacity = length;
111
+ return reinterpret_cast<uint32_t*>(bytes);
112
+ }
113
+
114
+ bool writeRecords(const narsil_tokens& tokens, uint32_t* records, size_t capacity) {
115
+ records[0] = tokens.token_count;
116
+ if (capacity - 1 < static_cast<size_t>(tokens.token_count) * TOKEN_RECORD_WORDS) return false;
117
+ uint32_t* record = records + 1;
118
+ for (uint32_t index = 0; index < tokens.token_count; index++) {
119
+ const narsil_token& token = tokens.tokens[index];
120
+ record[RECORD_POSITION] = token.position;
121
+ record[RECORD_TERM_OFFSET] = token.term_offset;
122
+ record[RECORD_TERM_LENGTH] = token.term_length;
123
+ record[RECORD_SURFACE_OFFSET] = token.surface_offset;
124
+ record[RECORD_SURFACE_LENGTH] = token.surface_length;
125
+ record[RECORD_ORIGINAL_OFFSET] = token.original_offset;
126
+ record[RECORD_ORIGINAL_LENGTH] = token.original_length;
127
+ record[RECORD_TERM_SLOT] = token.term_slot;
128
+ record += TOKEN_RECORD_WORDS;
129
+ }
130
+ return true;
131
+ }
132
+
133
+ jsi::Value statusValue(narsil_status status) { return jsi::Value(-static_cast<double>(status)); }
134
+
135
+ narsil_analyser* analyserOf(std::unique_ptr<narsil_analyser, AnalyserRelease>& held) {
136
+ if (held == nullptr) {
137
+ narsil_analyser* created = nullptr;
138
+ if (narsil_analyser_create(&created) != NARSIL_OK) return nullptr;
139
+ held.reset(created);
140
+ }
141
+ return held.get();
142
+ }
143
+
144
+ void readText(jsi::Runtime& runtime, const jsi::Value& value, const char* what, std::vector<uint16_t>& units) {
145
+ if (!value.isString()) throwInvalid(std::string(what) + " must be a string");
146
+ units.clear();
147
+ appendUnits(runtime, value.getString(runtime), units, NARSIL_MAX_ANALYSED_UNITS);
148
+ }
149
+
150
+ jsi::Value textOf(jsi::Runtime& runtime, std::u16string& out, const uint16_t* units, size_t length) {
151
+ out.resize(length);
152
+ if (length > 0) std::memcpy(out.data(), units, length * sizeof(uint16_t));
153
+ return jsi::String::createFromUtf16(runtime, out);
154
+ }
155
+
156
+ }
157
+
158
+ void HybridNarsilCoreImpl::loadHybridMethods() {
159
+ HybridNarsilCoreSpec::loadHybridMethods();
160
+ registerHybrids(this, [](Prototype& prototype) {
161
+ prototype.registerRawHybridMethod("languageCount", 0, &HybridNarsilCoreImpl::languageCount);
162
+ prototype.registerRawHybridMethod("languageName", 1, &HybridNarsilCoreImpl::languageName);
163
+ prototype.registerRawHybridMethod("languageRevision", 1, &HybridNarsilCoreImpl::languageRevision);
164
+ prototype.registerRawHybridMethod("languageStopWords", 1, &HybridNarsilCoreImpl::languageStopWords);
165
+ prototype.registerRawHybridMethod("createStopWordSet", 1, &HybridNarsilCoreImpl::createStopWordSet);
166
+ prototype.registerRawHybridMethod("analyse", ANALYSE_ARGUMENT_COUNT, &HybridNarsilCoreImpl::analyse);
167
+ prototype.registerRawHybridMethod("transform", TRANSFORM_ARGUMENT_COUNT, &HybridNarsilCoreImpl::transform);
168
+ prototype.registerRawHybridMethod("keywordScore", KEYWORD_SCORE_ARGUMENT_COUNT,
169
+ &HybridNarsilCoreImpl::keywordScore);
170
+ });
171
+ }
172
+
173
+ HybridNarsilCoreImpl::RuntimeState& HybridNarsilCoreImpl::stateOf(jsi::Runtime& runtime) {
174
+ std::lock_guard<std::mutex> guard(_runtimeStateLock);
175
+ std::unique_ptr<RuntimeState>& held = _stateByRuntime[&runtime];
176
+ if (held == nullptr) held = std::make_unique<RuntimeState>();
177
+ return *held;
178
+ }
179
+
180
+ jsi::Value HybridNarsilCoreImpl::languageCount(jsi::Runtime&, const jsi::Value&, const jsi::Value*, size_t) {
181
+ return jsi::Value(static_cast<double>(narsil_language_count()));
182
+ }
183
+
184
+ jsi::Value HybridNarsilCoreImpl::languageName(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* arguments,
185
+ size_t count) {
186
+ return jsi::String::createFromAscii(runtime, narsil_language_name(languageArgument(arguments, count, 0)));
187
+ }
188
+
189
+ jsi::Value HybridNarsilCoreImpl::languageRevision(jsi::Runtime& runtime, const jsi::Value&,
190
+ const jsi::Value* arguments, size_t count) {
191
+ return jsi::String::createFromAscii(runtime, narsil_language_revision(languageArgument(arguments, count, 0)));
192
+ }
193
+
194
+ jsi::Value HybridNarsilCoreImpl::languageStopWords(jsi::Runtime& runtime, const jsi::Value&,
195
+ const jsi::Value* arguments, size_t count) {
196
+ narsil_word_list list = {nullptr, nullptr, 0};
197
+ if (narsil_language_stop_words(languageArgument(arguments, count, 0), &list) != NARSIL_OK) {
198
+ throwInvalid("The core holds no stop words for that language");
199
+ }
200
+ std::u16string& out = stateOf(runtime).textOut;
201
+ jsi::Array words(runtime, list.count);
202
+ for (uint32_t index = 0; index < list.count; index++) {
203
+ uint32_t start = list.offsets[index];
204
+ words.setValueAtIndex(runtime, index, textOf(runtime, out, list.units + start, list.offsets[index + 1] - start));
205
+ }
206
+ return words;
207
+ }
208
+
209
+ jsi::Value HybridNarsilCoreImpl::createStopWordSet(jsi::Runtime& runtime, const jsi::Value&,
210
+ const jsi::Value* arguments, size_t count) {
211
+ if (count < 1 || !arguments[0].isObject() || !arguments[0].getObject(runtime).isArray(runtime)) {
212
+ throwInvalid("createStopWordSet takes one list of words");
213
+ }
214
+ jsi::Array list = arguments[0].getObject(runtime).getArray(runtime);
215
+ size_t wordCount = list.size(runtime);
216
+ if (wordCount >= UINT32_MAX) throwInvalid("createStopWordSet takes fewer than 4294967295 words");
217
+ std::vector<uint16_t> units;
218
+ std::vector<uint32_t> offsets(wordCount + 1, 0);
219
+ for (size_t index = 0; index < wordCount; index++) {
220
+ jsi::Value word = list.getValueAtIndex(runtime, index);
221
+ if (!word.isString()) throwInvalid("Every stop word must be a string");
222
+ size_t start = units.size();
223
+ appendUnits(runtime, word.getString(runtime), units, start + NARSIL_MAX_ANALYSED_UNITS);
224
+ if (units.size() > UINT32_MAX) throwInvalid("The stop words hold more code units than the core can index");
225
+ offsets[index + 1] = static_cast<uint32_t>(units.size());
226
+ }
227
+ auto state = std::make_shared<StopWordSetState>();
228
+ narsil_status status = narsil_stop_word_set_create(units.empty() ? NO_UNITS : units.data(), offsets.data(),
229
+ static_cast<uint32_t>(wordCount), &state->set);
230
+ if (status == NARSIL_OUT_OF_MEMORY) throwSystemError(ENOMEM, "hold the stop words", "");
231
+ if (status != NARSIL_OK) throwInvalid("The core cannot hold those stop words");
232
+ jsi::Object handle(runtime);
233
+ handle.setNativeState(runtime, state);
234
+ return handle;
235
+ }
236
+
237
+ jsi::Value HybridNarsilCoreImpl::analyse(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* arguments,
238
+ size_t count) {
239
+ narsil_analysis_request request = {0, nullptr, 0, nullptr, 0};
240
+ request.language = languageArgument(arguments, count, ANALYSE_LANGUAGE);
241
+ request.flags = wholeArgument(arguments, count, ANALYSE_FLAGS, "The analysis flags");
242
+ if (count < ANALYSE_ARGUMENT_COUNT) throwInvalid("analyse takes seven arguments");
243
+ request.stop_words = stopWordsArgument(runtime, arguments[ANALYSE_STOP_WORDS]);
244
+ size_t capacity = 0;
245
+ uint32_t* records = recordsArgument(runtime, arguments, count, &capacity);
246
+ RuntimeState& analysis = stateOf(runtime);
247
+ readText(runtime, arguments[ANALYSE_TEXT], "The text", analysis.textUnits);
248
+ narsil_analyser* active = analyserOf(analysis.analyser);
249
+ if (active == nullptr) return statusValue(NARSIL_OUT_OF_MEMORY);
250
+ request.text = analysis.textUnits.empty() ? NO_UNITS : analysis.textUnits.data();
251
+ request.length = static_cast<uint32_t>(analysis.textUnits.size());
252
+ narsil_tokens tokens = {nullptr, 0, nullptr, 0};
253
+ narsil_status status = narsil_analyse(active, &request, &tokens);
254
+ if (status != NARSIL_OK) return statusValue(status);
255
+ if (!writeRecords(tokens, records, capacity)) return jsi::Value::null();
256
+ return textOf(runtime, analysis.textOut, tokens.units, tokens.unit_count);
257
+ }
258
+
259
+ jsi::Value HybridNarsilCoreImpl::transform(jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* arguments,
260
+ size_t count) {
261
+ narsil_analysis_request request = {0, nullptr, 0, nullptr, 0};
262
+ request.language = languageArgument(arguments, count, TRANSFORM_LANGUAGE);
263
+ request.flags = wholeArgument(arguments, count, TRANSFORM_FLAGS, "The transform flags");
264
+ if (count < TRANSFORM_ARGUMENT_COUNT) throwInvalid("transform takes three arguments");
265
+ RuntimeState& analysis = stateOf(runtime);
266
+ readText(runtime, arguments[TRANSFORM_TEXT], "The token", analysis.textUnits);
267
+ narsil_analyser* active = analyserOf(analysis.analyser);
268
+ if (active == nullptr) return statusValue(NARSIL_OUT_OF_MEMORY);
269
+ request.text = analysis.textUnits.empty() ? NO_UNITS : analysis.textUnits.data();
270
+ request.length = static_cast<uint32_t>(analysis.textUnits.size());
271
+ narsil_term term = {nullptr, 0};
272
+ narsil_status status = narsil_transform(active, &request, &term);
273
+ if (status != NARSIL_OK) return statusValue(status);
274
+ return textOf(runtime, analysis.textOut, term.units, term.length);
275
+ }
276
+
277
+ }
@@ -1,20 +1,51 @@
1
1
  #pragma once
2
2
 
3
3
  #include "HybridNarsilCoreSpec.hpp"
4
+ #include "narsil_analysis.h"
4
5
  #include "narsil_core.h"
6
+ #include "narsil_keyword.h"
5
7
 
6
8
  #include <cstdint>
9
+ #include <memory>
7
10
  #include <mutex>
11
+ #include <string>
8
12
  #include <unordered_map>
9
13
  #include <unordered_set>
14
+ #include <vector>
10
15
 
11
16
  namespace margelo::nitro::narsil {
12
17
 
18
+ struct AnalyserRelease {
19
+ void operator()(narsil_analyser* analyser) const { narsil_analyser_destroy(analyser); }
20
+ };
21
+
22
+ inline constexpr size_t KEYWORD_SCORE_ARGUMENT_COUNT = 23;
23
+
24
+ struct WorkspaceRelease {
25
+ void operator()(narsil_workspace* workspace) const { narsil_workspace_destroy(workspace); }
26
+ };
27
+
13
28
  class HybridNarsilCoreImpl : public HybridNarsilCoreSpec {
14
29
  public:
15
30
  HybridNarsilCoreImpl() : HybridObject(TAG) {}
16
31
  ~HybridNarsilCoreImpl() override;
17
32
 
33
+ void loadHybridMethods() override;
34
+ jsi::Value languageCount(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
35
+ size_t count);
36
+ jsi::Value languageName(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
37
+ size_t count);
38
+ jsi::Value languageRevision(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
39
+ size_t count);
40
+ jsi::Value languageStopWords(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
41
+ size_t count);
42
+ jsi::Value createStopWordSet(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
43
+ size_t count);
44
+ jsi::Value analyse(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count);
45
+ jsi::Value transform(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count);
46
+ jsi::Value keywordScore(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
47
+ size_t count);
48
+
18
49
  double abiVersion() override;
19
50
  double workspaceBytes() override;
20
51
  std::shared_ptr<HybridNarsilAttachedGraphSpec> attachGraph(const GraphMemory& memory) override;
@@ -53,11 +84,23 @@ public:
53
84
  const MemoryView& ordinals, double count, const MemoryView& totals) override;
54
85
  double quantise(const std::shared_ptr<HybridNarsilAttachedStoreSpec>& store, double metric,
55
86
  const MemoryView& ordinals, double count) override;
87
+ double applyMath(double operation, const MemoryView& first, const MemoryView& second,
88
+ const MemoryView& results) override;
56
89
 
57
90
  narsil_workspace* claimBackgroundSlot(uint32_t threadSlot);
58
91
  void releaseBackgroundSlot(uint32_t threadSlot);
59
92
 
60
93
  private:
94
+ struct RuntimeState {
95
+ std::unique_ptr<narsil_analyser, AnalyserRelease> analyser;
96
+ std::vector<uint16_t> textUnits;
97
+ std::u16string textOut;
98
+ std::unique_ptr<narsil_workspace, WorkspaceRelease> keywordWorkspace;
99
+ std::vector<narsil_keyword_column> keywordLengths;
100
+ };
101
+ RuntimeState& stateOf(jsi::Runtime& runtime);
102
+ std::mutex _runtimeStateLock;
103
+ std::unordered_map<jsi::Runtime*, std::unique_ptr<RuntimeState>> _stateByRuntime;
61
104
  narsil_workspace* workspace();
62
105
  narsil_workspace* _workspace = nullptr;
63
106
  std::mutex _backgroundLock;