nyara 0.0.1.pre.9 → 0.1.pre.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/bin/nyara +3 -3
- data/changes +1 -0
- data/ext/event.c +16 -22
- data/ext/hashes.c +222 -4
- data/ext/inc/rdtsc.h +56 -0
- data/ext/inc/status_codes.inc +64 -0
- data/ext/inc/version.inc +1 -1
- data/ext/nyara.c +12 -10
- data/ext/nyara.h +5 -5
- data/ext/request.c +18 -24
- data/ext/request_parse.c +1 -1
- data/ext/route.cc +2 -4
- data/ext/url_encoded.c +51 -193
- data/lib/nyara/command.rb +39 -12
- data/lib/nyara/config.rb +10 -10
- data/lib/nyara/controller.rb +60 -14
- data/lib/nyara/cookie.rb +1 -1
- data/lib/nyara/hashes/config_hash.rb +2 -24
- data/lib/nyara/nyara.rb +33 -19
- data/lib/nyara/part.rb +7 -3
- data/lib/nyara/reload.rb +85 -0
- data/lib/nyara/request.rb +1 -1
- data/lib/nyara/route.rb +55 -19
- data/lib/nyara/templates/Gemfile +10 -1
- data/lib/nyara/templates/Rakefile +6 -1
- data/lib/nyara/templates/app/controllers/application_controller.rb +3 -0
- data/lib/nyara/templates/app/controllers/welcome_controller.rb +5 -0
- data/lib/nyara/templates/app/views/layouts/application.erb +12 -0
- data/lib/nyara/templates/app/views/welcome/index.erb +1 -0
- data/lib/nyara/templates/config/application.rb +34 -0
- data/lib/nyara/templates/config/boot.rb +4 -0
- data/lib/nyara/templates/config/development.rb +5 -0
- data/lib/nyara/templates/config/production.rb +8 -0
- data/lib/nyara/templates/config/test.rb +2 -0
- data/lib/nyara/templates/public/css/app.css +1 -0
- data/lib/nyara/templates/public/js/app.js +1 -0
- data/lib/nyara/templates/spec/spec_helper.rb +9 -0
- data/lib/nyara/test.rb +10 -2
- data/lib/nyara/view.rb +116 -67
- data/nyara.gemspec +3 -1
- data/rakefile +1 -1
- data/readme.md +1 -1
- data/spec/command_spec.rb +28 -24
- data/spec/config_spec.rb +24 -1
- data/spec/dummy/app/controllers/dummy_controller.rb +2 -0
- data/spec/dummy/app/models/dmmy_model.rb +2 -0
- data/spec/evented_io_spec.rb +2 -1
- data/spec/ext_route_spec.rb +2 -2
- data/spec/flash_spec.rb +8 -0
- data/spec/hashes_spec.rb +127 -0
- data/spec/integration_spec.rb +15 -0
- data/spec/path_helper_spec.rb +17 -5
- data/spec/performance/escape.rb +15 -4
- data/spec/performance/layout_render.rb +15 -10
- data/spec/performance/parse_accept_value.rb +24 -8
- data/spec/performance/parse_param.rb +14 -8
- data/spec/performance/performance_helper.rb +8 -21
- data/spec/performance_spec.rb +5 -4
- data/spec/route_spec.rb +7 -2
- data/spec/url_encoded_spec.rb +18 -74
- data/spec/view_spec.rb +1 -3
- data/spec/views/_partial.slim +1 -0
- data/spec/views/_partial_with_yield.erb +1 -0
- metadata +73 -43
- data/example/factorial.rb +0 -19
- data/example/hello.rb +0 -5
- data/example/project.rb +0 -11
- data/example/stream.rb +0 -14
- data/lib/nyara/controllers/public_controller.rb +0 -14
- data/lib/nyara/templates/config/session.key +0 -1
- data/tools/bench-cookie.rb +0 -22
- data/tools/foo.rb +0 -9
- data/tools/hello.rb +0 -46
- data/tools/memcheck.rb +0 -33
- data/tools/s.rb +0 -11
data/ext/inc/version.inc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
#define NYARA_VERSION "0.0
|
1
|
+
#define NYARA_VERSION "0.1.pre.0"
|
data/ext/nyara.c
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
#include <sys/socket.h>
|
6
6
|
#include <sys/resource.h>
|
7
7
|
#include <sys/fcntl.h>
|
8
|
+
#include "inc/rdtsc.h"
|
8
9
|
|
9
10
|
rb_encoding* u8_encoding;
|
10
11
|
static VALUE nyara;
|
@@ -31,17 +32,16 @@ static void set_fd_limit(int nofiles) {
|
|
31
32
|
}
|
32
33
|
}
|
33
34
|
|
34
|
-
static
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
static unsigned long long last_rdtsc = 0;
|
36
|
+
|
37
|
+
static VALUE ext_rdtsc_start(VALUE _) {
|
38
|
+
last_rdtsc = rdtsc();
|
39
|
+
return Qnil;
|
39
40
|
}
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
return toggle;
|
42
|
+
static VALUE ext_rdtsc(VALUE _) {
|
43
|
+
unsigned long long diff = rdtsc() - last_rdtsc;
|
44
|
+
return ULL2NUM(diff);
|
45
45
|
}
|
46
46
|
|
47
47
|
void Init_nyara() {
|
@@ -80,7 +80,9 @@ void Init_nyara() {
|
|
80
80
|
OBJ_FREEZE(status_map);
|
81
81
|
|
82
82
|
VALUE ext = rb_define_module_under(nyara, "Ext");
|
83
|
-
rb_define_singleton_method(ext, "
|
83
|
+
rb_define_singleton_method(ext, "rdtsc_start", ext_rdtsc_start, 0);
|
84
|
+
rb_define_singleton_method(ext, "rdtsc", ext_rdtsc, 0);
|
85
|
+
|
84
86
|
Init_accept(ext);
|
85
87
|
Init_mime(ext);
|
86
88
|
Init_request(nyara, ext);
|
data/ext/nyara.h
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
printf("%s: %.*s\n", __func__, (int)RSTRING_LEN(_xx), RSTRING_PTR(_xx));\
|
15
15
|
} while(0)
|
16
16
|
|
17
|
+
|
17
18
|
/* event.c */
|
18
19
|
void Init_event(VALUE ext);
|
19
20
|
void nyara_detach_rid(VALUE rid);
|
@@ -25,7 +26,6 @@ void Init_request_parse(VALUE nyara, VALUE ext);
|
|
25
26
|
|
26
27
|
/* request.c */
|
27
28
|
void Init_request(VALUE nyara, VALUE ext);
|
28
|
-
void nyara_request_init_env(VALUE request);
|
29
29
|
void nyara_request_term_close(VALUE request);
|
30
30
|
bool nyara_send_data(int fd, const char* s, long len);
|
31
31
|
|
@@ -37,8 +37,7 @@ void Init_test_response(VALUE nyara);
|
|
37
37
|
/* url_encoded.c */
|
38
38
|
void Init_url_encoded(VALUE ext);
|
39
39
|
long nyara_parse_path(VALUE path, const char*s, long len);
|
40
|
-
void
|
41
|
-
VALUE ext_parse_cookie(VALUE self, VALUE output, VALUE str);
|
40
|
+
void nyara_decode_uri_kv(volatile VALUE key, volatile VALUE value, const char* kv_s, long kv_len);
|
42
41
|
|
43
42
|
|
44
43
|
/* accept.c */
|
@@ -53,11 +52,13 @@ VALUE ext_mime_match(VALUE _, VALUE request_accept, VALUE accept_mimes);
|
|
53
52
|
|
54
53
|
/* hashes.c */
|
55
54
|
void Init_hashes(VALUE nyara);
|
55
|
+
void nyara_parse_query(VALUE output, const char* s, long len);
|
56
|
+
|
56
57
|
|
57
58
|
// "ab-cd" => "Ab-Cd"
|
58
59
|
// note str must be string created by nyara code
|
59
60
|
void nyara_headerlize(VALUE str);
|
60
|
-
int nyara_rb_hash_has_key(VALUE hash, VALUE key);
|
61
|
+
// int nyara_rb_hash_has_key(VALUE hash, VALUE key);
|
61
62
|
|
62
63
|
extern VALUE nyara_param_hash_class;
|
63
64
|
extern VALUE nyara_header_hash_class;
|
@@ -78,5 +79,4 @@ extern RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath,
|
|
78
79
|
|
79
80
|
/* nyara.c */
|
80
81
|
void nyara_set_nonblock(int fd);
|
81
|
-
void nyara_summary_request(int method, VALUE path, VALUE controller);
|
82
82
|
extern rb_encoding* u8_encoding;
|
data/ext/request.c
CHANGED
@@ -109,30 +109,6 @@ Request* nyara_request_new(int fd) {
|
|
109
109
|
return p;
|
110
110
|
}
|
111
111
|
|
112
|
-
void nyara_request_init_env(VALUE self) {
|
113
|
-
static VALUE session_mod = Qnil;
|
114
|
-
static VALUE flash_class = Qnil;
|
115
|
-
static VALUE str_cookie = Qnil;
|
116
|
-
static ID id_decode = 0;
|
117
|
-
if (session_mod == Qnil) {
|
118
|
-
VALUE nyara = rb_const_get(rb_cModule, rb_intern("Nyara"));
|
119
|
-
session_mod = rb_const_get(nyara, rb_intern("Session"));
|
120
|
-
flash_class = rb_const_get(nyara, rb_intern("Flash"));
|
121
|
-
str_cookie = rb_enc_str_new("Cookie", strlen("Cookie"), u8_encoding);
|
122
|
-
rb_gc_register_mark_object(str_cookie);
|
123
|
-
id_decode = rb_intern("decode");
|
124
|
-
}
|
125
|
-
|
126
|
-
P;
|
127
|
-
p->cookie = rb_class_new_instance(0, NULL, nyara_param_hash_class);
|
128
|
-
VALUE cookie = rb_hash_aref(p->header, str_cookie);
|
129
|
-
if (cookie != Qnil) {
|
130
|
-
ext_parse_cookie(Qnil, p->cookie, cookie);
|
131
|
-
}
|
132
|
-
p->session = rb_funcall(session_mod, id_decode, 1, p->cookie);
|
133
|
-
p->flash = rb_class_new_instance(1, &p->session, flash_class);
|
134
|
-
}
|
135
|
-
|
136
112
|
void nyara_request_term_close(VALUE self) {
|
137
113
|
P;
|
138
114
|
VALUE transfer_enc = rb_hash_aref(p->response_header, str_transfer_encoding);
|
@@ -202,11 +178,27 @@ static VALUE request_session(VALUE self) {
|
|
202
178
|
return p->session;
|
203
179
|
}
|
204
180
|
|
181
|
+
static VALUE request_session_eq(VALUE self, VALUE session) {
|
182
|
+
P;
|
183
|
+
if (p->session != Qnil) {
|
184
|
+
rb_raise(rb_eRuntimeError, "request.session already initialized");
|
185
|
+
}
|
186
|
+
return p->session = session;
|
187
|
+
}
|
188
|
+
|
205
189
|
static VALUE request_flash(VALUE self) {
|
206
190
|
P;
|
207
191
|
return p->flash;
|
208
192
|
}
|
209
193
|
|
194
|
+
static VALUE request_flash_eq(VALUE self, VALUE flash) {
|
195
|
+
P;
|
196
|
+
if (p->flash != Qnil) {
|
197
|
+
rb_raise(rb_eRuntimeError, "request.flash already initialized");
|
198
|
+
}
|
199
|
+
return p->flash = flash;
|
200
|
+
}
|
201
|
+
|
210
202
|
static VALUE request_body(VALUE self) {
|
211
203
|
P;
|
212
204
|
while (p->parse_state != PS_MESSAGE_COMPLETE) {
|
@@ -388,7 +380,9 @@ void Init_request(VALUE nyara, VALUE ext) {
|
|
388
380
|
rb_define_method(request_class, "format", request_format, 0);
|
389
381
|
rb_define_method(request_class, "cookie", request_cookie, 0);
|
390
382
|
rb_define_method(request_class, "session", request_session, 0);
|
383
|
+
rb_define_method(request_class, "session=", request_session_eq, 1);
|
391
384
|
rb_define_method(request_class, "flash", request_flash, 0);
|
385
|
+
rb_define_method(request_class, "flash=", request_flash_eq, 1);
|
392
386
|
rb_define_method(request_class, "body", request_body, 0);
|
393
387
|
rb_define_method(request_class, "message_complete?", request_message_complete_p, 0);
|
394
388
|
|
data/ext/request_parse.c
CHANGED
@@ -138,7 +138,7 @@ static void _parse_path_and_query(Request* p) {
|
|
138
138
|
long len = RSTRING_LEN(p->path_with_query);
|
139
139
|
long query_i = nyara_parse_path(p->path, s, len);
|
140
140
|
if (query_i < len) {
|
141
|
-
|
141
|
+
nyara_parse_query(p->query, s + query_i, len - query_i);
|
142
142
|
|
143
143
|
// do method override with _method=xxx in query
|
144
144
|
if (p->method == HTTP_POST) {
|
data/ext/route.cc
CHANGED
@@ -187,8 +187,7 @@ static VALUE ext_list_route(VALUE self) {
|
|
187
187
|
return route_hash;
|
188
188
|
}
|
189
189
|
|
190
|
-
static VALUE build_args(const char* suffix, std::vector<ID>& conv) {
|
191
|
-
volatile VALUE args = rb_ary_new();
|
190
|
+
static VALUE build_args(const char* suffix, std::vector<ID>& conv, volatile VALUE args) {
|
192
191
|
volatile VALUE str = rb_str_new2(""); // tmp for conversion, no need encoding
|
193
192
|
long last_len = 0;
|
194
193
|
for (size_t j = 0; j < conv.size(); j++) {
|
@@ -271,8 +270,7 @@ RouteResult nyara_lookup_route(enum http_method method_num, VALUE vpath, VALUE a
|
|
271
270
|
break;
|
272
271
|
}
|
273
272
|
}
|
274
|
-
r.args = build_args(suffix, i->conv);
|
275
|
-
rb_ary_push(r.args, i->id);
|
273
|
+
r.args = build_args(suffix, i->conv, rb_ary_new3(1, i->id));
|
276
274
|
r.controller = i->controller;
|
277
275
|
break;
|
278
276
|
}
|
data/ext/url_encoded.c
CHANGED
@@ -74,6 +74,8 @@ static long _decode_url_seg(VALUE output, const char*s, long len, char stop_char
|
|
74
74
|
// NOTE it's similar to _decode_url_seg, but:
|
75
75
|
// - "+" is not escaped
|
76
76
|
// - matrix uri params (segments starting with ";") are ignored
|
77
|
+
//
|
78
|
+
// returns parsed length, including matrix uri params
|
77
79
|
long nyara_parse_path(VALUE output, const char* s, long len) {
|
78
80
|
const char* last_s = s;
|
79
81
|
long last_len = 0;
|
@@ -133,75 +135,6 @@ long nyara_parse_path(VALUE output, const char* s, long len) {
|
|
133
135
|
return i;
|
134
136
|
}
|
135
137
|
|
136
|
-
static VALUE ext_parse_path(VALUE self, VALUE output, VALUE input) {
|
137
|
-
long parsed = nyara_parse_path(output, RSTRING_PTR(input), RSTRING_LEN(input));
|
138
|
-
return ULONG2NUM(parsed);
|
139
|
-
}
|
140
|
-
|
141
|
-
static void _error(const char* msg, const char* s, long len, long segment_i) {
|
142
|
-
if (s) {
|
143
|
-
rb_raise(rb_eRuntimeError,
|
144
|
-
"error parsing \"%.*s\": segments[%ld] is %s",
|
145
|
-
(int)len, s, segment_i, msg);
|
146
|
-
} else {
|
147
|
-
rb_raise(rb_eRuntimeError, "%s", msg);
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
static VALUE _new_child(long hash) {
|
152
|
-
return hash ? rb_class_new_instance(0, NULL, nyara_param_hash_class) : rb_ary_new();
|
153
|
-
}
|
154
|
-
|
155
|
-
// a, b, c = keys; h[a][b][c] = value
|
156
|
-
// the last 2 args are for error report
|
157
|
-
static void _aset_keys(VALUE output, volatile VALUE keys, VALUE value, const char* kv_s, long kv_len) {
|
158
|
-
VALUE* arr = RARRAY_PTR(keys);
|
159
|
-
long len = RARRAY_LEN(keys);
|
160
|
-
if (!len) {
|
161
|
-
rb_bug("bug: aset 0 length key");
|
162
|
-
return;
|
163
|
-
}
|
164
|
-
|
165
|
-
// first key seg
|
166
|
-
long is_hash_key = 1;
|
167
|
-
|
168
|
-
// middle key segs
|
169
|
-
for (long i = 0; i < len - 1; i++) {
|
170
|
-
long next_is_hash_key = RSTRING_LEN(arr[i + 1]);
|
171
|
-
if (is_hash_key) {
|
172
|
-
if (nyara_rb_hash_has_key(output, arr[i])) {
|
173
|
-
output = rb_hash_aref(output, arr[i]);
|
174
|
-
if (next_is_hash_key) {
|
175
|
-
if (TYPE(output) != T_HASH) {
|
176
|
-
// note: StringValueCStr requires VALUE* as param, and can raise another error if there's nul in the string
|
177
|
-
_error("not array index (expect to be empty)", kv_s, kv_len, i);
|
178
|
-
}
|
179
|
-
} else {
|
180
|
-
if (TYPE(output) != T_ARRAY) {
|
181
|
-
_error("not hash key (expect to be non-empty)", kv_s, kv_len, i);
|
182
|
-
}
|
183
|
-
}
|
184
|
-
} else {
|
185
|
-
volatile VALUE child = _new_child(next_is_hash_key);
|
186
|
-
rb_hash_aset(output, arr[i], child);
|
187
|
-
output = child;
|
188
|
-
}
|
189
|
-
} else {
|
190
|
-
volatile VALUE child = _new_child(next_is_hash_key);
|
191
|
-
rb_ary_push(output, child);
|
192
|
-
output = child;
|
193
|
-
}
|
194
|
-
is_hash_key = next_is_hash_key;
|
195
|
-
}
|
196
|
-
|
197
|
-
// terminate key seg: add value
|
198
|
-
if (is_hash_key) {
|
199
|
-
rb_hash_aset(output, arr[len - 1], value);
|
200
|
-
} else {
|
201
|
-
rb_ary_push(output, value);
|
202
|
-
}
|
203
|
-
}
|
204
|
-
|
205
138
|
static const char* _strnchr(const char* s, long len, char c) {
|
206
139
|
for (long i = 0; i < len; i++) {
|
207
140
|
if (s[i] == c) {
|
@@ -215,16 +148,16 @@ static inline VALUE _new_blank_str() {
|
|
215
148
|
return rb_enc_str_new("", 0, u8_encoding);
|
216
149
|
}
|
217
150
|
|
218
|
-
|
219
|
-
|
151
|
+
// key and value are for output
|
152
|
+
// usually should be blank string
|
153
|
+
// decode into key and value
|
154
|
+
void nyara_decode_uri_kv(volatile VALUE key, volatile VALUE value, const char* kv_s, long kv_len) {
|
220
155
|
const char* s = kv_s;
|
221
156
|
long len = kv_len;
|
222
157
|
if (!len) {
|
223
|
-
|
158
|
+
rb_raise(rb_eArgError, "empty key=value segment");
|
224
159
|
}
|
225
160
|
|
226
|
-
volatile VALUE value = _new_blank_str();
|
227
|
-
|
228
161
|
// rule out the value part
|
229
162
|
{
|
230
163
|
// strnstr is not available on linux :(
|
@@ -232,125 +165,34 @@ static void _url_encoded_seg(VALUE output, const char* kv_s, long kv_len, int ne
|
|
232
165
|
if (value_s) {
|
233
166
|
value_s++;
|
234
167
|
long value_len = s + len - value_s;
|
235
|
-
long
|
236
|
-
|
168
|
+
long skipped = 0;
|
169
|
+
for (;skipped < value_len; skipped++) {
|
170
|
+
if (!isspace(value_s[skipped])) {
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
long parsed = _decode_url_seg(value, value_s + skipped, value_len - skipped, '&');
|
175
|
+
if (parsed != value_len - skipped) {
|
237
176
|
rb_raise(rb_eArgError, "separator & in param segment");
|
238
177
|
}
|
239
178
|
len = value_s - s - 1;
|
240
179
|
}
|
241
180
|
// starts with '='
|
242
181
|
if (value_s == s) {
|
243
|
-
rb_hash_aset(output, _new_blank_str(), value);
|
244
182
|
return;
|
245
183
|
}
|
246
184
|
}
|
247
|
-
|
248
|
-
|
249
|
-
if (nested_mode) {
|
250
|
-
// todo fault-tolerant?
|
251
|
-
long parsed = _decode_url_seg(key, s, len, '[');
|
252
|
-
if (parsed == len) {
|
253
|
-
rb_hash_aset(output, key, value);
|
254
|
-
return;
|
255
|
-
}
|
256
|
-
s += parsed;
|
257
|
-
len -= parsed;
|
258
|
-
volatile VALUE keys = rb_ary_new3(1, key);
|
259
|
-
while (len) {
|
260
|
-
key = _new_blank_str();
|
261
|
-
parsed = _decode_url_seg(key, s, len, ']');
|
262
|
-
rb_ary_push(keys, key);
|
263
|
-
s += parsed;
|
264
|
-
len -= parsed;
|
265
|
-
if (len) {
|
266
|
-
if (s[0] == '[') {
|
267
|
-
s++;
|
268
|
-
len--;
|
269
|
-
} else {
|
270
|
-
rb_raise(rb_eRuntimeError, "malformed params: remaining chars in key but not starting with '['");
|
271
|
-
return;
|
272
|
-
}
|
273
|
-
}
|
274
|
-
}
|
275
|
-
_aset_keys(output, keys, value, kv_s, kv_len);
|
276
|
-
} else {
|
277
|
-
_decode_url_seg(key, s, len, '=');
|
278
|
-
rb_hash_aset(output, key, value);
|
279
|
-
}
|
280
|
-
|
281
|
-
return;
|
282
|
-
}
|
283
|
-
|
284
|
-
// "a[%20][][b]=c" ===> output["a", "\x20", nil, "b"] = "c"
|
285
|
-
static VALUE ext_parse_url_encoded_seg(VALUE self, VALUE output, VALUE kv, VALUE v_nested_mode) {
|
286
|
-
_url_encoded_seg(output, RSTRING_PTR(kv), RSTRING_LEN(kv), RTEST(v_nested_mode));
|
287
|
-
return output;
|
288
|
-
}
|
289
|
-
|
290
|
-
void nyara_parse_param(VALUE output, const char* s, long len) {
|
291
|
-
// split with /[&;] */
|
292
|
-
long last_i = 0;
|
293
|
-
long i = 0;
|
294
|
-
for (; i < len; i++) {
|
295
|
-
if (s[i] == '&' || s[i] == ';') {
|
296
|
-
if (i > last_i) {
|
297
|
-
_url_encoded_seg(output, s + last_i, i - last_i, 1);
|
298
|
-
}
|
299
|
-
while(i + 1 < len && s[i + 1] == ' ') {
|
300
|
-
i++;
|
301
|
-
}
|
302
|
-
last_i = i + 1;
|
303
|
-
}
|
304
|
-
}
|
305
|
-
if (i > last_i) {
|
306
|
-
_url_encoded_seg(output, s + last_i, i - last_i, 1);
|
185
|
+
while (len > 0 && isspace(s[len - 1])) {
|
186
|
+
len--;
|
307
187
|
}
|
188
|
+
_decode_url_seg(key, s, len, '=');
|
308
189
|
}
|
309
190
|
|
310
|
-
static VALUE
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
static VALUE _cookie_seg_str_new(const char* s, long len) {
|
316
|
-
// trim tailing space
|
317
|
-
for (; len > 0; len--) {
|
318
|
-
if (s[len - 1] != ' ') {
|
319
|
-
break;
|
320
|
-
}
|
321
|
-
}
|
322
|
-
return rb_enc_str_new(s, len, u8_encoding);
|
323
|
-
}
|
324
|
-
|
325
|
-
VALUE ext_parse_cookie(VALUE self, VALUE output, VALUE str) {
|
326
|
-
volatile VALUE arr = rb_ary_new();
|
327
|
-
const char* s = RSTRING_PTR(str);
|
328
|
-
long len = RSTRING_LEN(str);
|
329
|
-
|
330
|
-
// split with / *[,;] */
|
331
|
-
long last_i = 0;
|
332
|
-
long i = 0;
|
333
|
-
for (; i < len; i++) {
|
334
|
-
if (s[i] == ',' || s[i] == ';') {
|
335
|
-
// char* and len parse_seg
|
336
|
-
if (i > last_i) {
|
337
|
-
rb_ary_push(arr, _cookie_seg_str_new(s + last_i, i - last_i));
|
338
|
-
}
|
339
|
-
while(i + 1 < len && s[i + 1] == ' ') {
|
340
|
-
i++;
|
341
|
-
}
|
342
|
-
last_i = i + 1;
|
343
|
-
}
|
344
|
-
}
|
345
|
-
if (i > last_i) {
|
346
|
-
rb_ary_push(arr, _cookie_seg_str_new(s + last_i, i - last_i));
|
347
|
-
}
|
348
|
-
|
349
|
-
VALUE* arr_p = RARRAY_PTR(arr);
|
350
|
-
for (long j = RARRAY_LEN(arr) - 1; j >= 0; j--) {
|
351
|
-
_url_encoded_seg(output, RSTRING_PTR(arr_p[j]), RSTRING_LEN(arr_p[j]), 0);
|
352
|
-
}
|
353
|
-
return output;
|
191
|
+
static VALUE ext_decode_uri_kv(VALUE _, VALUE str) {
|
192
|
+
volatile VALUE k = _new_blank_str();
|
193
|
+
volatile VALUE v = _new_blank_str();
|
194
|
+
nyara_decode_uri_kv(k, v, RSTRING_PTR(str), RSTRING_LEN(str));
|
195
|
+
return rb_ary_new3(2, k, v);
|
354
196
|
}
|
355
197
|
|
356
198
|
static bool _should_escape(char c) {
|
@@ -391,7 +233,8 @@ static void _concat_char(VALUE s, char c, bool ispath) {
|
|
391
233
|
}
|
392
234
|
}
|
393
235
|
|
394
|
-
// escape for uri path ('/', '+' are not changed)
|
236
|
+
// escape for uri path ('/', '+' are not changed)
|
237
|
+
// or component ('/', '+' are changed)
|
395
238
|
static VALUE ext_escape(VALUE _, VALUE s, VALUE v_ispath) {
|
396
239
|
Check_Type(s, T_STRING);
|
397
240
|
long len = RSTRING_LEN(s);
|
@@ -405,20 +248,35 @@ static VALUE ext_escape(VALUE _, VALUE s, VALUE v_ispath) {
|
|
405
248
|
return res;
|
406
249
|
}
|
407
250
|
|
408
|
-
//
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
251
|
+
// caveats:
|
252
|
+
// - stops at '='
|
253
|
+
// - matrix uri params and query are ignored
|
254
|
+
static VALUE ext_unescape(VALUE _, volatile VALUE s, VALUE v_is_path) {
|
255
|
+
Check_Type(s, T_STRING);
|
256
|
+
if (RTEST(v_is_path)) {
|
257
|
+
volatile VALUE output = _new_blank_str();
|
258
|
+
if (nyara_parse_path(output, RSTRING_PTR(s), RSTRING_LEN(s))) {
|
259
|
+
}
|
260
|
+
return output;
|
261
|
+
} else {
|
262
|
+
volatile VALUE output = _new_blank_str();
|
263
|
+
_decode_url_seg(output, RSTRING_PTR(s), RSTRING_LEN(s), '=');
|
264
|
+
return output;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
// concats result into output<br>
|
269
|
+
// returns parsed length
|
270
|
+
static VALUE ext_parse_path(VALUE self, VALUE output, VALUE input) {
|
271
|
+
long parsed = nyara_parse_path(output, RSTRING_PTR(input), RSTRING_LEN(input));
|
272
|
+
return ULONG2NUM(parsed);
|
414
273
|
}
|
415
274
|
|
416
275
|
void Init_url_encoded(VALUE ext) {
|
417
|
-
rb_define_singleton_method(ext, "parse_param", ext_parse_param, 2);
|
418
|
-
rb_define_singleton_method(ext, "parse_cookie", ext_parse_cookie, 2);
|
419
276
|
rb_define_singleton_method(ext, "escape", ext_escape, 2);
|
420
|
-
rb_define_singleton_method(ext, "
|
421
|
-
|
422
|
-
|
277
|
+
rb_define_singleton_method(ext, "unescape", ext_unescape, 2);
|
278
|
+
|
279
|
+
// test only
|
280
|
+
rb_define_singleton_method(ext, "decode_uri_kv", ext_decode_uri_kv, 1);
|
423
281
|
rb_define_singleton_method(ext, "parse_path", ext_parse_path, 2);
|
424
282
|
}
|