Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
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);
    }
}
Beispiel #5
0
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);
}
Beispiel #6
0
SLVAL
sl_float_pow(sl_vm_t* vm, SLVAL self, SLVAL other)
{
    if(sl_is_a(vm, other, vm->lib.Bignum)) {
        return sl_float_pow(vm, self, sl_bignum_to_f(vm, other));
    }
    if(sl_is_a(vm, other, vm->lib.Int)) {
        return sl_float_pow(vm, self, sl_make_float(vm, sl_get_int(other)));
    }
    return sl_make_float(vm, pow(sl_get_float(vm, self), sl_get_float(vm, other)));
}
Beispiel #7
0
static SLVAL
enumerable_take(sl_vm_t* vm, SLVAL self, SLVAL countv)
{
    SLVAL ary = sl_make_array(vm, 0, NULL);
    SLVAL enumerator = sl_send(vm, self, "enumerate", 0);
    
    for(int count = sl_get_int(countv); count > 0; count--) {
        if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) {
            return ary;
        }
        SLVAL elem = sl_send(vm, enumerator, "current", 0);
        sl_array_push(vm, ary, 1, &elem);
    }
    
    return ary;
}
Beispiel #8
0
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);
}
Beispiel #9
0
SLVAL
sl_float_eq(sl_vm_t* vm, SLVAL self, SLVAL other)
{
    if(sl_is_a(vm, other, vm->lib.Int)) {
        return sl_float_eq(vm, self, sl_make_float(vm, sl_get_int(other)));
    }
    if(sl_is_a(vm, other, vm->lib.Bignum)) {
        if(fmod(sl_get_float(vm, self), 1.0) == 0.0) {
            return sl_bignum_eq(vm, sl_make_bignum_f(vm, sl_get_float(vm, self)), other);
        } else {
            return vm->lib._false;
        }
    }
    if(!sl_is_a(vm, other, vm->lib.Float)) {
        return vm->lib._false;
    }
    return sl_make_bool(vm, sl_get_float(vm, self) == sl_get_float(vm, other));
}
Beispiel #10
0
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;
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
    }
}
Beispiel #13
0
static SLVAL
int_ordinalize(sl_vm_t* vm, SLVAL self)
{
    int i = sl_get_int(self);
    return sl_string_concat(vm, sl_to_s(vm, self), ordinalize(vm, i % 10));
}
Beispiel #14
0
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;
}
Beispiel #15
-6
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;
}