iodine 0.7.11 → 0.7.12
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/iodine/fio.c +341 -154
- data/ext/iodine/fio.h +71 -33
- data/ext/iodine/fio_cli.c +25 -24
- data/ext/iodine/fiobj.h +4 -0
- data/ext/iodine/{fiobj4sock.h → fiobj4fio.h} +0 -0
- data/ext/iodine/fiobj_mustache.c +77 -54
- data/ext/iodine/fiobj_mustache.h +21 -3
- data/ext/iodine/http.c +19 -0
- data/ext/iodine/http.h +5 -1
- data/ext/iodine/http_internal.h +0 -2
- data/ext/iodine/iodine_connection.c +1 -1
- data/ext/iodine/iodine_http.c +17 -9
- data/ext/iodine/iodine_mustache.c +174 -91
- data/ext/iodine/mustache_parser.h +772 -695
- data/ext/iodine/redis_engine.c +0 -1
- data/lib/iodine/mustache.rb +4 -4
- data/lib/iodine/version.rb +1 -1
- metadata +4 -4
data/ext/iodine/fio.h
CHANGED
@@ -182,8 +182,8 @@ Version and helper macros
|
|
182
182
|
|
183
183
|
#ifndef FIO_IGNORE_MACRO
|
184
184
|
/**
|
185
|
-
* This is used internally to
|
186
|
-
* arguments when required.
|
185
|
+
* This is used internally to ignore macros that shadow functions (avoiding
|
186
|
+
* named arguments when required).
|
187
187
|
*/
|
188
188
|
#define FIO_IGNORE_MACRO
|
189
189
|
#endif
|
@@ -298,6 +298,18 @@ Memory pool / custom allocator for short lived objects
|
|
298
298
|
|
299
299
|
***************************************************************************** */
|
300
300
|
|
301
|
+
/* inform the compiler that the returned value is aligned on 16 byte marker */
|
302
|
+
#if FIO_FORCE_MALLOC
|
303
|
+
#define FIO_ALIGN
|
304
|
+
#define FIO_ALIGN_NEW
|
305
|
+
#elif __clang__ || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 8)
|
306
|
+
#define FIO_ALIGN __attribute__((assume_aligned(16)))
|
307
|
+
#define FIO_ALIGN_NEW __attribute__((malloc, assume_aligned(16)))
|
308
|
+
#else
|
309
|
+
#define FIO_ALIGN
|
310
|
+
#define FIO_ALIGN_NEW
|
311
|
+
#endif
|
312
|
+
|
301
313
|
/**
|
302
314
|
* Allocates memory using a per-CPU core block memory pool.
|
303
315
|
* Memory is zeroed out.
|
@@ -305,7 +317,7 @@ Memory pool / custom allocator for short lived objects
|
|
305
317
|
* Allocations above FIO_MEMORY_BLOCK_ALLOC_LIMIT (12,288 bytes when using 32Kb
|
306
318
|
* blocks) will be redirected to `mmap`, as if `fio_mmap` was called.
|
307
319
|
*/
|
308
|
-
void *fio_malloc(size_t size);
|
320
|
+
void *FIO_ALIGN_NEW fio_malloc(size_t size);
|
309
321
|
|
310
322
|
/**
|
311
323
|
* same as calling `fio_malloc(size_per_unit * unit_count)`;
|
@@ -313,7 +325,7 @@ void *fio_malloc(size_t size);
|
|
313
325
|
* Allocations above FIO_MEMORY_BLOCK_ALLOC_LIMIT (12,288 bytes when using 32Kb
|
314
326
|
* blocks) will be redirected to `mmap`, as if `fio_mmap` was called.
|
315
327
|
*/
|
316
|
-
void *fio_calloc(size_t size_per_unit, size_t unit_count);
|
328
|
+
void *FIO_ALIGN_NEW fio_calloc(size_t size_per_unit, size_t unit_count);
|
317
329
|
|
318
330
|
/** Frees memory that was allocated using this library. */
|
319
331
|
void fio_free(void *ptr);
|
@@ -322,7 +334,7 @@ void fio_free(void *ptr);
|
|
322
334
|
* Re-allocates memory. An attempt to avoid copying the data is made only for
|
323
335
|
* big memory allocations (larger than FIO_MEMORY_BLOCK_ALLOC_LIMIT).
|
324
336
|
*/
|
325
|
-
void *fio_realloc(void *ptr, size_t new_size);
|
337
|
+
void *FIO_ALIGN fio_realloc(void *ptr, size_t new_size);
|
326
338
|
|
327
339
|
/**
|
328
340
|
* Re-allocates memory. An attempt to avoid copying the data is made only for
|
@@ -330,7 +342,7 @@ void *fio_realloc(void *ptr, size_t new_size);
|
|
330
342
|
*
|
331
343
|
* This variation is slightly faster as it might copy less data.
|
332
344
|
*/
|
333
|
-
void *fio_realloc2(void *ptr, size_t new_size, size_t copy_length);
|
345
|
+
void *FIO_ALIGN fio_realloc2(void *ptr, size_t new_size, size_t copy_length);
|
334
346
|
|
335
347
|
/**
|
336
348
|
* Allocates memory directly using `mmap`, this is prefered for objects that
|
@@ -341,7 +353,7 @@ void *fio_realloc2(void *ptr, size_t new_size, size_t copy_length);
|
|
341
353
|
*
|
342
354
|
* `fio_free` can be used for deallocating the memory.
|
343
355
|
*/
|
344
|
-
void *fio_mmap(size_t size);
|
356
|
+
void *FIO_ALIGN_NEW fio_mmap(size_t size);
|
345
357
|
|
346
358
|
/**
|
347
359
|
* When forking is called manually, call this function to reset the facil.io
|
@@ -349,6 +361,8 @@ void *fio_mmap(size_t size);
|
|
349
361
|
*/
|
350
362
|
void fio_malloc_after_fork(void);
|
351
363
|
|
364
|
+
#undef FIO_ALIGN
|
365
|
+
|
352
366
|
#if FIO_FORCE_MALLOC
|
353
367
|
#define FIO_MALLOC(size) calloc((size), 1)
|
354
368
|
#define FIO_CALLOC(size, units) calloc((size), (units))
|
@@ -445,15 +459,12 @@ extern int FIO_LOG_LEVEL;
|
|
445
459
|
#define FIO_LOG_STATE(...)
|
446
460
|
#endif
|
447
461
|
|
448
|
-
#if DEBUG
|
449
462
|
#define FIO_ASSERT(cond, ...) \
|
450
463
|
if (!(cond)) { \
|
451
|
-
|
464
|
+
FIO_LOG_FATAL("(" __FILE__ ":" FIO_MACRO2STR(__LINE__) ") "__VA_ARGS__); \
|
465
|
+
perror(" errno"); \
|
452
466
|
exit(-1); \
|
453
467
|
}
|
454
|
-
#else
|
455
|
-
#define FIO_ASSERT(...)
|
456
|
-
#endif
|
457
468
|
|
458
469
|
#ifndef FIO_ASSERT_ALLOC
|
459
470
|
/** Tests for an allocation failure. The behavior can be overridden. */
|
@@ -466,6 +477,17 @@ extern int FIO_LOG_LEVEL;
|
|
466
477
|
}
|
467
478
|
#endif
|
468
479
|
|
480
|
+
#if DEBUG
|
481
|
+
#define FIO_ASSERT_DEBUG(cond, ...) \
|
482
|
+
if (!(cond)) { \
|
483
|
+
FIO_LOG_DEBUG(__VA_ARGS__); \
|
484
|
+
perror(" errno"); \
|
485
|
+
exit(-1); \
|
486
|
+
}
|
487
|
+
#else
|
488
|
+
#define FIO_ASSERT_DEBUG(...)
|
489
|
+
#endif
|
490
|
+
|
469
491
|
/* *****************************************************************************
|
470
492
|
|
471
493
|
|
@@ -564,9 +586,24 @@ void fio_attach(intptr_t uuid, fio_protocol_s *protocol);
|
|
564
586
|
* The old protocol's `on_close` (if any) will be scheduled.
|
565
587
|
*
|
566
588
|
* On error, the new protocol's `on_close` callback will be called immediately.
|
589
|
+
*
|
590
|
+
* NOTE: before attaching a file descriptor that was created outside of
|
591
|
+
* facil.io's library, make sure it is set to non-blocking mode (see
|
592
|
+
* `fio_set_non_block`). facil.io file descriptors are all non-blocking and it
|
593
|
+
* will assumes this is the case for the attached fd.
|
567
594
|
*/
|
568
595
|
void fio_attach_fd(int fd, fio_protocol_s *protocol);
|
569
596
|
|
597
|
+
/**
|
598
|
+
* Sets a socket to non blocking state.
|
599
|
+
*
|
600
|
+
* This will also set the O_CLOEXEC flag for the file descriptor.
|
601
|
+
*
|
602
|
+
* This function is called automatically for the new socket, when using
|
603
|
+
* `fio_accept` or `fio_connect`.
|
604
|
+
*/
|
605
|
+
int fio_set_non_block(int fd);
|
606
|
+
|
570
607
|
/**
|
571
608
|
* Returns the maximum number of open files facil.io can handle per worker
|
572
609
|
* process.
|
@@ -926,6 +963,9 @@ intptr_t fio_socket(const char *address, const char *port, uint8_t is_server);
|
|
926
963
|
* `fio_accept` accepts a new socket connection from a server socket - see the
|
927
964
|
* server flag on `fio_socket`.
|
928
965
|
*
|
966
|
+
* Accepted connection are automatically set to non-blocking mode and the
|
967
|
+
* O_CLOEXEC flag is set.
|
968
|
+
*
|
929
969
|
* NOTE: this function does NOT attach the socket to the IO reactor - see
|
930
970
|
* `fio_attach`.
|
931
971
|
*/
|
@@ -1237,17 +1277,6 @@ typedef struct fio_rw_hook_s {
|
|
1237
1277
|
* deadlock might occur.
|
1238
1278
|
*/
|
1239
1279
|
ssize_t (*write)(intptr_t uuid, void *udata, const void *buf, size_t count);
|
1240
|
-
/**
|
1241
|
-
* The `before_close` callback is called only once before closing the `uuid`.
|
1242
|
-
*
|
1243
|
-
* If the function returns a non-zero value, than closure will be delayed
|
1244
|
-
* until the `flush` returns 0 (or less). This allows a closure signal to be
|
1245
|
-
* sent by the read/write hook when such a signal is required.
|
1246
|
-
*
|
1247
|
-
* Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
|
1248
|
-
* deadlock might occur.
|
1249
|
-
* */
|
1250
|
-
ssize_t (*before_close)(intptr_t uuid, void *udata);
|
1251
1280
|
/**
|
1252
1281
|
* When implemented, this function will be called to flush any data remaining
|
1253
1282
|
* in the internal buffer.
|
@@ -1259,6 +1288,18 @@ typedef struct fio_rw_hook_s {
|
|
1259
1288
|
* deadlock might occur.
|
1260
1289
|
*/
|
1261
1290
|
ssize_t (*flush)(intptr_t uuid, void *udata);
|
1291
|
+
/**
|
1292
|
+
* The `before_close` callback is called only once before closing the `uuid`
|
1293
|
+
* and it might not get called at all if an abnormal closure is detected.
|
1294
|
+
*
|
1295
|
+
* If the function returns a non-zero value, than closure will be delayed
|
1296
|
+
* until the `flush` returns 0 (or less). This allows a closure signal to be
|
1297
|
+
* sent by the read/write hook when such a signal is required.
|
1298
|
+
*
|
1299
|
+
* Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
|
1300
|
+
* deadlock might occur.
|
1301
|
+
* */
|
1302
|
+
ssize_t (*before_close)(intptr_t uuid, void *udata);
|
1262
1303
|
/**
|
1263
1304
|
* Called to perform cleanup after the socket was closed or a new read/write
|
1264
1305
|
* hook was set using `fio_rw_hook_set`.
|
@@ -1499,14 +1540,6 @@ fio_protocol_s *fio_protocol_try_lock(intptr_t uuid, enum fio_protocol_lock_e);
|
|
1499
1540
|
* details. */
|
1500
1541
|
void fio_protocol_unlock(fio_protocol_s *pr, enum fio_protocol_lock_e);
|
1501
1542
|
|
1502
|
-
/**
|
1503
|
-
Sets a socket to non blocking state.
|
1504
|
-
|
1505
|
-
This function is called automatically for the new socket, when using
|
1506
|
-
`fio_accept` or `fio_connect`.
|
1507
|
-
*/
|
1508
|
-
int fio_set_non_block(int fd);
|
1509
|
-
|
1510
1543
|
/* *****************************************************************************
|
1511
1544
|
* Pub/Sub / Cluster Messages API
|
1512
1545
|
*
|
@@ -2853,18 +2886,21 @@ Embeded Linked List Implementation
|
|
2853
2886
|
|
2854
2887
|
/** Removes a node from the containing node. */
|
2855
2888
|
FIO_FUNC inline fio_ls_embd_s *fio_ls_embd_remove(fio_ls_embd_s *node) {
|
2856
|
-
if (node->next == node) {
|
2889
|
+
if (!node->next || node->next == node) {
|
2857
2890
|
/* never remove the list's head */
|
2858
2891
|
return NULL;
|
2859
2892
|
}
|
2860
2893
|
node->next->prev = node->prev;
|
2861
2894
|
node->prev->next = node->next;
|
2895
|
+
node->prev = node->next = node;
|
2862
2896
|
return node;
|
2863
2897
|
}
|
2864
2898
|
|
2865
2899
|
/** Adds a node to the list's head. */
|
2866
2900
|
FIO_FUNC inline void fio_ls_embd_push(fio_ls_embd_s *dest,
|
2867
2901
|
fio_ls_embd_s *node) {
|
2902
|
+
if (!dest || !node)
|
2903
|
+
return;
|
2868
2904
|
node->prev = dest->prev;
|
2869
2905
|
node->next = dest;
|
2870
2906
|
dest->prev->next = node;
|
@@ -2907,7 +2943,7 @@ Independent Linked List Implementation
|
|
2907
2943
|
|
2908
2944
|
/** Removes an object from the containing node. */
|
2909
2945
|
FIO_FUNC inline void *fio_ls_remove(fio_ls_s *node) {
|
2910
|
-
if (node->next == node) {
|
2946
|
+
if (!node || node->next == node) {
|
2911
2947
|
/* never remove the list's head */
|
2912
2948
|
return NULL;
|
2913
2949
|
}
|
@@ -2920,6 +2956,8 @@ FIO_FUNC inline void *fio_ls_remove(fio_ls_s *node) {
|
|
2920
2956
|
|
2921
2957
|
/** Adds an object to the list's head. */
|
2922
2958
|
FIO_FUNC inline fio_ls_s *fio_ls_push(fio_ls_s *pos, const void *obj) {
|
2959
|
+
if (!pos)
|
2960
|
+
return NULL;
|
2923
2961
|
/* prepare item */
|
2924
2962
|
fio_ls_s *item = (fio_ls_s *)malloc(sizeof(*item));
|
2925
2963
|
if (!item) {
|
data/ext/iodine/fio_cli.c
CHANGED
@@ -40,6 +40,8 @@ typedef struct {
|
|
40
40
|
int unnamed_max;
|
41
41
|
int pos;
|
42
42
|
int unnamed_count;
|
43
|
+
int argc;
|
44
|
+
char const **argv;
|
43
45
|
char const *description;
|
44
46
|
char const **names;
|
45
47
|
} fio_cli_parser_data_s;
|
@@ -138,32 +140,29 @@ static void fio_cli_set_arg(cstr_s arg, char const *value, char const *line,
|
|
138
140
|
char const *type = fio_cli_get_line_type(parser, line);
|
139
141
|
switch ((size_t)type) {
|
140
142
|
case /* FIO_CLI_TYPE_BOOL */ 0x2:
|
141
|
-
if (value &&
|
142
|
-
(value == arg.data + arg.len ||
|
143
|
-
(value == arg.data + arg.len + 1 && arg.data[arg.len] == '='))) {
|
143
|
+
if (value && value != parser->argv[parser->pos + 1]) {
|
144
144
|
goto error;
|
145
145
|
}
|
146
146
|
value = "1";
|
147
147
|
break;
|
148
148
|
case /* FIO_CLI_TYPE_INT */ 0x3: /* fallthrough */
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
++tmp;
|
161
|
-
}
|
162
|
-
if (*tmp) {
|
163
|
-
goto error;
|
149
|
+
if (value) {
|
150
|
+
char const *tmp = value;
|
151
|
+
if (*tmp == '-' || *tmp == '+') {
|
152
|
+
++tmp;
|
153
|
+
}
|
154
|
+
while (*tmp && *tmp >= '0' && *tmp <= '9') {
|
155
|
+
++tmp;
|
156
|
+
}
|
157
|
+
if (*tmp) {
|
158
|
+
goto error;
|
159
|
+
}
|
164
160
|
}
|
165
|
-
}
|
166
161
|
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
162
|
+
if (!value)
|
163
|
+
goto error;
|
164
|
+
if (!value[0])
|
165
|
+
goto finish;
|
167
166
|
break;
|
168
167
|
}
|
169
168
|
|
@@ -183,19 +182,19 @@ static void fio_cli_set_arg(cstr_s arg, char const *value, char const *line,
|
|
183
182
|
}
|
184
183
|
}
|
185
184
|
|
185
|
+
finish:
|
186
|
+
|
186
187
|
/* handle additional argv progress (if value is on separate argv) */
|
187
|
-
if (
|
188
|
-
|
189
|
-
/* advance the position marker more than once? */
|
188
|
+
if (value && parser->pos < parser->argc &&
|
189
|
+
value == parser->argv[parser->pos + 1])
|
190
190
|
++parser->pos;
|
191
|
-
}
|
192
191
|
return;
|
193
192
|
|
194
193
|
error: /* handle errors*/
|
195
194
|
/* TODO! */
|
196
195
|
fprintf(stderr, "\n\r\x1B[31mError:\x1B[0m unknown argument %.*s %s %s\n\n",
|
197
196
|
(int)arg.len, arg.data, arg.len ? "with value" : "",
|
198
|
-
value ? value : "(null)");
|
197
|
+
value ? (value[0] ? value : "(empty)") : "(null)");
|
199
198
|
print_help:
|
200
199
|
fprintf(stderr, "\n%s\n\n",
|
201
200
|
parser->description ? parser->description
|
@@ -307,6 +306,8 @@ void fio_cli_start AVOID_MACRO(int argc, char const *argv[], int unnamed_min,
|
|
307
306
|
.unnamed_min = unnamed_min,
|
308
307
|
.unnamed_max = unnamed_max,
|
309
308
|
.description = description,
|
309
|
+
.argc = argc,
|
310
|
+
.argv = argv,
|
310
311
|
.names = names,
|
311
312
|
.pos = 0,
|
312
313
|
};
|
data/ext/iodine/fiobj.h
CHANGED
File without changes
|
data/ext/iodine/fiobj_mustache.c
CHANGED
@@ -6,6 +6,14 @@
|
|
6
6
|
#include <fiobj_mustache.h>
|
7
7
|
#include <fiobj_str.h>
|
8
8
|
|
9
|
+
#ifndef FIO_IGNORE_MACRO
|
10
|
+
/**
|
11
|
+
* This is used internally to ignore macros that shadow functions (avoiding
|
12
|
+
* named arguments when required).
|
13
|
+
*/
|
14
|
+
#define FIO_IGNORE_MACRO
|
15
|
+
#endif
|
16
|
+
|
9
17
|
/**
|
10
18
|
* Loads a mustache template, converting it into an opaque instruction array.
|
11
19
|
*
|
@@ -20,6 +28,20 @@ mustache_s *fiobj_mustache_load(fio_str_info_s filename) {
|
|
20
28
|
return mustache_load(.filename = filename.data, .filename_len = filename.len);
|
21
29
|
}
|
22
30
|
|
31
|
+
/**
|
32
|
+
* Loads a mustache template, converting it into an opaque instruction array.
|
33
|
+
*
|
34
|
+
* Returns a pointer to the instruction array.
|
35
|
+
*
|
36
|
+
* The `folder` argument should contain the template's root folder which would
|
37
|
+
* also be used to search for any required partial templates.
|
38
|
+
*
|
39
|
+
* The `filename` argument should contain the template's file name.
|
40
|
+
*/
|
41
|
+
mustache_s *fiobj_mustache_new FIO_IGNORE_MACRO(mustache_load_args_s args) {
|
42
|
+
return mustache_load FIO_IGNORE_MACRO(args);
|
43
|
+
}
|
44
|
+
|
23
45
|
/** Free the mustache template */
|
24
46
|
void fiobj_mustache_free(mustache_s *mustache) { mustache_free(mustache); }
|
25
47
|
|
@@ -52,8 +74,10 @@ Mustache Callbacks
|
|
52
74
|
***************************************************************************** */
|
53
75
|
|
54
76
|
/** HTML ecape table, created using the following Ruby Script:
|
55
|
-
|
56
|
-
|
77
|
+
|
78
|
+
a = (0..255).to_a.map {|i| i.chr }
|
79
|
+
# 100.times {|i| a[i] = "&\#x#{ i < 16 ? "0#{i.to_s(16)}" : i.to_s(16)};"}
|
80
|
+
100.times {|i| a[i] = "&\##{i.to_s(10)};"}
|
57
81
|
('a'.ord..'z'.ord).each {|i| a[i] = i.chr }
|
58
82
|
('A'.ord..'Z'.ord).each {|i| a[i] = i.chr }
|
59
83
|
('0'.ord..'9'.ord).each {|i| a[i] = i.chr }
|
@@ -61,61 +85,58 @@ a['<'.ord] = "<"
|
|
61
85
|
a['>'.ord] = ">"
|
62
86
|
a['&'.ord] = "&"
|
63
87
|
a['"'.ord] = """
|
88
|
+
a["\'".ord] = "'"
|
89
|
+
a['|'.ord] = "&\##{'|'.ord.to_s(10)};"
|
64
90
|
|
65
91
|
b = a.map {|s| s.length }
|
66
92
|
puts "static char *html_escape_strs[] = {", a.to_s.slice(1..-2) ,"};",
|
67
93
|
"static uint8_t html_escape_len[] = {", b.to_s.slice(1..-2),"};"
|
68
94
|
*/
|
69
|
-
static
|
70
|
-
"&#
|
71
|
-
"&#
|
72
|
-
"&#
|
73
|
-
"&#
|
74
|
-
"&#
|
75
|
-
"&#
|
76
|
-
"
|
77
|
-
"
|
78
|
-
"
|
79
|
-
"
|
80
|
-
"
|
81
|
-
"
|
82
|
-
"
|
83
|
-
"
|
84
|
-
"
|
85
|
-
"
|
86
|
-
"
|
87
|
-
"
|
88
|
-
"
|
89
|
-
"
|
90
|
-
"
|
91
|
-
"
|
92
|
-
"
|
93
|
-
"
|
94
|
-
"
|
95
|
-
"
|
96
|
-
"
|
97
|
-
"
|
98
|
-
"
|
99
|
-
"
|
100
|
-
"
|
101
|
-
"
|
102
|
-
"à", "á", "â", "ã", "ä", "å", "æ",
|
103
|
-
"ç", "è", "é", "ê", "ë", "ì", "í",
|
104
|
-
"î", "ï", "ð", "ñ", "ò", "ó", "ô",
|
105
|
-
"õ", "ö", "÷", "ø", "ù", "ú", "û",
|
106
|
-
"ü", "ý", "þ", "ÿ"};
|
95
|
+
static char *html_escape_strs[] = {
|
96
|
+
"�", "", "", "", "", "", "", "",
|
97
|
+
"", "	", " ", "", "", " ", "", "",
|
98
|
+
"", "", "", "", "", "", "", "",
|
99
|
+
"", "", "", "", "", "", "", "",
|
100
|
+
" ", "!", """, "#", "$", "%", "&", "'",
|
101
|
+
"(", ")", "*", "+", ",", "-", ".", "/",
|
102
|
+
"0", "1", "2", "3", "4", "5", "6", "7",
|
103
|
+
"8", "9", ":", ";", "<", "=", ">", "?",
|
104
|
+
"@", "A", "B", "C", "D", "E", "F", "G",
|
105
|
+
"H", "I", "J", "K", "L", "M", "N", "O",
|
106
|
+
"P", "Q", "R", "S", "T", "U", "V", "W",
|
107
|
+
"X", "Y", "Z", "[", "\", "]", "^", "_",
|
108
|
+
"`", "a", "b", "c", "d", "e", "f", "g",
|
109
|
+
"h", "i", "j", "k", "l", "m", "n", "o",
|
110
|
+
"p", "q", "r", "s", "t", "u", "v", "w",
|
111
|
+
"x", "y", "z", "{", "|", "}", "~", "\x7F",
|
112
|
+
"\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87",
|
113
|
+
"\x88", "\x89", "\x8A", "\x8B", "\x8C", "\x8D", "\x8E", "\x8F",
|
114
|
+
"\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97",
|
115
|
+
"\x98", "\x99", "\x9A", "\x9B", "\x9C", "\x9D", "\x9E", "\x9F",
|
116
|
+
"\xA0", "\xA1", "\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7",
|
117
|
+
"\xA8", "\xA9", "\xAA", "\xAB", "\xAC", "\xAD", "\xAE", "\xAF",
|
118
|
+
"\xB0", "\xB1", "\xB2", "\xB3", "\xB4", "\xB5", "\xB6", "\xB7",
|
119
|
+
"\xB8", "\xB9", "\xBA", "\xBB", "\xBC", "\xBD", "\xBE", "\xBF",
|
120
|
+
"\xC0", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7",
|
121
|
+
"\xC8", "\xC9", "\xCA", "\xCB", "\xCC", "\xCD", "\xCE", "\xCF",
|
122
|
+
"\xD0", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7",
|
123
|
+
"\xD8", "\xD9", "\xDA", "\xDB", "\xDC", "\xDD", "\xDE", "\xDF",
|
124
|
+
"\xE0", "\xE1", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7",
|
125
|
+
"\xE8", "\xE9", "\xEA", "\xEB", "\xEC", "\xED", "\xEE", "\xEF",
|
126
|
+
"\xF0", "\xF1", "\xF2", "\xF3", "\xF4", "\xF5", "\xF6", "\xF7",
|
127
|
+
"\xF8", "\xF9", "\xFA", "\xFB", "\xFC", "\xFD", "\xFE", "\xFF"};
|
107
128
|
static uint8_t html_escape_len[] = {
|
108
|
-
|
109
|
-
|
110
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
111
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
112
|
-
|
113
|
-
1, 1, 1,
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
129
|
+
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
130
|
+
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5,
|
131
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 4, 5, 4, 5, 5, 1, 1, 1, 1, 1, 1, 1,
|
132
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5,
|
133
|
+
5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
134
|
+
1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
135
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
136
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
137
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
138
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
139
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
119
140
|
|
120
141
|
static inline FIOBJ fiobj_mustache_find_obj(mustache_section_s *section,
|
121
142
|
const char *name,
|
@@ -127,7 +148,7 @@ static inline FIOBJ fiobj_mustache_find_obj(mustache_section_s *section,
|
|
127
148
|
if (!FIOBJ_TYPE_IS((FIOBJ)section->udata2, FIOBJ_T_HASH))
|
128
149
|
continue;
|
129
150
|
o = fiobj_hash_get((FIOBJ)section->udata2, key);
|
130
|
-
section = section
|
151
|
+
section = mustache_section_parent(section);
|
131
152
|
} while (o == FIOBJ_INVALID && section);
|
132
153
|
return o;
|
133
154
|
}
|
@@ -201,13 +222,15 @@ static int mustache_on_text(mustache_section_s *section, const char *data,
|
|
201
222
|
* Please note, this will handle both normal and inverted sections.
|
202
223
|
*/
|
203
224
|
static int32_t mustache_on_section_test(mustache_section_s *section,
|
204
|
-
const char *name, uint32_t name_len
|
225
|
+
const char *name, uint32_t name_len,
|
226
|
+
uint8_t callable) {
|
205
227
|
FIOBJ o = fiobj_mustache_find_obj(section, name, name_len);
|
206
|
-
if (!o)
|
228
|
+
if (!o || FIOBJ_TYPE_IS(o, FIOBJ_T_FALSE))
|
207
229
|
return 0;
|
208
230
|
if (FIOBJ_TYPE_IS(o, FIOBJ_T_ARRAY))
|
209
231
|
return fiobj_ary_count(o);
|
210
232
|
return 1;
|
233
|
+
(void)callable;
|
211
234
|
}
|
212
235
|
|
213
236
|
/**
|