iodine 0.7.59 → 0.8.0
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.
- checksums.yaml +4 -4
- data/.clang-format +15 -0
- data/.rspec +1 -0
- data/.yardopts +1 -3
- data/CHANGELOG.md +132 -12
- data/Gemfile +5 -7
- data/LICENSE.txt +1 -1
- data/README.md +147 -671
- data/Rakefile +9 -16
- data/examples/chatroom.nru +9 -0
- data/examples/client +74 -0
- data/examples/config-hello.nru +9 -0
- data/examples/config-hello.ru +11 -0
- data/examples/config-hijack.ru +13 -0
- data/examples/config-shootout.ru +43 -0
- data/examples/config.nru +120 -0
- data/examples/config.rb +37 -0
- data/examples/config.ru +42 -53
- data/examples/fake +24 -0
- data/examples/hello_neorack +137 -0
- data/examples/routes.nru +29 -0
- data/examples/routes.ru +42 -0
- data/exe/iodine +218 -258
- data/ext/iodine/extconf.rb +27 -100
- data/ext/iodine/fio-stl.h +128336 -0
- data/ext/iodine/fio-stl.md +26396 -0
- data/ext/iodine/iodine.c +213 -1393
- data/ext/iodine/iodine.h +250 -55
- data/ext/iodine/iodine_arg_helper.h +329 -0
- data/ext/iodine/iodine_caller.h +234 -25
- data/ext/iodine/iodine_cli.h +434 -0
- data/ext/iodine/iodine_compression.h +312 -0
- data/ext/iodine/iodine_connection.h +3484 -34
- data/ext/iodine/iodine_core.h +363 -0
- data/ext/iodine/iodine_crypto.h +1441 -0
- data/ext/iodine/iodine_defer.h +225 -4
- data/ext/iodine/iodine_json.h +738 -4
- data/ext/iodine/iodine_listener.h +263 -0
- data/ext/iodine/iodine_log.h +297 -0
- data/ext/iodine/iodine_minimap.h +543 -0
- data/ext/iodine/iodine_mustache.h +461 -4
- data/ext/iodine/iodine_pubsub_eng.h +729 -0
- data/ext/iodine/iodine_pubsub_history.h +547 -0
- data/ext/iodine/iodine_pubsub_msg.h +228 -0
- data/ext/iodine/iodine_redis.h +322 -0
- data/ext/iodine/iodine_store.h +418 -16
- data/ext/iodine/iodine_threads.h +279 -0
- data/ext/iodine/iodine_tls.h +515 -6
- data/ext/iodine/iodine_utils.h +923 -0
- data/iodine.gemspec +37 -42
- data/lib/iodine/benchmark.rb +1690 -0
- data/lib/iodine/documentation.rb +3085 -0
- data/lib/iodine/version.rb +17 -1
- data/lib/iodine.rb +54 -255
- data/logo.svg +36 -0
- data/mustache.md +55 -0
- data/sig/iodine.rbs +4 -0
- metadata +58 -184
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
- data/.github/workflows/ruby.yml +0 -42
- data/.gitignore +0 -20
- data/LIMITS.md +0 -41
- data/SPEC-PubSub-Draft.md +0 -159
- data/SPEC-WebSocket-Draft.md +0 -239
- data/bin/console +0 -22
- data/bin/info.md +0 -353
- data/bin/mustache_bench.rb +0 -100
- data/bin/poc/Gemfile.lock +0 -23
- data/bin/poc/README.md +0 -37
- data/bin/poc/config.ru +0 -66
- data/bin/poc/gemfile +0 -1
- data/bin/poc/www/index.html +0 -57
- data/examples/async_task.ru +0 -92
- data/examples/bates/README.md +0 -3
- data/examples/bates/config.ru +0 -342
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +0 -600
- data/examples/echo.ru +0 -59
- data/examples/etag.ru +0 -16
- data/examples/hello.ru +0 -29
- data/examples/pubsub_engine.ru +0 -81
- data/examples/rack3.ru +0 -12
- data/examples/redis.ru +0 -70
- data/examples/shootout.ru +0 -73
- data/examples/sub-protocols.ru +0 -90
- data/examples/tcp_client.rb +0 -66
- data/examples/x-sendfile.ru +0 -14
- data/ext/iodine/fio.c +0 -11995
- data/ext/iodine/fio.h +0 -6371
- data/ext/iodine/fio_cli.c +0 -431
- data/ext/iodine/fio_cli.h +0 -189
- data/ext/iodine/fio_json_parser.h +0 -688
- data/ext/iodine/fio_siphash.c +0 -157
- data/ext/iodine/fio_siphash.h +0 -37
- data/ext/iodine/fio_tls.h +0 -129
- data/ext/iodine/fio_tls_missing.c +0 -649
- data/ext/iodine/fio_tls_openssl.c +0 -1106
- data/ext/iodine/fio_tmpfile.h +0 -50
- data/ext/iodine/fiobj.h +0 -44
- data/ext/iodine/fiobj4fio.h +0 -21
- data/ext/iodine/fiobj_ary.c +0 -333
- data/ext/iodine/fiobj_ary.h +0 -139
- data/ext/iodine/fiobj_data.c +0 -1187
- data/ext/iodine/fiobj_data.h +0 -167
- data/ext/iodine/fiobj_hash.c +0 -409
- data/ext/iodine/fiobj_hash.h +0 -176
- data/ext/iodine/fiobj_json.c +0 -622
- data/ext/iodine/fiobj_json.h +0 -68
- data/ext/iodine/fiobj_mem.h +0 -71
- data/ext/iodine/fiobj_mustache.c +0 -317
- data/ext/iodine/fiobj_mustache.h +0 -62
- data/ext/iodine/fiobj_numbers.c +0 -344
- data/ext/iodine/fiobj_numbers.h +0 -127
- data/ext/iodine/fiobj_str.c +0 -433
- data/ext/iodine/fiobj_str.h +0 -172
- data/ext/iodine/fiobject.c +0 -620
- data/ext/iodine/fiobject.h +0 -655
- data/ext/iodine/hpack.h +0 -1923
- data/ext/iodine/http.c +0 -2743
- data/ext/iodine/http.h +0 -1002
- data/ext/iodine/http1.c +0 -910
- data/ext/iodine/http1.h +0 -29
- data/ext/iodine/http1_parser.h +0 -878
- data/ext/iodine/http_internal.c +0 -1279
- data/ext/iodine/http_internal.h +0 -237
- data/ext/iodine/http_mime_parser.h +0 -350
- data/ext/iodine/iodine_caller.c +0 -230
- data/ext/iodine/iodine_connection.c +0 -941
- data/ext/iodine/iodine_defer.c +0 -420
- data/ext/iodine/iodine_fiobj2rb.h +0 -120
- data/ext/iodine/iodine_helpers.c +0 -282
- data/ext/iodine/iodine_helpers.h +0 -12
- data/ext/iodine/iodine_http.c +0 -1181
- data/ext/iodine/iodine_http.h +0 -23
- data/ext/iodine/iodine_json.c +0 -302
- data/ext/iodine/iodine_mustache.c +0 -567
- data/ext/iodine/iodine_pubsub.c +0 -580
- data/ext/iodine/iodine_pubsub.h +0 -26
- data/ext/iodine/iodine_rack_io.c +0 -273
- data/ext/iodine/iodine_rack_io.h +0 -20
- data/ext/iodine/iodine_store.c +0 -146
- data/ext/iodine/iodine_tcp.c +0 -346
- data/ext/iodine/iodine_tcp.h +0 -13
- data/ext/iodine/iodine_tls.c +0 -261
- data/ext/iodine/mustache_parser.h +0 -1546
- data/ext/iodine/redis_engine.c +0 -957
- data/ext/iodine/redis_engine.h +0 -79
- data/ext/iodine/resp_parser.h +0 -317
- data/ext/iodine/websocket_parser.h +0 -506
- data/ext/iodine/websockets.c +0 -743
- data/ext/iodine/websockets.h +0 -185
- data/lib/iodine/connection.rb +0 -61
- data/lib/iodine/json.rb +0 -42
- data/lib/iodine/mustache.rb +0 -113
- data/lib/iodine/pubsub.rb +0 -55
- data/lib/iodine/rack_utils.rb +0 -43
- data/lib/iodine/tls.rb +0 -16
- data/lib/rack/handler/iodine.rb +0 -33
- data/logo.png +0 -0
|
@@ -1,567 +0,0 @@
|
|
|
1
|
-
#include <ruby.h>
|
|
2
|
-
#define INCLUDE_MUSTACHE_IMPLEMENTATION 1
|
|
3
|
-
#include "mustache_parser.h"
|
|
4
|
-
|
|
5
|
-
#include "iodine.h"
|
|
6
|
-
|
|
7
|
-
#define FIO_INCLUDE_STR
|
|
8
|
-
#include <fio.h>
|
|
9
|
-
|
|
10
|
-
static ID call_func_id;
|
|
11
|
-
static VALUE filename_id;
|
|
12
|
-
static VALUE data_id;
|
|
13
|
-
static VALUE template_id;
|
|
14
|
-
/* *****************************************************************************
|
|
15
|
-
C <=> Ruby Data allocation
|
|
16
|
-
***************************************************************************** */
|
|
17
|
-
|
|
18
|
-
static size_t iodine_mustache_data_size(const void *c_) {
|
|
19
|
-
return sizeof(mustache_s *) +
|
|
20
|
-
(((mustache_s **)c_)[0]
|
|
21
|
-
? (((mustache_s **)c_)[0]->u.read_only.data_length +
|
|
22
|
-
(((mustache_s **)c_)[0]->u.read_only.intruction_count *
|
|
23
|
-
sizeof(struct mustache__instruction_s)))
|
|
24
|
-
: 0);
|
|
25
|
-
(void)c_;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static void iodine_mustache_data_free(void *c_) {
|
|
29
|
-
mustache_free(((mustache_s **)c_)[0]);
|
|
30
|
-
FIO_LOG_DEBUG("deallocated mustache data at: %p", ((void **)c_)[0]);
|
|
31
|
-
free((void *)c_);
|
|
32
|
-
FIO_LOG_DEBUG("deallocated mustache pointer at: %p", c_);
|
|
33
|
-
(void)c_;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
static const rb_data_type_t iodine_mustache_data_type = {
|
|
37
|
-
.wrap_struct_name = "IodineMustacheData",
|
|
38
|
-
.function =
|
|
39
|
-
{
|
|
40
|
-
.dmark = NULL,
|
|
41
|
-
.dfree = iodine_mustache_data_free,
|
|
42
|
-
.dsize = iodine_mustache_data_size,
|
|
43
|
-
},
|
|
44
|
-
.data = NULL,
|
|
45
|
-
// .flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/* Iodine::PubSub::Engine.allocate */
|
|
49
|
-
static VALUE iodine_mustache_data_alloc_c(VALUE self) {
|
|
50
|
-
void *m = malloc(sizeof(mustache_s *));
|
|
51
|
-
((mustache_s **)m)[0] = NULL;
|
|
52
|
-
FIO_LOG_DEBUG("allocated mustache pointer at: %p", m);
|
|
53
|
-
return TypedData_Wrap_Struct(self, &iodine_mustache_data_type, m);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/* *****************************************************************************
|
|
57
|
-
Parser Callbacks
|
|
58
|
-
***************************************************************************** */
|
|
59
|
-
|
|
60
|
-
static inline VALUE fiobj_mustache_find_obj_absolute(VALUE udata,
|
|
61
|
-
const char *name,
|
|
62
|
-
uint32_t name_len) {
|
|
63
|
-
VALUE tmp;
|
|
64
|
-
if (!RB_TYPE_P(udata, T_HASH)) {
|
|
65
|
-
if (name_len == 1 && name[0] == '.')
|
|
66
|
-
return udata;
|
|
67
|
-
/* search by method */
|
|
68
|
-
ID name_id = rb_intern2(name, name_len);
|
|
69
|
-
if (rb_respond_to(udata, name_id)) {
|
|
70
|
-
return IodineCaller.call(udata, name_id);
|
|
71
|
-
}
|
|
72
|
-
return Qnil;
|
|
73
|
-
}
|
|
74
|
-
/* search by Symbol */
|
|
75
|
-
ID name_id = rb_intern2(name, name_len);
|
|
76
|
-
VALUE key = ID2SYM(name_id);
|
|
77
|
-
tmp = rb_hash_lookup2(udata, key, Qundef);
|
|
78
|
-
if (tmp != Qundef)
|
|
79
|
-
return tmp;
|
|
80
|
-
/* search by String */
|
|
81
|
-
key = rb_sym2str(key);
|
|
82
|
-
tmp = rb_hash_lookup2(udata, key, Qundef);
|
|
83
|
-
rb_str_free(key);
|
|
84
|
-
if (tmp != Qundef)
|
|
85
|
-
return tmp;
|
|
86
|
-
/* search by method */
|
|
87
|
-
tmp = Qnil;
|
|
88
|
-
if (rb_respond_to(udata, name_id)) {
|
|
89
|
-
tmp = IodineCaller.call(udata, name_id);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return tmp;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
static inline VALUE fiobj_mustache_find_obj_tree(mustache_section_s *section,
|
|
96
|
-
const char *name,
|
|
97
|
-
uint32_t name_len) {
|
|
98
|
-
do {
|
|
99
|
-
VALUE tmp = fiobj_mustache_find_obj_absolute((VALUE)section->udata2, name,
|
|
100
|
-
name_len);
|
|
101
|
-
if (tmp != Qnil) {
|
|
102
|
-
return tmp;
|
|
103
|
-
}
|
|
104
|
-
} while ((section = mustache_section_parent(section)));
|
|
105
|
-
return Qnil;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
static inline VALUE fiobj_mustache_find_obj(mustache_section_s *section,
|
|
109
|
-
const char *name,
|
|
110
|
-
uint32_t name_len) {
|
|
111
|
-
VALUE tmp = fiobj_mustache_find_obj_tree(section, name, name_len);
|
|
112
|
-
if (tmp != Qnil)
|
|
113
|
-
return tmp;
|
|
114
|
-
/* interpolate sections... */
|
|
115
|
-
uint32_t dot = 0;
|
|
116
|
-
while (dot < name_len && name[dot] != '.')
|
|
117
|
-
++dot;
|
|
118
|
-
if (dot == name_len)
|
|
119
|
-
return Qnil;
|
|
120
|
-
tmp = fiobj_mustache_find_obj_tree(section, name, dot);
|
|
121
|
-
if (!tmp) {
|
|
122
|
-
return Qnil;
|
|
123
|
-
}
|
|
124
|
-
++dot;
|
|
125
|
-
for (;;) {
|
|
126
|
-
VALUE obj =
|
|
127
|
-
fiobj_mustache_find_obj_absolute(tmp, name + dot, name_len - dot);
|
|
128
|
-
if (obj != Qnil)
|
|
129
|
-
return obj;
|
|
130
|
-
name += dot;
|
|
131
|
-
name_len -= dot;
|
|
132
|
-
dot = 0;
|
|
133
|
-
while (dot < name_len && name[dot] != '.')
|
|
134
|
-
++dot;
|
|
135
|
-
if (dot == name_len) {
|
|
136
|
-
return Qnil;
|
|
137
|
-
}
|
|
138
|
-
tmp = fiobj_mustache_find_obj_absolute(tmp, name, dot);
|
|
139
|
-
if (tmp == Qnil)
|
|
140
|
-
return Qnil;
|
|
141
|
-
++dot;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Called when an argument name was detected in the current section.
|
|
146
|
-
*
|
|
147
|
-
* A conforming implementation will search for the named argument both in the
|
|
148
|
-
* existing section and all of it's parents (walking backwards towards the root)
|
|
149
|
-
* until a value is detected.
|
|
150
|
-
*
|
|
151
|
-
* A missing value should be treated the same as an empty string.
|
|
152
|
-
*
|
|
153
|
-
* A conforming implementation will output the named argument's value (either
|
|
154
|
-
* HTML escaped or not, depending on the `escape` flag) as a string.
|
|
155
|
-
*/
|
|
156
|
-
static int mustache_on_arg(mustache_section_s *section, const char *name,
|
|
157
|
-
uint32_t name_len, unsigned char escape) {
|
|
158
|
-
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
|
159
|
-
switch (o) {
|
|
160
|
-
case Qnil:
|
|
161
|
-
case Qfalse:
|
|
162
|
-
return 0;
|
|
163
|
-
case Qtrue:
|
|
164
|
-
fio_str_write(section->udata1, "true", 4);
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
if (!RB_TYPE_P(o, T_STRING)) {
|
|
168
|
-
if (rb_respond_to(o, call_func_id))
|
|
169
|
-
o = IodineCaller.call(o, call_func_id);
|
|
170
|
-
if (!RB_TYPE_P(o, T_STRING))
|
|
171
|
-
o = IodineCaller.call(o, iodine_to_s_id);
|
|
172
|
-
}
|
|
173
|
-
if (!RB_TYPE_P(o, T_STRING) || !RSTRING_LEN(o))
|
|
174
|
-
return 0;
|
|
175
|
-
return mustache_write_text(section, RSTRING_PTR(o), RSTRING_LEN(o), escape);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Called when simple template text (string) is detected.
|
|
180
|
-
*
|
|
181
|
-
* A conforming implementation will output data as a string (no escaping).
|
|
182
|
-
*/
|
|
183
|
-
static int mustache_on_text(mustache_section_s *section, const char *data,
|
|
184
|
-
uint32_t data_len) {
|
|
185
|
-
fio_str_write(section->udata1, data, data_len);
|
|
186
|
-
return 0;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Called for nested sections, must return the number of objects in the new
|
|
191
|
-
* subsection (depending on the argument's name).
|
|
192
|
-
*
|
|
193
|
-
* Arrays should return the number of objects in the array.
|
|
194
|
-
*
|
|
195
|
-
* `true` values should return 1.
|
|
196
|
-
*
|
|
197
|
-
* `false` values should return 0.
|
|
198
|
-
*
|
|
199
|
-
* A return value of -1 will stop processing with an error.
|
|
200
|
-
*
|
|
201
|
-
* Please note, this will handle both normal and inverted sections.
|
|
202
|
-
*/
|
|
203
|
-
static int32_t mustache_on_section_test(mustache_section_s *section,
|
|
204
|
-
const char *name, uint32_t name_len,
|
|
205
|
-
uint8_t callable) {
|
|
206
|
-
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
|
207
|
-
if (o == Qnil || o == Qfalse) {
|
|
208
|
-
return 0;
|
|
209
|
-
}
|
|
210
|
-
if (RB_TYPE_P(o, T_ARRAY)) {
|
|
211
|
-
return RARRAY_LEN(o);
|
|
212
|
-
}
|
|
213
|
-
if (callable && rb_respond_to(o, call_func_id)) {
|
|
214
|
-
size_t len;
|
|
215
|
-
const char *txt = mustache_section_text(section, &len);
|
|
216
|
-
VALUE str = Qnil;
|
|
217
|
-
if (txt && len) {
|
|
218
|
-
str = rb_str_new(txt, len);
|
|
219
|
-
}
|
|
220
|
-
o = IodineCaller.call2(o, call_func_id, 1, &str);
|
|
221
|
-
if (!RB_TYPE_P(o, T_STRING))
|
|
222
|
-
o = rb_funcall2(o, iodine_to_s_id, 0, NULL);
|
|
223
|
-
if (RB_TYPE_P(o, T_STRING) && RSTRING_LEN(o))
|
|
224
|
-
mustache_write_text(section, RSTRING_PTR(o), RSTRING_LEN(o), 0);
|
|
225
|
-
return 0;
|
|
226
|
-
}
|
|
227
|
-
return 1;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Called when entering a nested section.
|
|
232
|
-
*
|
|
233
|
-
* `index` is a zero based index indicating the number of repetitions that
|
|
234
|
-
* occurred so far (same as the array index for arrays).
|
|
235
|
-
*
|
|
236
|
-
* A return value of -1 will stop processing with an error.
|
|
237
|
-
*
|
|
238
|
-
* Note: this is a good time to update the subsection's `udata` with the value
|
|
239
|
-
* of the array index. The `udata` will always contain the value or the parent's
|
|
240
|
-
* `udata`.
|
|
241
|
-
*/
|
|
242
|
-
static int mustache_on_section_start(mustache_section_s *section,
|
|
243
|
-
char const *name, uint32_t name_len,
|
|
244
|
-
uint32_t index) {
|
|
245
|
-
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
|
246
|
-
if (RB_TYPE_P(o, T_ARRAY))
|
|
247
|
-
section->udata2 = (void *)rb_ary_entry(o, index);
|
|
248
|
-
else if (RB_TYPE_P(o, T_HASH))
|
|
249
|
-
section->udata2 = (void *)o;
|
|
250
|
-
return 0;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Called for cleanup in case of error.
|
|
255
|
-
*/
|
|
256
|
-
static void mustache_on_formatting_error(void *udata1, void *udata2) {
|
|
257
|
-
(void)udata1;
|
|
258
|
-
(void)udata2;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/* *****************************************************************************
|
|
262
|
-
Loading the template
|
|
263
|
-
***************************************************************************** */
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
Loads the mustache template found in `:filename`. If `:template` is provided it
|
|
267
|
-
will be used instead of reading the file's content.
|
|
268
|
-
|
|
269
|
-
Iodine::Mustache.new(filename, template = nil)
|
|
270
|
-
|
|
271
|
-
When template data is provided, filename (if any) will only be used for partial
|
|
272
|
-
template path resolution and the template data will be used for the template's
|
|
273
|
-
content. This allows, for example, for front matter to be extracted before
|
|
274
|
-
parsing the template.
|
|
275
|
-
|
|
276
|
-
Once a template was loaded, it could be rendered using {render}.
|
|
277
|
-
|
|
278
|
-
Accepts named arguments as well:
|
|
279
|
-
|
|
280
|
-
Iodine::Mustache.new(filename: "foo.mustache", template: "{{ bar }}")
|
|
281
|
-
|
|
282
|
-
*/
|
|
283
|
-
static VALUE iodine_mustache_new(int argc, VALUE *argv, VALUE self) {
|
|
284
|
-
VALUE filename = Qnil, template = Qnil;
|
|
285
|
-
if (argc == 1 && RB_TYPE_P(argv[0], T_HASH)) {
|
|
286
|
-
/* named arguments */
|
|
287
|
-
filename = rb_hash_aref(argv[0], filename_id);
|
|
288
|
-
template = rb_hash_aref(argv[0], template_id);
|
|
289
|
-
} else {
|
|
290
|
-
/* regular arguments */
|
|
291
|
-
if (argc == 0 || argc > 2)
|
|
292
|
-
rb_raise(rb_eArgError, "expecting 1..2 arguments or named arguments.");
|
|
293
|
-
filename = argv[0];
|
|
294
|
-
if (argc > 1) {
|
|
295
|
-
template = argv[1];
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
if (filename == Qnil && template == Qnil)
|
|
299
|
-
rb_raise(rb_eArgError, "need either template contents or file name.");
|
|
300
|
-
|
|
301
|
-
if (template != Qnil)
|
|
302
|
-
Check_Type(template, T_STRING);
|
|
303
|
-
if (filename != Qnil)
|
|
304
|
-
Check_Type(filename, T_STRING);
|
|
305
|
-
|
|
306
|
-
mustache_s **m = NULL;
|
|
307
|
-
TypedData_Get_Struct(self, mustache_s *, &iodine_mustache_data_type, m);
|
|
308
|
-
if (!m) {
|
|
309
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache allocation error.");
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
mustache_error_en err;
|
|
313
|
-
*m = mustache_load(.filename =
|
|
314
|
-
(filename == Qnil ? NULL : RSTRING_PTR(filename)),
|
|
315
|
-
.filename_len =
|
|
316
|
-
(filename == Qnil ? 0 : RSTRING_LEN(filename)),
|
|
317
|
-
.data = (template == Qnil ? NULL : RSTRING_PTR(template)),
|
|
318
|
-
.data_len = (template == Qnil ? 0 : RSTRING_LEN(template)),
|
|
319
|
-
.err = &err);
|
|
320
|
-
if (!*m)
|
|
321
|
-
goto error;
|
|
322
|
-
|
|
323
|
-
FIO_LOG_DEBUG("allocated / loaded mustache data at: %p", (void *)*m);
|
|
324
|
-
|
|
325
|
-
return self;
|
|
326
|
-
error:
|
|
327
|
-
switch (err) {
|
|
328
|
-
case MUSTACHE_OK:
|
|
329
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template ok, unknown error.");
|
|
330
|
-
break;
|
|
331
|
-
case MUSTACHE_ERR_TOO_DEEP:
|
|
332
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache element nesting too deep.");
|
|
333
|
-
break;
|
|
334
|
-
case MUSTACHE_ERR_CLOSURE_MISMATCH:
|
|
335
|
-
rb_raise(rb_eRuntimeError,
|
|
336
|
-
"Iodine::Mustache template error, closure mismatch.");
|
|
337
|
-
break;
|
|
338
|
-
case MUSTACHE_ERR_FILE_NOT_FOUND:
|
|
339
|
-
rb_raise(rb_eLoadError, "Iodine::Mustache template not found.");
|
|
340
|
-
break;
|
|
341
|
-
case MUSTACHE_ERR_FILE_TOO_BIG:
|
|
342
|
-
rb_raise(rb_eLoadError, "Iodine::Mustache template too big.");
|
|
343
|
-
break;
|
|
344
|
-
case MUSTACHE_ERR_FILE_NAME_TOO_LONG:
|
|
345
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template name too long.");
|
|
346
|
-
break;
|
|
347
|
-
case MUSTACHE_ERR_EMPTY_TEMPLATE:
|
|
348
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template is empty.");
|
|
349
|
-
break;
|
|
350
|
-
case MUSTACHE_ERR_UNKNOWN:
|
|
351
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache unknown error.");
|
|
352
|
-
break;
|
|
353
|
-
case MUSTACHE_ERR_USER_ERROR:
|
|
354
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache internal error.");
|
|
355
|
-
break;
|
|
356
|
-
case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
|
|
357
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
|
|
358
|
-
|
|
359
|
-
break;
|
|
360
|
-
case MUSTACHE_ERR_DELIMITER_TOO_LONG:
|
|
361
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
|
|
362
|
-
|
|
363
|
-
break;
|
|
364
|
-
case MUSTACHE_ERR_NAME_TOO_LONG:
|
|
365
|
-
rb_raise(rb_eRuntimeError,
|
|
366
|
-
"Iodine::Mustache section name in template is too long.");
|
|
367
|
-
default:
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
return self;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
/* *****************************************************************************
|
|
374
|
-
Rendering
|
|
375
|
-
***************************************************************************** */
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
Renders the mustache template using the data provided in the `data` argument.
|
|
379
|
-
|
|
380
|
-
Returns a String with the rendered template.
|
|
381
|
-
|
|
382
|
-
Raises an exception on error.
|
|
383
|
-
|
|
384
|
-
NOTE:
|
|
385
|
-
|
|
386
|
-
As one might notice, no binding is provided. Instead, a `data` Hash is assumed.
|
|
387
|
-
Iodine will search the Hash for any data while protecting against code
|
|
388
|
-
execution.
|
|
389
|
-
*/
|
|
390
|
-
static VALUE iodine_mustache_render(VALUE self, VALUE data) {
|
|
391
|
-
fio_str_s str = FIO_STR_INIT;
|
|
392
|
-
mustache_s **m = NULL;
|
|
393
|
-
TypedData_Get_Struct(self, mustache_s *, &iodine_mustache_data_type, m);
|
|
394
|
-
if (!m) {
|
|
395
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache allocation error.");
|
|
396
|
-
}
|
|
397
|
-
if (mustache_build(*m, .udata1 = &str, .udata2 = (void *)data))
|
|
398
|
-
goto error;
|
|
399
|
-
fio_str_info_s i = fio_str_info(&str);
|
|
400
|
-
VALUE ret = rb_str_new(i.data, i.len);
|
|
401
|
-
fio_str_free(&str);
|
|
402
|
-
return ret;
|
|
403
|
-
|
|
404
|
-
error:
|
|
405
|
-
fio_str_free(&str);
|
|
406
|
-
rb_raise(rb_eRuntimeError, "Couldn't build template frome data.");
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/**
|
|
410
|
-
Renders the mustache template found in `filename`, using the data provided in
|
|
411
|
-
the `data` argument. If `template` is provided it will be used instead of
|
|
412
|
-
reading the file's content.
|
|
413
|
-
|
|
414
|
-
Iodine::Mustache.render(filename, data, template = nil)
|
|
415
|
-
|
|
416
|
-
Returns a String with the rendered template.
|
|
417
|
-
|
|
418
|
-
Raises an exception on error.
|
|
419
|
-
|
|
420
|
-
template = "<h1>{{title}}</h1>"
|
|
421
|
-
filename = "templates/index"
|
|
422
|
-
data = {title: "Home"}
|
|
423
|
-
result = Iodine::Mustache.render(filename, data)
|
|
424
|
-
|
|
425
|
-
# filename will be used to resolve the path to any partials:
|
|
426
|
-
result = Iodine::Mustache.render(filename, data, template)
|
|
427
|
-
|
|
428
|
-
# OR, if we don't need partial template path resolution
|
|
429
|
-
result = Iodine::Mustache.render(template: template, data: data)
|
|
430
|
-
|
|
431
|
-
NOTE 1:
|
|
432
|
-
|
|
433
|
-
This function doesn't cache the template data.
|
|
434
|
-
|
|
435
|
-
The more complext the template the higher the cost of the template parsing
|
|
436
|
-
stage.
|
|
437
|
-
|
|
438
|
-
Consider creating a persistent template object using a new object and using the
|
|
439
|
-
instance {#render} method.
|
|
440
|
-
|
|
441
|
-
NOTE 2:
|
|
442
|
-
|
|
443
|
-
As one might notice, no binding is provided. Instead, a `data` Hash is assumed.
|
|
444
|
-
Iodine will search the Hash for any data while protecting against code
|
|
445
|
-
execution.
|
|
446
|
-
*/
|
|
447
|
-
static VALUE iodine_mustache_render_klass(int argc, VALUE *argv, VALUE self) {
|
|
448
|
-
VALUE filename = Qnil, data = Qnil, template = Qnil;
|
|
449
|
-
if (argc == 1) {
|
|
450
|
-
/* named arguments */
|
|
451
|
-
Check_Type(argv[0], T_HASH);
|
|
452
|
-
filename = rb_hash_aref(argv[0], filename_id);
|
|
453
|
-
data = rb_hash_aref(argv[0], data_id);
|
|
454
|
-
template = rb_hash_aref(argv[0], template_id);
|
|
455
|
-
} else {
|
|
456
|
-
/* regular arguments */
|
|
457
|
-
if (argc < 2 || argc > 3)
|
|
458
|
-
rb_raise(rb_eArgError, "expecting 2..3 arguments or named arguments.");
|
|
459
|
-
filename = argv[0];
|
|
460
|
-
data = argv[1];
|
|
461
|
-
if (argc > 2) {
|
|
462
|
-
template = argv[2];
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
if (filename == Qnil && template == Qnil)
|
|
466
|
-
rb_raise(rb_eArgError, "need either template contents or file name.");
|
|
467
|
-
|
|
468
|
-
if (template != Qnil)
|
|
469
|
-
Check_Type(template, T_STRING);
|
|
470
|
-
if (filename != Qnil)
|
|
471
|
-
Check_Type(filename, T_STRING);
|
|
472
|
-
|
|
473
|
-
fio_str_s str = FIO_STR_INIT;
|
|
474
|
-
|
|
475
|
-
mustache_s *m = NULL;
|
|
476
|
-
mustache_error_en err;
|
|
477
|
-
m = mustache_load(.filename =
|
|
478
|
-
(filename == Qnil ? NULL : RSTRING_PTR(filename)),
|
|
479
|
-
.filename_len =
|
|
480
|
-
(filename == Qnil ? 0 : RSTRING_LEN(filename)),
|
|
481
|
-
.data = (template == Qnil ? NULL : RSTRING_PTR(template)),
|
|
482
|
-
.data_len = (template == Qnil ? 0 : RSTRING_LEN(template)),
|
|
483
|
-
.err = &err);
|
|
484
|
-
if (!m)
|
|
485
|
-
goto error;
|
|
486
|
-
int e = mustache_build(m, .udata1 = &str, .udata2 = (void *)data);
|
|
487
|
-
mustache_free(m);
|
|
488
|
-
if (e)
|
|
489
|
-
goto render_error;
|
|
490
|
-
fio_str_info_s i = fio_str_info(&str);
|
|
491
|
-
VALUE ret = rb_str_new(i.data, i.len);
|
|
492
|
-
fio_str_free(&str);
|
|
493
|
-
return ret;
|
|
494
|
-
|
|
495
|
-
error:
|
|
496
|
-
switch (err) {
|
|
497
|
-
case MUSTACHE_OK:
|
|
498
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template ok, unknown error.");
|
|
499
|
-
break;
|
|
500
|
-
case MUSTACHE_ERR_TOO_DEEP:
|
|
501
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache element nesting too deep.");
|
|
502
|
-
break;
|
|
503
|
-
case MUSTACHE_ERR_CLOSURE_MISMATCH:
|
|
504
|
-
rb_raise(rb_eRuntimeError,
|
|
505
|
-
"Iodine::Mustache template error, closure mismatch.");
|
|
506
|
-
break;
|
|
507
|
-
case MUSTACHE_ERR_FILE_NOT_FOUND:
|
|
508
|
-
rb_raise(rb_eLoadError, "Iodine::Mustache template not found.");
|
|
509
|
-
break;
|
|
510
|
-
case MUSTACHE_ERR_FILE_TOO_BIG:
|
|
511
|
-
rb_raise(rb_eLoadError, "Iodine::Mustache template too big.");
|
|
512
|
-
break;
|
|
513
|
-
case MUSTACHE_ERR_FILE_NAME_TOO_LONG:
|
|
514
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template name too long.");
|
|
515
|
-
break;
|
|
516
|
-
case MUSTACHE_ERR_EMPTY_TEMPLATE:
|
|
517
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template is empty.");
|
|
518
|
-
break;
|
|
519
|
-
case MUSTACHE_ERR_UNKNOWN:
|
|
520
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache unknown error.");
|
|
521
|
-
break;
|
|
522
|
-
case MUSTACHE_ERR_USER_ERROR:
|
|
523
|
-
rb_raise(rb_eRuntimeError,
|
|
524
|
-
"Iodine::Mustache internal error or unexpected data structure.");
|
|
525
|
-
break;
|
|
526
|
-
case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
|
|
527
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
|
|
528
|
-
|
|
529
|
-
break;
|
|
530
|
-
case MUSTACHE_ERR_DELIMITER_TOO_LONG:
|
|
531
|
-
rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
|
|
532
|
-
|
|
533
|
-
break;
|
|
534
|
-
case MUSTACHE_ERR_NAME_TOO_LONG:
|
|
535
|
-
rb_raise(rb_eRuntimeError,
|
|
536
|
-
"Iodine::Mustache section name in template is too long.");
|
|
537
|
-
|
|
538
|
-
break;
|
|
539
|
-
default:
|
|
540
|
-
break;
|
|
541
|
-
}
|
|
542
|
-
return Qnil;
|
|
543
|
-
|
|
544
|
-
render_error:
|
|
545
|
-
fio_str_free(&str);
|
|
546
|
-
rb_raise(rb_eRuntimeError, "Couldn't build template frome data.");
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
/* *****************************************************************************
|
|
550
|
-
Initialize Iodine::Mustache
|
|
551
|
-
***************************************************************************** */
|
|
552
|
-
|
|
553
|
-
void iodine_init_mustache(void) {
|
|
554
|
-
call_func_id = rb_intern2("call", 4);
|
|
555
|
-
filename_id = rb_id2sym(rb_intern2("filename", 8));
|
|
556
|
-
data_id = rb_id2sym(rb_intern2("data", 4));
|
|
557
|
-
template_id = rb_id2sym(rb_intern2("template", 8));
|
|
558
|
-
rb_global_variable(&filename_id);
|
|
559
|
-
rb_global_variable(&data_id);
|
|
560
|
-
rb_global_variable(&template_id);
|
|
561
|
-
VALUE tmp = rb_define_class_under(IodineModule, "Mustache", rb_cObject);
|
|
562
|
-
rb_define_alloc_func(tmp, iodine_mustache_data_alloc_c);
|
|
563
|
-
rb_define_method(tmp, "initialize", iodine_mustache_new, -1);
|
|
564
|
-
rb_define_method(tmp, "render", iodine_mustache_render, 1);
|
|
565
|
-
rb_define_singleton_method(tmp, "render", iodine_mustache_render_klass, -1);
|
|
566
|
-
// rb_define_module_function(tmp, "render", iodine_mustache_render_klass, 2);
|
|
567
|
-
}
|