예제 #1
0
파일: Doc.c 프로젝트: gitpan/Lucy
static HV*
S_thaw_fields(lucy_InStream *instream) {
    // Read frozen data into an SV buffer.
    size_t len = (size_t)LUCY_InStream_Read_C64(instream);
    SV *buf_sv = newSV(len + 1);
    SvPOK_on(buf_sv);
    SvCUR_set(buf_sv, len);
    char *buf = SvPVX(buf_sv);
    LUCY_InStream_Read_Bytes(instream, buf, len);

    // Call back to Storable to thaw the frozen hash.
    dSP;
    ENTER;
    SAVETMPS;
    EXTEND(SP, 1);
    PUSHMARK(SP);
    mPUSHs(buf_sv);
    PUTBACK;
    call_pv("Storable::thaw", G_SCALAR);
    SPAGAIN;
    SV *frozen = POPs;
    if (frozen && !SvROK(frozen)) {
        CFISH_THROW(CFISH_ERR, "thaw failed");
    }
    HV *fields = (HV*)SvRV(frozen);
    (void)SvREFCNT_inc((SV*)fields);
    PUTBACK;
    FREETMPS;
    LEAVE;

    return fields;
}
예제 #2
0
파일: Host.c 프로젝트: gitpan/KinoSearch
static SV*
S_do_callback_sv(void *vobj, char *method, uint32_t num_args, va_list args) 
{
    SV *return_val;
    SI_push_args(vobj, args, num_args);
    {
        int num_returned = call_method(method, G_SCALAR);
        dSP;
        if (num_returned != 1) {
            CFISH_THROW(KINO_ERR, "Bad number of return vals from %s: %i32", method,
                (int32_t)num_returned);
        }
        return_val = POPs;
        PUTBACK;
    }
    return return_val;
}
예제 #3
0
파일: Host.c 프로젝트: gitpan/KinoSearch
void
kino_Host_callback(void *vobj, char *method, uint32_t num_args, ...) 
{
    va_list args;
    
    va_start(args, num_args);
    SI_push_args(vobj, args, num_args);
    va_end(args);
    
    {
        int count = call_method(method, G_VOID|G_DISCARD);
        if (count != 0) {
            CFISH_THROW(KINO_ERR, "callback '%s' returned too many values: %i32", 
                method, (int32_t)count);
        }
        FREETMPS;
        LEAVE;
    }
}
예제 #4
0
파일: Obj.c 프로젝트: gitpan/KinoSearch
kino_Obj*
kino_Obj_inc_refcount(kino_Obj *self)
{
    switch (self->ref.count) {
        case 0:
            CFISH_THROW(KINO_ERR, "Illegal refcount of 0");
            break; // useless 
        case 1:
        case 2:
            self->ref.count++;
            break;
        case 3:
            S_lazy_init_host_obj(self);
            // fall through 
        default:
            SvREFCNT_inc_simple_void_NN((SV*)self->ref.host_obj);
    }
    return self;
}
예제 #5
0
파일: Obj.c 프로젝트: gitpan/KinoSearch
uint32_t
kino_Obj_dec_refcount(kino_Obj *self)
{
    uint32_t modified_refcount = I32_MAX;
    switch (self->ref.count) {
        case 0:
            CFISH_THROW(KINO_ERR, "Illegal refcount of 0");
            break; // useless 
        case 1:
            modified_refcount = 0;
            Kino_Obj_Destroy(self);
            break;
        case 2:
        case 3:
            modified_refcount = --self->ref.count;
            break;
        default:
            modified_refcount = SvREFCNT((SV*)self->ref.host_obj) - 1;
            // If the SV's refcount falls to 0, DESTROY will be invoked from
            // Perl-space.
            SvREFCNT_dec((SV*)self->ref.host_obj);
    }
    return modified_refcount;
}
예제 #6
0
lucy_HitDoc*
lucy_DefDocReader_fetch_doc(lucy_DefaultDocReader *self, int32_t doc_id) {
    lucy_Schema   *const schema = self->schema;
    lucy_InStream *const dat_in = self->dat_in;
    lucy_InStream *const ix_in  = self->ix_in;
    HV *fields = newHV();
    int64_t start;
    uint32_t num_fields;
    SV *field_name_sv = newSV(1);

    // Get data file pointer from index, read number of fields.
    Lucy_InStream_Seek(ix_in, (int64_t)doc_id * 8);
    start = Lucy_InStream_Read_U64(ix_in);
    Lucy_InStream_Seek(dat_in, start);
    num_fields = Lucy_InStream_Read_C32(dat_in);

    // Decode stored data and build up the doc field by field.
    while (num_fields--) {
        STRLEN  field_name_len;
        char   *field_name_ptr;
        SV     *value_sv;
        lucy_FieldType *type;

        // Read field name.
        field_name_len = Lucy_InStream_Read_C32(dat_in);
        field_name_ptr = SvGROW(field_name_sv, field_name_len + 1);
        Lucy_InStream_Read_Bytes(dat_in, field_name_ptr, field_name_len);
        SvPOK_on(field_name_sv);
        SvCUR_set(field_name_sv, field_name_len);
        SvUTF8_on(field_name_sv);
        *SvEND(field_name_sv) = '\0';

        // Find the Field's FieldType.
        lucy_ZombieCharBuf *field_name_zcb
            = CFISH_ZCB_WRAP_STR(field_name_ptr, field_name_len);
        Lucy_ZCB_Assign_Str(field_name_zcb, field_name_ptr, field_name_len);
        type = Lucy_Schema_Fetch_Type(schema, (lucy_CharBuf*)field_name_zcb);

        // Read the field value.
        switch (Lucy_FType_Primitive_ID(type) & lucy_FType_PRIMITIVE_ID_MASK) {
            case lucy_FType_TEXT: {
                    STRLEN value_len = Lucy_InStream_Read_C32(dat_in);
                    value_sv = newSV((value_len ? value_len : 1));
                    Lucy_InStream_Read_Bytes(dat_in, SvPVX(value_sv), value_len);
                    SvCUR_set(value_sv, value_len);
                    *SvEND(value_sv) = '\0';
                    SvPOK_on(value_sv);
                    SvUTF8_on(value_sv);
                    break;
                }
            case lucy_FType_BLOB: {
                    STRLEN value_len = Lucy_InStream_Read_C32(dat_in);
                    value_sv = newSV((value_len ? value_len : 1));
                    Lucy_InStream_Read_Bytes(dat_in, SvPVX(value_sv), value_len);
                    SvCUR_set(value_sv, value_len);
                    *SvEND(value_sv) = '\0';
                    SvPOK_on(value_sv);
                    break;
                }
            case lucy_FType_FLOAT32:
                value_sv = newSVnv(Lucy_InStream_Read_F32(dat_in));
                break;
            case lucy_FType_FLOAT64:
                value_sv = newSVnv(Lucy_InStream_Read_F64(dat_in));
                break;
            case lucy_FType_INT32:
                value_sv = newSViv((int32_t)Lucy_InStream_Read_C32(dat_in));
                break;
            case lucy_FType_INT64:
                if (sizeof(IV) == 8) {
                    int64_t val = (int64_t)Lucy_InStream_Read_C64(dat_in);
                    value_sv = newSViv((IV)val);
                }
                else { // (lossy)
                    int64_t val = (int64_t)Lucy_InStream_Read_C64(dat_in);
                    value_sv = newSVnv((double)val);
                }
                break;
            default:
                value_sv = NULL;
                CFISH_THROW(LUCY_ERR, "Unrecognized type: %o", type);
        }

        // Store the value.
        (void)hv_store_ent(fields, field_name_sv, value_sv, 0);
    }
    SvREFCNT_dec(field_name_sv);

    lucy_HitDoc *retval = lucy_HitDoc_new(fields, doc_id, 0.0);
    SvREFCNT_dec((SV*)fields);
    return retval;
}
예제 #7
0
파일: Host.c 프로젝트: gitpan/KinoSearch
// Convert all arguments to Perl and place them on the Perl stack. 
static CHY_INLINE void
SI_push_args(void *vobj, va_list args, uint32_t num_args)
{
    kino_Obj *obj = (kino_Obj*)vobj;
    SV *invoker;
    uint32_t i;
    dSP;

    uint32_t stack_slots_needed = num_args < 2
                                ? num_args + 1
                                : (num_args * 2) + 1;
    EXTEND(SP, stack_slots_needed);
    
    if (Kino_Obj_Is_A(obj, KINO_VTABLE)) {
        kino_VTable *vtable = (kino_VTable*)obj;
        // TODO: Creating a new class name SV every time is wasteful. 
        invoker = XSBind_cb_to_sv(Kino_VTable_Get_Name(vtable));
    }
    else {
        invoker = (SV*)Kino_Obj_To_Host(obj);
    }

    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    PUSHs( sv_2mortal(invoker) );

    for (i = 0; i < num_args; i++) {
        uint32_t arg_type = va_arg(args, uint32_t);
        char *label = va_arg(args, char*);
        if (num_args > 1) {
            PUSHs( sv_2mortal( newSVpvn(label, strlen(label)) ) );
        }
        switch (arg_type & CFISH_HOST_ARGTYPE_MASK) {
        case CFISH_HOST_ARGTYPE_I32: {
                int32_t value = va_arg(args, int32_t);
                PUSHs( sv_2mortal( newSViv(value) ) );
            }
            break;
        case CFISH_HOST_ARGTYPE_I64: {
                int64_t value = va_arg(args, int64_t);
                if (sizeof(IV) == 8) {
                    PUSHs( sv_2mortal( newSViv((IV)value) ) );
                }
                else {
                    // lossy 
                    PUSHs( sv_2mortal( newSVnv((double)value) ) );
                }
            }
            break;
        case CFISH_HOST_ARGTYPE_F32:
        case CFISH_HOST_ARGTYPE_F64: {
                // Floats are promoted to doubles by variadic calling. 
                double value = va_arg(args, double);
                PUSHs( sv_2mortal( newSVnv(value) ) );
            }
            break;
        case CFISH_HOST_ARGTYPE_STR: {
                kino_CharBuf *string = va_arg(args, kino_CharBuf*);
                PUSHs( sv_2mortal( XSBind_cb_to_sv(string) ) );
            }
            break;
        case CFISH_HOST_ARGTYPE_OBJ: {
                kino_Obj* anObj = va_arg(args, kino_Obj*);
                SV *arg_sv = anObj == NULL
                    ? newSV(0)
                    : XSBind_cfish_to_perl(anObj);
                PUSHs( sv_2mortal(arg_sv) );
            }
            break;
        default:
            CFISH_THROW(KINO_ERR, "Unrecognized arg type: %u32", arg_type);
        }
    }

    PUTBACK;
}