static void parse_query_string(sl_vm_t* vm, SLVAL dict, size_t len, uint8_t* query_string) { uint8_t *key = query_string, *value = NULL; size_t key_len = 0, value_len = 0; size_t i; SLVAL addee = dict, k, v; int bracket_mode = 0, in_bracket = 0; for(i = 0; i <= len; i++) { if(i == len || query_string[i] == '&') { if(key_len > 0) { k = sl_string_url_decode(vm, sl_make_string(vm, key, key_len)); if(value) { v = sl_string_url_decode(vm, sl_make_string(vm, value, value_len)); } sl_dict_set(vm, addee, k, value ? v : vm->lib.nil); } key = query_string + i + 1; key_len = 0; value = NULL; value_len = 0; addee = dict; in_bracket = 0; bracket_mode = 0; continue; } if(query_string[i] == '=' && !value) { value = query_string + i + 1; continue; } if(value) { value_len++; } else { if(query_string[i] == '[') { k = sl_make_string(vm, key, key_len); key = query_string + i + 1; key_len = 0; if(!sl_is_a(vm, sl_dict_get(vm, addee, k), vm->lib.Dict)) { sl_dict_set(vm, addee, k, sl_make_dict(vm, 0, NULL)); } addee = sl_dict_get(vm, addee, k); in_bracket = 1; bracket_mode = 1; continue; } if(query_string[i] == ']' && in_bracket) { in_bracket = 0; continue; } if(bracket_mode && !in_bracket) { /* skip until \0, & or = */ while(i + 1 < len && query_string[i + 1] != '&' && query_string[i + 1] != '=') { i++; } continue; } key_len++; } } }
void sl_request_set_opts(sl_vm_t* vm, sl_request_opts_t* opts) { size_t i; SLVAL n, v, cookies; sl_string_t* str; sl_request_internal_opts_t* req = sl_alloc(vm->arena, sizeof(sl_request_internal_opts_t)); req->method = sl_make_cstring(vm, opts->method); req->uri = sl_make_cstring(vm, opts->uri); req->path_info = sl_make_cstring(vm, opts->path_info ? opts->path_info : ""); req->query_string = sl_make_cstring(vm, opts->query_string ? opts->query_string : ""); req->remote_addr = sl_make_cstring(vm, opts->remote_addr); req->headers = sl_make_dict(vm, 0, NULL); req->env = sl_make_dict(vm, 0, NULL); req->get = sl_make_dict(vm, 0, NULL); req->post = sl_make_dict(vm, 0, NULL); req->post_data = sl_make_string(vm, (uint8_t*)opts->post_data, opts->post_length); req->cookies = sl_make_dict(vm, 0, NULL); for(i = 0; i < opts->header_count; i++) { n = sl_make_cstring(vm, opts->headers[i].name); v = sl_make_cstring(vm, opts->headers[i].value); sl_dict_set(vm, req->headers, n, v); } for(i = 0; i < opts->env_count; i++) { n = sl_make_cstring(vm, opts->env[i].name); v = sl_make_cstring(vm, opts->env[i].value); sl_dict_set(vm, req->env, n, v); } if(opts->query_string) { parse_query_string(vm, req->get, strlen(opts->query_string), (uint8_t*)opts->query_string); } if(opts->content_type && strcmp(opts->content_type, "application/x-www-form-urlencoded") == 0) { parse_query_string(vm, req->post, opts->post_length, (uint8_t*)opts->post_data); } cookies = sl_dict_get(vm, req->headers, sl_make_cstring(vm, "Cookie")); if(sl_is_a(vm, cookies, vm->lib.String)) { str = (sl_string_t*)sl_get_ptr(cookies); parse_cookie_string(vm, req->cookies, str->buff_len, str->buff); } req->params = sl_dict_merge(vm, req->get, req->post); sl_vm_store_put(vm, &Request_opts, sl_make_ptr((sl_object_t*)req)); }
static void json_dump(json_dump_t* state, SLVAL object) { sl_string_t* str; size_t i, len; SLVAL* keys; switch(sl_get_primitive_type(object)) { case SL_T_NIL: JSON_DUMP_NEED_BYTES(4); memcpy(state->buffer + state->buffer_len, "null", 4); state->buffer_len += 4; break; case SL_T_TRUE: JSON_DUMP_NEED_BYTES(4); memcpy(state->buffer + state->buffer_len, "true", 4); state->buffer_len += 4; break; case SL_T_FALSE: JSON_DUMP_NEED_BYTES(5); memcpy(state->buffer + state->buffer_len, "false", 5); state->buffer_len += 5; break; case SL_T_INT: str = (sl_string_t*)sl_get_ptr(sl_int_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_FLOAT: str = (sl_string_t*)sl_get_ptr(sl_float_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_BIGNUM: str = (sl_string_t*)sl_get_ptr(sl_bignum_to_s(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_STRING: str = (sl_string_t*)sl_get_ptr(sl_string_inspect(state->vm, object)); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; case SL_T_ARRAY: JSON_CHECK_RECURSION(object); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '['; len = sl_get_int(sl_array_length(state->vm, object)); for(i = 0; i < len; i++) { if(i) { JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ','; } json_dump(state, sl_array_get(state->vm, object, i)); } JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ']'; JSON_END_CHECK_RECURSION(); break; case SL_T_DICT: JSON_CHECK_RECURSION(object); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '{'; keys = sl_dict_keys(state->vm, object, &len); for(i = 0; i < len; i++) { if(i) { JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ','; } json_dump(state, sl_to_s(state->vm, keys[i])); JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = ':'; json_dump(state, sl_dict_get(state->vm, object, keys[i])); } JSON_DUMP_NEED_BYTES(1); state->buffer[state->buffer_len++] = '}'; JSON_END_CHECK_RECURSION(); break; default: if(!sl_responds_to(state->vm, object, "to_json")) { SLVAL DumpError = state->vm->store[cJSON_DumpError]; sl_error(state->vm, DumpError, "Can't convert type %V to JSON. You can implement #to_json to fix this.", sl_class_of(state->vm, object)); } str = (sl_string_t*)sl_get_ptr(sl_to_s(state->vm, sl_send(state->vm, object, "to_json", 0, NULL))); JSON_DUMP_NEED_BYTES(str->buff_len); memcpy(state->buffer + state->buffer_len, str->buff, str->buff_len); state->buffer_len += str->buff_len; break; } }
static SLVAL request_index(sl_vm_t* vm, SLVAL self, SLVAL name) { (void)self; return sl_dict_get(vm, request(vm)->params, name); }