/* Here we add the accessors for the structure #define kG(x) ((x)->G0) #define kC(x) kG(x) #define kH(x) ((H*)kG(x)) #define kI(x) ((I*)kG(x)) #define kJ(x) ((J*)kG(x)) #define kE(x) ((E*)kG(x)) #define kF(x) ((F*)kG(x)) #define kS(x) ((S*)kG(x)) #define kK(x) ((K*)kG(x)) */ // Is this a perl scalar value we can handle? #define SCALAR(x) (x == SVt_IV || x == SVt_NV || x == SVt_PV || x == SVt_PVNV) #define dumpK(x,s) {fprintf(stderr,"%s -> Ref:%d Typ:%d Num:%d g:%hhu h:%d i:%d j:%g e:%g f:%g G01:%hhu G02:%hhu\n",s,x->r,x->t,x->n,x->g,x->h,x->i,x->j,x->e,x->f,x->G0[0],x->G0[1]);} #define myerr(s) {fprintf(stderr,s);} // 0 ==> turn off Z to epoch conversion // 1 ==> turn on Z to epoch conversion // 2 ==> turn on Z to epoch plus millisecond conversion static int __Z2e = 1; int __Z2epoch(int mode) { __Z2e = mode; R(__Z2e);} /* Recall that a UNIX time is the number of seconds since 1970.01.01T00:00:00 while a Kdb+ datetime is a 64 bit float number of days since 2000.01.01 // return 86400*(datetime+10957); // return epoch/8.64e4-10957; */ double epoch2Z(int epoch) { double datetime = epoch/8.64e4-10957; // fprintf(stderr,"epoch2Z: %d -> %g\n",epoch,datetime); return(datetime); } double Z2epochf(double datetime) { double frac, epoch; if(__Z2e == 0) return datetime; // days * secs in day + secs to 1/1/2000 // epoch = ((int) datetime) * 86400 + 946645200; epoch = ((int) datetime +10957) * 86400; // now get hours added in // fraction of datetime * seconds in day / seconds in hour // gives hh.blah frac = ((datetime - (int)datetime) * 86400)/3600; epoch += ((int) frac) * 3600; // minutes frac = (frac - (int) frac) * 60; epoch += ((int) frac) * 60; // Seconds frac = (frac - (int) frac) * 60; epoch += ((int) frac); // milli Seconds frac = (frac - (int) frac) * 1000; frac = round(frac) / 1000.0; epoch += frac; return(epoch); } int Z2epoch(double datetime) { //int epoch = 86400*(datetime+10957); int epoch = Z2epochf(datetime); // fprintf(stderr,"Z2epoch: %g -> %d\n",datetime,epoch); return(epoch); } int D2epoch(double datetime) { int epoch = 86400*(datetime+10957); // fprintf(stderr,"D2epoch: %g -> %d\n",datetime,epoch); return(epoch); } unsigned char kChar (Kstruct * x) { return kC(x)[0]; }; short * kShort (Kstruct * x) { return kH(x); }; int * kInt (Kstruct * x) { return kI(x); }; long long * kLong (Kstruct * x) { return kJ(x); }; float * kReal (Kstruct * x) { return kE(x); }; double * kFloat (Kstruct * x) { return kF(x); }; char * kSymbol (Kstruct * x) { return (char*)kS(x); }; Kstruct * kStruct (Kstruct * x) { return (Kstruct *)kK(x); }; Kstruct * kStructi (Kstruct * x, int i) { return (Kstruct *)kK(x)[i]; }; /* An accessor for the number */ short kNum (Kstruct * x) { return ((x)->n); }; /* An accessor for the reference count details */ int kRefCnt (Kstruct * x) { return ((x)->r); }; /* An accessor for the type details */ short kType (Kstruct * x) { return ((x)->t); }; /* An accessor for the Attributes */ short kAtt (Kstruct * x) { return ((x)->u); }; #define Assert(e,s) {if(e) printf("%s\n",s);} /* accessor for a ktd*/ Kstruct * Ktd (Kstruct * x) { K y,keys; // Connection broken if( x == 0 ) { myerr("Kx::Ktd connection broken\n"); return(x); } // Error if( x->t == -128 ) { myerr("Kx::Ktd syntax error\n"); return(x); } // Assert(!(x=ktd(x)),"type") x=ktd(x); if( x == 0 ) { myerr("Kx::Ktd ktd() type failure\n"); return(x); } y = x->k; // dict from flip above. if( !(y->t == 99) ) { myerr("Kx::Ktd ktd() can't convert to a dict\n"); return(x); } keys=kK(x->k)[0]; // holds an array of symbols if( !(keys->t == KS) ) { myerr("Kx::Ktd ktd() Keys should be an array of symbols\n"); return(x); } return(x); }; /* accessor for a table select */ Kstruct * kTable (int c, char * cmd) { K x,y,tmp,keys; // run command and return a result, New k object created x = k(c,cmd,0); // Connection broken if( x == 0 ) { myerr("Kx::kTable connection broken\n"); return(x); } // Error if( x->t == -128 ) { myerr("Kx::kTable syntax error\n"); return(x); } // Assert(!(t=ktd(x)),"type") tmp=ktd(x); if( tmp == 0 ) { myerr("Kx::kTable ktd() type failure\n"); return(x); } x = tmp; // x was deallocated in ktd y = x->k; // dict from flip above. if( !(y->t == 99) ) { myerr("Kx::kTable ktd() can't convert to a dict\n"); return(x); } keys=kK(x->k)[0]; // holds an array of symbols if( !(keys->t == KS) ) { myerr("Kx::kTable ktd() Keys should be an array of symbols\n"); return(x); } return(x); }; /* accessor for a table column headings */ Kstruct * kTableH (Kstruct * x) { K keys=kK(x->k)[0]; Assert(!(keys->t == KS),"kTableH Keys should be an array of symbols") return(keys); }; /* accessor for K list of arrays of values by type for each column */ Kstruct * kTableCols (Kstruct * x) { K keys=kK(x->k)[0]; K vals=kK(x->k)[1]; Assert(!(keys->t == KS),"kTableCols Keys should be an array of symbols") return(vals); }; int kTableNumRows (Kstruct * x) { K y; K keys=kK(x->k)[0]; K vals=kK(x->k)[1]; Assert(!(keys->t == KS),"kTableNumRows Keys should be an array of symbols") y = kK(vals)[0]; return(y->n); }; int kTableNumCols (Kstruct * x) { K keys=kK(x->k)[0]; K vals=kK(x->k)[1]; Assert(!(keys->t == KS),"kTableNumCols Keys should be an array of symbols") return(vals->n); }; /* Return the value found at index(row,col) */ SV * k2p (Kstruct * ); SV * kTableIndex (Kstruct * x, int row, int col) { K chdr; H ctyp; K keys=kK(x->k)[0]; K vals=kK(x->k)[1]; Assert(!(keys->t == KS),"Keys should be an array of symbols") chdr = kK(vals)[col]; // the head of this column ctyp = chdr->t; // this columns type if(ctyp > 0 ) { switch(ctyp) { CS(KB,return newSViv(kG(chdr)[row])) CS(KG,return newSViv(kG(chdr)[row])) CS(KH,return newSViv(kH(chdr)[row])) CS(KI,return newSViv(kI(chdr)[row])) CS(KE,return newSVnv((double)kE(chdr)[row])) CS(KF,return newSVnv((double)kF(chdr)[row])) CS(KJ,return newSVnv((double)kJ(chdr)[row])) CS(KC,return newSViv(kC(chdr)[row])) CS(KS,return newSVpv((const char*)kS(chdr)[row],0)) CS(KM,return newSViv(kI(chdr)[row])) CS(KD,return newSViv(D2epoch((double)kI(chdr)[row]))) CS(KZ,return __Z2e == 1 ? newSViv(Z2epoch(kF(chdr)[row])) : newSVnv(Z2epochf(kF(chdr)[row]))) CS(KU,return newSViv(kI(chdr)[row])) CS(KV,return newSViv(kI(chdr)[row])) CS(KT,return newSViv(kI(chdr)[row])) CD: return newSV(0); }; } else { return k2p(kK(chdr)[row]); } } /* Return a Perl Scalar value representation for the K value handed in. K types 'date' and 'datetime' are converted to epoch seconds. Symbols are converted to strings If x->t is negative then the object is a scalar and we should use the scalar accessors. If x->t is greater than zero then we use vector accessors as all the elements are of that type (eg. x->t == 9 for a vector of Kdb+ floats). A more interesting case is where x->t is exactly zero. This means that the K object contains a mixed list of other K objects. Each element in the list is a pointer to another K object. To access each element of the object x we use the kK object accessor. At the moment we assume (no require) the object to hold a simple scalar */ SV * k2pscalar (Kstruct * x) { // The type should be negative for an atom. H typ = x->t; // this objects type if(typ >= 0) { return k2p(x); // bail out, let k2p handle it } typ = abs(typ); switch(typ) { CS(KB,return newSViv((int)x->g)) CS(KG,return newSViv((int)x->g)) CS(KH,return newSViv((int)x->h)) CS(KI,return newSViv(x->i)) CS(KE,return newSVnv((double)x->e)) CS(KF,return newSVnv((double)x->f)) CS(KJ,return newSVnv((double)x->j)) CS(KC,return newSViv((int)x->g)) CS(KS,return newSVpv((const char*)x->s,0)) CS(128,return newSVpv((const char*)x->s,0)) CS(KM,return newSViv(x->i)) CS(KD,return newSViv(D2epoch((double)x->i))) CS(KZ,return __Z2e == 1 ? newSViv(Z2epoch(x->f)) : newSVnv(Z2epochf(x->f))) CS(KU,return newSViv(x->i)) CS(KV,return newSViv(x->i)) CS(KT,return newSViv(x->i)) CD: return newSV(0); }; }; SV * k2pscalar0 (Kstruct * x) { SV *sv = k2pscalar(x); r0(x); return sv; } #define DOAV(n,AV,x) {I i=0,_i=(n);for(;i<_i;++i){av_push(AV, x);}} HV* k2phash (Kstruct *x); // Convert a K vector of objects to a Perl array AV * k2parray (Kstruct * x) { AV *av1; HV *hv; H typ = x->t; // this arrays type AV *av = newAV(); if(typ < 0) { warn("Kx::k2parray arg is not right type got %i\n",typ); return av; // bail out as its a scalar } // warn(" In k2parray doing type = %i, num = %i\n",typ,x->n); // is it a mixed list? if(typ == 0) { /* Loop through the list working out what the types are and doing * the conversion as required */ I i=0; for(; i < x->n; ++i) { K atom = kK(x)[i]; if(atom->t == XT || atom->t == XD) { // a table/dict hv = k2phash(atom); av_push(av, newRV_noinc((SV*) hv)); } else if(atom->t >= 0) { // another vector, so recurse av1 = k2parray(atom); av_push(av, newRV_noinc((SV*) av1)); } else { av_push(av, k2pscalar(atom)); } } // warn(" Out k2parray doing type = %i, num = %i\n\n",typ,x->n); return av; } else { /* The list is of a single consistent type. So the 'for' loop is * done within each case statement. KG (bytes) and KC (chars) are * converted into a single string. */ HV *hv; switch(typ) { CS(KB, DOAV(x->n,av,newSViv(kG(x)[i]))) CS(KG, av_push(av, newSVpv((const char*)kG(x),x->n))) CS(KH, DOAV(x->n,av,newSViv(kH(x)[i]))) CS(KI, DOAV(x->n,av,newSViv(kI(x)[i]))) CS(KE, DOAV(x->n,av,newSVnv((double)kE(x)[i]))) CS(KF, DOAV(x->n,av,newSVnv((double)kF(x)[i]))) CS(KJ, DOAV(x->n,av,newSVnv((double)kJ(x)[i]))) CS(KC, av_push(av, newSVpv((const char*)kC(x),x->n))) CS(KS, DOAV(x->n,av,newSVpv((const char*)kS(x)[i],0))) CS(KM, DOAV(x->n,av,newSViv(kI(x)[i]))) CS(KD, DOAV(x->n,av,newSViv(D2epoch((double)kI(x)[i])))) CS(KZ, DOAV(x->n,av,__Z2e == 1 ? newSViv(Z2epoch(kF(x)[i])) : newSVnv(Z2epochf(kF(x)[i])) )) CS(KU, DOAV(x->n,av,newSViv(kI(x)[i]))) CS(KV, DOAV(x->n,av,newSViv(kI(x)[i]))) CS(KT, DOAV(x->n,av,newSViv(kI(x)[i]))) CS(XT, hv = k2phash(x); av_push(av, newRV_noinc((SV*) hv))) CS(XD, hv = k2phash(x); av_push(av, newRV_noinc((SV*) hv))) // CD: warn("Null Array type=%i\n",typ);return av; // undef CD: return av; // undef }; } // warn(" Out k2parray doing type = %i, num = %i\n\n",typ,x->n); return av; } // Convert a K vector of objects to a Perl array, drop refcount on x AV * k2parray0 (Kstruct * x) { AV *av = k2parray(x); r0(x); return av; } /* Return a Perl Hash that describes a K dict or Table object */ HV* k2phash (Kstruct *tb) { K x, tmp; SV *sv; SV **skey; SV **test; AV *av, *keys; I32 len; int cols, i; HV *hv = newHV(); int releaseX = 0; // do we need to release mem // warn("In khash\n"); if(tb->t == 99 && (kK(tb)[0])->t == 98 && (kK(tb)[1])->t == 98) // Keyed Table { // Convert keyed table to an unkeyed version, then to dict r1(tb); tmp = ktd(tb); if(tmp != 0) { x = tmp->k; // dict from table, tb has been deallocated releaseX=1; // x is a merged copy of tb that needs r0 } else { warn("Failed to convert Keyed table to normal table\n"); r0(tb); return hv; } } else if(tb->t == 99) // Dict { x = tb; } else if (tb->t == 98) // Normal Table { x = tb->k; // dict from table } else { myerr("Kx::k2phash wrong type"); return hv; } // Ok we now are sure we have dict to play with // Loop through each column list and assign that vector (*AV) to the // appropriate key (column name) // $a = { 'col1' => [1,2,3,4], 'col2' => [0,8,7,6] } effectively keys = k2parray(xx); cols = xx->n; // number of columns for(i=0;it > 0 && xy->t < XT) { H typ = xy->t; // this objects type typ = abs(typ); switch(typ) { CS(KB,sv = newSViv((int)(kG(xy)[i]))) CS(KG,sv = newSViv((int)(kG(xy)[i]))) CS(KH,sv = newSViv((int)(kH(xy)[i]))) CS(KI,sv = newSViv(kI(xy)[i])) CS(KE,sv = newSVnv((double)(kE(xy)[i]))) CS(KF,sv = newSVnv((double)(kF(xy)[i]))) CS(KJ,sv = newSVnv((double)(kJ(xy)[i]))) CS(KC,sv = newSViv((int)(kC(xy)[i]))) CS(KS,sv = newSVpv((const char*)(kS(xy)[i]),0)) CS(KM,sv = newSViv(kI(xy)[i])) CS(KD,sv = newSViv(D2epoch((double)(kI(xy)[i])))) CS(KZ,sv = __Z2e == 1 ? newSViv(Z2epoch(kF(xy)[i])) : newSVnv(Z2epochf((kF(xy)[i])))) CS(KU,sv = newSViv(kI(xy)[i])) CS(KV,sv = newSViv(kI(xy)[i])) CS(KT,sv = newSViv(kI(xy)[i])) CD: sv = newSV(0); }; } else if(xy->t == 0) // its a mixed list of possible other lists/scalars { if((kK(xy)[i])->t < 0) { sv = k2pscalar(kK(xy)[i]); } else // assume a list { av = k2parray(kK(xy)[i]); // Now is this vector a singleton array holding a perl Hash data // structure. If so promote it. len = av_len(av); // get its last index value if(len== 0) { // Get at the value so we can test it test = av_fetch(av,0,0); if(SvROK(*test)) // its a reference { int typ = SvTYPE(SvRV(*test)); // if(typ == SVt_PVAV || typ == SVt_PVHV) // array or hash if(typ == SVt_PVHV) // array or hash { sv = newRV_inc((SV*) SvRV(*test)); // hmm inc av_undef(av); // av not required anymore } else { sv = newRV_noinc((SV*) av); } } else // Not a reference do normal stuff { sv = newRV_noinc((SV*) av); } } else // Normal stuff { sv = newRV_noinc((SV*) av); } } } else // something weird here { croak("Kx::k2phash something weird here, probably death"); } // Get at the symbol and convert it to a string skey = av_fetch(keys,i,0); if(!hv_store_ent(hv, *skey, sv, 0)) { myerr("Kx::k2phash: hv_store failed"); } } // warn("Out khash\n\n"); if(releaseX) r0(tmp); av_undef(keys); // get rid of keys array as they are in the hash proper return hv; } // Convert a K dict/table to a Perl hash, drop refcount on x HV * k2phash0 (Kstruct * x) { HV *hv = k2phash(x); r0(x); return hv; } /* Return a Perl ref that describes a K object */ SV* k2p (Kstruct * k) { SV* rtn; AV* av; HV* hv; if(k->t < 0) // scalar { return k2pscalar(k); } else if (k->t == XD || k->t == XT) // dict/table with prim key or table { hv = k2phash(k); rtn = newRV_noinc((SV*) hv); return rtn; } else if (k->t >= 0 && k->t <= KT) // mixed => time { av = k2parray(k); rtn = newRV_noinc((SV*) av); return rtn; } else { return newSV(0); } } SV * getKarray(K list, int i) { if(i >= list->n || list->t < 0) { return newSV(0); // undef } if(i < 0) { i = list->n + i - 1; if(i < 0) { return newSV(0); } // undef } switch(list->t) { CS(0, return(k2p(kK(list)[i]))) CS(KB, return(newSViv(kG(list)[i]))) CS(KG, return(newSViv(kG(list)[i]))) CS(KH, return(newSViv(kH(list)[i]))) CS(KI, return(newSViv(kI(list)[i]))) CS(KE, return(newSVnv((double)kE(list)[i]))) CS(KF, return(newSVnv((double)kF(list)[i]))) CS(KJ, return(newSVnv((double)kJ(list)[i]))) CS(KC, return(newSViv(kC(list)[i]))) CS(KS, return(newSVpv((const char*)kS(list)[i],0))) CS(KM, return(newSViv(kI(list)[i]))) CS(KD, return(newSViv(D2epoch((double)kI(list)[i])))) CS(KZ, return(__Z2e == 1 ? newSViv(Z2epoch(kF(list)[i])) : newSVnv(Z2epochf(kF(list)[i])))) CS(KU, return(newSViv(kI(list)[i]))) CS(KV, return(newSViv(kI(list)[i]))) CS(KT, return(newSViv(kI(list)[i]))) CS(XT, return(k2p(kK(list)[i]))) CS(XD, return(k2p(kK(list)[i]))) CD: return newSV(0); // undef }; } /* creating K object from Perl */ K phash2k(HV * h); K pscalar2k(SV * p); K parray2k(AV * a); K p2k(SV * ref) { K kv; int typ; if(!SvROK(ref)) { warn("Kx::p2k(perl_ref) has have a perl reference\n"); return (K)0; } typ = SvTYPE(SvRV(ref)); if(SCALAR(typ)) { kv = pscalar2k((SV *)SvRV(ref)); } else if(typ == SVt_PVAV) // array { kv = parray2k((AV *)SvRV(ref)); } else if(typ == SVt_PVHV) // hash { kv = phash2k((HV *)SvRV(ref)); } else { warn("Kx::p2k(perl_ref) unknown type(%i)\n",typ); return (K)0; } return kv; } K pscalar2k(SV * p) { K k; SV * sv = p; if(!SvOK(sv)) { // Hmm check if its a reference if(SvROK(sv)) { sv = SvRV(sv); } else { warn("pscalar2k arg not a scalar. Type is %i\n",SvTYPE(sv)); return ki(0); } } if(SvIOK(sv)) // Its an integer { IV i = SvIV(sv); return kj(i); } else if(SvNOK(sv)) // real { double i = SvNV(sv); return kf(i); } else if(SvPOK(sv)) // its a symbol... maybe { STRLEN len; unsigned char * ptr = (unsigned char *)SvPV(sv, len); return ks(sn(ptr, len)); } else // What on earth is it? { warn("pscalar2k what on earth is this type(%i)?\n",SvTYPE(sv)); } } K parray2k(AV * av) { K k; int mixed, typ; I32 i; SV** svp; I32 len = av_len(av); // get its last index value if(len == -1) { // empty array TODO } /* * Need to get an idea of what sorts of things are in this list. That * way we can work out if its a mixed list we need to create or a * simple list type. This requires us to loop through the list * checking the type doesn't change. If it does then we do the mixed * list option. This is slower but uses less memory than building as * we go and assuming it is a simple list */ i = 0; mixed = 0; svp = av_fetch(av,0,0); // get 1st val so can find type typ = SvTYPE(*svp); for(i=1; i <= len; i++) { svp = av_fetch(av,i,0); if(typ != SvTYPE(*svp)) { mixed++; break; } } // OK now we know what sort of K list to create if(mixed || typ == SVt_RV) { K kv = ktn(0,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); typ = SvTYPE(*svp); if(SCALAR(typ)) { kK(kv)[i] = pscalar2k(*svp); } else if(typ == SVt_RV && SvTYPE(SvRV(*svp)) == SVt_PVAV) // array { kK(kv)[i] = parray2k((AV*) SvRV(*svp)); } else if(typ == SVt_RV && SvTYPE(SvRV(*svp)) == SVt_PVHV) // hash { kK(kv)[i] = phash2k((HV*) SvRV(*svp)); } else { warn("Kx::parray2k unknown type(%i)\n",typ); return (K)0; } } return kv; } else // simple list { K kv; if(typ == SVt_IV || typ == SVt_NV || typ == SVt_PV) { if(typ == SVt_IV) // int { kv = ktn(KJ,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); kJ(kv)[i] = (long) SvIV(*svp); } } else if(typ == SVt_NV) // double { kv = ktn(KF,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); kF(kv)[i] = (double) SvNV(*svp); } } else // typ == SVt_PV) // symbol { STRLEN l; unsigned char * ptr; kv = ktn(KS,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); ptr = (unsigned char *) SvPV(*svp, l); kS(kv)[i] = sn(ptr, l); } } return kv; } else if(typ == SVt_PVAV) // array of array { kv = ktn(0,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); kK(kv)[i] = parray2k((AV *)(*svp)); } } else if(typ == SVt_PVHV) // array of hash { kv = ktn(0,len+1); for(i=0; i <= len; i++) { svp = av_fetch(av,i,0); kK(kv)[i] = phash2k((HV *)(*svp)); } } else { warn("Kx::parry2k unknown type %i\n",typ); return (K)0; } return kv; } } K phash2k(HV * h) { int i, typ; SV * sv; char * key; I32 keylen; int n = hv_iterinit(h); K x = xD(ktn(KS,n), ktn(0,n)); for(i = 0; i < n ; ++i) { // Pick up the next key and value sv = hv_iternextsv(h, &key, &keylen); // Store em in the Dict kS(xx)[i] = sn((unsigned char *)key, keylen); typ = SvTYPE(sv); // If we have a reference then we need to dereference it while(typ == SVt_RV) { typ = SvTYPE(SvRV(sv)); // underlying typ sv = SvRV(sv); // dereference } if(SCALAR(typ)) { kK(xy)[i] = pscalar2k(sv); } else if(typ == SVt_PVAV) // array { kK(xy)[i] = parray2k((AV*) sv); } else if(typ == SVt_PVHV) // hash { kK(xy)[i] = phash2k((HV*) sv); } else { warn("Kx::phash2k unknown type\n"); return (K)0; } } return x; } /* * We assume arref is valid and has stuff in it! It must also be of only * one type and that type must un-mixed */ #define NEWKDO(n,x) {for(i=0;in + x -1; if(x < 0) { return 0; } // too negative to be of any use } if(x >= list->n) { return 0; } /* The list is of a single consistent type. */ switch(list->t) { CS(KB, (kG(list)[x]) = SvIV(val)) CS(KG, (kG(list)[x]) = SvIV(val)) CS(KH, (kH(list)[x]) = SvIV(val)) CS(KI, (kI(list)[x]) = SvIV(val)) CS(KE, (kE(list)[x]) = (float)SvNV(val)) CS(KF, (kF(list)[x]) = SvNV(val)) CS(KJ, (kJ(list)[x]) = (long long)SvNV(val)) CS(KC, (kC(list)[x]) = SvIV(val)) CS(KS, (kS(list)[x]) = ss((S)SvPV_nolen(val))) CS(KM, (kI(list)[x]) = SvIV(val)) CS(KD, (kI(list)[x]) = (int)(floor(SvIV(val)))) CS(KZ, (kF(list)[x]) = epoch2Z(SvNV(val))) CS(KU, (kI(list)[x]) = SvIV(val)) CS(KV, (kI(list)[x]) = SvIV(val)) CS(KT, (kI(list)[x]) = SvIV(val)) CD: return 0; }; return 1; } int setKarraymixed(K list, int x, K val) { if(x < 0) { x = list->n + x -1; if(x < 0) { return 0; } // too negative to be of any use } if(x >= list->n) { return 0; } r1(val); kK(list)[x] = val; return 1; } /* * Take a Perl string and map it directly onto a KDB+ data structure * starting at index x. The list must be of type KG list and the string * must fit the length */ int setKarraybinary(K list, int x, SV * val) { STRLEN len; char * ptr; int i; ptr = SvPV(val, len); if(x < 0) { x = list->n + x -1; if(x < 0) { return 0; } // too negative to be of any use } if(x+len > list->n) { myerr("x+len too big"); return 0; } if(list->t != KG) { myerr("Not a byte list"); return 0; } for(i=0; i < len; i++) { kG(list)[i+x] = *(ptr+i); } return 1; } SV * getKarraybinary(K list, int from, int sz) { if(from+sz >= list->n || list->t != KG || from < 0 || sz < 0) { return newSV(0); // undef } if(sz == 0) { sz = list->n - from; } return(newSVpv((const char*)(&(kG(list)[from])),sz)); } K call_ja(K list, SV* atom) { int i; double d; unsigned char * s, c; float f; long long l; i = SvIV(atom); d = SvNV(atom); s = (unsigned char *)SvPV_nolen(atom); if(list->t == KE) { f = (float) d; } if(list->t == KJ) { l = (long long) d; } if(list->t == KC) { c = (unsigned char) i; } if(list->t == KS) { s = ss(s); } if(list->t == KD) { i = (int)(floor(epoch2Z(i))); } switch(list->t) { CS(KB, ja(&list,&i)) CS(KG, ja(&list,&i)) CS(KH, ja(&list,&i)) CS(KI, ja(&list,&i)) CS(KE, ja(&list,&f)) CS(KF, ja(&list,&d)) CS(KJ, ja(&list,&l)) CS(KC, ja(&list,&c)) CS(KS, ja(&list,&s)) CS(KM, ja(&list,&i)) CS(KD, ja(&list,&i)) CS(KZ, ja(&list,&d)) CS(KU, ja(&list,&i)) CS(KV, ja(&list,&i)) CS(KT, ja(&list,&i)) CD: return list; }; return list; }