isomorfeus-iodine 0.7.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +32 -0
  6. data/.yardopts +8 -0
  7. data/CHANGELOG.md +1038 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/LIMITS.md +41 -0
  11. data/README.md +782 -0
  12. data/Rakefile +44 -0
  13. data/SPEC-PubSub-Draft.md +159 -0
  14. data/SPEC-WebSocket-Draft.md +239 -0
  15. data/bin/console +22 -0
  16. data/bin/info.md +353 -0
  17. data/bin/mustache_bench.rb +100 -0
  18. data/bin/poc/Gemfile.lock +23 -0
  19. data/bin/poc/README.md +37 -0
  20. data/bin/poc/config.ru +66 -0
  21. data/bin/poc/gemfile +1 -0
  22. data/bin/poc/www/index.html +57 -0
  23. data/examples/async_task.ru +92 -0
  24. data/examples/config.ru +56 -0
  25. data/examples/echo.ru +59 -0
  26. data/examples/hello.ru +29 -0
  27. data/examples/pubsub_engine.ru +81 -0
  28. data/examples/redis.ru +70 -0
  29. data/examples/shootout.ru +73 -0
  30. data/examples/sub-protocols.ru +90 -0
  31. data/examples/tcp_client.rb +66 -0
  32. data/examples/x-sendfile.ru +14 -0
  33. data/exe/iodine +277 -0
  34. data/ext/iodine/extconf.rb +109 -0
  35. data/ext/iodine/fio.c +11985 -0
  36. data/ext/iodine/fio.h +6373 -0
  37. data/ext/iodine/fio_cli.c +431 -0
  38. data/ext/iodine/fio_cli.h +189 -0
  39. data/ext/iodine/fio_json_parser.h +687 -0
  40. data/ext/iodine/fio_siphash.c +157 -0
  41. data/ext/iodine/fio_siphash.h +37 -0
  42. data/ext/iodine/fio_tls.h +129 -0
  43. data/ext/iodine/fio_tls_missing.c +649 -0
  44. data/ext/iodine/fio_tls_openssl.c +1056 -0
  45. data/ext/iodine/fio_tmpfile.h +50 -0
  46. data/ext/iodine/fiobj.h +44 -0
  47. data/ext/iodine/fiobj4fio.h +21 -0
  48. data/ext/iodine/fiobj_ary.c +333 -0
  49. data/ext/iodine/fiobj_ary.h +139 -0
  50. data/ext/iodine/fiobj_data.c +1185 -0
  51. data/ext/iodine/fiobj_data.h +167 -0
  52. data/ext/iodine/fiobj_hash.c +409 -0
  53. data/ext/iodine/fiobj_hash.h +176 -0
  54. data/ext/iodine/fiobj_json.c +622 -0
  55. data/ext/iodine/fiobj_json.h +68 -0
  56. data/ext/iodine/fiobj_mem.h +71 -0
  57. data/ext/iodine/fiobj_mustache.c +317 -0
  58. data/ext/iodine/fiobj_mustache.h +62 -0
  59. data/ext/iodine/fiobj_numbers.c +344 -0
  60. data/ext/iodine/fiobj_numbers.h +127 -0
  61. data/ext/iodine/fiobj_str.c +433 -0
  62. data/ext/iodine/fiobj_str.h +172 -0
  63. data/ext/iodine/fiobject.c +620 -0
  64. data/ext/iodine/fiobject.h +654 -0
  65. data/ext/iodine/hpack.h +1923 -0
  66. data/ext/iodine/http.c +2754 -0
  67. data/ext/iodine/http.h +1002 -0
  68. data/ext/iodine/http1.c +912 -0
  69. data/ext/iodine/http1.h +29 -0
  70. data/ext/iodine/http1_parser.h +873 -0
  71. data/ext/iodine/http_internal.c +1278 -0
  72. data/ext/iodine/http_internal.h +237 -0
  73. data/ext/iodine/http_mime_parser.h +350 -0
  74. data/ext/iodine/iodine.c +1430 -0
  75. data/ext/iodine/iodine.h +63 -0
  76. data/ext/iodine/iodine_caller.c +218 -0
  77. data/ext/iodine/iodine_caller.h +27 -0
  78. data/ext/iodine/iodine_connection.c +933 -0
  79. data/ext/iodine/iodine_connection.h +55 -0
  80. data/ext/iodine/iodine_defer.c +420 -0
  81. data/ext/iodine/iodine_defer.h +6 -0
  82. data/ext/iodine/iodine_fiobj2rb.h +120 -0
  83. data/ext/iodine/iodine_helpers.c +282 -0
  84. data/ext/iodine/iodine_helpers.h +12 -0
  85. data/ext/iodine/iodine_http.c +1171 -0
  86. data/ext/iodine/iodine_http.h +23 -0
  87. data/ext/iodine/iodine_json.c +302 -0
  88. data/ext/iodine/iodine_json.h +6 -0
  89. data/ext/iodine/iodine_mustache.c +567 -0
  90. data/ext/iodine/iodine_mustache.h +6 -0
  91. data/ext/iodine/iodine_pubsub.c +580 -0
  92. data/ext/iodine/iodine_pubsub.h +26 -0
  93. data/ext/iodine/iodine_rack_io.c +281 -0
  94. data/ext/iodine/iodine_rack_io.h +20 -0
  95. data/ext/iodine/iodine_store.c +142 -0
  96. data/ext/iodine/iodine_store.h +20 -0
  97. data/ext/iodine/iodine_tcp.c +346 -0
  98. data/ext/iodine/iodine_tcp.h +13 -0
  99. data/ext/iodine/iodine_tls.c +261 -0
  100. data/ext/iodine/iodine_tls.h +13 -0
  101. data/ext/iodine/mustache_parser.h +1546 -0
  102. data/ext/iodine/redis_engine.c +957 -0
  103. data/ext/iodine/redis_engine.h +79 -0
  104. data/ext/iodine/resp_parser.h +317 -0
  105. data/ext/iodine/websocket_parser.h +505 -0
  106. data/ext/iodine/websockets.c +735 -0
  107. data/ext/iodine/websockets.h +185 -0
  108. data/isomorfeus-iodine.gemspec +42 -0
  109. data/lib/iodine/connection.rb +61 -0
  110. data/lib/iodine/json.rb +42 -0
  111. data/lib/iodine/mustache.rb +113 -0
  112. data/lib/iodine/pubsub.rb +55 -0
  113. data/lib/iodine/rack_utils.rb +43 -0
  114. data/lib/iodine/tls.rb +16 -0
  115. data/lib/iodine/version.rb +3 -0
  116. data/lib/iodine.rb +274 -0
  117. data/lib/rack/handler/iodine.rb +33 -0
  118. data/logo.png +0 -0
  119. metadata +271 -0
