nomen-lang 0.0.6 → 0.0.7
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.
- package/dist/index.mjs +4443 -3813
- package/package.json +1 -1
- package/src/bench_loop.nm +113 -0
- package/src/index.ts +17 -0
- package/src/test.ts +518 -0
- package/test/fixtures/build/calc.test +0 -0
- package/test/fixtures/build/calc.test.c +969 -0
- package/test/fixtures/build/main.h +170 -0
- package/test/fixtures/calc.test.nm +32 -0
|
@@ -0,0 +1,969 @@
|
|
|
1
|
+
typedef struct { void* ptr; long len; } nomen_view;
|
|
2
|
+
#pragma STDC FP_CONTRACT OFF
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <math.h>
|
|
7
|
+
#include <sys/stat.h>
|
|
8
|
+
#include <sys/types.h>
|
|
9
|
+
#include <unistd.h>
|
|
10
|
+
#include "main.h"
|
|
11
|
+
|
|
12
|
+
typedef struct Console
|
|
13
|
+
{
|
|
14
|
+
void *_vt;
|
|
15
|
+
} Console;
|
|
16
|
+
typedef struct Time
|
|
17
|
+
{
|
|
18
|
+
void *_vt;
|
|
19
|
+
} Time;
|
|
20
|
+
typedef struct Tester
|
|
21
|
+
{
|
|
22
|
+
void *_vt;
|
|
23
|
+
unsigned char has_failed;
|
|
24
|
+
long passed;
|
|
25
|
+
long failed;
|
|
26
|
+
long total_failed;
|
|
27
|
+
char* current;
|
|
28
|
+
unsigned long long started;
|
|
29
|
+
unsigned char bench_pending;
|
|
30
|
+
char* bench_label;
|
|
31
|
+
long bench_samples;
|
|
32
|
+
} Tester;
|
|
33
|
+
typedef struct Math
|
|
34
|
+
{
|
|
35
|
+
void *_vt;
|
|
36
|
+
} Math;
|
|
37
|
+
typedef struct Buffer_int
|
|
38
|
+
{
|
|
39
|
+
void *_vt;
|
|
40
|
+
unsigned long long data;
|
|
41
|
+
long cap;
|
|
42
|
+
} Buffer_int;
|
|
43
|
+
typedef struct List_int
|
|
44
|
+
{
|
|
45
|
+
void *_vt;
|
|
46
|
+
long length;
|
|
47
|
+
struct Buffer_int items;
|
|
48
|
+
} List_int;
|
|
49
|
+
// Trait Stringable
|
|
50
|
+
typedef struct Stringable
|
|
51
|
+
{
|
|
52
|
+
} Stringable;
|
|
53
|
+
char* Stringable_to_string(struct Stringable *self)
|
|
54
|
+
{
|
|
55
|
+
struct Stringable _self = *self;
|
|
56
|
+
char* _return_val = strdup("");
|
|
57
|
+
return _return_val;
|
|
58
|
+
;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Trait Disposable
|
|
62
|
+
typedef struct Disposable
|
|
63
|
+
{
|
|
64
|
+
} Disposable;
|
|
65
|
+
void Disposable_dispose(struct Disposable *self)
|
|
66
|
+
{
|
|
67
|
+
struct Disposable _self = *self;
|
|
68
|
+
Console_write("\nboom!");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Trait Equatable
|
|
72
|
+
typedef struct Equatable
|
|
73
|
+
{
|
|
74
|
+
} Equatable;
|
|
75
|
+
|
|
76
|
+
// Trait Hashable
|
|
77
|
+
typedef struct Hashable
|
|
78
|
+
{
|
|
79
|
+
} Hashable;
|
|
80
|
+
unsigned long Hashable_hash(struct Hashable *self)
|
|
81
|
+
{
|
|
82
|
+
struct Hashable _self = *self;
|
|
83
|
+
long _return_val = 0L;
|
|
84
|
+
return _return_val;
|
|
85
|
+
;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Trait Viewable
|
|
89
|
+
typedef struct Viewable
|
|
90
|
+
{
|
|
91
|
+
} Viewable;
|
|
92
|
+
|
|
93
|
+
// Struct int
|
|
94
|
+
char* int_to_string(long self)
|
|
95
|
+
{
|
|
96
|
+
int length = snprintf(NULL, 0, "%ld", self);
|
|
97
|
+
char* str = malloc(length + 1);
|
|
98
|
+
snprintf(str, length + 1, "%ld", self);
|
|
99
|
+
return str;
|
|
100
|
+
}
|
|
101
|
+
long int_parse(char* s)
|
|
102
|
+
{
|
|
103
|
+
return atoi(s);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Struct char
|
|
107
|
+
char* char_to_string(char self)
|
|
108
|
+
{
|
|
109
|
+
int length = snprintf(NULL, 0, "%c", self);
|
|
110
|
+
char* str = malloc(length + 1);
|
|
111
|
+
snprintf(str, length + 1, "%c", self);
|
|
112
|
+
return str;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Struct bool
|
|
116
|
+
char* bool_to_string(unsigned char self)
|
|
117
|
+
{
|
|
118
|
+
int length = snprintf(NULL, 0, "%s", self ? "true" : "false");
|
|
119
|
+
char* str = malloc(length + 1);
|
|
120
|
+
snprintf(str, length + 1, "%s", self ? "true" : "false");
|
|
121
|
+
return str;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Struct string
|
|
125
|
+
char* string_to_string(char* self)
|
|
126
|
+
{
|
|
127
|
+
return strdup(self);
|
|
128
|
+
}
|
|
129
|
+
char string_at(char* self, long index)
|
|
130
|
+
{
|
|
131
|
+
return self[index];
|
|
132
|
+
}
|
|
133
|
+
nomen_view string_slice(char* self, long start, long end)
|
|
134
|
+
{
|
|
135
|
+
nomen_view _r;
|
|
136
|
+
_r.ptr = (void*)(self + start);
|
|
137
|
+
_r.len = (long)(end - start);
|
|
138
|
+
return _r;
|
|
139
|
+
}
|
|
140
|
+
void string_set(char* *self, long index, char value)
|
|
141
|
+
{
|
|
142
|
+
(*self)[index] = value;
|
|
143
|
+
}
|
|
144
|
+
unsigned char string_eq(char* self, char* other)
|
|
145
|
+
{
|
|
146
|
+
return strcmp(self, other) == 0;
|
|
147
|
+
}
|
|
148
|
+
char* string_add(char* self, char* other)
|
|
149
|
+
{
|
|
150
|
+
int left_len = strlen(self);
|
|
151
|
+
int right_len = strlen(other);
|
|
152
|
+
char* result = malloc(left_len + right_len + 1);
|
|
153
|
+
strcpy(result, self);
|
|
154
|
+
strcat(result, other);
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
char* string_mul(char* self, long count)
|
|
158
|
+
{
|
|
159
|
+
size_t str_len = strlen(self);
|
|
160
|
+
size_t total = str_len * (size_t)count + 1;
|
|
161
|
+
char* buf = malloc(total);
|
|
162
|
+
char* p = buf;
|
|
163
|
+
for (int i = 0; i < count; i++) {
|
|
164
|
+
memcpy(p, self, str_len);
|
|
165
|
+
p += str_len;
|
|
166
|
+
}
|
|
167
|
+
*p = 0;
|
|
168
|
+
return buf;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Struct Console
|
|
172
|
+
struct Console Console_init()
|
|
173
|
+
{
|
|
174
|
+
struct Console _self;
|
|
175
|
+
return _self;
|
|
176
|
+
}
|
|
177
|
+
void Console_write(char* line)
|
|
178
|
+
{
|
|
179
|
+
printf("%s", line);
|
|
180
|
+
}
|
|
181
|
+
void Console_write_line(char* line)
|
|
182
|
+
{
|
|
183
|
+
printf("%s\n", line);
|
|
184
|
+
}
|
|
185
|
+
char* Console_read_line()
|
|
186
|
+
{
|
|
187
|
+
int cap = 16;
|
|
188
|
+
int len = 0;
|
|
189
|
+
char *buf = (char*)malloc(cap);
|
|
190
|
+
int c = getchar();
|
|
191
|
+
while (c != EOF && c != '\n') {
|
|
192
|
+
if (len + 2 > cap) {
|
|
193
|
+
cap *= 2;
|
|
194
|
+
buf = (char*)realloc(buf, cap);
|
|
195
|
+
}
|
|
196
|
+
buf[len++] = (char)c;
|
|
197
|
+
c = getchar();
|
|
198
|
+
}
|
|
199
|
+
buf[len] = 0;
|
|
200
|
+
return buf;
|
|
201
|
+
char* _return_val = strdup("");
|
|
202
|
+
return _return_val;
|
|
203
|
+
;
|
|
204
|
+
}
|
|
205
|
+
char Console_read_char()
|
|
206
|
+
{
|
|
207
|
+
return (char)getchar();
|
|
208
|
+
}
|
|
209
|
+
char* Console_platform()
|
|
210
|
+
{
|
|
211
|
+
return strdup("macos");
|
|
212
|
+
char* _return_val = strdup("");
|
|
213
|
+
return _return_val;
|
|
214
|
+
;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Struct uint
|
|
218
|
+
char* uint_to_string(unsigned long self)
|
|
219
|
+
{
|
|
220
|
+
int length = snprintf(NULL, 0, "%ld", self);
|
|
221
|
+
char* str = malloc(length + 1);
|
|
222
|
+
snprintf(str, length + 1, "%ld", self);
|
|
223
|
+
return str;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Struct int8
|
|
227
|
+
char* int8_to_string(char self)
|
|
228
|
+
{
|
|
229
|
+
int length = snprintf(NULL, 0, "%d", self);
|
|
230
|
+
char* str = malloc(length + 1);
|
|
231
|
+
snprintf(str, length + 1, "%d", self);
|
|
232
|
+
return str;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Struct uint8
|
|
236
|
+
char* uint8_to_string(unsigned char self)
|
|
237
|
+
{
|
|
238
|
+
int length = snprintf(NULL, 0, "%d", self);
|
|
239
|
+
char* str = malloc(length + 1);
|
|
240
|
+
snprintf(str, length + 1, "%d", self);
|
|
241
|
+
return str;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Struct float
|
|
245
|
+
char* float_to_string(double self)
|
|
246
|
+
{
|
|
247
|
+
int length = snprintf(NULL, 0, "%f", self);
|
|
248
|
+
char* str = malloc(length + 1);
|
|
249
|
+
snprintf(str, length + 1, "%f", self);
|
|
250
|
+
return str;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Struct uint64
|
|
254
|
+
char* uint64_to_string(unsigned long long self)
|
|
255
|
+
{
|
|
256
|
+
int length = snprintf(NULL, 0, "%llu", self);
|
|
257
|
+
char* str = malloc(length + 1);
|
|
258
|
+
snprintf(str, length + 1, "%llu", self);
|
|
259
|
+
return str;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Struct Time
|
|
263
|
+
struct Time Time_init()
|
|
264
|
+
{
|
|
265
|
+
struct Time _self;
|
|
266
|
+
return _self;
|
|
267
|
+
}
|
|
268
|
+
unsigned long long Time_now_ms()
|
|
269
|
+
{
|
|
270
|
+
struct timespec ts;
|
|
271
|
+
clock_gettime(CLOCK_REALTIME, &ts);
|
|
272
|
+
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
|
|
273
|
+
unsigned long long _return_val = 0L;
|
|
274
|
+
return _return_val;
|
|
275
|
+
;
|
|
276
|
+
}
|
|
277
|
+
unsigned long long Time_now_ns()
|
|
278
|
+
{
|
|
279
|
+
struct timespec ts;
|
|
280
|
+
clock_gettime(CLOCK_REALTIME, &ts);
|
|
281
|
+
return (uint64_t)ts.tv_sec * 1000000000 + (uint64_t)ts.tv_nsec;
|
|
282
|
+
unsigned long long _return_val = 0L;
|
|
283
|
+
return _return_val;
|
|
284
|
+
;
|
|
285
|
+
}
|
|
286
|
+
unsigned long long Time_now_unix()
|
|
287
|
+
{
|
|
288
|
+
return (uint64_t)time(NULL);
|
|
289
|
+
}
|
|
290
|
+
void Time_sleep_ms(unsigned long long ms)
|
|
291
|
+
{
|
|
292
|
+
struct timespec ts;
|
|
293
|
+
ts.tv_sec = ms / 1000;
|
|
294
|
+
ts.tv_nsec = (long)(ms % 1000) * 1000000;
|
|
295
|
+
nanosleep(&ts, NULL);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Struct int64
|
|
299
|
+
char* int64_to_string(long long self)
|
|
300
|
+
{
|
|
301
|
+
int length = snprintf(NULL, 0, "%lld", self);
|
|
302
|
+
char* str = malloc(length + 1);
|
|
303
|
+
snprintf(str, length + 1, "%lld", self);
|
|
304
|
+
return str;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Struct Tester
|
|
308
|
+
struct Tester* Tester_init()
|
|
309
|
+
{
|
|
310
|
+
struct Tester* _self = malloc(sizeof(struct Tester));
|
|
311
|
+
_self->has_failed = 0;
|
|
312
|
+
_self->passed = 0L;
|
|
313
|
+
_self->failed = 0L;
|
|
314
|
+
_self->total_failed = 0L;
|
|
315
|
+
_self->current = "";
|
|
316
|
+
_self->started = 0L;
|
|
317
|
+
_self->bench_pending = 0;
|
|
318
|
+
_self->bench_label = "";
|
|
319
|
+
_self->bench_samples = 1000L;
|
|
320
|
+
return _self;
|
|
321
|
+
}
|
|
322
|
+
void Tester_begin_test(struct Tester *self, char* name)
|
|
323
|
+
{
|
|
324
|
+
self->has_failed = 0;
|
|
325
|
+
self->passed = 0L;
|
|
326
|
+
self->failed = 0L;
|
|
327
|
+
self->current = name;
|
|
328
|
+
char* _param_6 = string_add("\\nomen|start|", name);
|
|
329
|
+
Console_write_line(_param_6);
|
|
330
|
+
self->started = Time_now_ns();
|
|
331
|
+
|
|
332
|
+
// Auto-free
|
|
333
|
+
free(_param_6);
|
|
334
|
+
}
|
|
335
|
+
void Tester_end_test(struct Tester *self)
|
|
336
|
+
{
|
|
337
|
+
unsigned long long elapsed = (Time_now_ns() - self->started);
|
|
338
|
+
char* _param_7 = int_to_string(self->passed);
|
|
339
|
+
char* _param_8 = int_to_string(self->failed);
|
|
340
|
+
char* _param_9 = uint64_to_string(elapsed);
|
|
341
|
+
char* _param_10 = ({ char* _ltmp_1 = string_add("\\nomen|done|", self->current); char* _rtmp_1 = _string_interpolate_3("|%s|%s|%s", _param_7, _param_8, _param_9); char* _cres_1 = string_add(_ltmp_1, _rtmp_1); free(_ltmp_1); free(_rtmp_1); _cres_1; });
|
|
342
|
+
Console_write_line(_param_10);
|
|
343
|
+
|
|
344
|
+
// Auto-free
|
|
345
|
+
free(_param_7);
|
|
346
|
+
free(_param_8);
|
|
347
|
+
free(_param_9);
|
|
348
|
+
free(_param_10);
|
|
349
|
+
}
|
|
350
|
+
unsigned char Tester_any_failed(struct Tester *self)
|
|
351
|
+
{
|
|
352
|
+
struct Tester _self = *self;
|
|
353
|
+
unsigned char _return_val = (self->total_failed > 0L);
|
|
354
|
+
return _return_val;
|
|
355
|
+
;
|
|
356
|
+
}
|
|
357
|
+
void Tester_expect(struct Tester *self, unsigned char condition, char* message)
|
|
358
|
+
{
|
|
359
|
+
if (self->has_failed) {
|
|
360
|
+
return;
|
|
361
|
+
;
|
|
362
|
+
}
|
|
363
|
+
if (condition) {
|
|
364
|
+
self->passed += 1L;
|
|
365
|
+
return;
|
|
366
|
+
;
|
|
367
|
+
}
|
|
368
|
+
Tester_record_failure(self, message);
|
|
369
|
+
}
|
|
370
|
+
void Tester_fail(struct Tester *self, char* message)
|
|
371
|
+
{
|
|
372
|
+
if (self->has_failed) {
|
|
373
|
+
return;
|
|
374
|
+
;
|
|
375
|
+
}
|
|
376
|
+
Tester_record_failure(self, message);
|
|
377
|
+
}
|
|
378
|
+
void Tester_assert_int_string(struct Tester *self, long value, char* message)
|
|
379
|
+
{
|
|
380
|
+
unsigned char _param_11 = (value != 0);
|
|
381
|
+
Tester_expect(self, _param_11, message);
|
|
382
|
+
}
|
|
383
|
+
void Tester_assert_uint_string(struct Tester *self, unsigned long value, char* message)
|
|
384
|
+
{
|
|
385
|
+
unsigned char _param_12 = (value != 0);
|
|
386
|
+
Tester_expect(self, _param_12, message);
|
|
387
|
+
}
|
|
388
|
+
void Tester_assert_int64_string(struct Tester *self, long long value, char* message)
|
|
389
|
+
{
|
|
390
|
+
unsigned char _param_13 = (value != 0);
|
|
391
|
+
Tester_expect(self, _param_13, message);
|
|
392
|
+
}
|
|
393
|
+
void Tester_assert_uint64_string(struct Tester *self, unsigned long long value, char* message)
|
|
394
|
+
{
|
|
395
|
+
unsigned char _param_14 = (value != 0);
|
|
396
|
+
Tester_expect(self, _param_14, message);
|
|
397
|
+
}
|
|
398
|
+
void Tester_assert_int8_string(struct Tester *self, char value, char* message)
|
|
399
|
+
{
|
|
400
|
+
unsigned char _param_15 = (value != 0);
|
|
401
|
+
Tester_expect(self, _param_15, message);
|
|
402
|
+
}
|
|
403
|
+
void Tester_assert_uint8_string(struct Tester *self, unsigned char value, char* message)
|
|
404
|
+
{
|
|
405
|
+
unsigned char _param_16 = (value != 0);
|
|
406
|
+
Tester_expect(self, _param_16, message);
|
|
407
|
+
}
|
|
408
|
+
void Tester_assert_float_string(struct Tester *self, double value, char* message)
|
|
409
|
+
{
|
|
410
|
+
unsigned char _param_17 = (value != 0);
|
|
411
|
+
Tester_expect(self, _param_17, message);
|
|
412
|
+
}
|
|
413
|
+
void Tester_assert_bool_string(struct Tester *self, unsigned char value, char* message)
|
|
414
|
+
{
|
|
415
|
+
unsigned char _param_18 = (value != 0);
|
|
416
|
+
Tester_expect(self, _param_18, message);
|
|
417
|
+
}
|
|
418
|
+
void Tester_assert_char_string(struct Tester *self, char value, char* message)
|
|
419
|
+
{
|
|
420
|
+
unsigned char _param_19 = (value != 0);
|
|
421
|
+
Tester_expect(self, _param_19, message);
|
|
422
|
+
}
|
|
423
|
+
void Tester_assert_string_string(struct Tester *self, char* value, char* message)
|
|
424
|
+
{
|
|
425
|
+
unsigned char _param_20 = (value != 0);
|
|
426
|
+
Tester_expect(self, _param_20, message);
|
|
427
|
+
}
|
|
428
|
+
void Tester_bench(struct Tester *self, char* label, void* body)
|
|
429
|
+
{
|
|
430
|
+
if (self->has_failed) {
|
|
431
|
+
return;
|
|
432
|
+
;
|
|
433
|
+
}
|
|
434
|
+
self->bench_pending = 1;
|
|
435
|
+
self->bench_label = label;
|
|
436
|
+
self->bench_samples = 1000L;
|
|
437
|
+
}
|
|
438
|
+
void Tester_bench_n(struct Tester *self, char* label, void* body, long samples)
|
|
439
|
+
{
|
|
440
|
+
if (self->has_failed) {
|
|
441
|
+
return;
|
|
442
|
+
;
|
|
443
|
+
}
|
|
444
|
+
self->bench_pending = 1;
|
|
445
|
+
self->bench_label = label;
|
|
446
|
+
self->bench_samples = samples;
|
|
447
|
+
}
|
|
448
|
+
void Tester_record_bench(struct Tester *self, char* label, long n, long min, long median, long max, double mean, double stddev)
|
|
449
|
+
{
|
|
450
|
+
if (self->has_failed) {
|
|
451
|
+
return;
|
|
452
|
+
;
|
|
453
|
+
}
|
|
454
|
+
char* _param_21 = int_to_string(n);
|
|
455
|
+
char* _param_22 = int_to_string(min);
|
|
456
|
+
char* _param_23 = int_to_string(median);
|
|
457
|
+
char* _param_24 = int_to_string(max);
|
|
458
|
+
char* _param_25 = float_to_string(mean);
|
|
459
|
+
char* _param_26 = float_to_string(stddev);
|
|
460
|
+
char* _param_27 = ({ char* _ltmp_2 = string_add("\\nomen|bench|", label); char* _rtmp_2 = _string_interpolate_6("|%s|%s|%s|%s|%s|%s", _param_21, _param_22, _param_23, _param_24, _param_25, _param_26); char* _cres_2 = string_add(_ltmp_2, _rtmp_2); free(_ltmp_2); free(_rtmp_2); _cres_2; });
|
|
461
|
+
Console_write_line(_param_27);
|
|
462
|
+
|
|
463
|
+
// Auto-free
|
|
464
|
+
free(_param_21);
|
|
465
|
+
free(_param_22);
|
|
466
|
+
free(_param_23);
|
|
467
|
+
free(_param_24);
|
|
468
|
+
free(_param_25);
|
|
469
|
+
free(_param_26);
|
|
470
|
+
free(_param_27);
|
|
471
|
+
}
|
|
472
|
+
void Tester_record_failure(struct Tester *self, char* message)
|
|
473
|
+
{
|
|
474
|
+
self->failed += 1L;
|
|
475
|
+
self->total_failed += 1L;
|
|
476
|
+
self->has_failed = 1;
|
|
477
|
+
char* _param_28 = ({ char* _ltmp_3 = ({ char* _ltmp_4 = string_add("\\nomen|fail|", self->current); char* _rtmp_4 = "|"; char* _cres_4 = string_add(_ltmp_4, _rtmp_4); free(_ltmp_4); _cres_4; }); char* _rtmp_3 = message; char* _cres_3 = string_add(_ltmp_3, _rtmp_3); free(_ltmp_3); _cres_3; });
|
|
478
|
+
Console_write_line(_param_28);
|
|
479
|
+
|
|
480
|
+
// Auto-free
|
|
481
|
+
free(_param_28);
|
|
482
|
+
}
|
|
483
|
+
void Tester_destroy(struct Tester *self)
|
|
484
|
+
{
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Struct Math
|
|
488
|
+
struct Math Math_init()
|
|
489
|
+
{
|
|
490
|
+
struct Math _self;
|
|
491
|
+
return _self;
|
|
492
|
+
}
|
|
493
|
+
long Math_power(long base, long exp)
|
|
494
|
+
{
|
|
495
|
+
int result = 1;
|
|
496
|
+
for (int i = 0; i < exp; i++) {
|
|
497
|
+
result *= base;
|
|
498
|
+
}
|
|
499
|
+
return result;
|
|
500
|
+
}
|
|
501
|
+
double Math_sqrt(double x)
|
|
502
|
+
{
|
|
503
|
+
return sqrt(x);
|
|
504
|
+
}
|
|
505
|
+
double Math_log(double x)
|
|
506
|
+
{
|
|
507
|
+
return log(x);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Struct Buffer_int
|
|
511
|
+
struct Buffer_int Buffer_int_init()
|
|
512
|
+
{
|
|
513
|
+
struct Buffer_int _self;
|
|
514
|
+
_self.data = 0L;
|
|
515
|
+
_self.cap = 0L;
|
|
516
|
+
return _self;
|
|
517
|
+
}
|
|
518
|
+
long Buffer_int_alloc(struct Buffer_int *self, long size)
|
|
519
|
+
{
|
|
520
|
+
self->cap = size;
|
|
521
|
+
self->data = (unsigned long long)(unsigned int*)calloc(size, sizeof(unsigned int));
|
|
522
|
+
return self->cap;
|
|
523
|
+
}
|
|
524
|
+
long Buffer_int_grow(struct Buffer_int *self, long needed)
|
|
525
|
+
{
|
|
526
|
+
if (self->cap >= needed) return self->cap;
|
|
527
|
+
int new_cap = self->cap;
|
|
528
|
+
if (new_cap == 0) new_cap = 8;
|
|
529
|
+
while (new_cap < needed) new_cap *= 2;
|
|
530
|
+
self->data = (unsigned long long)(unsigned int*)realloc((unsigned int*)(unsigned long long)self->data, new_cap * sizeof(unsigned int));
|
|
531
|
+
memset((unsigned int*)(unsigned long long)self->data + self->cap, 0, (new_cap - self->cap) * sizeof(unsigned int));
|
|
532
|
+
self->cap = new_cap;
|
|
533
|
+
return self->cap;
|
|
534
|
+
}
|
|
535
|
+
void Buffer_int_zero(struct Buffer_int *self, long len)
|
|
536
|
+
{
|
|
537
|
+
memset((unsigned int*)(unsigned long long)self->data, 0, len * sizeof(unsigned int));
|
|
538
|
+
}
|
|
539
|
+
unsigned int Buffer_int_load(struct Buffer_int *self, long i)
|
|
540
|
+
{
|
|
541
|
+
struct Buffer_int _self = *self;
|
|
542
|
+
return ((unsigned int*)(unsigned long long)self->data)[i];
|
|
543
|
+
}
|
|
544
|
+
void Buffer_int_store(struct Buffer_int *self, long i, unsigned int val)
|
|
545
|
+
{
|
|
546
|
+
((unsigned int*)(unsigned long long)self->data)[i] = val;
|
|
547
|
+
}
|
|
548
|
+
void Buffer_int_store_or(struct Buffer_int *self, long i, unsigned int val)
|
|
549
|
+
{
|
|
550
|
+
((unsigned int*)(unsigned long long)self->data)[i] |= val;
|
|
551
|
+
}
|
|
552
|
+
long Buffer_int_alloc_int(struct Buffer_int *self, long size)
|
|
553
|
+
{
|
|
554
|
+
self->cap = size;
|
|
555
|
+
self->data = (unsigned long long)(long*)calloc(size, sizeof(long));
|
|
556
|
+
return self->cap;
|
|
557
|
+
}
|
|
558
|
+
long Buffer_int_grow_int(struct Buffer_int *self, long needed)
|
|
559
|
+
{
|
|
560
|
+
if (self->cap >= needed) return self->cap;
|
|
561
|
+
int new_cap = self->cap;
|
|
562
|
+
if (new_cap == 0) new_cap = 4;
|
|
563
|
+
while (new_cap < needed) new_cap *= 2;
|
|
564
|
+
self->data = (unsigned long long)(long*)realloc((long*)(unsigned long long)self->data, new_cap * sizeof(long));
|
|
565
|
+
memset((long*)(unsigned long long)self->data + self->cap, 0, (new_cap - self->cap) * sizeof(long));
|
|
566
|
+
self->cap = new_cap;
|
|
567
|
+
return self->cap;
|
|
568
|
+
}
|
|
569
|
+
long Buffer_int_load_int(struct Buffer_int *self, long i)
|
|
570
|
+
{
|
|
571
|
+
struct Buffer_int _self = *self;
|
|
572
|
+
return ((long*)(unsigned long long)self->data)[i];
|
|
573
|
+
}
|
|
574
|
+
void Buffer_int_store_int(struct Buffer_int *self, long i, long val)
|
|
575
|
+
{
|
|
576
|
+
((long*)(unsigned long long)self->data)[i] = val;
|
|
577
|
+
}
|
|
578
|
+
long Buffer_int_move_int(struct Buffer_int *self, long i)
|
|
579
|
+
{
|
|
580
|
+
long *slots = (long*)(unsigned long long)self->data;
|
|
581
|
+
long val = slots[i];
|
|
582
|
+
slots[i] = 0;
|
|
583
|
+
return val;
|
|
584
|
+
}
|
|
585
|
+
void Buffer_int_replace_int(struct Buffer_int *self, long i, long val)
|
|
586
|
+
{
|
|
587
|
+
((long*)(unsigned long long)self->data)[i] = val;
|
|
588
|
+
}
|
|
589
|
+
void Buffer_int_zero_int(struct Buffer_int *self, long len)
|
|
590
|
+
{
|
|
591
|
+
memset((long*)(unsigned long long)self->data, 0, len * sizeof(long));
|
|
592
|
+
}
|
|
593
|
+
long Buffer_int_alloc_T(struct Buffer_int *self, long size)
|
|
594
|
+
{
|
|
595
|
+
self->cap = size;
|
|
596
|
+
self->data = (unsigned long long)(long*)calloc(size, 8);
|
|
597
|
+
return self->cap;
|
|
598
|
+
}
|
|
599
|
+
long Buffer_int_grow_T(struct Buffer_int *self, long needed)
|
|
600
|
+
{
|
|
601
|
+
if (self->cap >= needed) return self->cap;
|
|
602
|
+
int new_cap = self->cap;
|
|
603
|
+
if (new_cap == 0) new_cap = 4;
|
|
604
|
+
while (new_cap < needed) new_cap *= 2;
|
|
605
|
+
self->data = (unsigned long long)(long*)realloc((long*)(unsigned long long)self->data, new_cap * 8);
|
|
606
|
+
memset((char*)(unsigned long long)self->data + self->cap * 8, 0, (new_cap - self->cap) * 8);
|
|
607
|
+
self->cap = new_cap;
|
|
608
|
+
return self->cap;
|
|
609
|
+
}
|
|
610
|
+
long Buffer_int_load_T(struct Buffer_int *self, long i)
|
|
611
|
+
{
|
|
612
|
+
struct Buffer_int _self = *self;
|
|
613
|
+
return ((long*)(unsigned long long)self->data)[i];
|
|
614
|
+
}
|
|
615
|
+
void Buffer_int_store_T(struct Buffer_int *self, long i, long val)
|
|
616
|
+
{
|
|
617
|
+
((long*)(unsigned long long)self->data)[i] = val;
|
|
618
|
+
}
|
|
619
|
+
nomen_view Buffer_int_slice(struct Buffer_int *self, long start, long end)
|
|
620
|
+
{
|
|
621
|
+
struct Buffer_int _self = *self;
|
|
622
|
+
nomen_view _r;
|
|
623
|
+
_r.ptr = (void*)((long*)(unsigned long long)self->data + start);
|
|
624
|
+
_r.len = (long)(end - start);
|
|
625
|
+
return _r;
|
|
626
|
+
}
|
|
627
|
+
void Buffer_int_zero_T(struct Buffer_int *self, long len)
|
|
628
|
+
{
|
|
629
|
+
memset((long*)(unsigned long long)self->data, 0, len * 8);
|
|
630
|
+
}
|
|
631
|
+
void Buffer_int_store_or_int(struct Buffer_int *self, long i, long val)
|
|
632
|
+
{
|
|
633
|
+
((long*)(unsigned long long)self->data)[i] |= val;
|
|
634
|
+
}
|
|
635
|
+
long Buffer_int_alloc_float(struct Buffer_int *self, long size)
|
|
636
|
+
{
|
|
637
|
+
self->cap = size;
|
|
638
|
+
self->data = (unsigned long long)(double*)calloc(size, sizeof(double));
|
|
639
|
+
return self->cap;
|
|
640
|
+
}
|
|
641
|
+
double Buffer_int_load_float(struct Buffer_int *self, long i)
|
|
642
|
+
{
|
|
643
|
+
struct Buffer_int _self = *self;
|
|
644
|
+
return ((double*)(unsigned long long)self->data)[i];
|
|
645
|
+
}
|
|
646
|
+
void Buffer_int_store_float(struct Buffer_int *self, long i, double val)
|
|
647
|
+
{
|
|
648
|
+
((double*)(unsigned long long)self->data)[i] = val;
|
|
649
|
+
}
|
|
650
|
+
void Buffer_int_destroy(struct Buffer_int *self)
|
|
651
|
+
{
|
|
652
|
+
if (self->data) free((unsigned int*)(unsigned long long)self->data);
|
|
653
|
+
self->data = 0;
|
|
654
|
+
self->cap = 0;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Struct List_int
|
|
658
|
+
void *_List_int_Viewable_funcs[] = {};
|
|
659
|
+
void *_List_int_destroy_funcs[] = {List_int_destroy};
|
|
660
|
+
void *_List_int_traits[] = {&_List_int_destroy_funcs, NULL, NULL, NULL, NULL, &_List_int_Viewable_funcs};
|
|
661
|
+
struct List_int List_int_init()
|
|
662
|
+
{
|
|
663
|
+
struct List_int _self;
|
|
664
|
+
_self._vt = &_List_int_traits;
|
|
665
|
+
_self.length = 0L;
|
|
666
|
+
_self.items = Buffer_int_init();
|
|
667
|
+
return _self;
|
|
668
|
+
}
|
|
669
|
+
void List_int_push(struct List_int *self, long value)
|
|
670
|
+
{
|
|
671
|
+
if ((self->length >= self->items.cap)) {
|
|
672
|
+
long new_cap = 4L;
|
|
673
|
+
long old_cap = self->items.cap;
|
|
674
|
+
if ((old_cap >= 4L)) {
|
|
675
|
+
new_cap = (old_cap * 2L);
|
|
676
|
+
}
|
|
677
|
+
Buffer_int_grow_int(&self->items, new_cap);
|
|
678
|
+
}
|
|
679
|
+
Buffer_int_store_int(&self->items, self->length, value);
|
|
680
|
+
self->length += 1L;
|
|
681
|
+
}
|
|
682
|
+
long List_int_pop(struct List_int *self)
|
|
683
|
+
{
|
|
684
|
+
if ((self->length <= 0L)) {
|
|
685
|
+
long _return_val = 0L;
|
|
686
|
+
return _return_val;
|
|
687
|
+
;
|
|
688
|
+
}
|
|
689
|
+
long idx = (self->length - 1L);
|
|
690
|
+
self->length = idx;
|
|
691
|
+
long _return_val = Buffer_int_move_int(&self->items, idx);
|
|
692
|
+
return _return_val;
|
|
693
|
+
;
|
|
694
|
+
}
|
|
695
|
+
long List_int_at(struct List_int *self, long i)
|
|
696
|
+
{
|
|
697
|
+
struct List_int _self = *self;
|
|
698
|
+
long _return_val = Buffer_int_load_int(&self->items, i);
|
|
699
|
+
return _return_val;
|
|
700
|
+
;
|
|
701
|
+
}
|
|
702
|
+
nomen_view List_int_slice(struct List_int *self, long start, long end)
|
|
703
|
+
{
|
|
704
|
+
struct List_int _self = *self;
|
|
705
|
+
nomen_view _return_val = Buffer_int_slice(&self->items, start, end);
|
|
706
|
+
return _return_val;
|
|
707
|
+
;
|
|
708
|
+
}
|
|
709
|
+
void List_int_set(struct List_int *self, long i, long value)
|
|
710
|
+
{
|
|
711
|
+
long v = value;
|
|
712
|
+
Buffer_int_replace_int(&self->items, i, v);
|
|
713
|
+
}
|
|
714
|
+
void List_int_destroy(struct List_int *self)
|
|
715
|
+
{
|
|
716
|
+
Buffer_int_destroy(&self->items);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// Func add
|
|
720
|
+
long add(long a, long b)
|
|
721
|
+
{
|
|
722
|
+
long _return_val = (a + b);
|
|
723
|
+
return _return_val;
|
|
724
|
+
;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// Func mul
|
|
728
|
+
long mul(long a, long b)
|
|
729
|
+
{
|
|
730
|
+
long _return_val = (a * b);
|
|
731
|
+
return _return_val;
|
|
732
|
+
;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// Func add_once
|
|
736
|
+
void add_once()
|
|
737
|
+
{
|
|
738
|
+
long r = add(1L, 1L);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
// Func test_add
|
|
742
|
+
void test_add(struct Tester **t)
|
|
743
|
+
{
|
|
744
|
+
unsigned char _param_0 = (add(1L, 1L) == 2L);
|
|
745
|
+
Tester_expect((*t), _param_0, "1 + 1 should be 2");
|
|
746
|
+
unsigned char _param_1 = (add(2L, 3L) == 5L);
|
|
747
|
+
Tester_expect((*t), _param_1, "2 + 3 should be 5");
|
|
748
|
+
unsigned char _param_2 = (add(100L, 1L) == 101L);
|
|
749
|
+
Tester_expect((*t), _param_2, "100 + 1 should be 101");
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// Func test_mul
|
|
753
|
+
void test_mul(struct Tester **t)
|
|
754
|
+
{
|
|
755
|
+
unsigned char _param_3 = (mul(2L, 2L) == 4L);
|
|
756
|
+
Tester_expect((*t), _param_3, "2 * 2 should be 4");
|
|
757
|
+
unsigned char _param_4 = (mul(3L, 3L) == 10L);
|
|
758
|
+
Tester_expect((*t), _param_4, "3 * 3 should be 9 (this fails on purpose)");
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Func test_assert_not_null
|
|
762
|
+
void test_assert_not_null(struct Tester **t)
|
|
763
|
+
{
|
|
764
|
+
long maybe = 42L;
|
|
765
|
+
Tester_assert_int_string((*t), maybe, "maybe should hold a value");
|
|
766
|
+
char* none = 0;
|
|
767
|
+
Tester_assert_string_string((*t), none, "none should be null (this fails on purpose)");
|
|
768
|
+
|
|
769
|
+
// Auto-free
|
|
770
|
+
free(none);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Func bench_add
|
|
774
|
+
void bench_add(struct Tester **t)
|
|
775
|
+
{
|
|
776
|
+
Tester_bench((*t), "add", add_once);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Func bench_loop_bench_add
|
|
780
|
+
void bench_loop_bench_add(struct Tester **t)
|
|
781
|
+
{
|
|
782
|
+
long __w = 0L;
|
|
783
|
+
while ((__w < 8L)) {
|
|
784
|
+
add_once();
|
|
785
|
+
__w += 1L;
|
|
786
|
+
}
|
|
787
|
+
struct List_int __samples = List_int_init();
|
|
788
|
+
long __sum = 0L;
|
|
789
|
+
double __sum_sq = 0.0;
|
|
790
|
+
long __min = 0L;
|
|
791
|
+
long __max = 0L;
|
|
792
|
+
long __i = 0L;
|
|
793
|
+
while ((__i < 1000L)) {
|
|
794
|
+
unsigned long long __t0 = Time_now_ns();
|
|
795
|
+
add_once();
|
|
796
|
+
unsigned long long __t1 = Time_now_ns();
|
|
797
|
+
long __dt = (long)((__t1 - __t0));
|
|
798
|
+
List_int_push(&__samples, __dt);
|
|
799
|
+
__sum += __dt;
|
|
800
|
+
__sum_sq = (__sum_sq + (((double)__dt) * ((double)__dt)));
|
|
801
|
+
if ((__i == 0L)) {
|
|
802
|
+
__min = __dt;
|
|
803
|
+
__max = __dt;
|
|
804
|
+
}
|
|
805
|
+
if ((__i > 0L)) {
|
|
806
|
+
if ((__dt < __min)) {
|
|
807
|
+
__min = __dt;
|
|
808
|
+
}
|
|
809
|
+
if ((__dt > __max)) {
|
|
810
|
+
__max = __dt;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
__i += 1L;
|
|
814
|
+
}
|
|
815
|
+
long __n = __samples.length;
|
|
816
|
+
if ((__n > 0L)) {
|
|
817
|
+
double __fn = (double)__n;
|
|
818
|
+
double __mean = (((double)__sum) / __fn);
|
|
819
|
+
double __variance = ((__sum_sq / __fn) - (__mean * __mean));
|
|
820
|
+
if ((__variance < 0.0)) {
|
|
821
|
+
__variance = 0.0;
|
|
822
|
+
}
|
|
823
|
+
double __stddev = Math_sqrt(__variance);
|
|
824
|
+
long __s = 1L;
|
|
825
|
+
while ((__s < __n)) {
|
|
826
|
+
if (((__s >= 0L) && (__s < __samples.length))) {
|
|
827
|
+
long __v = List_int_at(&__samples, __s);
|
|
828
|
+
long __j = __s;
|
|
829
|
+
unsigned char __more = 1;
|
|
830
|
+
while (__more) {
|
|
831
|
+
long __pm1 = (__j - 1L);
|
|
832
|
+
if (((__pm1 >= 0L) && (__pm1 < __samples.length))) {
|
|
833
|
+
long __prev = List_int_at(&__samples, __pm1);
|
|
834
|
+
if ((__prev > __v)) {
|
|
835
|
+
if (((__j >= 0L) && (__j < __samples.length))) {
|
|
836
|
+
List_int_set(&__samples, __j, __prev);
|
|
837
|
+
}
|
|
838
|
+
__j -= 1L;
|
|
839
|
+
} else {
|
|
840
|
+
__more = 0;
|
|
841
|
+
}
|
|
842
|
+
} else {
|
|
843
|
+
__more = 0;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
if (((__j >= 0L) && (__j < __samples.length))) {
|
|
847
|
+
List_int_set(&__samples, __j, __v);
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
__s += 1L;
|
|
851
|
+
}
|
|
852
|
+
long __median = __min;
|
|
853
|
+
long __hi = (__n / 2L);
|
|
854
|
+
if (((__hi >= 0L) && (__hi < __samples.length))) {
|
|
855
|
+
__median = List_int_at(&__samples, __hi);
|
|
856
|
+
}
|
|
857
|
+
if (((__n % 2L) == 0L)) {
|
|
858
|
+
long __lo = ((__n / 2L) - 1L);
|
|
859
|
+
if (((__lo >= 0L) && (__lo < __samples.length))) {
|
|
860
|
+
if (((__hi >= 0L) && (__hi < __samples.length))) {
|
|
861
|
+
long __a = List_int_at(&__samples, __lo);
|
|
862
|
+
long __b = List_int_at(&__samples, __hi);
|
|
863
|
+
__median = (((__a + __b)) / 2L);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
char* _param_5 = (*t)->bench_label;
|
|
868
|
+
Tester_record_bench((*t), _param_5, __n, __min, __median, __max, __mean, __stddev);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// Auto-free
|
|
872
|
+
Buffer_int_destroy(&__samples.items);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// Func main
|
|
876
|
+
int main()
|
|
877
|
+
{
|
|
878
|
+
struct Tester *t = Tester_init();
|
|
879
|
+
Tester_begin_test(t, "test_add");
|
|
880
|
+
test_add(&t);
|
|
881
|
+
Tester_end_test(t);
|
|
882
|
+
Tester_begin_test(t, "test_mul");
|
|
883
|
+
test_mul(&t);
|
|
884
|
+
Tester_end_test(t);
|
|
885
|
+
Tester_begin_test(t, "test_assert_not_null");
|
|
886
|
+
test_assert_not_null(&t);
|
|
887
|
+
Tester_end_test(t);
|
|
888
|
+
t->has_failed = 0;
|
|
889
|
+
t->bench_pending = 0;
|
|
890
|
+
bench_add(&t);
|
|
891
|
+
if (t->bench_pending) {
|
|
892
|
+
bench_loop_bench_add(&t);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Auto-free
|
|
896
|
+
Tester_destroy(t); free(t);
|
|
897
|
+
return 0;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
void **_get_trait_func(void **obj, int trait_index, int func_index)
|
|
902
|
+
{
|
|
903
|
+
void **vt = *obj;
|
|
904
|
+
// Slot 0 of _<Struct>_traits is the destroy-funcs pointer (reserved so a
|
|
905
|
+
// trait-typed collection can dispatch destroy polymorphically). Real trait
|
|
906
|
+
// tables start at index 1, so shift trait_index by 1.
|
|
907
|
+
void **trait = *(vt + 1 + trait_index);
|
|
908
|
+
void **func = *(trait + func_index);
|
|
909
|
+
return func;
|
|
910
|
+
}
|
|
911
|
+
void Stringable_destroy(void *obj)
|
|
912
|
+
{
|
|
913
|
+
void **vt = *(void **)obj;
|
|
914
|
+
void **destroy_funcs = (void **)vt[0];
|
|
915
|
+
if (destroy_funcs) {
|
|
916
|
+
void (*destroy)(void *) = (void (*)(void *))*destroy_funcs;
|
|
917
|
+
if (destroy) destroy(obj);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
void Disposable_destroy(void *obj)
|
|
921
|
+
{
|
|
922
|
+
void **vt = *(void **)obj;
|
|
923
|
+
void **destroy_funcs = (void **)vt[0];
|
|
924
|
+
if (destroy_funcs) {
|
|
925
|
+
void (*destroy)(void *) = (void (*)(void *))*destroy_funcs;
|
|
926
|
+
if (destroy) destroy(obj);
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
void Equatable_destroy(void *obj)
|
|
930
|
+
{
|
|
931
|
+
void **vt = *(void **)obj;
|
|
932
|
+
void **destroy_funcs = (void **)vt[0];
|
|
933
|
+
if (destroy_funcs) {
|
|
934
|
+
void (*destroy)(void *) = (void (*)(void *))*destroy_funcs;
|
|
935
|
+
if (destroy) destroy(obj);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
void Hashable_destroy(void *obj)
|
|
939
|
+
{
|
|
940
|
+
void **vt = *(void **)obj;
|
|
941
|
+
void **destroy_funcs = (void **)vt[0];
|
|
942
|
+
if (destroy_funcs) {
|
|
943
|
+
void (*destroy)(void *) = (void (*)(void *))*destroy_funcs;
|
|
944
|
+
if (destroy) destroy(obj);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
void Viewable_destroy(void *obj)
|
|
948
|
+
{
|
|
949
|
+
void **vt = *(void **)obj;
|
|
950
|
+
void **destroy_funcs = (void **)vt[0];
|
|
951
|
+
if (destroy_funcs) {
|
|
952
|
+
void (*destroy)(void *) = (void (*)(void *))*destroy_funcs;
|
|
953
|
+
if (destroy) destroy(obj);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
char *_string_interpolate_3(char *pattern, char *arg1, char *arg2, char *arg3)
|
|
957
|
+
{
|
|
958
|
+
int length = snprintf(NULL, 0, pattern, arg1, arg2, arg3);
|
|
959
|
+
char *str = malloc(length + 1);
|
|
960
|
+
snprintf(str, length + 1, pattern, arg1, arg2, arg3);
|
|
961
|
+
return str;
|
|
962
|
+
}
|
|
963
|
+
char *_string_interpolate_6(char *pattern, char *arg1, char *arg2, char *arg3, char *arg4, char *arg5, char *arg6)
|
|
964
|
+
{
|
|
965
|
+
int length = snprintf(NULL, 0, pattern, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
966
|
+
char *str = malloc(length + 1);
|
|
967
|
+
snprintf(str, length + 1, pattern, arg1, arg2, arg3, arg4, arg5, arg6);
|
|
968
|
+
return str;
|
|
969
|
+
}
|