// // RSEXP.m // Rgui // // Created by Simon Urbanek on Wed Dec 10 2003. // Copyright (c) 2003-4 Simon Urbanek. All rights reserved. // /* IMPORTANT: the entire REngine/REXP framework assumes that you're not returning contol to R in the life of a RSEXP. If you do, make sure you copy the content of interest and release the RSEXP before returing constrol to R. Baiscally the point is that all SEXP objects are unprotected before exiting the functions, so that we never get an unbalanced stack. This implies that R may garbage-collect your objects if it gets control. Alternatively you may use protect/uprotect methods, but make sure the calls are *always* balanced! */ #import "RSEXP.h" @implementation RSEXP - (RSEXP*) initWithSEXP: (SEXP) ct { xp=ct; attr=nil; if (ATTRIB(ct) && TYPEOF(ATTRIB(ct))!=NILSXP && ATTRIB(ct)!=ct) attr=[[RSEXP alloc] initWithSEXP: ATTRIB(ct)]; //NSLog(@"initWithSEXP result: %@", self); return self; } - (RSEXP*) initWithString: (NSString*) str { PROTECT(xp=allocVector(STRSXP, 1)); SET_VECTOR_ELT(xp, 0, mkChar([str cString])); UNPROTECT(1); attr=nil; //NSLog(@"initWithString result: %@", self); return self; } - (RSEXP*) initWithDoubleArray: (double*) arr length: (int) len { if (len<0) len=0; PROTECT(xp=allocVector(REALSXP, len)); if (len>0) memcpy(REAL(xp),arr,sizeof(double)*len); UNPROTECT(1); attr=nil; //NSLog(@"initWithDoubleArray result: %@", self); return self; } - (RSEXP*) initWithIntArray: (int*) arr length: (int) len { if (len<0) len=0; PROTECT(xp=allocVector(INTSXP, len)); if (len>0) memcpy(INTEGER(xp),arr,sizeof(int)*len); UNPROTECT(1); attr=nil; //NSLog(@"initWithIntArray result: %@", self); return self; } - (int) type { return (xp)?TYPEOF(xp):NILSXP; } - (NSString*) typeName { if (!xp) return @""; switch(TYPEOF(xp)) { case NILSXP: return @"NULL"; case SYMSXP: return @"symbol"; case LISTSXP: return @"list"; case CLOSXP: return @"closure"; case ENVSXP: return @"environment"; case PROMSXP: return @"promise"; case LANGSXP: return @"lang.construct"; case SPECIALSXP: return @"special"; case BUILTINSXP: return @"built-in"; case CHARSXP: return @"scalar-str"; case LGLSXP: return @"logical"; case INTSXP: return @"integer"; case REALSXP: return @"real"; case CPLXSXP: return @"complex"; case STRSXP: return @"string"; case DOTSXP: return @"..."; case ANYSXP: return @"any"; case VECSXP: return @"array"; case EXPRSXP: return @"expressions"; case BCODESXP: return @"byte-code"; case EXTPTRSXP: return @"ext.ptr"; case WEAKREFSXP: return @"weak-reference"; } return @""; } - (NSString*) description { return [NSString stringWithFormat:@"RSEXP, %@[%d]",[self typeName],[self length]]; } - (int) length { if (!xp) return 0; switch (TYPEOF(xp)) { case VECSXP: case STRSXP: case INTSXP: case REALSXP: case CPLXSXP: case LGLSXP: case EXPRSXP: return LENGTH(xp); } return 1; } - (RSEXP*) attribute { return attr; } - (SEXP) directSEXP { return xp; } - (void) protect { PROTECT(xp); } - (void) unprotect { UNPROTECT(1); } - (RSEXP*) elementAt: (int) index { if (index<0 || index>=LENGTH(xp)) return nil; //XX return [[RSEXP alloc] initWithSEXP: VECTOR_ELT(xp, index)]; } - (double*) doubleArray { return (TYPEOF(xp)==REALSXP)?REAL(xp):NULL; } - (int*) intArray { return (TYPEOF(xp)==INTSXP)?INTEGER(xp):NULL; } - (NSString*) string { return (TYPEOF(xp)==STRSXP && LENGTH(xp)>0)?[NSString stringWithCString: (char*) CHAR(STRING_ELT(xp, 0))]:nil; } - (int) integer { return (TYPEOF(xp)==INTSXP)?INTEGER(xp)[0]:0; } - (double) real { return (TYPEOF(xp)==REALSXP)?REAL(xp)[0]:0.0; } - (NSArray*) array { if (TYPEOF(xp)==STRSXP) { int i=0, l=LENGTH(xp); id *cont=(id *) malloc(sizeof(id)*l); while (i