summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c
new file mode 100644
index 00000000..a5f90b98
--- /dev/null
+++ b/web/server/h2o/libh2o/deps/mruby-input-stream/src/mruby_input_stream.c
@@ -0,0 +1,278 @@
+#include <string.h>
+#include "mruby.h"
+#include "mruby/value.h"
+#include "mruby/data.h"
+#include "mruby/string.h"
+#include "mruby_input_stream.h"
+
+typedef struct mrb_input_stream_t {
+ const char *base;
+ mrb_int len;
+ mrb_int pos;
+ mrb_input_stream_free_callback free_cb;
+ void *free_cb_data;
+} mrb_input_stream_t;
+
+static mrb_input_stream_t*
+mrb_input_stream_create(mrb_state *mrb, const char *base, mrb_int len, mrb_input_stream_free_callback cb, void *cb_data);
+
+static void
+mrb_mruby_input_stream_free(mrb_state *mrb, void *ptr);
+
+static mrb_int
+seek_char(mrb_input_stream_t *stream, const char chr);
+
+const static struct mrb_data_type mrb_input_stream_type = {
+ "InputStream",
+ mrb_mruby_input_stream_free,
+};
+
+static void
+assert_is_open(mrb_state *mrb, mrb_input_stream_t *stream)
+{
+ if (stream->len < 0) {
+ struct RClass *klass = mrb_class_get(mrb, "IOError");
+ if (klass == NULL)
+ klass = E_RUNTIME_ERROR;
+ mrb_raise(mrb, klass, "stream closed");
+ }
+}
+
+static mrb_value
+mrb_input_stream_init(mrb_state *mrb, mrb_value self)
+{
+ mrb_value str;
+ mrb_int len;
+ char *ptr;
+ mrb_input_stream_t *stream;
+ mrb_int n = mrb_get_args(mrb, "|S", &str);
+ if (n > 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(n));
+ }
+
+ if (n == 1) {
+ len = RSTRING_LEN(str);
+ ptr = RSTRING_PTR(str);
+ stream = mrb_input_stream_create(mrb, ptr, len, NULL, NULL);
+ } else {
+ stream = mrb_input_stream_create(mrb, NULL, 0, NULL, NULL);
+ }
+
+ DATA_TYPE(self) = &mrb_input_stream_type;
+ DATA_PTR(self) = stream;
+ return self;
+}
+
+static void
+default_free_cb(mrb_state *mrb, const char *base, mrb_int len, void *cb_data)
+{
+ if (base != NULL)
+ mrb_free(mrb, (void *)base);
+}
+
+static void
+mrb_mruby_input_stream_free(mrb_state *mrb, void *ptr)
+{
+ mrb_input_stream_t *stream = (mrb_input_stream_t *)ptr;
+ if (stream->free_cb != NULL)
+ stream->free_cb(mrb, stream->base, stream->len, stream->free_cb_data);
+ mrb_free(mrb, stream);
+}
+
+static void setup_stream(mrb_state *mrb, mrb_input_stream_t *stream, const char *base, mrb_int len, mrb_int pos, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ if (free_cb == NULL) {
+ if (len > 0) {
+ char *dst_base = (char *)mrb_malloc(mrb, sizeof(char)*len);
+ memcpy(dst_base, base, len);
+ stream->base = dst_base;
+ stream->len = len;
+ } else {
+ stream->base = NULL;
+ stream->len = len;
+ }
+ stream->free_cb = default_free_cb;
+ stream->free_cb_data = NULL;
+ } else {
+ stream->base = base;
+ stream->len = len;
+ stream->free_cb = free_cb;
+ stream->free_cb_data = free_cb_data;
+ }
+
+ stream->pos = pos;
+}
+
+mrb_input_stream_t*
+mrb_input_stream_create(mrb_state *mrb, const char *base, mrb_int len, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ mrb_input_stream_t *stream = (mrb_input_stream_t *)mrb_malloc(mrb, sizeof(mrb_input_stream_t));
+
+ setup_stream(mrb, stream, base, len, 0, free_cb, free_cb_data);
+ return stream;
+}
+
+mrb_value
+mrb_input_stream_value(mrb_state *mrb, const char *base, mrb_int len)
+{
+ mrb_input_stream_t *stream = mrb_input_stream_create(mrb, base, len, NULL, NULL);
+ struct RClass *c = mrb_class_get(mrb, "InputStream");
+ struct RData *d = mrb_data_object_alloc(mrb, c, stream, &mrb_input_stream_type);
+
+ return mrb_obj_value(d);
+}
+
+void
+mrb_input_stream_get_data(mrb_state *mrb, mrb_value self, const char **base, mrb_int *len, mrb_int *pos, mrb_input_stream_free_callback *free_cb, void **free_cb_data)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+
+ if (base != NULL)
+ *base = stream->base;
+ if (len != NULL)
+ *len = stream->len;
+ if (pos != NULL)
+ *pos = stream->pos;
+ if (free_cb != NULL)
+ *free_cb = stream->free_cb;
+ if (free_cb_data != NULL)
+ *free_cb_data = stream->free_cb_data;
+}
+
+void
+mrb_input_stream_set_data(mrb_state *mrb, mrb_value self, const char *base, mrb_int len, mrb_int pos, mrb_input_stream_free_callback free_cb, void *free_cb_data)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+
+ if (stream->free_cb != NULL)
+ stream->free_cb(mrb, stream->base, stream->len, stream->free_cb_data);
+ setup_stream(mrb, stream, base, len, pos, free_cb, free_cb_data);
+}
+
+static mrb_value
+mrb_input_stream_gets(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ mrb_int pos, len;
+
+ assert_is_open(mrb, stream);
+
+ pos = stream->pos;
+ len = seek_char(stream, '\n');
+ if (len < 0) {
+ return mrb_nil_value();
+ }
+ if (stream->pos + len < stream->len) {
+ len++;
+ }
+ stream->pos += len;
+ return mrb_str_new(mrb, (stream->base + pos), len);
+}
+
+static mrb_int
+seek_char(mrb_input_stream_t *stream, char chr){
+ const char *base = stream->base;
+ size_t len = stream->len;
+ mrb_int pos = stream->pos;
+ const char *end = base + len;
+ const char *start = base + pos;
+ const char *s = start;
+
+ if (pos >= len) {
+ return -1;
+ }
+
+ while (s < end) {
+ if (*s == chr) {
+ break;
+ }
+ s++;
+ }
+ return (s - start);
+}
+
+static mrb_value
+mrb_input_stream_read(mrb_state *mrb, mrb_value self)
+{
+ mrb_int len;
+ mrb_value buf;
+ mrb_int n = mrb_get_args(mrb, "|iS", &len, &buf), pos;
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ const char *start;
+
+ assert_is_open(mrb, stream);
+
+ pos = stream->pos;
+ start = stream->base + pos;
+
+ if (pos >= stream->len) {
+ return mrb_nil_value();
+ }
+ if (n == 0) {
+ stream->pos = stream->len;
+ return mrb_str_new(mrb, start, stream->len - pos);
+ } else {
+ mrb_int newpos = pos + len;
+ if (newpos > stream->len) {
+ newpos = stream->len;
+ }
+ stream->pos = newpos;
+ if (n == 1) {
+ return mrb_str_new(mrb, start, newpos - pos);
+ } else {
+ return mrb_str_cat(mrb, buf, start, newpos - pos);
+ }
+ }
+}
+
+static mrb_value
+mrb_input_stream_rewind(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ assert_is_open(mrb, stream);
+ stream->pos = 0;
+ return self;
+}
+
+
+static mrb_value
+mrb_input_stream_byteindex(mrb_state *mrb, mrb_value self)
+{
+ mrb_input_stream_t *stream = DATA_PTR(self);
+ mrb_int chr, n, len;
+
+ assert_is_open(mrb, stream);
+
+ n = mrb_get_args(mrb, "i", &chr);
+ if (n != 1) {
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1)", mrb_fixnum_value(n));
+ }
+ if (chr < 0 || chr > 255) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "index should be a byte (0 - 255)");
+ }
+
+ len = seek_char(stream, chr);
+ if (len < 0) {
+ return mrb_nil_value();
+ }
+
+ return mrb_fixnum_value(len);
+}
+
+
+void
+mrb_mruby_input_stream_gem_init(mrb_state* mrb)
+{
+ struct RClass * c = mrb_define_class(mrb, "InputStream", mrb->object_class);
+
+ mrb_define_method(mrb, c, "gets", mrb_input_stream_gets, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "read", mrb_input_stream_read, MRB_ARGS_ANY());
+ mrb_define_method(mrb, c, "initialize", mrb_input_stream_init, MRB_ARGS_BLOCK());
+ mrb_define_method(mrb, c, "rewind", mrb_input_stream_rewind, MRB_ARGS_NONE());
+ mrb_define_method(mrb, c, "byteindex", mrb_input_stream_byteindex, MRB_ARGS_ANY());
+}
+
+void
+mrb_mruby_input_stream_gem_final(mrb_state* mrb)
+{
+}