@@ -0,0 +1,71 @@
1
+ /*
2
+ Copyright: Boaz Segev, 2018
3
+ License: MIT
4
+
5
+ Feel free to copy, use and enjoy according to the license provided.
6
+ */
7
+ #ifndef H_FIOBJ_MEM_H
8
+
9
+ /**
10
+ * This is a placeholder for facil.io memory allocator functions in fio.h.
11
+ *
12
+ * In cases where the FIOBJ library is extracted from facil.io, these functions
13
+ * will call the system's memory allocator (`malloc`, `free`, etc').
14
+ */
15
+ #define H_FIOBJ_MEM_H
16
+
17
+ #include <stdlib.h>
18
+
19
+ /**
20
+ * Allocates memory using a per-CPU core block memory pool.
21
+ * Memory is zeroed out.
22
+ *
23
+ * Allocations above FIO_MEMORY_BLOCK_ALLOC_LIMIT (12,288 bytes when using 32Kb
24
+ * blocks) will be redirected to `mmap`, as if `fio_mmap` was called.
25
+ */
26
+ void *fio_malloc(size_t size);
27
+
28
+ /**
29
+ * same as calling `fio_malloc(size_per_unit * unit_count)`;
30
+ *
31
+ * Allocations above FIO_MEMORY_BLOCK_ALLOC_LIMIT (12,288 bytes when using 32Kb
32
+ * blocks) will be redirected to `mmap`, as if `fio_mmap` was called.
33
+ */
34
+ void *fio_calloc(size_t size_per_unit, size_t unit_count);
35
+
36
+ /** Frees memory that was allocated using this library. */
37
+ void fio_free(void *ptr);
38
+
39
+ /**
40
+ * Re-allocates memory. An attept to avoid copying the data is made only for big
41
+ * memory allocations (larger than FIO_MEMORY_BLOCK_ALLOC_LIMIT).
42
+ */
43
+ void *fio_realloc(void *ptr, size_t new_size);
44
+
45
+ /**
46
+ * Re-allocates memory. An attept to avoid copying the data is made only for big
47
+ * memory allocations (larger than FIO_MEMORY_BLOCK_ALLOC_LIMIT).
48
+ *
49
+ * This variation is slightly faster as it might copy less data.
50
+ */
51
+ void *fio_realloc2(void *ptr, size_t new_size, size_t copy_length);
52
+
53
+ /**
54
+ * Allocates memory directly using `mmap`, this is prefered for objects that
55
+ * both require almost a page of memory (or more) and expect a long lifetime.
56
+ *
57
+ * However, since this allocation will invoke the system call (`mmap`), it will
58
+ * be inherently slower.
59
+ *
60
+ * `fio_free` can be used for deallocating the memory.
61
+ */
62
+ void *fio_mmap(size_t size);
63
+
64
+ #if FIO_OVERRIDE_MALLOC
65
+ #define malloc fio_malloc
66
+ #define free fio_free
67
+ #define realloc fio_realloc
68
+ #define calloc fio_calloc
69
+ #endif
70
+
71
+ #endif /* H_FIOBJ_MEM_H */
@@ -0,0 +1,317 @@
1
+ /*
2
+ Copyright: Boaz Segev, 2018-2019
3
+ License: MIT
4
+ */
5
+ #define INCLUDE_MUSTACHE_IMPLEMENTATION 1
6
+ #include <mustache_parser.h>
7
+
8
+ #include <fiobj_ary.h>
9
+ #include <fiobj_hash.h>
10
+ #include <fiobj_mustache.h>
11
+ #include <fiobj_str.h>
12
+
13
+ #ifndef FIO_IGNORE_MACRO
14
+ /**
15
+ * This is used internally to ignore macros that shadow functions (avoiding
16
+ * named arguments when required).
17
+ */
18
+ #define FIO_IGNORE_MACRO
19
+ #endif
20
+
21
+ /**
22
+ * Loads a mustache template, converting it into an opaque instruction array.
23
+ *
24
+ * Returns a pointer to the instruction array.
25
+ *
26
+ * The `folder` argument should contain the template's root folder which would
27
+ * also be used to search for any required partial templates.
28
+ *
29
+ * The `filename` argument should contain the template's file name.
30
+ */
31
+ mustache_s *fiobj_mustache_load(fio_str_info_s filename) {
32
+ return mustache_load(.filename = filename.data, .filename_len = filename.len);
33
+ }
34
+
35
+ /**
36
+ * Loads a mustache template, converting it into an opaque instruction array.
37
+ *
38
+ * Returns a pointer to the instruction array.
39
+ *
40
+ * The `folder` argument should contain the template's root folder which would
41
+ * also be used to search for any required partial templates.
42
+ *
43
+ * The `filename` argument should contain the template's file name.
44
+ */
45
+ mustache_s *fiobj_mustache_new FIO_IGNORE_MACRO(mustache_load_args_s args) {
46
+ return mustache_load FIO_IGNORE_MACRO(args);
47
+ }
48
+
49
+ /** Free the mustache template */
50
+ void fiobj_mustache_free(mustache_s *mustache) { mustache_free(mustache); }
51
+
52
+ /**
53
+ * Renders a template into an existing FIOBJ String (`dest`'s end), using the
54
+ * information in the `data` object.
55
+ *
56
+ * Returns FIOBJ_INVALID if an error occured and a FIOBJ String on success.
57
+ */
58
+ FIOBJ fiobj_mustache_build2(FIOBJ dest, mustache_s *mustache, FIOBJ data) {
59
+ mustache_build(mustache, .udata1 = (void *)dest, .udata2 = (void *)data);
60
+ return dest;
61
+ }
62
+
63
+ /**
64
+ * Creates a FIOBJ String containing the rendered template using the information
65
+ * in the `data` object.
66
+ *
67
+ * Returns FIOBJ_INVALID if an error occured and a FIOBJ String on success.
68
+ */
69
+ FIOBJ fiobj_mustache_build(mustache_s *mustache, FIOBJ data) {
70
+ if (!mustache)
71
+ return FIOBJ_INVALID;
72
+ return fiobj_mustache_build2(fiobj_str_buf(mustache->u.read_only.data_length),
73
+ mustache, data);
74
+ }
75
+
76
+ /* *****************************************************************************
77
+ Mustache Callbacks
78
+ ***************************************************************************** */
79
+
80
+ static inline FIOBJ fiobj_mustache_find_obj_absolute(FIOBJ parent, FIOBJ key) {
81
+ if (!FIOBJ_TYPE_IS(parent, FIOBJ_T_HASH))
82
+ return FIOBJ_INVALID;
83
+ FIOBJ o = FIOBJ_INVALID;
84
+ o = fiobj_hash_get(parent, key);
85
+ return o;
86
+ }
87
+
88
+ static inline FIOBJ fiobj_mustache_find_obj_tree(mustache_section_s *section,
89
+ const char *name,
90
+ uint32_t name_len) {
91
+ FIOBJ key = fiobj_str_tmp();
92
+ fiobj_str_write(key, name, name_len);
93
+ do {
94
+ FIOBJ tmp = fiobj_mustache_find_obj_absolute((FIOBJ)section->udata2, key);
95
+ if (tmp != FIOBJ_INVALID) {
96
+ return tmp;
97
+ }
98
+ } while ((section = mustache_section_parent(section)));
99
+ return FIOBJ_INVALID;
100
+ }
101
+
102
+ static inline FIOBJ fiobj_mustache_find_obj(mustache_section_s *section,
103
+ const char *name,
104
+ uint32_t name_len) {
105
+ FIOBJ tmp = fiobj_mustache_find_obj_tree(section, name, name_len);
106
+ if (tmp != FIOBJ_INVALID)
107
+ return tmp;
108
+ /* interpolate sections... */
109
+ uint32_t dot = 0;
110
+ while (dot < name_len && name[dot] != '.')
111
+ ++dot;
112
+ if (dot == name_len)
113
+ return FIOBJ_INVALID;
114
+ tmp = fiobj_mustache_find_obj_tree(section, name, dot);
115
+ if (!tmp) {
116
+ return FIOBJ_INVALID;
117
+ }
118
+ ++dot;
119
+ for (;;) {
120
+ FIOBJ key = fiobj_str_tmp();
121
+ fiobj_str_write(key, name + dot, name_len - dot);
122
+ FIOBJ obj = fiobj_mustache_find_obj_absolute(tmp, key);
123
+ if (obj != FIOBJ_INVALID)
124
+ return obj;
125
+ name += dot;
126
+ name_len -= dot;
127
+ dot = 0;
128
+ while (dot < name_len && name[dot] != '.')
129
+ ++dot;
130
+ if (dot == name_len) {
131
+ return FIOBJ_INVALID;
132
+ }
133
+ key = fiobj_str_tmp();
134
+ fiobj_str_write(key, name, dot);
135
+ tmp = fiobj_mustache_find_obj_absolute(tmp, key);
136
+ if (tmp == FIOBJ_INVALID)
137
+ return FIOBJ_INVALID;
138
+ ++dot;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Called when an argument name was detected in the current section.
144
+ *
145
+ * A conforming implementation will search for the named argument both in the
146
+ * existing section and all of it's parents (walking backwards towards the root)
147
+ * until a value is detected.
148
+ *
149
+ * A missing value should be treated the same as an empty string.
150
+ *
151
+ * A conforming implementation will output the named argument's value (either
152
+ * HTML escaped or not, depending on the `escape` flag) as a string.
153
+ */
154
+ static int mustache_on_arg(mustache_section_s *section, const char *name,
155
+ uint32_t name_len, unsigned char escape) {
156
+ FIOBJ o = fiobj_mustache_find_obj(section, name, name_len);
157
+ if (!o)
158
+ return 0;
159
+ fio_str_info_s i = fiobj_obj2cstr(o);
160
+ if (!i.len)
161
+ return 0;
162
+ return mustache_write_text(section, i.data, i.len, escape);
163
+ }
164
+
165
+ /**
166
+ * Called when simple template text (string) is detected.
167
+ *
168
+ * A conforming implementation will output data as a string (no escaping).
169
+ */
170
+ static int mustache_on_text(mustache_section_s *section, const char *data,
171
+ uint32_t data_len) {
172
+ FIOBJ dest = (FIOBJ)section->udata1;
173
+ fiobj_str_write(dest, data, data_len);
174
+ return 0;
175
+ }
176
+
177
+ /**
178
+ * Called for nested sections, must return the number of objects in the new
179
+ * subsection (depending on the argument's name).
180
+ *
181
+ * Arrays should return the number of objects in the array.
182
+ *
183
+ * `true` values should return 1.
184
+ *
185
+ * `false` values should return 0.
186
+ *
187
+ * A return value of -1 will stop processing with an error.
188
+ *
189
+ * Please note, this will handle both normal and inverted sections.
190
+ */
191
+ static int32_t mustache_on_section_test(mustache_section_s *section,
192
+ const char *name, uint32_t name_len,
193
+ uint8_t callable) {
194
+ FIOBJ o = fiobj_mustache_find_obj(section, name, name_len);
195
+ if (!o || FIOBJ_TYPE_IS(o, FIOBJ_T_FALSE))
196
+ return 0;
197
+ if (FIOBJ_TYPE_IS(o, FIOBJ_T_ARRAY))
198
+ return fiobj_ary_count(o);
199
+ return 1;
200
+ (void)callable; /* FIOBJ doesn't support lambdas */
201
+ }
202
+
203
+ /**
204
+ * Called when entering a nested section.
205
+ *
206
+ * `index` is a zero based index indicating the number of repetitions that
207
+ * occurred so far (same as the array index for arrays).
208
+ *
209
+ * A return value of -1 will stop processing with an error.
210
+ *
211
+ * Note: this is a good time to update the subsection's `udata` with the value
212
+ * of the array index. The `udata` will always contain the value or the parent's
213
+ * `udata`.
214
+ */
215
+ static int mustache_on_section_start(mustache_section_s *section,
216
+ char const *name, uint32_t name_len,
217
+ uint32_t index) {
218
+ FIOBJ o = fiobj_mustache_find_obj(section, name, name_len);
219
+ if (!o)
220
+ return -1;
221
+ if (FIOBJ_TYPE_IS(o, FIOBJ_T_ARRAY))
222
+ section->udata2 = (void *)fiobj_ary_index(o, index);
223
+ else
224
+ section->udata2 = (void *)o;
225
+ return 0;
226
+ }
227
+
228
+ /**
229
+ * Called for cleanup in case of error.
230
+ */
231
+ static void mustache_on_formatting_error(void *udata1, void *udata2) {
232
+ (void)udata1;
233
+ (void)udata2;
234
+ }
235
+
236
+ /* *****************************************************************************
237
+ Testing
238
+ ***************************************************************************** */
239
+
240
+ #if DEBUG
241
+ static inline void mustache_save2file(char const *filename, char const *data,
242
+ size_t length) {
243
+ #ifdef __MINGW32__
244
+ int fd = _open(filename, _O_CREAT | _O_RDWR);
245
+ #else
246
+ int fd = open(filename, O_CREAT | O_RDWR, 0);
247
+ #endif
248
+ if (fd == -1) {
249
+ perror("Couldn't open / create file for template testing");
250
+ exit(-1);
251
+ }
252
+ #ifdef __MINGW32__
253
+ _chmod(filename, _S_IREAD | _S_IWRITE);
254
+ #else
255
+ fchmod(fd, 0777);
256
+ #endif
257
+ if (pwrite(fd, data, length, 0) != (ssize_t)length) {
258
+ perror("Mustache template write error");
259
+ exit(-1);
260
+ }
261
+ close(fd);
262
+ }
263
+
264
+ void fiobj_mustache_test(void) {
265
+ #define TEST_ASSERT(cond, ...) \
266
+ if (!(cond)) { \
267
+ fprintf(stderr, "* " __VA_ARGS__); \
268
+ fprintf(stderr, "\n !!! Testing failed !!!\n"); \
269
+ exit(-1); \
270
+ }
271
+
272
+ char const *template =
273
+ "{{=<< >>=}}* Users:\r\n<<#users>><<id>>. <<& name>> "
274
+ "(<<name>>)\r\n<</users>>\r\nNested: <<& nested.item >>.";
275
+ char const *template_name = "mustache_test_template.mustache";
276
+ fprintf(stderr, "mustache test saving template %s\n", template_name);
277
+ mustache_save2file(template_name, template, strlen(template));
278
+ mustache_s *m =
279
+ fiobj_mustache_load((fio_str_info_s){.data = (char *)template_name});
280
+ unlink(template_name);
281
+ TEST_ASSERT(m, "fiobj_mustache_load failed.\n");
282
+ FIOBJ data = fiobj_hash_new();
283
+ FIOBJ key = fiobj_str_new("users", 5);
284
+ FIOBJ ary = fiobj_ary_new2(4);
285
+ fiobj_hash_set(data, key, ary);
286
+ fiobj_free(key);
287
+ for (int i = 0; i < 4; ++i) {
288
+ FIOBJ id = fiobj_str_buf(4);
289
+ fiobj_str_write_i(id, i);
290
+ FIOBJ name = fiobj_str_buf(4);
291
+ fiobj_str_write(name, "User ", 5);
292
+ fiobj_str_write_i(name, i);
293
+ FIOBJ usr = fiobj_hash_new2(2);
294
+ key = fiobj_str_new("id", 2);
295
+ fiobj_hash_set(usr, key, id);
296
+ fiobj_free(key);
297
+ key = fiobj_str_new("name", 4);
298
+ fiobj_hash_set(usr, key, name);
299
+ fiobj_free(key);
300
+ fiobj_ary_push(ary, usr);
301
+ }
302
+ key = fiobj_str_new("nested", 6);
303
+ ary = fiobj_hash_new2(2);
304
+ fiobj_hash_set(data, key, ary);
305
+ fiobj_free(key);
306
+ key = fiobj_str_new("item", 4);
307
+ fiobj_hash_set(ary, key, fiobj_str_new("dot notation success", 20));
308
+ fiobj_free(key);
309
+ key = fiobj_mustache_build(m, data);
310
+ fiobj_free(data);
311
+ TEST_ASSERT(key, "fiobj_mustache_build failed!\n");
312
+ fprintf(stderr, "%s\n", fiobj_obj2cstr(key).data);
313
+ fiobj_free(key);
314
+ fiobj_mustache_free(m);
315
+ }
316
+
317
+ #endif
@@ -0,0 +1,62 @@
1
+ /*
2
+ Copyright: Boaz Segev, 2018-2019
3
+ License: MIT
4
+ */
5
+ #ifndef H_FIOBJ_MUSTACHE_H
6
+ #define H_FIOBJ_MUSTACHE_H
7
+
8
+ #include <fiobject.h>
9
+
10
+ #include <mustache_parser.h>
11
+
12
+ /**
13
+ * Loads a mustache template, converting it into an opaque instruction array.
14
+ *
15
+ * Returns a pointer to the instruction array or NULL (on error).
16
+ *
17
+ * The `filename` argument should contain the template's file name.
18
+ */
19
+ mustache_s *fiobj_mustache_load(fio_str_info_s filename);
20
+
21
+ /**
22
+ * Loads a mustache template, either from memory of a file, converting it into
23
+ * an opaque instruction array.
24
+ *
25
+ * Returns a pointer to the instruction array or NULL (on error).
26
+ *
27
+ * Accepts any of the following named arguments:
28
+ * * `char const *filename` - The root template's file name.
29
+ * * `size_t filename_len` - The file name's length.
30
+ * * `char const *data` - If set, will be used as the file's contents.
31
+ * * `size_t data_len` - If set, `data` will be used as the file's contents.
32
+ * * `mustache_error_en *err` - A container for any template load errors (see
33
+ * mustache_parser.h).
34
+ */
35
+ mustache_s *fiobj_mustache_new(mustache_load_args_s args);
36
+ #define fiobj_mustache_new(...) \
37
+ fiobj_mustache_new((mustache_load_args_s){__VA_ARGS__})
38
+
39
+ /** Free the mustache template */
40
+ void fiobj_mustache_free(mustache_s *mustache);
41
+
42
+ /**
43
+ * Creates a FIOBJ String containing the rendered template using the information
44
+ * in the `data` object.
45
+ *
46
+ * Returns FIOBJ_INVALID if an error occurred and a FIOBJ String on success.
47
+ */
48
+ FIOBJ fiobj_mustache_build(mustache_s *mustache, FIOBJ data);
49
+
50
+ /**
51
+ * Renders a template into an existing FIOBJ String (`dest`'s end), using the
52
+ * information in the `data` object.
53
+ *
54
+ * Returns FIOBJ_INVALID if an error occurred and a FIOBJ String on success.
55
+ */
56
+ FIOBJ fiobj_mustache_build2(FIOBJ dest, mustache_s *mustache, FIOBJ data);
57
+
58
+ #if DEBUG
59
+ void fiobj_mustache_test(void);
60
+ #endif
61
+
62
+ #endif /* H_FIOBJ_MUSTACHE_H */