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/fiobj_mustache.h
CHANGED
@@ -8,12 +8,30 @@
|
|
8
8
|
/**
|
9
9
|
* Loads a mustache template, converting it into an opaque instruction array.
|
10
10
|
*
|
11
|
-
* Returns a pointer to the instruction array.
|
11
|
+
* Returns a pointer to the instruction array or NULL (on error).
|
12
12
|
*
|
13
13
|
* The `filename` argument should contain the template's file name.
|
14
14
|
*/
|
15
15
|
mustache_s *fiobj_mustache_load(fio_str_info_s filename);
|
16
16
|
|
17
|
+
/**
|
18
|
+
* Loads a mustache template, either from memory of a file, converting it into
|
19
|
+
* an opaque instruction array.
|
20
|
+
*
|
21
|
+
* Returns a pointer to the instruction array or NULL (on error).
|
22
|
+
*
|
23
|
+
* Accepts any of the following named arguments:
|
24
|
+
* * `char const *filename` - The root template's file name.
|
25
|
+
* * `size_t filename_len` - The file name's length.
|
26
|
+
* * `char const *data` - If set, will be used as the file's contents.
|
27
|
+
* * `size_t data_len` - If set, `data` will be used as the file's contents.
|
28
|
+
* * `mustache_error_en *err` - A container for any template load errors (see
|
29
|
+
* mustache_parser.h).
|
30
|
+
*/
|
31
|
+
mustache_s *fiobj_mustache_new(mustache_load_args_s args);
|
32
|
+
#define fiobj_mustache_new(...) \
|
33
|
+
fiobj_mustache_new((mustache_load_args_s){__VA_ARGS__})
|
34
|
+
|
17
35
|
/** Free the mustache template */
|
18
36
|
void fiobj_mustache_free(mustache_s *mustache);
|
19
37
|
|
@@ -21,7 +39,7 @@ void fiobj_mustache_free(mustache_s *mustache);
|
|
21
39
|
* Creates a FIOBJ String containing the rendered template using the information
|
22
40
|
* in the `data` object.
|
23
41
|
*
|
24
|
-
* Returns FIOBJ_INVALID if an error
|
42
|
+
* Returns FIOBJ_INVALID if an error occurred and a FIOBJ String on success.
|
25
43
|
*/
|
26
44
|
FIOBJ fiobj_mustache_build(mustache_s *mustache, FIOBJ data);
|
27
45
|
|
@@ -29,7 +47,7 @@ FIOBJ fiobj_mustache_build(mustache_s *mustache, FIOBJ data);
|
|
29
47
|
* Renders a template into an existing FIOBJ String (`dest`'s end), using the
|
30
48
|
* information in the `data` object.
|
31
49
|
*
|
32
|
-
* Returns FIOBJ_INVALID if an error
|
50
|
+
* Returns FIOBJ_INVALID if an error occurred and a FIOBJ String on success.
|
33
51
|
*/
|
34
52
|
FIOBJ fiobj_mustache_build2(FIOBJ dest, mustache_s *mustache, FIOBJ data);
|
35
53
|
|
data/ext/iodine/http.c
CHANGED
@@ -2665,6 +2665,25 @@ parse_path:
|
|
2665
2665
|
++url;
|
2666
2666
|
result.target.data = (char *)url;
|
2667
2667
|
result.target.len = end - result.target.data;
|
2668
|
+
|
2669
|
+
/* set any empty values to NULL */
|
2670
|
+
if (!result.scheme.len)
|
2671
|
+
result.scheme.data = NULL;
|
2672
|
+
if (!result.user.len)
|
2673
|
+
result.user.data = NULL;
|
2674
|
+
if (!result.password.len)
|
2675
|
+
result.password.data = NULL;
|
2676
|
+
if (!result.host.len)
|
2677
|
+
result.host.data = NULL;
|
2678
|
+
if (!result.port.len)
|
2679
|
+
result.port.data = NULL;
|
2680
|
+
if (!result.path.len)
|
2681
|
+
result.path.data = NULL;
|
2682
|
+
if (!result.query.len)
|
2683
|
+
result.query.data = NULL;
|
2684
|
+
if (!result.target.len)
|
2685
|
+
result.target.data = NULL;
|
2686
|
+
|
2668
2687
|
return result;
|
2669
2688
|
}
|
2670
2689
|
|
data/ext/iodine/http.h
CHANGED
@@ -978,8 +978,12 @@ typedef struct {
|
|
978
978
|
* i.e.:
|
979
979
|
* example.com
|
980
980
|
* example.com/index.html
|
981
|
-
* user:1234@example.com:8080
|
982
981
|
* example.com:8080/index.html
|
982
|
+
* example.com:8080/index.html?key=val#target
|
983
|
+
*
|
984
|
+
* * `user:password@host:port/path?query#target`
|
985
|
+
*
|
986
|
+
* i.e.: user:1234@example.com:8080/index.html
|
983
987
|
*
|
984
988
|
* * `schema://user:password@host:port/path?query#target`
|
985
989
|
*
|
data/ext/iodine/http_internal.h
CHANGED
data/ext/iodine/iodine_http.c
CHANGED
@@ -938,7 +938,14 @@ static VALUE iodine_http_listen(VALUE self, VALUE opt) {
|
|
938
938
|
IodineStore.add(port);
|
939
939
|
} else if (port == Qfalse)
|
940
940
|
port = 0;
|
941
|
-
else
|
941
|
+
else if (address &&
|
942
|
+
(StringValueCStr(address)[0] > '9' ||
|
943
|
+
StringValueCStr(address)[0] < '0') &&
|
944
|
+
StringValueCStr(address)[0] != ':' &&
|
945
|
+
(RSTRING_LEN(address) < 3 || StringValueCStr(address)[2] != ':')) {
|
946
|
+
/* address is likely a Unix domain socket address, not an IP address... */
|
947
|
+
port = Qnil;
|
948
|
+
} else {
|
942
949
|
port = rb_str_new("3000", 4);
|
943
950
|
IodineStore.add(port);
|
944
951
|
}
|
@@ -948,14 +955,15 @@ static VALUE iodine_http_listen(VALUE self, VALUE opt) {
|
|
948
955
|
else
|
949
956
|
app = 0;
|
950
957
|
|
951
|
-
if (http_listen(
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
958
|
+
if (http_listen((port ? StringValueCStr(port) : NULL),
|
959
|
+
(address ? StringValueCStr(address) : NULL),
|
960
|
+
.on_request = on_rack_request, .on_upgrade = on_rack_upgrade,
|
961
|
+
.udata = (void *)app,
|
962
|
+
.timeout = (tout ? FIX2INT(tout) : tout), .ws_timeout = ping,
|
963
|
+
.ws_max_msg_size = max_msg, .max_header_size = max_headers,
|
964
|
+
.on_finish = free_iodine_http, .log = log_http,
|
965
|
+
.max_body_size = max_body,
|
966
|
+
.public_folder = (www ? StringValueCStr(www) : NULL)) == -1) {
|
959
967
|
FIO_LOG_ERROR("Failed to initialize a listening HTTP socket for port %s",
|
960
968
|
port ? StringValueCStr(port) : "3000");
|
961
969
|
rb_raise(rb_eRuntimeError, "Listening socket initialization failed");
|
@@ -51,8 +51,10 @@ Parser Callbacks
|
|
51
51
|
***************************************************************************** */
|
52
52
|
|
53
53
|
/** HTML ecape table, created using the following Ruby Script:
|
54
|
-
|
55
|
-
|
54
|
+
|
55
|
+
a = (0..255).to_a.map {|i| i.chr }
|
56
|
+
# 100.times {|i| a[i] = "&\#x#{ i < 16 ? "0#{i.to_s(16)}" : i.to_s(16)};"}
|
57
|
+
100.times {|i| a[i] = "&\##{i.to_s(10)};"}
|
56
58
|
('a'.ord..'z'.ord).each {|i| a[i] = i.chr }
|
57
59
|
('A'.ord..'Z'.ord).each {|i| a[i] = i.chr }
|
58
60
|
('0'.ord..'9'.ord).each {|i| a[i] = i.chr }
|
@@ -60,94 +62,127 @@ a['<'.ord] = "<"
|
|
60
62
|
a['>'.ord] = ">"
|
61
63
|
a['&'.ord] = "&"
|
62
64
|
a['"'.ord] = """
|
65
|
+
a["\'".ord] = "'"
|
66
|
+
a['|'.ord] = "&\##{'|'.ord.to_s(10)};"
|
63
67
|
|
64
68
|
b = a.map {|s| s.length }
|
65
69
|
puts "static char *html_escape_strs[] = {", a.to_s.slice(1..-2) ,"};",
|
66
70
|
"static uint8_t html_escape_len[] = {", b.to_s.slice(1..-2),"};"
|
67
71
|
*/
|
68
|
-
static
|
69
|
-
"&#
|
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
|
-
"ü", "ý", "þ", "ÿ"};
|
72
|
+
static char *html_escape_strs[] = {
|
73
|
+
"�", "", "", "", "", "", "", "",
|
74
|
+
"", "	", " ", "", "", " ", "", "",
|
75
|
+
"", "", "", "", "", "", "", "",
|
76
|
+
"", "", "", "", "", "", "", "",
|
77
|
+
" ", "!", """, "#", "$", "%", "&", "'",
|
78
|
+
"(", ")", "*", "+", ",", "-", ".", "/",
|
79
|
+
"0", "1", "2", "3", "4", "5", "6", "7",
|
80
|
+
"8", "9", ":", ";", "<", "=", ">", "?",
|
81
|
+
"@", "A", "B", "C", "D", "E", "F", "G",
|
82
|
+
"H", "I", "J", "K", "L", "M", "N", "O",
|
83
|
+
"P", "Q", "R", "S", "T", "U", "V", "W",
|
84
|
+
"X", "Y", "Z", "[", "\", "]", "^", "_",
|
85
|
+
"`", "a", "b", "c", "d", "e", "f", "g",
|
86
|
+
"h", "i", "j", "k", "l", "m", "n", "o",
|
87
|
+
"p", "q", "r", "s", "t", "u", "v", "w",
|
88
|
+
"x", "y", "z", "{", "|", "}", "~", "\x7F",
|
89
|
+
"\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87",
|
90
|
+
"\x88", "\x89", "\x8A", "\x8B", "\x8C", "\x8D", "\x8E", "\x8F",
|
91
|
+
"\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97",
|
92
|
+
"\x98", "\x99", "\x9A", "\x9B", "\x9C", "\x9D", "\x9E", "\x9F",
|
93
|
+
"\xA0", "\xA1", "\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7",
|
94
|
+
"\xA8", "\xA9", "\xAA", "\xAB", "\xAC", "\xAD", "\xAE", "\xAF",
|
95
|
+
"\xB0", "\xB1", "\xB2", "\xB3", "\xB4", "\xB5", "\xB6", "\xB7",
|
96
|
+
"\xB8", "\xB9", "\xBA", "\xBB", "\xBC", "\xBD", "\xBE", "\xBF",
|
97
|
+
"\xC0", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7",
|
98
|
+
"\xC8", "\xC9", "\xCA", "\xCB", "\xCC", "\xCD", "\xCE", "\xCF",
|
99
|
+
"\xD0", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7",
|
100
|
+
"\xD8", "\xD9", "\xDA", "\xDB", "\xDC", "\xDD", "\xDE", "\xDF",
|
101
|
+
"\xE0", "\xE1", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7",
|
102
|
+
"\xE8", "\xE9", "\xEA", "\xEB", "\xEC", "\xED", "\xEE", "\xEF",
|
103
|
+
"\xF0", "\xF1", "\xF2", "\xF3", "\xF4", "\xF5", "\xF6", "\xF7",
|
104
|
+
"\xF8", "\xF9", "\xFA", "\xFB", "\xFC", "\xFD", "\xFE", "\xFF"};
|
106
105
|
static uint8_t html_escape_len[] = {
|
107
|
-
|
108
|
-
|
109
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
110
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
111
|
-
|
112
|
-
1, 1, 1,
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
106
|
+
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
107
|
+
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5, 5,
|
108
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 4, 5, 4, 5, 5, 1, 1, 1, 1, 1, 1, 1,
|
109
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 5, 5, 5,
|
110
|
+
5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
111
|
+
1, 1, 1, 1, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
112
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
113
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
114
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
115
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
116
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
117
|
+
|
118
|
+
static inline VALUE fiobj_mustache_find_obj_absolute(VALUE udata,
|
119
|
+
const char *name,
|
120
|
+
uint32_t name_len) {
|
121
|
+
VALUE tmp;
|
122
|
+
if (!RB_TYPE_P(udata, T_HASH)) {
|
123
|
+
if (name_len == 1 && name[0] == '.')
|
124
|
+
return udata;
|
125
|
+
return Qnil;
|
126
|
+
}
|
127
|
+
/* search by String */
|
128
|
+
VALUE key = rb_str_new(name, name_len);
|
129
|
+
tmp = rb_hash_aref(udata, key);
|
130
|
+
if (tmp != Qnil)
|
131
|
+
return tmp;
|
132
|
+
/* search by Symbol */
|
133
|
+
key = rb_id2sym(rb_intern2(name, name_len));
|
134
|
+
tmp = rb_hash_aref(udata, key);
|
135
|
+
return tmp;
|
136
|
+
}
|
118
137
|
|
119
|
-
static inline VALUE
|
120
|
-
|
121
|
-
|
138
|
+
static inline VALUE fiobj_mustache_find_obj_tree(mustache_section_s *section,
|
139
|
+
const char *name,
|
140
|
+
uint32_t name_len) {
|
122
141
|
do {
|
123
|
-
VALUE tmp
|
124
|
-
|
125
|
-
|
126
|
-
if (name[0] >= '0' && name[0] <= '9' &&
|
127
|
-
RB_TYPE_P((VALUE)section->udata2, T_ARRAY)) {
|
128
|
-
char **pos = (char **)&name;
|
129
|
-
tmp = rb_ary_entry((VALUE)section->udata2, fio_atol(pos));
|
130
|
-
if (tmp)
|
131
|
-
return tmp;
|
132
|
-
}
|
133
|
-
#endif
|
134
|
-
if (!RB_TYPE_P((VALUE)section->udata2, T_HASH)) {
|
135
|
-
continue;
|
136
|
-
}
|
137
|
-
/* search by String */
|
138
|
-
VALUE key = rb_str_new(name, name_len);
|
139
|
-
tmp = rb_hash_aref((VALUE)section->udata2, key);
|
140
|
-
if (tmp != Qnil)
|
142
|
+
VALUE tmp = fiobj_mustache_find_obj_absolute((VALUE)section->udata2, name,
|
143
|
+
name_len);
|
144
|
+
if (tmp != Qnil) {
|
141
145
|
return tmp;
|
142
|
-
|
143
|
-
|
144
|
-
tmp = rb_hash_aref((VALUE)section->udata2, key);
|
145
|
-
if (tmp != Qnil)
|
146
|
-
return tmp;
|
147
|
-
section = section->parent;
|
148
|
-
} while (section);
|
146
|
+
}
|
147
|
+
} while ((section = mustache_section_parent(section)));
|
149
148
|
return Qnil;
|
150
149
|
}
|
150
|
+
|
151
|
+
static inline VALUE fiobj_mustache_find_obj(mustache_section_s *section,
|
152
|
+
const char *name,
|
153
|
+
uint32_t name_len) {
|
154
|
+
VALUE tmp = fiobj_mustache_find_obj_tree(section, name, name_len);
|
155
|
+
if (tmp != Qnil)
|
156
|
+
return tmp;
|
157
|
+
/* interpolate sections... */
|
158
|
+
uint32_t dot = 0;
|
159
|
+
while (dot < name_len && name[dot] != '.')
|
160
|
+
++dot;
|
161
|
+
if (dot == name_len)
|
162
|
+
return Qnil;
|
163
|
+
tmp = fiobj_mustache_find_obj_tree(section, name, dot);
|
164
|
+
if (!tmp) {
|
165
|
+
return Qnil;
|
166
|
+
}
|
167
|
+
++dot;
|
168
|
+
for (;;) {
|
169
|
+
VALUE obj =
|
170
|
+
fiobj_mustache_find_obj_absolute(tmp, name + dot, name_len - dot);
|
171
|
+
if (obj != Qnil)
|
172
|
+
return obj;
|
173
|
+
name += dot;
|
174
|
+
name_len -= dot;
|
175
|
+
dot = 0;
|
176
|
+
while (dot < name_len && name[dot] != '.')
|
177
|
+
++dot;
|
178
|
+
if (dot == name_len)
|
179
|
+
return Qnil;
|
180
|
+
tmp = fiobj_mustache_find_obj_absolute(tmp, name, dot);
|
181
|
+
if (tmp == Qnil || !RB_TYPE_P(tmp, T_HASH))
|
182
|
+
return Qnil;
|
183
|
+
++dot;
|
184
|
+
}
|
185
|
+
}
|
151
186
|
/**
|
152
187
|
* Called when an argument name was detected in the current section.
|
153
188
|
*
|
@@ -163,13 +198,19 @@ static inline VALUE fiobj_mustache_find_obj(mustache_section_s *section,
|
|
163
198
|
static int mustache_on_arg(mustache_section_s *section, const char *name,
|
164
199
|
uint32_t name_len, unsigned char escape) {
|
165
200
|
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
166
|
-
|
201
|
+
switch (o) {
|
202
|
+
case Qnil:
|
203
|
+
case Qfalse:
|
167
204
|
return 0;
|
205
|
+
case Qtrue:
|
206
|
+
fio_str_write(section->udata1, "true", 4);
|
207
|
+
break;
|
208
|
+
}
|
168
209
|
if (rb_respond_to(o, call_func_id))
|
169
210
|
goto callable;
|
170
211
|
if (!RB_TYPE_P(o, T_STRING))
|
171
212
|
o = IodineCaller.call(o, to_s_func_id);
|
172
|
-
if (!RB_TYPE_P(o, T_STRING) || !
|
213
|
+
if (!RB_TYPE_P(o, T_STRING) || !RSTRING_LEN(o))
|
173
214
|
return 0;
|
174
215
|
if (!escape) {
|
175
216
|
fio_str_write(section->udata1, RSTRING_PTR(o), RSTRING_LEN(o));
|
@@ -193,9 +234,10 @@ static int mustache_on_arg(mustache_section_s *section, const char *name,
|
|
193
234
|
(void)escape;
|
194
235
|
return 0;
|
195
236
|
callable:
|
196
|
-
o =
|
197
|
-
|
198
|
-
|
237
|
+
o = IodineCaller.call(o, call_func_id);
|
238
|
+
if (RB_TYPE_P(o, T_STRING))
|
239
|
+
o = rb_funcall2(o, to_s_func_id, 0, NULL);
|
240
|
+
fio_str_write(section->udata1, RSTRING_PTR(o), RSTRING_LEN(o));
|
199
241
|
return 0;
|
200
242
|
}
|
201
243
|
|
@@ -225,14 +267,29 @@ static int mustache_on_text(mustache_section_s *section, const char *data,
|
|
225
267
|
* Please note, this will handle both normal and inverted sections.
|
226
268
|
*/
|
227
269
|
static int32_t mustache_on_section_test(mustache_section_s *section,
|
228
|
-
const char *name, uint32_t name_len
|
270
|
+
const char *name, uint32_t name_len,
|
271
|
+
uint8_t callable) {
|
229
272
|
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
230
|
-
if (o == Qnil) {
|
273
|
+
if (o == Qnil || o == Qfalse) {
|
231
274
|
return 0;
|
232
275
|
}
|
233
276
|
if (RB_TYPE_P(o, T_ARRAY)) {
|
234
277
|
return RARRAY_LEN(o);
|
235
278
|
}
|
279
|
+
if (callable && rb_respond_to(o, call_func_id)) {
|
280
|
+
size_t len;
|
281
|
+
const char *txt = mustache_section_text(section, &len);
|
282
|
+
VALUE str = Qnil;
|
283
|
+
if (txt && len) {
|
284
|
+
str = rb_str_new(txt, len);
|
285
|
+
}
|
286
|
+
o = IodineCaller.call2(o, call_func_id, 1, &str);
|
287
|
+
if (!RB_TYPE_P(o, T_STRING))
|
288
|
+
o = rb_funcall2(o, to_s_func_id, 0, NULL);
|
289
|
+
if (RB_TYPE_P(o, T_STRING) && RSTRING_LEN(o))
|
290
|
+
fio_str_write(section->udata1, RSTRING_PTR(o), RSTRING_LEN(o));
|
291
|
+
return 0;
|
292
|
+
}
|
236
293
|
return 1;
|
237
294
|
}
|
238
295
|
|
@@ -252,11 +309,9 @@ static int mustache_on_section_start(mustache_section_s *section,
|
|
252
309
|
char const *name, uint32_t name_len,
|
253
310
|
uint32_t index) {
|
254
311
|
VALUE o = fiobj_mustache_find_obj(section, name, name_len);
|
255
|
-
if (o == Qnil)
|
256
|
-
return 0;
|
257
312
|
if (RB_TYPE_P(o, T_ARRAY))
|
258
313
|
section->udata2 = (void *)rb_ary_entry(o, index);
|
259
|
-
else
|
314
|
+
else if (RB_TYPE_P(o, T_HASH))
|
260
315
|
section->udata2 = (void *)o;
|
261
316
|
return 0;
|
262
317
|
}
|
@@ -321,6 +376,19 @@ error:
|
|
321
376
|
case MUSTACHE_ERR_USER_ERROR:
|
322
377
|
rb_raise(rb_eRuntimeError, "Iodine::Mustache internal error.");
|
323
378
|
break;
|
379
|
+
case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
|
380
|
+
rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
|
381
|
+
|
382
|
+
break;
|
383
|
+
case MUSTACHE_ERR_DELIMITER_TOO_LONG:
|
384
|
+
rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
|
385
|
+
|
386
|
+
break;
|
387
|
+
case MUSTACHE_ERR_NAME_TOO_LONG:
|
388
|
+
rb_raise(rb_eRuntimeError,
|
389
|
+
"Iodine::Mustache section name in template is too long.");
|
390
|
+
default:
|
391
|
+
break;
|
324
392
|
}
|
325
393
|
return self;
|
326
394
|
}
|
@@ -438,7 +506,6 @@ static VALUE iodine_mustache_render_klass(int argc, VALUE *argv, VALUE self) {
|
|
438
506
|
.err = &err);
|
439
507
|
if (!m)
|
440
508
|
goto error;
|
441
|
-
|
442
509
|
int e = mustache_build(m, .udata1 = &str, .udata2 = (void *)data);
|
443
510
|
mustache_free(m);
|
444
511
|
if (e)
|
@@ -476,7 +543,23 @@ error:
|
|
476
543
|
rb_raise(rb_eRuntimeError, "Iodine::Mustache unknown error.");
|
477
544
|
break;
|
478
545
|
case MUSTACHE_ERR_USER_ERROR:
|
479
|
-
rb_raise(rb_eRuntimeError,
|
546
|
+
rb_raise(rb_eRuntimeError,
|
547
|
+
"Iodine::Mustache internal error or unexpected data structure.");
|
548
|
+
break;
|
549
|
+
case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
|
550
|
+
rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
|
551
|
+
|
552
|
+
break;
|
553
|
+
case MUSTACHE_ERR_DELIMITER_TOO_LONG:
|
554
|
+
rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
|
555
|
+
|
556
|
+
break;
|
557
|
+
case MUSTACHE_ERR_NAME_TOO_LONG:
|
558
|
+
rb_raise(rb_eRuntimeError,
|
559
|
+
"Iodine::Mustache section name in template is too long.");
|
560
|
+
|
561
|
+
break;
|
562
|
+
default:
|
480
563
|
break;
|
481
564
|
}
|
482
565
|
return Qnil;
|