static SLVAL sl_mysql_init(sl_vm_t* vm, SLVAL self, SLVAL host, SLVAL user, SLVAL password) { char *host_s = NULL, *user_s = NULL, *password_s = NULL, *db_s = NULL; int port_i = 3306, flag_i = CLIENT_IGNORE_SIGPIPE | CLIENT_MULTI_STATEMENTS; mysql_t* mysql = sl_data_get_ptr(vm, &mysql_data_type, self); if(sl_is_truthy(host)) { host_s = sl_to_cstr(vm, sl_expect(vm, host, vm->lib.String)); } if(sl_is_truthy(user)) { user_s = sl_to_cstr(vm, sl_expect(vm, user, vm->lib.String)); } if(sl_is_truthy(password)) { password_s = sl_to_cstr(vm, sl_expect(vm, password, vm->lib.String)); } if(!mysql_real_connect(&mysql->mysql, host_s, user_s, password_s, db_s, port_i, NULL, flag_i)) { sl_mysql_check_error(vm, &mysql->mysql); } if(!mysql_set_character_set(&mysql->mysql, "utf8")) { sl_mysql_check_error(vm, &mysql->mysql); } mysql->valid = 1; return self; }
static SLVAL response_set_header(sl_vm_t* vm, SLVAL self, SLVAL name, SLVAL value) { char* h; sl_response_internal_opts_t* resp = response(vm); (void)self; sl_expect(vm, name, vm->lib.String); sl_expect(vm, value, vm->lib.String); if(resp->header_count >= resp->header_cap) { resp->header_cap *= 2; resp->headers = sl_realloc(vm->arena, resp->headers, sizeof(sl_response_key_value_t) * resp->header_cap); } h = sl_to_cstr(vm, name); if(strchr(h, '\n') || strchr(h, '\r')) { return vm->lib._false; } resp->headers[resp->header_count].name = h; h = sl_to_cstr(vm, value); if(strchr(h, '\n') || strchr(h, '\r')) { return vm->lib._false; } resp->headers[resp->header_count].value = h; resp->header_count++; return vm->lib._true; }
static SLVAL response_set_cookie(sl_vm_t* vm, SLVAL self, SLVAL name, SLVAL value) { SLVAL header; sl_expect(vm, name, vm->lib.String); sl_expect(vm, value, vm->lib.String); name = sl_string_url_encode(vm, name); value = sl_string_url_encode(vm, value); header = name; header = sl_string_concat(vm, header, sl_make_cstring(vm, "=")); header = sl_string_concat(vm, header, value); return response_set_header(vm, self, sl_make_cstring(vm, "Set-Cookie"), header); }
SLVAL sl_string_char_at_index(sl_vm_t* vm, SLVAL self, SLVAL index) { sl_string_t* str = sl_get_string(vm, self); if(sl_is_a(vm, index, vm->lib.Range_Inclusive) || sl_is_a(vm, index, vm->lib.Range_Exclusive)) { return string_range_index(vm, self, index); } long idx = sl_get_int(sl_expect(vm, index, vm->lib.Int)); if(idx < 0) { idx += str->char_len; } if(idx < 0 || idx >= (long)str->char_len) { return vm->lib.nil; } uint8_t* buff_ptr = str->buff; size_t len = str->buff_len; while(idx) { sl_utf8_each_char(vm, &buff_ptr, &len); idx--; } size_t slice_len = 1; while(slice_len < len && (buff_ptr[slice_len] & 0xc0) == 0x80) { slice_len++; } return sl_make_string(vm, buff_ptr, slice_len); }
SLVAL sl_regexp_match(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { sl_regexp_t* re = get_regexp_check(vm, self); sl_string_t* str = sl_get_string(vm, argv[0]); int offset = 0, rc, ncaps; int* caps; sl_regexp_match_t* match; if(argc > 1) { offset = sl_get_int(sl_expect(vm, argv[1], vm->lib.Int)); } offset = sl_string_byte_offset_for_index(vm, argv[0], offset); if(offset < 0) { return vm->lib.nil; } pcre_fullinfo(re->re, re->study, PCRE_INFO_CAPTURECOUNT, &ncaps); ncaps += 1; ncaps *= 3; caps = sl_alloc(vm->arena, sizeof(int) * ncaps); rc = pcre_exec(re->re, re->study, (char*)str->buff, str->buff_len, offset, PCRE_NEWLINE_LF, caps, ncaps); if(rc == PCRE_ERROR_NOMATCH) { return vm->lib.nil; } check_pcre_error(vm, rc); match = (sl_regexp_match_t*)sl_get_ptr(sl_allocate(vm, vm->lib.Regexp_Match)); match->re = re; match->match_string = argv[0]; match->capture_count = ncaps / 3; match->captures = caps; return sl_make_ptr((sl_object_t*)match); }
static SLVAL sl_string_replace(sl_vm_t* vm, SLVAL self, SLVAL search, SLVAL replace) { if(sl_is_a(vm, search, vm->lib.String)) { return sl_enumerable_join(vm, sl_string_split(vm, self, 1, &search), 1, &replace); } sl_expect(vm, search, vm->lib.Regexp); SLVAL retn = sl_make_cstring(vm, ""); while(1) { SLVAL match = sl_regexp_match(vm, search, 1, &self); if(!sl_is_truthy(match)) { return sl_string_concat(vm, retn, self); } else { SLVAL part = sl_regexp_match_before(vm, match); if(sl_is_a(vm, replace, vm->lib.String)) { part = sl_string_concat(vm, part, replace); } else { part = sl_string_concat(vm, part, sl_send_id(vm, replace, vm->id.call, 1, match)); } retn = sl_string_concat(vm, retn, part); } self = sl_regexp_match_after(vm, match); } }
static sl_ruby_object_t* get_ruby_object(sl_vm_t* vm, SLVAL obj) { SLVAL Ruby_Object = sl_vm_store_get(vm, &cRuby_Object); sl_expect(vm, obj, Ruby_Object); return (sl_ruby_object_t*)sl_get_ptr(obj); }
static SLVAL response_status_set(sl_vm_t* vm, SLVAL self, SLVAL status) { (void)self; sl_expect(vm, status, vm->lib.Int); response(vm)->status = sl_get_int(status); return status; }
static SLVAL sl_mysql_use(sl_vm_t* vm, SLVAL self, SLVAL db) { mysql_t* mysql = get_mysql(vm, self); mysql_select_db(&mysql->mysql, sl_to_cstr(vm, sl_expect(vm, db, vm->lib.String))); sl_mysql_check_error(vm, &mysql->mysql); return vm->lib._true; }
static gcrypt_algorithm_t* get_algo(sl_vm_t* vm, SLVAL obj) { SLVAL klass = sl_vm_store_get(vm, &cGCrypt_Algorithm); gcrypt_algorithm_t* ptr; sl_expect(vm, obj, klass); ptr = (gcrypt_algorithm_t*)sl_get_ptr(obj); return ptr; }
static sl_regexp_match_t* get_regexp_match(sl_vm_t* vm, SLVAL matchv) { sl_regexp_match_t* match; sl_expect(vm, matchv, vm->lib.Regexp_Match); match = (sl_regexp_match_t*)sl_get_ptr(matchv); if(!match->re) { sl_throw_message2(vm, vm->lib.TypeError, "Invalid Regexp::Match"); } return match; }
SLVAL sl_method_bind(sl_vm_t* vm, SLVAL method, SLVAL receiver) { sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); if(!(methp->base.user_flags & SL_FLAG_METHOD_INITIALIZED)) { sl_throw_message2(vm, vm->lib.TypeError, "Can't bind uninitialized Method"); } sl_method_t* bmethp = method_dup(vm, methp); bmethp->extra->bound_self = sl_expect(vm, receiver, methp->extra->klass); bmethp->base.klass = vm->lib.BoundMethod; return sl_make_ptr((sl_object_t*)bmethp); }
SLVAL sl_make_c_func(sl_vm_t* vm, SLVAL klass, SLID name, int arity, SLVAL(*c_func)()) { SLVAL method = sl_allocate(vm, vm->lib.Method); sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); methp->name = name; methp->is_c_func = 1; methp->arity = arity; methp->klass = sl_expect(vm, klass, vm->lib.Class); methp->as.c.func = c_func; methp->initialized = 1; return method; }
SLVAL sl_make_c_func(sl_vm_t* vm, SLVAL klass, SLID name, int arity, SLVAL(*c_func)()) { SLVAL method = sl_allocate(vm, vm->lib.Method); sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); methp->extra->name = name; methp->arity = arity; methp->extra->klass = sl_expect(vm, klass, vm->lib.Class); methp->as.c.func = c_func; methp->base.user_flags |= SL_FLAG_METHOD_INITIALIZED | SL_FLAG_METHOD_IS_C_FUNC; return method; }
SLVAL sl_string_times(sl_vm_t* vm, SLVAL self, SLVAL other) { sl_string_t* str = sl_get_string(vm, self); long mul = sl_get_int(sl_expect(vm, other, vm->lib.Int)); if(mul && (size_t)LONG_MAX / mul < str->buff_len) { sl_throw_message2(vm, vm->lib.ArgumentError, "String multiplier is too big"); } sl_string_t* new_str = sl_get_string(vm, sl_make_string(vm, NULL, 0)); new_str->buff_len = str->buff_len * mul; new_str->buff = sl_alloc(vm->arena, new_str->buff_len); for(size_t i = 0; i < new_str->buff_len; i += str->buff_len) { memcpy(new_str->buff + i, str->buff, str->buff_len); } new_str->char_len = str->char_len * mul; return sl_make_ptr((sl_object_t*)new_str); }
SLVAL sl_float_cmp(sl_vm_t* vm, SLVAL self, SLVAL other) { if(sl_is_a(vm, other, vm->lib.Int)) { return sl_float_cmp(vm, self, sl_make_float(vm, sl_get_int(other))); } if(sl_is_a(vm, other, vm->lib.Bignum)) { return sl_make_int(vm, -sl_get_int(sl_bignum_cmp(vm, other, self))); } sl_expect(vm, other, vm->lib.Float); if(sl_get_float(vm, self) < sl_get_float(vm, other)) { return sl_make_int(vm, -1); } else if(sl_get_float(vm, self) > sl_get_float(vm, other)) { return sl_make_int(vm, 1); } else { return sl_make_int(vm, 0); } }
SLVAL sl_make_method(sl_vm_t* vm, SLVAL klass, SLID name, sl_vm_section_t* section, sl_vm_exec_ctx_t* parent_ctx) { SLVAL method = sl_allocate(vm, vm->lib.Method); sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); methp->name = name; methp->is_c_func = 0; if(section->req_registers < section->arg_registers) { methp->arity = -section->req_registers - 1; } else { methp->arity = (int)section->arg_registers; } methp->klass = sl_expect(vm, klass, vm->lib.Class); methp->as.sl.section = section; methp->as.sl.parent_ctx = parent_ctx; methp->initialized = 1; return method; }
static int cap_index(sl_vm_t* vm, SLVAL regexp_match, SLVAL i) { sl_regexp_match_t* match = get_regexp_match(vm, regexp_match); int index; if(sl_is_a(vm, i, vm->lib.String)) { char* named_cap = sl_to_cstr(vm, i); index = pcre_get_stringnumber(match->re->re, named_cap); if(index < 0) { return -1; } } else { index = sl_get_int(sl_expect(vm, i, vm->lib.Int)); } if(index < 0 || index >= match->capture_count) { return -1; } return index * 2; }
SLVAL sl_make_method(sl_vm_t* vm, SLVAL klass, SLID name, sl_vm_section_t* section, sl_vm_exec_ctx_t* parent_ctx) { SLVAL method = sl_allocate(vm, vm->lib.Method); sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); methp->extra->name = name; if(section->req_registers < section->arg_registers) { methp->arity = -section->req_registers - 1; } else if(section->has_extra_rest_arg) { methp->arity = -(int)section->req_registers - 1; } else { methp->arity = (int)section->req_registers; } methp->extra->klass = sl_expect(vm, klass, vm->lib.Class); methp->as.sl.section = section; methp->as.sl.parent_ctx = parent_ctx; methp->base.user_flags |= SL_FLAG_METHOD_INITIALIZED; return method; }
SLVAL sl_method_bind(sl_vm_t* vm, SLVAL method, SLVAL receiver) { sl_method_t* methp = (sl_method_t*)sl_get_ptr(method); sl_bound_method_t* bmethp = (sl_bound_method_t*)sl_get_ptr(sl_allocate(vm, vm->lib.BoundMethod)); if(!methp->initialized) { sl_throw_message2(vm, vm->lib.TypeError, "Can't bind uninitialized Method"); } bmethp->method.initialized = 1; bmethp->method.name = methp->name; bmethp->method.klass = methp->klass; bmethp->method.is_c_func = methp->is_c_func; bmethp->method.arity = methp->arity; bmethp->method.as = methp->as; bmethp->self = sl_expect(vm, receiver, methp->klass); return sl_make_ptr((sl_object_t*)bmethp); }
SLVAL sl_regexp_match(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { sl_regexp_t* re = get_regexp_check(vm, self); sl_string_t* str = sl_get_string(vm, argv[0]); int offset = 0, rc, ncaps; int* caps; char err_buff[256]; sl_regexp_match_t* match; if(argc > 1) { offset = sl_get_int(sl_expect(vm, argv[1], vm->lib.Int)); } offset = sl_string_byte_offset_for_index(vm, argv[0], offset); if(offset < 0) { return vm->lib.nil; } pcre_fullinfo(re->re, re->study, PCRE_INFO_CAPTURECOUNT, &ncaps); ncaps += 1; ncaps *= 3; caps = sl_alloc(vm->arena, sizeof(int) * ncaps); rc = pcre_exec(re->re, re->study, (char*)str->buff, str->buff_len, offset, PCRE_NEWLINE_LF, caps, ncaps); if(rc < 0) { if(rc == PCRE_ERROR_NOMATCH) { return vm->lib.nil; } if(rc == PCRE_ERROR_BADUTF8) { sl_throw_message2(vm, vm->lib.EncodingError, "Invalid UTF-8 in regular expression or match text"); } sprintf(err_buff, "PCRE error (%d)", rc); sl_throw_message2(vm, vm->lib.Error, err_buff); } match = (sl_regexp_match_t*)sl_get_ptr(sl_allocate(vm, vm->lib.Regexp_Match)); match->re = re; match->match_string = argv[0]; match->capture_count = ncaps / 3; match->captures = caps; return sl_make_ptr((sl_object_t*)match); }
static sl_range_t* get_range(sl_vm_t* vm, SLVAL obj) { sl_expect(vm, obj, vm->lib.Range); return (sl_range_t*)sl_get_ptr(obj); }
static sl_range_enumerator_t* get_range_enumerator(sl_vm_t* vm, SLVAL obj) { sl_expect(vm, obj, vm->lib.Range_Enumerator); return (sl_range_enumerator_t*)sl_get_ptr(obj); }
sl_string_t* sl_get_string(sl_vm_t* vm, SLVAL obj) { sl_expect(vm, obj, vm->lib.String); return (sl_string_t*)sl_get_ptr(obj); }
SLVAL sl_string_split(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { SLVAL substr = argv[0]; sl_string_t* haystack = sl_get_string(vm, self); sl_string_t* needle = sl_get_string(vm, substr); SLVAL ret = sl_make_array(vm, 0, NULL), piece; uint8_t* haystack_buff = haystack->buff; uint8_t* start_ptr = haystack_buff; size_t haystack_len = haystack->buff_len; uint8_t buff[12]; size_t buff_len; uint32_t c; long limit = 0; if(argc > 1) { limit = sl_get_int(sl_expect(vm, argv[1], vm->lib.Int)); if(limit < 0) { limit = 0; } } long length = 0; if(needle->buff_len == 0) { while(haystack_len) { length++; if(limit && length == limit) { SLVAL rest = sl_make_string(vm, haystack_buff, haystack_len); sl_array_push(vm, ret, 1, &rest); break; } c = sl_utf8_each_char(vm, &haystack_buff, &haystack_len); buff_len = sl_utf32_char_to_utf8(vm, c, buff); piece = sl_make_string(vm, buff, buff_len); sl_array_push(vm, ret, 1, &piece); } return ret; } else { if(limit == 1) { return sl_make_array(vm, 1, &self); } while(haystack_len >= needle->buff_len) { if(memcmp(haystack_buff, needle->buff, needle->buff_len) == 0) { piece = sl_make_string(vm, start_ptr, haystack_buff - start_ptr); sl_array_push(vm, ret, 1, &piece); haystack_buff += needle->buff_len; haystack_len -= needle->buff_len; length++; if(limit && length + 1 == limit) { SLVAL rest = sl_make_string(vm, haystack_buff, haystack_len); sl_array_push(vm, ret, 1, &rest); return ret; } start_ptr = haystack_buff; continue; } haystack_buff++; haystack_len--; } piece = sl_make_string(vm, start_ptr, haystack_buff - start_ptr + haystack_len); sl_array_push(vm, ret, 1, &piece); return ret; } return vm->lib.nil; }
static sl_float_t* get_float(sl_vm_t* vm, SLVAL val) { sl_expect(vm, val, vm->lib.Float); return (sl_float_t*)sl_get_ptr(val); }
static sl_class_t* get_class(sl_vm_t* vm, SLVAL klass) { sl_expect(vm, klass, vm->lib.Class); return (sl_class_t*)sl_get_ptr(klass); }
SLID sl_intern2(sl_vm_t* vm, SLVAL str) { return sl_intern2_no_check(vm, sl_expect(vm, str, vm->lib.String)); }
static sl_regexp_t* get_regexp(sl_vm_t* vm, SLVAL re) { sl_expect(vm, re, vm->lib.Regexp); return (sl_regexp_t*)sl_get_ptr(re); }
static SLVAL sl_json_parse(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { sl_string_t* str = sl_get_string(vm, argv[0]); json_parse_t json; yajl_alloc_funcs alloc_funcs = { sl_yajl_alloc, sl_yajl_realloc, sl_yajl_free, NULL }; alloc_funcs.ctx = vm->arena; json.vm = vm; json.max_depth = 32; json.stack_len = 0; json.stack_cap = 32; json.stack = sl_alloc(vm->arena, sizeof(SLVAL) * json.stack_cap); json.type_stack = sl_alloc(vm->arena, json.stack_cap); if(argc > 1) { json.max_depth = sl_get_int(sl_expect(vm, argv[1], vm->lib.Int)); } json.yajl = yajl_alloc(&callbacks, &alloc_funcs, &json); sl_json_parse_check_error(vm, str, &json, yajl_parse(json.yajl, str->buff, str->buff_len)); sl_json_parse_check_error(vm, str, &json, yajl_complete_parse(json.yajl)); yajl_free(json.yajl); /* must've been OK! */ return json.stack[0]; (void)self; }