xref: /unit/src/ruby/nxt_ruby_stream_io.c (revision 1870)
1584Salexander.borisov@nginx.com 
2584Salexander.borisov@nginx.com /*
3584Salexander.borisov@nginx.com  * Copyright (C) Alexander Borisov
4584Salexander.borisov@nginx.com  * Copyright (C) NGINX, Inc.
5584Salexander.borisov@nginx.com  */
6584Salexander.borisov@nginx.com 
7584Salexander.borisov@nginx.com #include <ruby/nxt_ruby.h>
8743Smax.romanov@nginx.com #include <nxt_unit.h>
9584Salexander.borisov@nginx.com 
10584Salexander.borisov@nginx.com 
111687Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_new(VALUE class, VALUE arg);
12584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self);
131337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_gets(VALUE obj);
141337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_each(VALUE obj);
15584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_read(VALUE obj, VALUE args);
161337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_rewind(VALUE obj);
17584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_puts(VALUE obj, VALUE args);
18584Salexander.borisov@nginx.com static VALUE nxt_ruby_stream_io_write(VALUE obj, VALUE args);
191687Smax.romanov@nginx.com nxt_inline long nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val);
201337Smax.romanov@nginx.com static VALUE nxt_ruby_stream_io_flush(VALUE obj);
21584Salexander.borisov@nginx.com 
22584Salexander.borisov@nginx.com 
23584Salexander.borisov@nginx.com VALUE
24584Salexander.borisov@nginx.com nxt_ruby_stream_io_input_init(void)
25584Salexander.borisov@nginx.com {
26584Salexander.borisov@nginx.com     VALUE  stream_io;
27584Salexander.borisov@nginx.com 
28*1870So.canty@f5.com     stream_io = rb_define_class("NGINX_Unit_Stream_IO_Read", rb_cObject);
29*1870So.canty@f5.com 
30*1870So.canty@f5.com     rb_undef_alloc_func(stream_io);
31584Salexander.borisov@nginx.com 
32584Salexander.borisov@nginx.com     rb_gc_register_address(&stream_io);
33584Salexander.borisov@nginx.com 
34584Salexander.borisov@nginx.com     rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1);
351235Sigor@sysoev.ru     rb_define_method(stream_io, "initialize",
361235Sigor@sysoev.ru                      nxt_ruby_stream_io_initialize, -1);
37584Salexander.borisov@nginx.com     rb_define_method(stream_io, "gets", nxt_ruby_stream_io_gets, 0);
38584Salexander.borisov@nginx.com     rb_define_method(stream_io, "each", nxt_ruby_stream_io_each, 0);
39584Salexander.borisov@nginx.com     rb_define_method(stream_io, "read", nxt_ruby_stream_io_read, -2);
40584Salexander.borisov@nginx.com     rb_define_method(stream_io, "rewind", nxt_ruby_stream_io_rewind, 0);
41584Salexander.borisov@nginx.com 
42584Salexander.borisov@nginx.com     return stream_io;
43584Salexander.borisov@nginx.com }
44584Salexander.borisov@nginx.com 
45584Salexander.borisov@nginx.com 
46584Salexander.borisov@nginx.com VALUE
47584Salexander.borisov@nginx.com nxt_ruby_stream_io_error_init(void)
48584Salexander.borisov@nginx.com {
49584Salexander.borisov@nginx.com     VALUE  stream_io;
50584Salexander.borisov@nginx.com 
51*1870So.canty@f5.com     stream_io = rb_define_class("NGINX_Unit_Stream_IO_Error", rb_cObject);
52*1870So.canty@f5.com 
53*1870So.canty@f5.com     rb_undef_alloc_func(stream_io);
54584Salexander.borisov@nginx.com 
55584Salexander.borisov@nginx.com     rb_gc_register_address(&stream_io);
56584Salexander.borisov@nginx.com 
57584Salexander.borisov@nginx.com     rb_define_singleton_method(stream_io, "new", nxt_ruby_stream_io_new, 1);
581235Sigor@sysoev.ru     rb_define_method(stream_io, "initialize",
591235Sigor@sysoev.ru                      nxt_ruby_stream_io_initialize, -1);
60584Salexander.borisov@nginx.com     rb_define_method(stream_io, "puts", nxt_ruby_stream_io_puts, -2);
61584Salexander.borisov@nginx.com     rb_define_method(stream_io, "write", nxt_ruby_stream_io_write, -2);
62584Salexander.borisov@nginx.com     rb_define_method(stream_io, "flush", nxt_ruby_stream_io_flush, 0);
63584Salexander.borisov@nginx.com 
64584Salexander.borisov@nginx.com     return stream_io;
65584Salexander.borisov@nginx.com }
66584Salexander.borisov@nginx.com 
67584Salexander.borisov@nginx.com 
68584Salexander.borisov@nginx.com static VALUE
691687Smax.romanov@nginx.com nxt_ruby_stream_io_new(VALUE class, VALUE arg)
70584Salexander.borisov@nginx.com {
711687Smax.romanov@nginx.com     VALUE  self;
72584Salexander.borisov@nginx.com 
731687Smax.romanov@nginx.com     self = Data_Wrap_Struct(class, 0, 0, (void *) (uintptr_t) arg);
74584Salexander.borisov@nginx.com 
75584Salexander.borisov@nginx.com     rb_obj_call_init(self, 0, NULL);
76584Salexander.borisov@nginx.com 
77584Salexander.borisov@nginx.com     return self;
78584Salexander.borisov@nginx.com }
79584Salexander.borisov@nginx.com 
80584Salexander.borisov@nginx.com 
81584Salexander.borisov@nginx.com static VALUE
82584Salexander.borisov@nginx.com nxt_ruby_stream_io_initialize(int argc, VALUE *argv, VALUE self)
83584Salexander.borisov@nginx.com {
84584Salexander.borisov@nginx.com     return self;
85584Salexander.borisov@nginx.com }
86584Salexander.borisov@nginx.com 
87584Salexander.borisov@nginx.com 
88584Salexander.borisov@nginx.com static VALUE
891337Smax.romanov@nginx.com nxt_ruby_stream_io_gets(VALUE obj)
90584Salexander.borisov@nginx.com {
91743Smax.romanov@nginx.com     VALUE                    buf;
921398Smax.romanov@nginx.com     ssize_t                  res;
931687Smax.romanov@nginx.com     nxt_ruby_ctx_t           *rctx;
94743Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
95584Salexander.borisov@nginx.com 
961687Smax.romanov@nginx.com     Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx);
971687Smax.romanov@nginx.com     req = rctx->req;
98743Smax.romanov@nginx.com 
99743Smax.romanov@nginx.com     if (req->content_length == 0) {
100584Salexander.borisov@nginx.com         return Qnil;
101584Salexander.borisov@nginx.com     }
102584Salexander.borisov@nginx.com 
1031398Smax.romanov@nginx.com     res = nxt_unit_request_readline_size(req, SSIZE_MAX);
1041398Smax.romanov@nginx.com     if (nxt_slow_path(res < 0)) {
105584Salexander.borisov@nginx.com         return Qnil;
106584Salexander.borisov@nginx.com     }
107584Salexander.borisov@nginx.com 
1081398Smax.romanov@nginx.com     buf = rb_str_buf_new(res);
109743Smax.romanov@nginx.com 
1101398Smax.romanov@nginx.com     if (nxt_slow_path(buf == Qnil)) {
1111398Smax.romanov@nginx.com         return Qnil;
1121398Smax.romanov@nginx.com     }
1131398Smax.romanov@nginx.com 
1141398Smax.romanov@nginx.com     res = nxt_unit_request_read(req, RSTRING_PTR(buf), res);
1151398Smax.romanov@nginx.com 
1161398Smax.romanov@nginx.com     rb_str_set_len(buf, res);
117584Salexander.borisov@nginx.com 
118584Salexander.borisov@nginx.com     return buf;
119584Salexander.borisov@nginx.com }
120584Salexander.borisov@nginx.com 
121584Salexander.borisov@nginx.com 
122584Salexander.borisov@nginx.com static VALUE
1231337Smax.romanov@nginx.com nxt_ruby_stream_io_each(VALUE obj)
124584Salexander.borisov@nginx.com {
125584Salexander.borisov@nginx.com     VALUE  chunk;
126584Salexander.borisov@nginx.com 
127584Salexander.borisov@nginx.com     if (rb_block_given_p() == 0) {
128584Salexander.borisov@nginx.com         rb_raise(rb_eArgError, "Expected block on rack.input 'each' method");
129584Salexander.borisov@nginx.com     }
130584Salexander.borisov@nginx.com 
131584Salexander.borisov@nginx.com     for ( ;; ) {
1321337Smax.romanov@nginx.com         chunk = nxt_ruby_stream_io_gets(obj);
133584Salexander.borisov@nginx.com 
134584Salexander.borisov@nginx.com         if (chunk == Qnil) {
135584Salexander.borisov@nginx.com             return Qnil;
136584Salexander.borisov@nginx.com         }
137584Salexander.borisov@nginx.com 
138584Salexander.borisov@nginx.com         rb_yield(chunk);
139584Salexander.borisov@nginx.com     }
140584Salexander.borisov@nginx.com 
141584Salexander.borisov@nginx.com     return Qnil;
142584Salexander.borisov@nginx.com }
143584Salexander.borisov@nginx.com 
144584Salexander.borisov@nginx.com 
145584Salexander.borisov@nginx.com static VALUE
146584Salexander.borisov@nginx.com nxt_ruby_stream_io_read(VALUE obj, VALUE args)
147584Salexander.borisov@nginx.com {
1481687Smax.romanov@nginx.com     VALUE           buf;
1491687Smax.romanov@nginx.com     long            copy_size, u_size;
1501687Smax.romanov@nginx.com     nxt_ruby_ctx_t  *rctx;
151584Salexander.borisov@nginx.com 
1521687Smax.romanov@nginx.com     Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx);
153584Salexander.borisov@nginx.com 
1541687Smax.romanov@nginx.com     copy_size = rctx->req->content_length;
155584Salexander.borisov@nginx.com 
156584Salexander.borisov@nginx.com     if (RARRAY_LEN(args) > 0 && TYPE(RARRAY_PTR(args)[0]) == T_FIXNUM) {
157584Salexander.borisov@nginx.com         u_size = NUM2LONG(RARRAY_PTR(args)[0]);
158584Salexander.borisov@nginx.com 
159584Salexander.borisov@nginx.com         if (u_size < 0 || copy_size == 0) {
160584Salexander.borisov@nginx.com             return Qnil;
161584Salexander.borisov@nginx.com         }
162584Salexander.borisov@nginx.com 
163584Salexander.borisov@nginx.com         if (copy_size > u_size) {
164584Salexander.borisov@nginx.com             copy_size = u_size;
165584Salexander.borisov@nginx.com         }
166584Salexander.borisov@nginx.com     }
167584Salexander.borisov@nginx.com 
168584Salexander.borisov@nginx.com     if (copy_size == 0) {
169584Salexander.borisov@nginx.com         return rb_str_new_cstr("");
170584Salexander.borisov@nginx.com     }
171584Salexander.borisov@nginx.com 
172584Salexander.borisov@nginx.com     buf = rb_str_buf_new(copy_size);
173584Salexander.borisov@nginx.com 
174584Salexander.borisov@nginx.com     if (nxt_slow_path(buf == Qnil)) {
175584Salexander.borisov@nginx.com         return Qnil;
176584Salexander.borisov@nginx.com     }
177584Salexander.borisov@nginx.com 
1781687Smax.romanov@nginx.com     copy_size = nxt_unit_request_read(rctx->req, RSTRING_PTR(buf), copy_size);
179584Salexander.borisov@nginx.com 
180584Salexander.borisov@nginx.com     if (RARRAY_LEN(args) > 1 && TYPE(RARRAY_PTR(args)[1]) == T_STRING) {
181584Salexander.borisov@nginx.com 
182584Salexander.borisov@nginx.com         rb_str_set_len(RARRAY_PTR(args)[1], 0);
183584Salexander.borisov@nginx.com         rb_str_cat(RARRAY_PTR(args)[1], RSTRING_PTR(buf), copy_size);
184584Salexander.borisov@nginx.com     }
185584Salexander.borisov@nginx.com 
186743Smax.romanov@nginx.com     rb_str_set_len(buf, copy_size);
187584Salexander.borisov@nginx.com 
188584Salexander.borisov@nginx.com     return buf;
189584Salexander.borisov@nginx.com }
190584Salexander.borisov@nginx.com 
191584Salexander.borisov@nginx.com 
192584Salexander.borisov@nginx.com static VALUE
1931337Smax.romanov@nginx.com nxt_ruby_stream_io_rewind(VALUE obj)
194584Salexander.borisov@nginx.com {
195584Salexander.borisov@nginx.com     return Qnil;
196584Salexander.borisov@nginx.com }
197584Salexander.borisov@nginx.com 
198584Salexander.borisov@nginx.com 
199584Salexander.borisov@nginx.com static VALUE
200584Salexander.borisov@nginx.com nxt_ruby_stream_io_puts(VALUE obj, VALUE args)
201584Salexander.borisov@nginx.com {
2021687Smax.romanov@nginx.com     nxt_ruby_ctx_t  *rctx;
203584Salexander.borisov@nginx.com 
204584Salexander.borisov@nginx.com     if (RARRAY_LEN(args) != 1) {
205584Salexander.borisov@nginx.com         return Qnil;
206584Salexander.borisov@nginx.com     }
207584Salexander.borisov@nginx.com 
2081687Smax.romanov@nginx.com     Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx);
209584Salexander.borisov@nginx.com 
2101687Smax.romanov@nginx.com     nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]);
211584Salexander.borisov@nginx.com 
212584Salexander.borisov@nginx.com     return Qnil;
213584Salexander.borisov@nginx.com }
214584Salexander.borisov@nginx.com 
215584Salexander.borisov@nginx.com 
216584Salexander.borisov@nginx.com static VALUE
217584Salexander.borisov@nginx.com nxt_ruby_stream_io_write(VALUE obj, VALUE args)
218584Salexander.borisov@nginx.com {
2191687Smax.romanov@nginx.com     long            len;
2201687Smax.romanov@nginx.com     nxt_ruby_ctx_t  *rctx;
221584Salexander.borisov@nginx.com 
222584Salexander.borisov@nginx.com     if (RARRAY_LEN(args) != 1) {
223584Salexander.borisov@nginx.com         return Qnil;
224584Salexander.borisov@nginx.com     }
225584Salexander.borisov@nginx.com 
2261687Smax.romanov@nginx.com     Data_Get_Struct(obj, nxt_ruby_ctx_t, rctx);
227584Salexander.borisov@nginx.com 
2281687Smax.romanov@nginx.com     len = nxt_ruby_stream_io_s_write(rctx, RARRAY_PTR(args)[0]);
229584Salexander.borisov@nginx.com 
230584Salexander.borisov@nginx.com     return LONG2FIX(len);
231584Salexander.borisov@nginx.com }
232584Salexander.borisov@nginx.com 
233584Salexander.borisov@nginx.com 
234584Salexander.borisov@nginx.com nxt_inline long
2351687Smax.romanov@nginx.com nxt_ruby_stream_io_s_write(nxt_ruby_ctx_t *rctx, VALUE val)
236584Salexander.borisov@nginx.com {
237584Salexander.borisov@nginx.com     if (nxt_slow_path(val == Qnil)) {
238584Salexander.borisov@nginx.com         return 0;
239584Salexander.borisov@nginx.com     }
240584Salexander.borisov@nginx.com 
241584Salexander.borisov@nginx.com     if (TYPE(val) != T_STRING) {
242584Salexander.borisov@nginx.com         val = rb_funcall(val, rb_intern("to_s"), 0);
243584Salexander.borisov@nginx.com 
244584Salexander.borisov@nginx.com         if (TYPE(val) != T_STRING) {
245584Salexander.borisov@nginx.com             return 0;
246584Salexander.borisov@nginx.com         }
247584Salexander.borisov@nginx.com     }
248584Salexander.borisov@nginx.com 
2491687Smax.romanov@nginx.com     nxt_unit_req_error(rctx->req, "Ruby: %s", RSTRING_PTR(val));
250584Salexander.borisov@nginx.com 
251584Salexander.borisov@nginx.com     return RSTRING_LEN(val);
252584Salexander.borisov@nginx.com }
253584Salexander.borisov@nginx.com 
254584Salexander.borisov@nginx.com 
255584Salexander.borisov@nginx.com static VALUE
2561337Smax.romanov@nginx.com nxt_ruby_stream_io_flush(VALUE obj)
257584Salexander.borisov@nginx.com {
258584Salexander.borisov@nginx.com     return Qnil;
259584Salexander.borisov@nginx.com }
260