SLVAL sl_string_eq(sl_vm_t* vm, SLVAL self, SLVAL other) { if(!sl_is_a(vm, other, vm->lib.String)) { return vm->lib._false; } sl_string_t* a = sl_get_string(vm, self); sl_string_t* b = sl_get_string(vm, other); return sl_make_bool(vm, str_cmp(vm, a, b) == 0); }
SLVAL sl_string_concat(sl_vm_t* vm, SLVAL self, SLVAL other) { sl_string_t* a = sl_get_string(vm, self); sl_string_t* b = sl_get_string(vm, other); uint8_t* buff = (uint8_t*)sl_alloc_buffer(vm->arena, a->buff_len + b->buff_len); memcpy(buff, a->buff, a->buff_len); memcpy(buff + a->buff_len, b->buff, b->buff_len); return sl_make_string(vm, buff, a->buff_len + b->buff_len); }
SLVAL sl_string_concat(sl_vm_t* vm, SLVAL self, SLVAL other) { sl_string_t* a = sl_get_string(vm, self); sl_string_t* b = sl_get_string(vm, other); if(strcmp(a->encoding, b->encoding) != 0) { return sl_string_concat(vm, self, sl_string_encode(vm, other, a->encoding)); } uint8_t* buff = (uint8_t*)sl_alloc_buffer(vm->arena, a->buff_len + b->buff_len); memcpy(buff, a->buff, a->buff_len); memcpy(buff + a->buff_len, b->buff, b->buff_len); return sl_make_string(vm, buff, a->buff_len + b->buff_len); }
SLVAL sl_string_html_escape(sl_vm_t* vm, SLVAL self) { sl_string_t* str = sl_get_string(vm, self); size_t out_cap = 32; size_t out_len = 0; size_t str_i; uint8_t* out = sl_alloc_buffer(vm->arena, out_cap); for(str_i = 0; str_i < str->buff_len; str_i++) { if(out_len + 8 >= out_cap) { out_cap *= 2; out = sl_realloc(vm->arena, out, out_cap); } if(str->buff[str_i] == '<') { memcpy(out + out_len, "<", 4); out_len += 4; } else if(str->buff[str_i] == '>') { memcpy(out + out_len, ">", 4); out_len += 4; } else if(str->buff[str_i] == '"') { memcpy(out + out_len, """, 6); out_len += 6; } else if(str->buff[str_i] == '\'') { memcpy(out + out_len, "'", 6); out_len += 6; } else if(str->buff[str_i] == '&') { memcpy(out + out_len, "&", 5); out_len += 5; } else { out[out_len++] = str->buff[str_i]; } } return sl_make_string(vm, out, out_len); }
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_string_url_decode(sl_vm_t* vm, SLVAL self) { sl_string_t* str = sl_get_string(vm, self); size_t out_cap = 32; size_t out_len = 0; uint8_t* out = sl_alloc_buffer(vm->arena, out_cap); size_t str_i; char tmp[3]; for(str_i = 0; str_i < str->buff_len; str_i++) { if(out_len + 8 >= out_cap) { out_cap *= 2; out = sl_realloc(vm->arena, out, out_cap); } if(str->buff[str_i] == '%') { if(str_i + 2 < str->buff_len) { if(is_hex_char(str->buff[str_i + 1]) && is_hex_char(str->buff[str_i + 2])) { tmp[0] = str->buff[str_i + 1]; tmp[1] = str->buff[str_i + 2]; tmp[2] = 0; out[out_len++] = strtol(tmp, NULL, 16); str_i += 2; continue; } } } if(str->buff[str_i] == '+') { out[out_len++] = ' '; continue; } out[out_len++] = str->buff[str_i]; } return sl_make_string(vm, out, out_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_regexp_init(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { sl_regexp_t* re_ptr = get_regexp(vm, self); sl_string_t* re = sl_get_string(vm, argv[0]); sl_string_t* opts; if(argc > 1) { opts = sl_get_string(vm, argv[1]); } else { opts = sl_cstring(vm, ""); } if(re_ptr->re) { sl_throw_message2(vm, vm->lib.TypeError, "Cannot reinitialize already initialized Regexp"); } sl_setup_regexp(vm, re_ptr, re->buff, re->buff_len, opts->buff, opts->buff_len); return self; }
SLVAL sl_string_encode(sl_vm_t* vm, SLVAL self, char* encoding) { sl_string_t* str = sl_get_string(vm, self); size_t out_len; char* out_buff = sl_iconv(vm, (char*)str->buff, str->buff_len, "UTF-8", encoding, &out_len); return sl_make_buffer(vm, out_buff, out_len); }
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); }
static SLVAL sl_mysql_escape(sl_vm_t* vm, SLVAL self, SLVAL str) { mysql_t* mysql = get_mysql(vm, self); sl_string_t* s = sl_get_string(vm, str); char* esc = sl_alloc(vm->arena, s->buff_len * 2 + 1); size_t esc_len = mysql_real_escape_string(&mysql->mysql, esc, (char*)s->buff, s->buff_len); return sl_make_string(vm, (uint8_t*)esc, esc_len); }
SLVAL sl_string_index(sl_vm_t* vm, SLVAL self, SLVAL substr) { sl_string_t* haystack = sl_get_string(vm, self); sl_string_t* needle = sl_get_string(vm, substr); /* @TODO use a more efficient algorithm */ uint8_t* haystack_buff = haystack->buff; size_t haystack_len = haystack->buff_len; size_t i = 0; while(haystack_len >= needle->buff_len) { if(memcmp(haystack_buff, needle->buff, needle->buff_len) == 0) { return sl_make_int(vm, i); } sl_utf8_each_char(vm, &haystack_buff, &haystack_len); i++; } return vm->lib.nil; }
SLVAL sl_string_lower(sl_vm_t* vm, SLVAL selfv) { sl_string_t* self = sl_get_string(vm, selfv); sl_string_t* retn = sl_get_string(vm, sl_allocate(vm, vm->lib.String)); memcpy(retn, self, sizeof(sl_string_t)); retn->buff = sl_alloc_buffer(vm->arena, retn->buff_len); size_t len = self->buff_len; uint8_t* buff = self->buff; size_t out_offset = 0; uint32_t lower_c; while(len) { uint32_t c = sl_utf8_each_char(vm, &buff, &len); lower_c = sl_unicode_tolower(c); out_offset += sl_utf32_char_to_utf8(vm, lower_c, retn->buff + out_offset); } return sl_make_ptr((sl_object_t*)retn); }
SLVAL sl_string_eq(sl_vm_t* vm, SLVAL self, SLVAL other) { if(!sl_is_a(vm, other, vm->lib.String)) { return vm->lib._false; } sl_string_t* a = sl_get_string(vm, self); sl_string_t* b = sl_get_string(vm, other); if(a->encoding == b->encoding) { if(str_cmp((sl_string_t*)sl_get_ptr(self), (sl_string_t*)sl_get_ptr(other)) == 0) { return vm->lib._true; } else { return vm->lib._false; } } sl_vm_frame_t frame; SLVAL err; volatile SLVAL retn; SL_TRY(frame, SL_UNWIND_EXCEPTION, { retn = sl_string_eq(vm, self, sl_string_encode(vm, other, a->encoding)); }, err, {
SLVAL sl_regexp_is_match(sl_vm_t* vm, SLVAL self, SLVAL other) { sl_regexp_t* re = get_regexp_check(vm, self); sl_string_t* str = sl_get_string(vm, other); int rc = pcre_exec(re->re, re->study, (char*)str->buff, str->buff_len, 0, PCRE_NEWLINE_LF, NULL, 0); if(rc == PCRE_ERROR_NOMATCH) { return vm->lib._false; } check_pcre_error(vm, rc); return vm->lib._true; }
static SLVAL sl_gcrypt_algorithm_hex_digest(sl_vm_t* vm, SLVAL self, SLVAL strv) { size_t i; sl_string_t* str = sl_get_string(vm, strv); gcrypt_algorithm_t* algo = get_algo_check(vm, self); size_t digest_len = gcry_md_get_algo_dlen(algo->algo); char* digest = alloca(digest_len); char* hex_digest = alloca(digest_len * 2); gcry_md_hash_buffer(algo->algo, digest, str->buff, str->buff_len); for(i = 0; i < digest_len; i++) { sprintf(hex_digest + 2 * i, "%02x", (uint8_t)digest[i]); } return sl_make_string(vm, (uint8_t*)hex_digest, digest_len * 2); }
int sl_string_byte_offset_for_index(sl_vm_t* vm, SLVAL strv, int index) { sl_string_t* str = sl_get_string(vm, strv); uint8_t* buff = str->buff; size_t len = str->buff_len; while(len) { if(index == 0) { return buff - str->buff; } sl_utf8_each_char(vm, &buff, &len); index--; } return -1; }
SLVAL sl_string_url_encode(sl_vm_t* vm, SLVAL self) { sl_string_t* str = sl_get_string(vm, self); size_t out_cap = 32; size_t out_len = 0; uint8_t* out = sl_alloc_buffer(vm->arena, out_cap); size_t clen = str->buff_len; uint8_t* cbuff = str->buff; uint32_t c; uint8_t utf8buff[8]; uint32_t utf8len; while(clen) { if(out_len + 16 >= out_cap) { out_cap *= 2; out = sl_realloc(vm->arena, out, out_cap); } c = sl_utf8_each_char(vm, &cbuff, &clen); if(c >= 'A' && c <= 'Z') { out[out_len++] = c; continue; } if(c >= 'a' && c <= 'z') { out[out_len++] = c; continue; } if(c >= '0' && c <= '9') { out[out_len++] = c; continue; } if(c == '-' || c == '_' || c == '.' || c == '~') { out[out_len++] = c; continue; } if(c == ' ') { out[out_len++] = '+'; continue; } utf8len = sl_utf32_char_to_utf8(vm, c, utf8buff); for(unsigned int i = 0; i < utf8len; i++) { sprintf((char*)out + out_len, "%%%2X", utf8buff[i]); out_len += 3; } } return sl_make_string(vm, out, out_len); }
SLVAL sl_string_inspect(sl_vm_t* vm, SLVAL self) { sl_string_t* str = sl_get_string(vm, self); size_t out_cap = 32; size_t out_len = 0; size_t str_i; uint8_t* out = sl_alloc_buffer(vm->arena, out_cap); out[out_len++] = '"'; for(str_i = 0; str_i < str->buff_len; str_i++) { if(out_len + 8 >= out_cap) { out_cap *= 2; out = sl_realloc(vm->arena, out, out_cap); } if(str->buff[str_i] == '"') { memcpy(out + out_len, "\\\"", 2); out_len += 2; } else if(str->buff[str_i] == '\\') { memcpy(out + out_len, "\\\\", 2); out_len += 2; } else if(str->buff[str_i] == '\n') { memcpy(out + out_len, "\\n", 2); out_len += 2; } else if(str->buff[str_i] == '\r') { memcpy(out + out_len, "\\r", 2); out_len += 2; } else if(str->buff[str_i] == '\t') { memcpy(out + out_len, "\\t", 2); out_len += 2; } else if(str->buff[str_i] < 0x20) { out[out_len++] = '\\'; out[out_len++] = 'x'; out[out_len++] = '0' + str->buff[str_i] / 0x10; if(str->buff[str_i] % 0x10 < 10) { out[out_len++] = '0' + str->buff[str_i] % 0x10; } else { out[out_len++] = 'A' + (str->buff[str_i] % 0x10) - 10; } } else { out[out_len++] = str->buff[str_i]; } } out[out_len++] = '"'; return sl_make_string(vm, out, out_len); }
int sl_string_index_for_byte_offset(sl_vm_t* vm, SLVAL strv, int byte_offset) { sl_string_t* str = sl_get_string(vm, strv); uint8_t* buff = str->buff; size_t len = str->buff_len; int index = 0; while(len && byte_offset > 0) { size_t old_len = len; sl_utf8_each_char(vm, &buff, &len); index++; byte_offset -= old_len - len; } if(byte_offset > 0) { return -1; } return index; }
static SLVAL sl_mysql_prepare(sl_vm_t* vm, SLVAL self, SLVAL query) { mysql_t* mysql = get_mysql(vm, self); SLVAL stmtv = sl_allocate(vm, vm->store[cMySQL_Statement]); mysql_stmt_t* stmt = sl_data_get_ptr(vm, &mysql_stmt_data_type, stmtv); stmt->mysql = mysql; if(!(stmt->stmt = mysql_stmt_init(&mysql->mysql))) { sl_mysql_check_error(vm, &mysql->mysql); } sl_string_t* str = sl_get_string(vm, query); if(mysql_stmt_prepare(stmt->stmt, (char*)str->buff, str->buff_len)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } return stmtv; }
static SLVAL string_range_index(sl_vm_t* vm, SLVAL self, SLVAL range) { sl_string_t* str = sl_get_string(vm, self); SLVAL lowerv = sl_range_lower(vm, range); SLVAL upperv = sl_range_upper(vm, range); if(!sl_is_a(vm, lowerv, vm->lib.Int) || !sl_is_a(vm, upperv, vm->lib.Int)) { sl_throw_message2(vm, vm->lib.TypeError, "Expected range of integers"); } long lower = sl_get_int(lowerv), upper = sl_get_int(upperv); if(lower < 0) { lower += str->char_len; } if(lower < 0 || (size_t)lower >= str->char_len) { return sl_make_cstring(vm, ""); } if(upper < 0) { upper += str->char_len; } if(upper < 0) { return sl_make_cstring(vm, ""); } if(sl_range_is_exclusive(vm, range)) { upper--; } if(upper < lower) { return sl_make_cstring(vm, ""); } uint8_t* begin_ptr = str->buff; uint8_t* end_ptr; size_t len = str->buff_len; long idx = 0; while(idx < lower && len) { idx++; sl_utf8_each_char(vm, &begin_ptr, &len); } end_ptr = begin_ptr; while(lower <= upper) { lower++; sl_utf8_each_char(vm, &end_ptr, &len); } return sl_make_string(vm, begin_ptr, (size_t)end_ptr - (size_t)begin_ptr); }
static SLVAL sl_mysql_raw_query(sl_vm_t* vm, SLVAL self, SLVAL query) { mysql_t* mysql = get_mysql(vm, self); sl_string_t* str = sl_get_string(vm, query); if(mysql_real_query(&mysql->mysql, (char*)str->buff, str->buff_len)) { sl_mysql_check_error(vm, &mysql->mysql); } MYSQL_RES* result; if((result = mysql_store_result(&mysql->mysql))) { /* do shit */ int ncolumns = mysql_num_fields(result); int nrows = mysql_num_rows(result); SLVAL* rows = sl_alloc(vm->arena, sizeof(SLVAL) * nrows); MYSQL_FIELD* fields = mysql_fetch_fields(result); for(int i = 0; i < nrows; i++) { SLVAL* cells = sl_alloc(vm->arena, sizeof(SLVAL) * ncolumns * 2); MYSQL_ROW row = mysql_fetch_row(result); size_t* lengths = mysql_fetch_lengths(result); for(int j = 0; j < ncolumns; j++) { cells[j * 2] = sl_make_cstring(vm, fields[j].name); if(row[j]) { cells[j * 2 + 1] = sl_make_string(vm, (uint8_t*)row[j], lengths[j]); } else { cells[j * 2 + 1] = vm->lib.nil; } } rows[i] = sl_make_dict(vm, ncolumns, cells); } mysql_free_result(result); return sl_make_array(vm, nrows, rows); } else { if(mysql_field_count(&mysql->mysql) != 0) { sl_mysql_check_error(vm, &mysql->mysql); } return sl_make_int(vm, mysql_affected_rows(&mysql->mysql)); } }
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 SLVAL sl_mysql_stmt_execute(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv) { mysql_stmt_t* stmt = get_mysql_stmt(vm, self); size_t req = mysql_stmt_param_count(stmt->stmt); if(argc < req) { char buff[100]; sprintf(buff, "Prepared statement has %lu parameter markers, but only %lu parameters were given", req, argc); sl_throw_message2(vm, vm->lib.ArgumentError, buff); } if(!stmt->bind) { stmt->bind = sl_alloc(vm->arena, sizeof(MYSQL_BIND) * req); } for(size_t i = 0; i < req; i++) { stmt->bind[i].buffer_type = MYSQL_TYPE_STRING; sl_string_t* str = sl_get_string(vm, sl_to_s(vm, argv[i])); stmt->bind[i].buffer = str->buff; stmt->bind[i].buffer_length = str->buff_len; stmt->bind[i].length = NULL; stmt->bind[i].is_null = NULL; stmt->bind[i].is_unsigned = 1; stmt->bind[i].error = NULL; } if(mysql_stmt_bind_param(stmt->stmt, stmt->bind)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } if(mysql_stmt_execute(stmt->stmt)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } MYSQL_RES* res = mysql_stmt_result_metadata(stmt->stmt); if(!res) { /* query did not produce a result set */ return sl_make_int(vm, mysql_stmt_affected_rows(stmt->stmt)); } int field_count = mysql_stmt_field_count(stmt->stmt); MYSQL_FIELD* field; SLVAL field_names[field_count]; enum enum_field_types field_types[field_count]; size_t field_i = 0; while((field = mysql_fetch_field(res))) { field_names[field_i] = sl_make_cstring(vm, field->name); if(field->type == MYSQL_TYPE_LONG || field->type == MYSQL_TYPE_SHORT || field->type == MYSQL_TYPE_TINY) { field_types[field_i] = MYSQL_TYPE_LONG; } else { field_types[field_i] = MYSQL_TYPE_STRING; } field_i++; } MYSQL_BIND output_binds[field_count]; my_bool output_errors[field_count]; my_bool output_is_nulls[field_count]; unsigned long output_lengths[field_count]; for(int i = 0; i < field_count; i++) { output_binds[i].buffer_type = MYSQL_TYPE_STRING; output_binds[i].buffer = NULL; output_binds[i].buffer_length = 0; output_binds[i].length = &output_lengths[i]; output_binds[i].is_null = &output_is_nulls[i]; output_binds[i].error = &output_errors[i]; } if(mysql_stmt_bind_result(stmt->stmt, output_binds)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL result_rows = sl_make_array(vm, 0, NULL); while(1) { int code = mysql_stmt_fetch(stmt->stmt); if(code == MYSQL_NO_DATA) { break; } if(code == 1) { sl_mysql_stmt_check_error(vm, stmt->stmt); } SLVAL row = sl_make_dict(vm, 0, NULL); for(int i = 0; i < field_count; i++) { MYSQL_BIND cell; cell.length = &output_lengths[i]; cell.is_null = &output_is_nulls[i]; cell.error = &output_errors[i]; cell.buffer_type = field_types[i]; int buffer_long; switch(field_types[i]) { case MYSQL_TYPE_LONG: cell.buffer = &buffer_long; cell.buffer_length = sizeof(buffer_long); break; default: /* MYSQL_TYPE_STRING */ cell.buffer = sl_alloc_buffer(vm->arena, output_lengths[i] + 1); cell.buffer_length = output_lengths[i]; break; } if(mysql_stmt_fetch_column(stmt->stmt, &cell, i, 0)) { sl_mysql_stmt_check_error(vm, stmt->stmt); } switch(field_types[i]) { case MYSQL_TYPE_LONG: sl_dict_set(vm, row, field_names[i], sl_make_int(vm, buffer_long)); break; default: /* MYSQL_TYPE_STRING */ sl_dict_set(vm, row, field_names[i], sl_make_string(vm, cell.buffer, output_lengths[i])); break; } } sl_array_push(vm, result_rows, 1, &row); } return result_rows; }
SLVAL sl_string_length(sl_vm_t* vm, SLVAL self) { return sl_make_int(vm, sl_get_string(vm, self)->char_len); }
static SLVAL sl_string_hash(sl_vm_t* vm, SLVAL self) { return sl_make_int(vm, str_hash(vm, sl_get_string(vm, self))); }
static SLVAL sl_string_spaceship(sl_vm_t* vm, SLVAL self, SLVAL other) { return sl_make_int(vm, str_cmp(vm, sl_get_string(vm, self), sl_get_string(vm, other))); }
static SLVAL sl_string_to_i(sl_vm_t* vm, SLVAL self) { sl_string_t* str = sl_get_string(vm, self); return sl_integer_parse(vm, str->buff, str->buff_len); }
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; }