Ejemplo n.º 1
0
Archivo: string.c Proyecto: richo/slash
char*
sl_iconv(sl_vm_t* vm, char* input_string, size_t input_length, char* from_encoding, char* to_encoding, size_t* output_length)
{
    iconv_t cd = iconv_open(to_encoding, from_encoding);
    if(cd == (iconv_t)(-1)) {
        sl_throw_message2(vm, vm->lib.EncodingError, "Unknown encoding");
    }
    char* in_buff = input_string;
    size_t in_bytes_left = input_length;
    size_t out_bytes_left = in_bytes_left * 4 + 15;
    size_t out_cap = out_bytes_left;
    char* out_buff = sl_alloc_buffer(vm->arena, out_cap);
    char* retn_out_buff = out_buff;
    while(1) {
        size_t ret = iconv(cd, &in_buff, &in_bytes_left, &out_buff, &out_bytes_left);
        if(ret != (size_t)(-1)) {
            break;
        }
        if(errno == E2BIG) {
            out_bytes_left = input_length;
            out_cap += input_length;
            out_buff = sl_realloc(vm->arena, out_buff, out_cap);
            continue;
        }
        if(errno == EILSEQ || errno == EINVAL) {
            iconv_close(cd);
            sl_throw_message2(vm, vm->lib.EncodingError, "Invalid encoding in source buffer");
        }
        break;
    }
    iconv_close(cd);
    *output_length = out_cap - out_bytes_left;
    return retn_out_buff;
}
Ejemplo n.º 2
0
Archivo: string.c Proyecto: richo/slash
static void
ensure_utf8(sl_vm_t* vm, uint8_t* buff, size_t buff_len)
{
    if(!sl_is_valid_utf8(buff, buff_len)) {
        sl_throw_message2(vm, vm->lib.EncodingError, "Invalid UTF-8");
    }
}
Ejemplo n.º 3
0
Archivo: mysql.c Proyecto: Hmaal/slash
static void
sl_mysql_stmt_check_error(sl_vm_t* vm, MYSQL_STMT* stmt)
{
    const char* cerr = mysql_stmt_error(stmt);
    if(!cerr[0]) {
        return;
    }
    sl_throw_message2(vm, vm->store[cMySQL_Error], (char*)cerr);
}
Ejemplo n.º 4
0
static gcrypt_algorithm_t*
get_algo_check(sl_vm_t* vm, SLVAL obj)
{
    gcrypt_algorithm_t* ptr = get_algo(vm, obj);
    if(ptr->algo == 0) {
        sl_throw_message2(vm, vm->lib.TypeError, "Invalid GCrypt::Algorithm");
    }
    return ptr;
}
Ejemplo n.º 5
0
Archivo: method.c Proyecto: Hmaal/slash
static SLVAL
method_apply(sl_vm_t* vm, SLVAL method, size_t argc, SLVAL* argv)
{
    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 apply uninitialized Method");
    }
    return sl_apply_method(vm, argv[0], methp, argc - 1, argv + 1);
}
Ejemplo n.º 6
0
static SLVAL
method_apply(sl_vm_t* vm, SLVAL method, size_t argc, SLVAL* argv)
{
    sl_method_t* methp = (sl_method_t*)sl_get_ptr(method);
    if(!methp->initialized) {
        sl_throw_message2(vm, vm->lib.TypeError, "Can't apply uninitialized Method");
    }
    return sl_apply_method(vm, argv[0], methp, argc - 1, argv + 1);
}
Ejemplo n.º 7
0
static sl_regexp_t*
get_regexp_check(sl_vm_t* vm, SLVAL rev)
{
    sl_regexp_t* re = get_regexp(vm, rev);
    if(!re->re) {
        sl_throw_message2(vm, vm->lib.TypeError, "Invalid operation on uninitialized regexp");
    }
    return re;
}
Ejemplo n.º 8
0
Archivo: method.c Proyecto: Hmaal/slash
static SLVAL
bound_method_call(sl_vm_t* vm, SLVAL bmethod, size_t argc, SLVAL* argv)
{
    sl_method_t* methp = (sl_method_t*)sl_get_ptr(bmethod);
    if(!(methp->base.user_flags & SL_FLAG_METHOD_INITIALIZED)) {
        sl_throw_message2(vm, vm->lib.TypeError, "Can't call uninitialized BoundMethod");
    }
    return sl_apply_method(vm, methp->extra->bound_self, methp, argc, argv);
}
Ejemplo n.º 9
0
Archivo: mysql.c Proyecto: Hmaal/slash
static mysql_t*
get_mysql(sl_vm_t* vm, SLVAL obj)
{
    mysql_t* mysql = sl_data_get_ptr(vm, &mysql_data_type, obj);
    if(!mysql->valid) {
        sl_throw_message2(vm, vm->lib.TypeError, "Invalid MySQL instance");
    }
    return mysql;
}
Ejemplo n.º 10
0
Archivo: mysql.c Proyecto: Hmaal/slash
static mysql_stmt_t*
get_mysql_stmt(sl_vm_t* vm, SLVAL obj)
{
    mysql_stmt_t* stmt = sl_data_get_ptr(vm, &mysql_stmt_data_type, obj);
    if(!stmt->stmt) {
        sl_throw_message2(vm, vm->lib.TypeError, "Invalid operation on uninitialized MySQL::Statement instance");
    }
    return stmt;
}
Ejemplo n.º 11
0
static SLVAL
bound_method_call(sl_vm_t* vm, SLVAL bmethod, size_t argc, SLVAL* argv)
{
    sl_bound_method_t* bmethp = (sl_bound_method_t*)sl_get_ptr(bmethod);
    if(!bmethp->method.initialized) {
        sl_throw_message2(vm, vm->lib.TypeError, "Can't call uninitialized BoundMethod");
    }
    return sl_apply_method(vm, bmethp->self, &bmethp->method, argc, argv);
}
Ejemplo n.º 12
0
Archivo: regexp.c Proyecto: Hmaal/slash
static void
check_pcre_error(sl_vm_t* vm, int rc)
{
    if(rc == PCRE_ERROR_BADUTF8) {
        sl_throw_message2(vm, vm->lib.EncodingError, "Invalid UTF-8 in regular expression or match text");
    }
    if(rc < 0) {
        sl_error(vm, vm->lib.Error, "PCRE error (%d)", rc);
    }
}
Ejemplo n.º 13
0
static SLVAL
range_enumerator_current(sl_vm_t* vm, SLVAL self)
{
    sl_range_enumerator_t* range_enum = get_range_enumerator(vm, self);
    check_range_enumerator(vm, range_enum);
    if(range_enum->state != ES_ITERATING) {
        sl_throw_message2(vm, vm->lib.TypeError, "Invalid operation on Range::Enumerator");
    }
    return range_enum->current;
}
Ejemplo n.º 14
0
static void
check_range_enumerator(sl_vm_t* vm, sl_range_enumerator_t* range_enum)
{
    if(sl_responds_to2(vm, range_enum->current, vm->id.succ)) {
        if(sl_responds_to2(vm, range_enum->current, range_enum->method)) {
            return;
        }
    }
    sl_throw_message2(vm, vm->lib.TypeError, "Uniterable type in range");
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
Archivo: method.c Proyecto: Hmaal/slash
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);
}
Ejemplo n.º 17
0
Archivo: method.c Proyecto: Hmaal/slash
static SLVAL
bound_method_unbind(sl_vm_t* vm, SLVAL bmethod)
{
    sl_method_t* bmethp = (sl_method_t*)sl_get_ptr(bmethod);
    if(!(bmethp->base.user_flags & SL_FLAG_METHOD_INITIALIZED)) {
        sl_throw_message2(vm, vm->lib.TypeError, "Can't unbind uninitalized BoundMethod");
    }
    sl_method_t* methp = method_dup(vm, bmethp);
    methp->extra->bound_self = vm->lib.nil;
    methp->base.klass = vm->lib.Method;
    return sl_make_ptr((sl_object_t*)methp);
}
Ejemplo n.º 18
0
static void
sl_setup_regexp(sl_vm_t* vm, sl_regexp_t* re_ptr, uint8_t* re_buff, size_t re_len, uint8_t* opts_buff, size_t opts_len)
{
    char buff[256];
    const char* error;
    char* rez;
    int error_offset;
    int opts = DEFAULT_OPTIONS;
    pcre* re;
    size_t i;
    for(i = 0; i < opts_len; i++) {
        switch(opts_buff[i]) {
            case 'i':
                opts |= PCRE_CASELESS;
                break;
            case 'x':
                opts |= PCRE_EXTENDED;
                break;
            default:
                sprintf(buff, "Unknown regular expression option '%c'", opts_buff[i]);
                sl_throw_message2(vm, vm->lib.ArgumentError, buff);
        }
    }
    if(memchr(re_buff, 0, re_len)) {
        sl_throw_message2(vm, vm->lib.ArgumentError, "Regular expression contains null byte");
    }
    rez = sl_alloc_buffer(vm->arena, re_len + 1);
    memcpy(rez, re_buff, re_len);
    rez[re_len] = 0;
    re = pcre_compile(rez, opts, &error, &error_offset, NULL);
    if(!re) {
        sl_throw_message2(vm, vm->lib.SyntaxError, (char*)error);
    }
    re_ptr->source = sl_make_string(vm, re_buff, re_len);
    re_ptr->options = opts;
    re_ptr->re = re;
    re_ptr->study = NULL;
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
Archivo: string.c Proyecto: richo/slash
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 == 0) {
        return sl_make_cstring(vm, "");
    }
    if(mul < 0) {
        sl_throw_message2(vm, vm->lib.ArgumentError, "String multiplier must be positive");
    }
    if(mul > 0 && (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);
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
Archivo: string.c Proyecto: richo/slash
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);
}
Ejemplo n.º 23
0
Archivo: json.c Proyecto: Hmaal/slash
static void
sl_json_parse_check_error(sl_vm_t* vm, sl_string_t* str, json_parse_t* json, yajl_status status)
{
    uint8_t* err_str;
    SLVAL err;
    if(status == yajl_status_client_canceled) {
        /* the only reason we'd cancel the parse is if the data structre is too deep */
        yajl_free(json->yajl);
        sl_throw_message2(vm, vm->store[cJSON_ParseError],
            "JSON structure recurses too deep");
    }
    if(status == yajl_status_error) {
        err_str = yajl_get_error(json->yajl, 0, (const uint8_t*)str->buff, (size_t)str->buff_len);
        err = sl_make_cstring(vm, (char*)err_str);
        yajl_free_error(json->yajl, err_str);
        yajl_free(json->yajl);
        sl_throw(vm, sl_make_error2(vm, vm->store[cJSON_ParseError], err));
    }
}
Ejemplo n.º 24
0
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);
}
Ejemplo n.º 25
0
static SLVAL
enumerable_reduce(sl_vm_t* vm, SLVAL self, size_t argc, SLVAL* argv)
{
    SLVAL enumerator = sl_send(vm, self, "enumerate", 0);
    SLVAL acc, val, f;
    if(argc == 1) {
        if(!sl_is_truthy(sl_send(vm, enumerator, "next", 0))) {
            sl_throw_message2(vm, vm->lib.ArgumentError, "Can't reduce empty array without initializer");
        } else {
            acc = sl_send(vm, enumerator, "current", 0);
        }
        f = argv[0];
    } else {
        acc = argv[0];
        f = argv[1];
    }
    while(sl_is_truthy(sl_send(vm, enumerator, "next", 0))) {
        val = sl_send(vm, enumerator, "current", 0);
        acc = sl_send(vm, f, "call", 2, acc, val);
    }
    return acc;
}
Ejemplo n.º 26
0
Archivo: mysql.c Proyecto: Hmaal/slash
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;
}