pyscriptc 0.1.0__py3-none-any.whl
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.
- pyscriptc/__init__.py +3 -0
- pyscriptc/__main__.py +3 -0
- pyscriptc/_posthog_token.py +1 -0
- pyscriptc/builtins.py +156 -0
- pyscriptc/canonical.py +167 -0
- pyscriptc/check.py +49 -0
- pyscriptc/cli.py +271 -0
- pyscriptc/coverage.py +388 -0
- pyscriptc/debug.py +120 -0
- pyscriptc/diagnostics.py +179 -0
- pyscriptc/errors.py +56 -0
- pyscriptc/ir.py +365 -0
- pyscriptc/llvm.py +2129 -0
- pyscriptc/log.py +127 -0
- pyscriptc/lower/__init__.py +1071 -0
- pyscriptc/lower/_calls.py +1499 -0
- pyscriptc/lower/_classes.py +969 -0
- pyscriptc/lower/_core.py +301 -0
- pyscriptc/lower/_expr.py +886 -0
- pyscriptc/lower/_stdlib.py +491 -0
- pyscriptc/lower/_stdlib_shared.py +93 -0
- pyscriptc/lower/_stmt.py +1173 -0
- pyscriptc/package.py +249 -0
- pyscriptc/restlower.py +1008 -0
- pyscriptc/runtime/ps_argv.c +28 -0
- pyscriptc/runtime/ps_b64.c +168 -0
- pyscriptc/runtime/ps_coll.c +133 -0
- pyscriptc/runtime/ps_dt.c +388 -0
- pyscriptc/runtime/ps_hash.c +411 -0
- pyscriptc/runtime/ps_help.c +219 -0
- pyscriptc/runtime/ps_hmac.c +120 -0
- pyscriptc/runtime/ps_io.c +198 -0
- pyscriptc/runtime/ps_island.c +272 -0
- pyscriptc/runtime/ps_json.c +402 -0
- pyscriptc/runtime/ps_mix.c +47 -0
- pyscriptc/runtime/ps_more.c +1089 -0
- pyscriptc/runtime/ps_osmore.c +447 -0
- pyscriptc/runtime/ps_path.c +547 -0
- pyscriptc/runtime/ps_re.c +1102 -0
- pyscriptc/runtime/ps_rt.c +1175 -0
- pyscriptc/runtime/ps_rt.h +189 -0
- pyscriptc/runtime/ps_struct.c +291 -0
- pyscriptc/runtime/ps_time.c +207 -0
- pyscriptc/runtime/ps_unicode.c +1521 -0
- pyscriptc/runtime/ps_url.c +327 -0
- pyscriptc/stdlib_queue.py +191 -0
- pyscriptc/stdmore.py +1596 -0
- pyscriptc/telemetry.py +219 -0
- pyscriptc-0.1.0.dist-info/METADATA +187 -0
- pyscriptc-0.1.0.dist-info/RECORD +54 -0
- pyscriptc-0.1.0.dist-info/WHEEL +5 -0
- pyscriptc-0.1.0.dist-info/entry_points.txt +2 -0
- pyscriptc-0.1.0.dist-info/licenses/LICENSE +201 -0
- pyscriptc-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
/* json.loads / json.dumps for int, bool, str, list, and dict[str, ...].
|
|
2
|
+
Float text and null are ValueError. Object key order follows insertion. */
|
|
3
|
+
|
|
4
|
+
#include "ps_rt.h"
|
|
5
|
+
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
typedef struct PsJson {
|
|
11
|
+
const char *p;
|
|
12
|
+
int64_t n;
|
|
13
|
+
int64_t i;
|
|
14
|
+
const PsType *types;
|
|
15
|
+
} PsJson;
|
|
16
|
+
|
|
17
|
+
static void ps_json_fail(const char *msg) { ps_raise_cstr(PS_VALUE, msg); }
|
|
18
|
+
|
|
19
|
+
static void ps_skip(PsJson *j) {
|
|
20
|
+
while (j->i < j->n) {
|
|
21
|
+
char c = j->p[j->i];
|
|
22
|
+
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') {
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
j->i++;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static char ps_peek(PsJson *j) {
|
|
30
|
+
ps_skip(j);
|
|
31
|
+
if (j->i >= j->n) {
|
|
32
|
+
ps_json_fail("unexpected end of JSON");
|
|
33
|
+
}
|
|
34
|
+
return j->p[j->i];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static int ps_hex_digit(char c) {
|
|
38
|
+
if (c >= '0' && c <= '9') {
|
|
39
|
+
return c - '0';
|
|
40
|
+
}
|
|
41
|
+
if (c >= 'a' && c <= 'f') {
|
|
42
|
+
return c - 'a' + 10;
|
|
43
|
+
}
|
|
44
|
+
if (c >= 'A' && c <= 'F') {
|
|
45
|
+
return c - 'A' + 10;
|
|
46
|
+
}
|
|
47
|
+
return -1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static void ps_parse_string(PsJson *j, PsBuf *out) {
|
|
51
|
+
if (ps_peek(j) != '"') {
|
|
52
|
+
ps_json_fail("JSON string expected");
|
|
53
|
+
}
|
|
54
|
+
j->i++;
|
|
55
|
+
PsGrow g;
|
|
56
|
+
ps_grow_init(&g);
|
|
57
|
+
while (j->i < j->n) {
|
|
58
|
+
unsigned char c = (unsigned char)j->p[j->i++];
|
|
59
|
+
if (c == '"') {
|
|
60
|
+
ps_grow_finish(&g, out);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (c == '\\') {
|
|
64
|
+
if (j->i >= j->n) {
|
|
65
|
+
free(g.data);
|
|
66
|
+
ps_json_fail("bad JSON string escape");
|
|
67
|
+
}
|
|
68
|
+
char e = j->p[j->i++];
|
|
69
|
+
if (e == '"' || e == '\\' || e == '/') {
|
|
70
|
+
ps_grow_byte(&g, (unsigned char)e);
|
|
71
|
+
} else if (e == 'b') {
|
|
72
|
+
ps_grow_byte(&g, '\b');
|
|
73
|
+
} else if (e == 'f') {
|
|
74
|
+
ps_grow_byte(&g, '\f');
|
|
75
|
+
} else if (e == 'n') {
|
|
76
|
+
ps_grow_byte(&g, '\n');
|
|
77
|
+
} else if (e == 'r') {
|
|
78
|
+
ps_grow_byte(&g, '\r');
|
|
79
|
+
} else if (e == 't') {
|
|
80
|
+
ps_grow_byte(&g, '\t');
|
|
81
|
+
} else if (e == 'u') {
|
|
82
|
+
int cp = 0;
|
|
83
|
+
for (int k = 0; k < 4; k++) {
|
|
84
|
+
if (j->i >= j->n) {
|
|
85
|
+
free(g.data);
|
|
86
|
+
ps_json_fail("bad JSON unicode escape");
|
|
87
|
+
}
|
|
88
|
+
int d = ps_hex_digit(j->p[j->i++]);
|
|
89
|
+
if (d < 0) {
|
|
90
|
+
free(g.data);
|
|
91
|
+
ps_json_fail("bad JSON unicode escape");
|
|
92
|
+
}
|
|
93
|
+
cp = (cp << 4) | d;
|
|
94
|
+
}
|
|
95
|
+
if (cp > 127) {
|
|
96
|
+
free(g.data);
|
|
97
|
+
ps_json_fail("non-ASCII JSON string is not lowered");
|
|
98
|
+
}
|
|
99
|
+
ps_grow_byte(&g, (unsigned char)cp);
|
|
100
|
+
} else {
|
|
101
|
+
free(g.data);
|
|
102
|
+
ps_json_fail("bad JSON string escape");
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (c < 0x20) {
|
|
107
|
+
free(g.data);
|
|
108
|
+
ps_json_fail("unescaped control character in JSON string");
|
|
109
|
+
}
|
|
110
|
+
if (c > 127) {
|
|
111
|
+
free(g.data);
|
|
112
|
+
ps_json_fail("non-ASCII JSON string is not lowered");
|
|
113
|
+
}
|
|
114
|
+
ps_grow_byte(&g, c);
|
|
115
|
+
}
|
|
116
|
+
free(g.data);
|
|
117
|
+
ps_json_fail("unterminated JSON string");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static void ps_parse_int(PsJson *j, int64_t *out) {
|
|
121
|
+
ps_skip(j);
|
|
122
|
+
int neg = 0;
|
|
123
|
+
if (j->i < j->n && j->p[j->i] == '-') {
|
|
124
|
+
neg = 1;
|
|
125
|
+
j->i++;
|
|
126
|
+
}
|
|
127
|
+
if (j->i >= j->n || j->p[j->i] < '0' || j->p[j->i] > '9') {
|
|
128
|
+
ps_json_fail("JSON number expected");
|
|
129
|
+
}
|
|
130
|
+
if (j->p[j->i] == '0') {
|
|
131
|
+
j->i++;
|
|
132
|
+
if (j->i < j->n && j->p[j->i] >= '0' && j->p[j->i] <= '9') {
|
|
133
|
+
ps_json_fail("JSON number has a leading zero");
|
|
134
|
+
}
|
|
135
|
+
if (j->i < j->n && (j->p[j->i] == '.' || j->p[j->i] == 'e' || j->p[j->i] == 'E')) {
|
|
136
|
+
ps_json_fail("float JSON is not lowered");
|
|
137
|
+
}
|
|
138
|
+
*out = 0;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
uint64_t mag = 0;
|
|
142
|
+
while (j->i < j->n && j->p[j->i] >= '0' && j->p[j->i] <= '9') {
|
|
143
|
+
int digit = j->p[j->i] - '0';
|
|
144
|
+
if (mag > (UINT64_MAX - (uint64_t)digit) / 10) {
|
|
145
|
+
ps_json_fail("JSON integer does not fit in i64");
|
|
146
|
+
}
|
|
147
|
+
mag = mag * 10 + (uint64_t)digit;
|
|
148
|
+
j->i++;
|
|
149
|
+
}
|
|
150
|
+
if (j->i < j->n && (j->p[j->i] == '.' || j->p[j->i] == 'e' || j->p[j->i] == 'E')) {
|
|
151
|
+
ps_json_fail("float JSON is not lowered");
|
|
152
|
+
}
|
|
153
|
+
if (!neg) {
|
|
154
|
+
if (mag > (uint64_t)INT64_MAX) {
|
|
155
|
+
ps_json_fail("JSON integer does not fit in i64");
|
|
156
|
+
}
|
|
157
|
+
*out = (int64_t)mag;
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (mag > (uint64_t)INT64_MAX + 1) {
|
|
161
|
+
ps_json_fail("JSON integer does not fit in i64");
|
|
162
|
+
}
|
|
163
|
+
if (mag == (uint64_t)INT64_MAX + 1) {
|
|
164
|
+
*out = INT64_MIN;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
*out = -(int64_t)mag;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static int64_t ps_slot(int kind) {
|
|
171
|
+
if (kind == PS_JSON_INT) {
|
|
172
|
+
return 8;
|
|
173
|
+
}
|
|
174
|
+
if (kind == PS_JSON_BOOL) {
|
|
175
|
+
return 4;
|
|
176
|
+
}
|
|
177
|
+
if (kind == PS_JSON_STR) {
|
|
178
|
+
return 16;
|
|
179
|
+
}
|
|
180
|
+
return 8;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static void ps_parse_value(PsJson *j, int32_t idx, void *out);
|
|
184
|
+
|
|
185
|
+
static void ps_expect(PsJson *j, char c) {
|
|
186
|
+
if (ps_peek(j) != c) {
|
|
187
|
+
ps_json_fail("JSON value does not match the annotation");
|
|
188
|
+
}
|
|
189
|
+
j->i++;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
static void ps_parse_value(PsJson *j, int32_t idx, void *out) {
|
|
193
|
+
PsType typ = j->types[idx];
|
|
194
|
+
char c = ps_peek(j);
|
|
195
|
+
if (c == 'n' && j->i + 4 <= j->n && memcmp(j->p + j->i, "null", 4) == 0) {
|
|
196
|
+
ps_json_fail("JSON null is not lowered");
|
|
197
|
+
}
|
|
198
|
+
if (typ.kind == PS_JSON_INT) {
|
|
199
|
+
int64_t v = 0;
|
|
200
|
+
ps_parse_int(j, &v);
|
|
201
|
+
memcpy(out, &v, 8);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (typ.kind == PS_JSON_BOOL) {
|
|
205
|
+
if (j->i + 4 <= j->n && memcmp(j->p + j->i, "true", 4) == 0) {
|
|
206
|
+
j->i += 4;
|
|
207
|
+
int32_t v = 1;
|
|
208
|
+
memcpy(out, &v, 4);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (j->i + 5 <= j->n && memcmp(j->p + j->i, "false", 5) == 0) {
|
|
212
|
+
j->i += 5;
|
|
213
|
+
int32_t v = 0;
|
|
214
|
+
memcpy(out, &v, 4);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
ps_json_fail("JSON bool expected");
|
|
218
|
+
}
|
|
219
|
+
if (typ.kind == PS_JSON_STR) {
|
|
220
|
+
ps_parse_string(j, out);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (typ.kind == PS_JSON_LIST) {
|
|
224
|
+
ps_expect(j, '[');
|
|
225
|
+
PsType child = j->types[typ.child];
|
|
226
|
+
PsSeq *seq = ps_seq_new(ps_slot(child.kind), 0);
|
|
227
|
+
ps_skip(j);
|
|
228
|
+
if (j->i < j->n && j->p[j->i] == ']') {
|
|
229
|
+
j->i++;
|
|
230
|
+
memcpy(out, &seq, 8);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
for (;;) {
|
|
234
|
+
unsigned char slot[16];
|
|
235
|
+
memset(slot, 0, sizeof slot);
|
|
236
|
+
ps_parse_value(j, typ.child, slot);
|
|
237
|
+
ps_seq_push(seq, slot);
|
|
238
|
+
ps_skip(j);
|
|
239
|
+
if (j->i < j->n && j->p[j->i] == ',') {
|
|
240
|
+
j->i++;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (j->i < j->n && j->p[j->i] == ']') {
|
|
244
|
+
j->i++;
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
ps_json_fail("JSON array is not closed");
|
|
248
|
+
}
|
|
249
|
+
memcpy(out, &seq, 8);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (typ.kind == PS_JSON_DICT) {
|
|
253
|
+
ps_expect(j, '{');
|
|
254
|
+
PsType child = j->types[typ.child];
|
|
255
|
+
PsMap *map = ps_map_new(2, 16, ps_slot(child.kind), 0);
|
|
256
|
+
ps_skip(j);
|
|
257
|
+
if (j->i < j->n && j->p[j->i] == '}') {
|
|
258
|
+
j->i++;
|
|
259
|
+
memcpy(out, &map, 8);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
for (;;) {
|
|
263
|
+
PsBuf key;
|
|
264
|
+
ps_parse_string(j, &key);
|
|
265
|
+
ps_skip(j);
|
|
266
|
+
if (j->i >= j->n || j->p[j->i] != ':') {
|
|
267
|
+
ps_json_fail("JSON object expects ':'");
|
|
268
|
+
}
|
|
269
|
+
j->i++;
|
|
270
|
+
unsigned char slot[16];
|
|
271
|
+
memset(slot, 0, sizeof slot);
|
|
272
|
+
ps_parse_value(j, typ.child, slot);
|
|
273
|
+
ps_map_put(map, &key, slot);
|
|
274
|
+
ps_skip(j);
|
|
275
|
+
if (j->i < j->n && j->p[j->i] == ',') {
|
|
276
|
+
j->i++;
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (j->i < j->n && j->p[j->i] == '}') {
|
|
280
|
+
j->i++;
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
ps_json_fail("JSON object is not closed");
|
|
284
|
+
}
|
|
285
|
+
memcpy(out, &map, 8);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
ps_json_fail("JSON type is not lowered");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
void ps_json_loads(int64_t n, char *p, const PsType *types, int32_t root, void *out) {
|
|
292
|
+
PsJson j = {p, n, 0, types};
|
|
293
|
+
ps_parse_value(&j, root, out);
|
|
294
|
+
ps_skip(&j);
|
|
295
|
+
if (j.i != j.n) {
|
|
296
|
+
ps_json_fail("trailing JSON");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static void ps_dump(const PsType *types, int32_t idx, const void *value, PsGrow *g);
|
|
301
|
+
|
|
302
|
+
static void ps_dump_str(PsBuf buf, PsGrow *g) {
|
|
303
|
+
ps_grow_byte(g, '"');
|
|
304
|
+
for (int64_t i = 0; i < buf.len; i++) {
|
|
305
|
+
unsigned char c = (unsigned char)buf.data[i];
|
|
306
|
+
if (c == '"' || c == '\\') {
|
|
307
|
+
ps_grow_byte(g, '\\');
|
|
308
|
+
ps_grow_byte(g, c);
|
|
309
|
+
} else if (c == '\b') {
|
|
310
|
+
ps_grow_add(g, "\\b", 2);
|
|
311
|
+
} else if (c == '\f') {
|
|
312
|
+
ps_grow_add(g, "\\f", 2);
|
|
313
|
+
} else if (c == '\n') {
|
|
314
|
+
ps_grow_add(g, "\\n", 2);
|
|
315
|
+
} else if (c == '\r') {
|
|
316
|
+
ps_grow_add(g, "\\r", 2);
|
|
317
|
+
} else if (c == '\t') {
|
|
318
|
+
ps_grow_add(g, "\\t", 2);
|
|
319
|
+
} else if (c < 0x20) {
|
|
320
|
+
char tmp[7];
|
|
321
|
+
snprintf(tmp, sizeof tmp, "\\u%04x", c);
|
|
322
|
+
ps_grow_add(g, tmp, 6);
|
|
323
|
+
} else {
|
|
324
|
+
ps_grow_byte(g, c);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
ps_grow_byte(g, '"');
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static void ps_dump(const PsType *types, int32_t idx, const void *value, PsGrow *g) {
|
|
331
|
+
PsType typ = types[idx];
|
|
332
|
+
if (typ.kind == PS_JSON_INT) {
|
|
333
|
+
int64_t v = 0;
|
|
334
|
+
memcpy(&v, value, 8);
|
|
335
|
+
char tmp[32];
|
|
336
|
+
int wrote = snprintf(tmp, sizeof tmp, "%lld", (long long)v);
|
|
337
|
+
if (wrote < 0) {
|
|
338
|
+
ps_json_fail("cannot format JSON integer");
|
|
339
|
+
}
|
|
340
|
+
ps_grow_add(g, tmp, wrote);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (typ.kind == PS_JSON_BOOL) {
|
|
344
|
+
int32_t v = 0;
|
|
345
|
+
memcpy(&v, value, 4);
|
|
346
|
+
if (v) {
|
|
347
|
+
ps_grow_add(g, "true", 4);
|
|
348
|
+
} else {
|
|
349
|
+
ps_grow_add(g, "false", 5);
|
|
350
|
+
}
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
if (typ.kind == PS_JSON_STR) {
|
|
354
|
+
PsBuf buf;
|
|
355
|
+
memcpy(&buf, value, 16);
|
|
356
|
+
ps_dump_str(buf, g);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (typ.kind == PS_JSON_LIST) {
|
|
360
|
+
PsSeq *seq = NULL;
|
|
361
|
+
memcpy(&seq, value, 8);
|
|
362
|
+
PsType child = types[typ.child];
|
|
363
|
+
ps_grow_byte(g, '[');
|
|
364
|
+
for (int64_t i = 0; i < seq->len; i++) {
|
|
365
|
+
if (i > 0) {
|
|
366
|
+
ps_grow_add(g, ", ", 2);
|
|
367
|
+
}
|
|
368
|
+
ps_dump(types, typ.child, (char *)seq->data + (size_t)i * (size_t)seq->elem, g);
|
|
369
|
+
}
|
|
370
|
+
ps_grow_byte(g, ']');
|
|
371
|
+
(void)child;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (typ.kind == PS_JSON_DICT) {
|
|
375
|
+
PsMap *map = NULL;
|
|
376
|
+
memcpy(&map, value, 8);
|
|
377
|
+
ps_grow_byte(g, '{');
|
|
378
|
+
for (int64_t i = 0; i < ps_map_len(map); i++) {
|
|
379
|
+
if (i > 0) {
|
|
380
|
+
ps_grow_add(g, ", ", 2);
|
|
381
|
+
}
|
|
382
|
+
PsBuf key;
|
|
383
|
+
ps_map_key_at(map, i, &key);
|
|
384
|
+
ps_dump_str(key, g);
|
|
385
|
+
ps_grow_add(g, ": ", 2);
|
|
386
|
+
unsigned char slot[16];
|
|
387
|
+
memset(slot, 0, sizeof slot);
|
|
388
|
+
ps_map_val_at(map, i, slot);
|
|
389
|
+
ps_dump(types, typ.child, slot, g);
|
|
390
|
+
}
|
|
391
|
+
ps_grow_byte(g, '}');
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
ps_json_fail("JSON type is not lowered");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
void ps_json_dumps(const PsType *types, int32_t root, void *value, PsBuf *out) {
|
|
398
|
+
PsGrow g;
|
|
399
|
+
ps_grow_init(&g);
|
|
400
|
+
ps_dump(types, root, value, &g);
|
|
401
|
+
ps_grow_finish(&g, out);
|
|
402
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Load libmix.so by its C ABI. No Python headers: this file is linked into
|
|
2
|
+
the small runtime, and only a call to ps_mix_* opens the library.
|
|
3
|
+
|
|
4
|
+
PYSCRIPTC_MIX_SO is the absolute path of that .so. A PyInit_* extension
|
|
5
|
+
cannot be opened this way; see ps_island_mix_crc32. */
|
|
6
|
+
|
|
7
|
+
#include "ps_rt.h"
|
|
8
|
+
|
|
9
|
+
#include <dlfcn.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
|
|
12
|
+
typedef int64_t (*ps_mix_crc_fn)(const char *, int64_t);
|
|
13
|
+
typedef int64_t (*ps_mix_crc_n_fn)(const char *, int64_t, int64_t);
|
|
14
|
+
|
|
15
|
+
static void *ps_mix_lib;
|
|
16
|
+
static ps_mix_crc_fn ps_mix_crc;
|
|
17
|
+
static ps_mix_crc_n_fn ps_mix_crc_n;
|
|
18
|
+
|
|
19
|
+
static void ps_mix_load(void) {
|
|
20
|
+
const char *path;
|
|
21
|
+
if (ps_mix_lib != NULL) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
path = getenv("PYSCRIPTC_MIX_SO");
|
|
25
|
+
if (path == NULL || path[0] == '\0') {
|
|
26
|
+
ps_raise_cstr(PS_RUNTIME, "PYSCRIPTC_MIX_SO is unset");
|
|
27
|
+
}
|
|
28
|
+
ps_mix_lib = dlopen(path, RTLD_NOW);
|
|
29
|
+
if (ps_mix_lib == NULL) {
|
|
30
|
+
ps_raise_cstr(PS_RUNTIME, dlerror());
|
|
31
|
+
}
|
|
32
|
+
ps_mix_crc = (ps_mix_crc_fn)dlsym(ps_mix_lib, "mix_crc32");
|
|
33
|
+
ps_mix_crc_n = (ps_mix_crc_n_fn)dlsym(ps_mix_lib, "mix_crc32_n");
|
|
34
|
+
if (ps_mix_crc == NULL || ps_mix_crc_n == NULL) {
|
|
35
|
+
ps_raise_cstr(PS_RUNTIME, "libmix.so is missing mix_crc32");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
int64_t ps_mix_crc32(int64_t n, const char *data) {
|
|
40
|
+
ps_mix_load();
|
|
41
|
+
return ps_mix_crc(data, n);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
int64_t ps_mix_crc32_n(int64_t n, const char *data, int64_t times) {
|
|
45
|
+
ps_mix_load();
|
|
46
|
+
return ps_mix_crc_n(data, n, times);
|
|
47
|
+
}
|