static mrb_value mrb_str_byteslice(mrb_state *mrb, mrb_value str) { mrb_value a1; mrb_int len; int argc; argc = mrb_get_args(mrb, "o|i", &a1, &len); if (argc == 2) { return mrb_str_substr(mrb, str, mrb_fixnum(a1), len); } switch (mrb_type(a1)) { case MRB_TT_RANGE: { mrb_int beg; len = RSTRING_LEN(str); if (mrb_range_beg_len(mrb, a1, &beg, &len, len)) { return mrb_str_substr(mrb, str, beg, len); } return mrb_nil_value(); } case MRB_TT_FLOAT: a1 = mrb_fixnum_value((mrb_int)mrb_float(a1)); /* fall through */ case MRB_TT_FIXNUM: return mrb_str_substr(mrb, str, mrb_fixnum(a1), 1); default: mrb_raise(mrb, E_TYPE_ERROR, "wrong type of argument"); } /* not reached */ return mrb_nil_value(); }
static mrb_value mrb_http_url_fragment(mrb_state *mrb, mrb_value self) { mrb_value value_context; struct http_parser_url* context; value_context = mrb_iv_get(mrb, self, mrb_intern(mrb, "context")); Data_Get_Struct(mrb, value_context, &http_url_type, context); if (!context) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } if (context->field_set & (1<<UF_FRAGMENT)) { return mrb_str_substr(mrb, URL_GET(mrb, self, "buf"), context->field_data[UF_FRAGMENT].off, context->field_data[UF_FRAGMENT].len); } return mrb_nil_value(); }
static mrb_value mrb_http_request_query(mrb_state *mrb, mrb_value self) { mrb_value value_context; mrb_http_parser_context* context; value_context = mrb_iv_get(mrb, self, mrb_intern(mrb, "context")); Data_Get_Struct(mrb, value_context, &http_parser_context_type, context); if (!context) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } if (context->handle.field_set & (1<<UF_QUERY)) { return mrb_str_substr(mrb, PARSER_GET(context, "buf"), context->handle.field_data[UF_QUERY].off, context->handle.field_data[UF_QUERY].len); } return mrb_nil_value(); }
static mrb_value mrb_http_parser_parse_url(mrb_state *mrb, mrb_value self) { mrb_value c; mrb_value arg_data; struct http_parser_url handle = {0}; struct RClass* _class_http, *_class_http_url; mrb_get_args(mrb, "S", &arg_data); if (http_parser_parse_url(RSTRING_PTR(arg_data), RSTRING_LEN(arg_data), FALSE, &handle)) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid URL"); } _class_http = mrb_module_get(mrb, "HTTP"); _class_http_url = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(_class_http), mrb_intern_cstr(mrb, "URL"))); c = mrb_obj_new(mrb, _class_http_url, 0, NULL); if (handle.field_set & (1<<UF_SCHEMA)) { OBJECT_SET(mrb, c, "schema", mrb_str_substr(mrb, arg_data, handle.field_data[UF_SCHEMA].off, handle.field_data[UF_SCHEMA].len)); } if (handle.field_set & (1<<UF_HOST)) { OBJECT_SET(mrb, c, "host", mrb_str_substr(mrb, arg_data, handle.field_data[UF_HOST].off, handle.field_data[UF_HOST].len)); } if (handle.field_set & (1<<UF_HOST)) { OBJECT_SET(mrb, c, "host", mrb_str_substr(mrb, arg_data, handle.field_data[UF_HOST].off, handle.field_data[UF_HOST].len)); } if (handle.field_set & (1<<UF_PORT)) { OBJECT_SET(mrb, c, "port", mrb_fixnum_value(handle.port)); } else { if (handle.field_set & (1<<UF_SCHEMA)) { mrb_value schema = mrb_str_substr(mrb, arg_data, handle.field_data[UF_SCHEMA].off, handle.field_data[UF_SCHEMA].len); if (!mrb_nil_p(schema) && !strcmp("https", (char*) RSTRING_PTR(schema))) { OBJECT_SET(mrb, c, "port", mrb_fixnum_value(443)); } } } if (handle.field_set & (1<<UF_PATH)) { OBJECT_SET(mrb, c, "path", mrb_str_substr(mrb, arg_data, handle.field_data[UF_PATH].off, handle.field_data[UF_PATH].len)); } if (handle.field_set & (1<<UF_QUERY)) { OBJECT_SET(mrb, c, "query", mrb_str_substr(mrb, arg_data, handle.field_data[UF_QUERY].off, handle.field_data[UF_QUERY].len)); } if (handle.field_set & (1<<UF_FRAGMENT)) { OBJECT_SET(mrb, c, "fragment", mrb_str_substr(mrb, arg_data, handle.field_data[UF_FRAGMENT].off, handle.field_data[UF_FRAGMENT].len)); } return c; }
static mrb_value mrb_http_parser_parse_url(mrb_state *mrb, mrb_value self) { mrb_value uri_string; mrb_bool is_connect = FALSE; mrb_get_args(mrb, "S|b", &uri_string, &is_connect); struct http_parser_url parser; http_parser_url_init(&parser); enum http_parser_url_rcs rc = http_parser_parse_url(RSTRING_PTR(uri_string), RSTRING_LEN(uri_string), is_connect, &parser); switch (rc) { case URL_OKAY: { mrb_value argv[UF_MAX + 1]; for (int curr_url_field = 0; curr_url_field < UF_MAX; curr_url_field++) { if (parser.field_set & (1 << curr_url_field)) { if (curr_url_field == UF_PORT) { argv[curr_url_field] = mrb_fixnum_value(parser.port); } else { argv[curr_url_field] = mrb_str_substr(mrb, uri_string, parser.field_data[curr_url_field].off, parser.field_data[curr_url_field].len); } } else { argv[curr_url_field] = mrb_nil_value(); } } argv[UF_MAX] = uri_string; return mrb_obj_new(mrb, MRB_URI_PARSED, sizeof(argv) / sizeof(argv[0]), argv); } break; case MALFORMED_URL: mrb_raise(mrb, E_URI_MALFORMED, "Malformed URL"); break; case HOST_NOT_PRESENT: mrb_raise(mrb, E_URI_HOST_NOT_PRESENT, "Host not present"); break; case HOST_NOT_PARSEABLE: mrb_raise(mrb, E_URI_HOST_NOT_PARSEABLE, "Host not parseable"); break; case CONNECT_MALFORMED: mrb_raise(mrb, E_URI_CONNECT_MALFORMED, "Connect malformed"); break; case PORT_TOO_LARGE: mrb_raise(mrb, E_URI_PORT_TOO_LARGE, "Port too large"); break; } }
static int parser_settings_on_message_complete(http_parser* parser) { mrb_http_parser_context *context = (mrb_http_parser_context*) parser->data; mrb_state* mrb = context->mrb; mrb_value c = context->instance; if (context->handle.field_set & (1<<UF_SCHEMA)) { OBJECT_SET(mrb, c, "schema", mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_SCHEMA].off, context->handle.field_data[UF_SCHEMA].len)); } if (context->handle.field_set & (1<<UF_HOST)) { OBJECT_SET(mrb, c, "host", mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_HOST].off, context->handle.field_data[UF_HOST].len)); } if (context->handle.field_set & (1<<UF_HOST)) { OBJECT_SET(mrb, c, "host", mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_HOST].off, context->handle.field_data[UF_HOST].len)); } if (context->handle.field_set & (1<<UF_PORT)) { OBJECT_SET(mrb, c, "port", mrb_fixnum_value(context->handle.port)); } else { if (context->handle.field_set & (1<<UF_SCHEMA)) { mrb_value schema = mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_SCHEMA].off, context->handle.field_data[UF_SCHEMA].len); if (!mrb_nil_p(schema) && !strcmp("https", (char*) RSTRING_PTR(schema))) { OBJECT_SET(mrb, c, "port", mrb_fixnum_value(443)); } } } if (context->handle.field_set & (1<<UF_PATH)) { OBJECT_SET(mrb, c, "path", mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_PATH].off, context->handle.field_data[UF_PATH].len)); } if (context->handle.field_set & (1<<UF_QUERY)) { OBJECT_SET(mrb, c, "query", mrb_str_substr(mrb, OBJECT_GET(mrb, c, "buf"), context->handle.field_data[UF_QUERY].off, context->handle.field_data[UF_QUERY].len)); } if (context->parser.method) OBJECT_SET(mrb, c, "method", mrb_str_new_cstr(mrb, http_method_str(context->parser.method))); if (context->parser.status_code) OBJECT_SET(mrb, c, "status_code", mrb_fixnum_value(context->parser.status_code)); if (context->parser.content_length) OBJECT_SET(mrb, c, "content_length", mrb_fixnum_value(context->parser.content_length)); OBJECT_REMOVE(mrb, c, "last_header_field"); OBJECT_REMOVE(mrb, c, "last_header_value"); OBJECT_REMOVE(mrb, c, "buf"); return 0; }
int main(int argc, char **argv) { char ruby_code[1024] = { 0 }; char last_code_line[1024] = { 0 }; #ifndef ENABLE_READLINE int last_char; int char_index; #else char *home = NULL; #endif mrbc_context *cxt; struct mrb_parser_state *parser; mrb_state *mrb; mrb_value result; struct _args args; int n; mrb_bool code_block_open = FALSE; mrb_value MIRB_BIN; int ai; unsigned int stack_keep = 0; /* new interpreter instance */ mrb = mrb_open(); if (mrb == NULL) { fputs("Invalid mrb interpreter, exiting mirb\n", stderr); return EXIT_FAILURE; } mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0)); n = parse_args(mrb, argc, argv, &args); if (n == EXIT_FAILURE) { cleanup(mrb, &args); usage(argv[0]); return n; } print_hint(); cxt = mrbc_context_new(mrb); cxt->capture_errors = 1; cxt->lineno = 1; mrbc_filename(mrb, cxt, "(mirb)"); if (args.verbose) cxt->dump_result = 1; MIRB_BIN= mrb_str_new(mrb, argv[0], strlen(argv[0])); mrb_define_global_const(mrb, "MIRB_BIN", MIRB_BIN); #ifdef ENABLE_REQUIRE mrb_value LOAD_PATH = mrb_gv_get(mrb, mrb_intern(mrb, "$:")); if (mrb_str_cmp(mrb, MIRB_BIN, mrb_str_new2(mrb, "mirb")) != 0) { int len = strrchr(RSTRING_PTR(MIRB_BIN), '/') - RSTRING_PTR(MIRB_BIN); mrb_value extdir = mrb_str_substr(mrb, mrb_str_dup(mrb, MIRB_BIN), 0, len); mrb_str_cat2(mrb, extdir, "/../ext"); if (mrb_obj_eq(mrb, mrb_file_exist(mrb, extdir), mrb_true_value())) { mrb_ary_push(mrb, LOAD_PATH, extdir); } } #endif /* ENABLE_REQUIRE */ ai = mrb_gc_arena_save(mrb); #ifdef ENABLE_READLINE MIRB_USING_HISTORY(); home = getenv("HOME"); #ifdef _WIN32 if (!home) home = getenv("USERPROFILE"); #endif if (home) { strcpy(history_path, home); strcat(history_path, "/"); strcat(history_path, history_file_name); MIRB_READ_HISTORY(history_path); } #endif while (TRUE) { #ifndef ENABLE_READLINE print_cmdline(code_block_open); char_index = 0; while ((last_char = getchar()) != '\n') { if (last_char == EOF) break; last_code_line[char_index++] = last_char; } if (last_char == EOF) { fputs("\n", stdout); break; } last_code_line[char_index] = '\0'; #else char* line = MIRB_READLINE(code_block_open ? "* " : "> "); if (line == NULL) { printf("\n"); break; } strncpy(last_code_line, line, sizeof(last_code_line)-1); MIRB_ADD_HISTORY(line); free(line); #endif if (code_block_open) { strcat(ruby_code, "\n"); strcat(ruby_code, last_code_line); } else { if ((strcmp(last_code_line, "quit") == 0) || (strcmp(last_code_line, "exit") == 0)) { break; } strcpy(ruby_code, last_code_line); } /* parse code */ parser = mrb_parser_new(mrb); parser->s = ruby_code; parser->send = ruby_code + strlen(ruby_code); parser->lineno = cxt->lineno; mrb_parser_parse(parser, cxt); code_block_open = is_code_block_open(parser); if (code_block_open) { /* no evaluation of code */ } else { if (0 < parser->nerr) { /* syntax error */ printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message); } else { /* generate bytecode */ struct RProc *proc = mrb_generate_code(mrb, parser); if (args.verbose) { mrb_codedump_all(mrb, proc); } /* pass a proc for evaulation */ /* evaluate the bytecode */ result = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); stack_keep = proc->body.irep->nlocals; /* did an exception occur? */ if (mrb->exc) { p(mrb, mrb_obj_value(mrb->exc), 0); mrb->exc = 0; } else { /* no */ if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){ result = mrb_any_to_s(mrb,result); } p(mrb, result, 1); } } ruby_code[0] = '\0'; last_code_line[0] = '\0'; mrb_gc_arena_restore(mrb, ai); } mrb_parser_free(parser); cxt->lineno++; } mrbc_context_free(mrb, cxt); mrb_close(mrb); #ifdef ENABLE_READLINE MIRB_WRITE_HISTORY(history_path); #endif return 0; }
/* * call-seq: * string.chr -> string * * Returns a one-character string at the beginning of the string. * * a = "abcde" * a.chr #=> "a" */ static mrb_value mrb_str_chr(mrb_state *mrb, mrb_value self) { return mrb_str_substr(mrb, self, 0, 1); }