Mercurial > forge
changeset 7760:c211a946f136 octave-forge
fix check of input arguments; support for STATA files versuions less than 114; remove trailing blanks
author | schloegl |
---|---|
date | Wed, 24 Nov 2010 21:28:59 +0000 |
parents | 6d5f67bc6c0f |
children | 031e12c82fae |
files | extra/NaN/src/xptopen.cpp |
diffstat | 1 files changed, 243 insertions(+), 243 deletions(-) [+] |
line wrap: on
line diff
--- a/extra/NaN/src/xptopen.cpp Wed Nov 24 18:44:09 2010 +0000 +++ b/extra/NaN/src/xptopen.cpp Wed Nov 24 21:28:59 2010 +0000 @@ -1,17 +1,17 @@ //------------------------------------------------------------------- -// C-MEX implementation of kth element - this function is part of the NaN-toolbox. +// C-MEX implementation of kth element - this function is part of the NaN-toolbox. // // usage: x = xptopen(filename) // usage: x = xptopen(filename,'r') // read filename and return variables in struct x // usage: xptopen(filename,'w',x) -// save fields of struct x in filename +// save fields of struct x in filename // usage: x = xptopen(filename,'a',x) -// append fields of struct x to filename +// append fields of struct x to filename // -// References: +// References: // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -34,11 +34,11 @@ // References: // [1] TS-140 THE RECORD LAYOUT OF A DATA SET IN SAS TRANSPORT (XPORT) FORMAT // http://support.sas.com/techsup/technote/ts140.html -// [2] IBM floating point format +// [2] IBM floating point format // http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture // [3] see http://old.nabble.com/Re%3A-IBM-integer-and-double-formats-p20428979.html // [4] STATA File Format -// http://www.stata.com/help.cgi?dta +// http://www.stata.com/help.cgi? // http://www.stata.com/help.cgi?dta_113 //------------------------------------------------------------------- @@ -62,11 +62,11 @@ #if (MX_API_VER<=0x07020000) typedef int mwSize; typedef int mwIndex; - #endif -#endif + #endif +#endif #define NaN (0.0/0.0) -#define fix(m) (m<0 ? ceil(m) : floor(m)) +#define fix(m) (m<0 ? ceil(m) : floor(m)) #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) @@ -74,7 +74,7 @@ #ifdef __linux__ /* use byteswap macros from the host system, hopefully optimized ones ;-) */ #include <byteswap.h> -#endif +#endif #ifdef _WIN32 #define __LITTLE_ENDIAN 1234 @@ -143,20 +143,20 @@ double tm_time2gdf_time(struct tm *t); /* - compare first n characters of two strings, ignore case + compare first n characters of two strings, ignore case */ int strncmpi(const char* str1, const char* str2, size_t n) -{ +{ unsigned int k=0; int r=0; while (!r && str1[k] && str2[k] && (k<n)) { r = tolower(str1[k]) - tolower(str2[k]); - k++; - } - return(r); + k++; + } + return(r); } -void mexFunction(int POutputCount, mxArray* POutput[], int PInputCount, const mxArray *PInputs[]) +void mexFunction(int POutputCount, mxArray* POutput[], int PInputCount, const mxArray *PInputs[]) { const char L1[] = "HEADER RECORD*******LIBRARY HEADER RECORD!!!!!!!000000000000000000000000000000 "; const char L2[] = "SAS SAS SASLIB 6.06 bsd4.2 13APR89:10:20:06"; @@ -169,18 +169,18 @@ const char LO[] = "HEADER RECORD*******OBS HEADER RECORD!!!!!!!000000000000000000000000000000 "; const char DATEFORMAT[] = "%d%b%y:%H:%M:%S"; - char *fn = NULL; - char Mode[3] = "r"; - FILE *fid; + char *fn = NULL; + char Mode[3] = "r"; + FILE *fid; size_t count = 0, NS = 0, HeadLen0=80*8, HeadLen2=0, sz2 = 0, M=0; char H0[HeadLen0]; char *H2 = NULL; char SWAP = 0; - + // check for proper number of input and output arguments - if ( PInputCount > 0 && mxGetClassID(PInputs[1])==mxCHAR_CLASS) { + if ( PInputCount > 0 && mxGetClassID(PInputs[0])==mxCHAR_CLASS) { size_t buflen = (mxGetM(PInputs[0]) * mxGetN(PInputs[0]) * sizeof(mxChar)) + 1; - fn = (char*)malloc(buflen); + fn = (char*)malloc(buflen); mxGetString(PInputs[0], fn, buflen); } else { @@ -196,7 +196,7 @@ mexPrintf("\nThe SAS-XPT format stores Date/Time as numeric value counting the number of days since 1960-01-01.\n\n"); return; } - if ( PInputCount > 1) + if ( PInputCount > 1) if (mxGetClassID(PInputs[1])==mxCHAR_CLASS && mxGetNumberOfElements(PInputs[1])) { mxGetString(PInputs[1],Mode,3); Mode[2]=0; @@ -205,23 +205,23 @@ fid = fopen(fn,Mode); if (fid < 0) { mexErrMsgTxt("Error XPTOPEN: cannot open file\n"); - } + } if (Mode[0]=='r' || Mode[0]=='a' ) { - count += fread(H0,1,80*8,fid); + count += fread(H0,1,80*8,fid); enum FileFormat { noFile, unknown, ARFF, SASXPT, SPSS, STATA }; enum FileFormat TYPE; /* type of file format */ - uint8_t LittleEndian; /* 1 if file is LittleEndian data format and 0 for big endian data format*/ + uint8_t LittleEndian; /* 1 if file is LittleEndian data format and 0 for big endian data format*/ - TYPE = unknown; + TYPE = unknown; if (!memcmp(H0,"$FL2@(#) SPSS DATA FILE",27) || !memcmp(H0,"$FL2@(#) PASW STATISTICS DATA FILE",27)) { /* - SPSS file format + SPSS file format */ - TYPE = SPSS; + TYPE = SPSS; switch (*(uint32_t*)(H0+64)) { case 0x00000002: case 0x00000003: @@ -237,11 +237,11 @@ NS = b_endian_i32(*(uint32_t*)(H0+68)); M = b_endian_i32(*(uint32_t*)(H0+80)); break; - default: - TYPE = unknown; + default: + TYPE = unknown; } NS = *(int32_t*)(H0+80); - M = *(int32_t*)(H0+80); + M = *(int32_t*)(H0+80); if (SWAP) { NS = bswap_32(NS); M = bswap_32(M); @@ -249,14 +249,14 @@ HeadLen0 = 184; char *H2 = (char*)malloc(NS*32); size_t c2 = 0; - + /* - Read Variable SPSS header + Read Variable SPSS header */ int ns = 0; - const char **ListOfVarNames = (const char**)malloc((NS+1) * sizeof(char*)); - char *VarNames = (char*)malloc((NS+1) * sizeof(char) * 9); - double *MISSINGS = (double*)malloc((NS+1) * sizeof(double)); + const char **ListOfVarNames = (const char**)malloc((NS+1) * sizeof(char*)); + char *VarNames = (char*)malloc((NS+1) * sizeof(char) * 9); + double *MISSINGS = (double*)malloc((NS+1) * sizeof(double)); for (uint32_t k=0; k<NS; k++) { int32_t rec_type, type, FlagHasLabel, FlagMissing; c2 += fread(&rec_type,1,4,fid); @@ -268,7 +268,7 @@ rec_type = bswap_32(rec_type); type = bswap_32(type); FlagHasLabel = bswap_32(FlagHasLabel); - } + } if (rec_type != 2) ;//error('invalid SPSS file'); c2 += fread(VarNames+9*ns,1,8,fid); VarNames[9*ns+8] = 0; @@ -277,19 +277,19 @@ int32_t LenLabel; c2 += fread(&LenLabel,1,4,fid); if (SWAP) LenLabel = bswap_32(LenLabel); - if (LenLabel%4) LenLabel += 4 - LenLabel % 4; + if (LenLabel%4) LenLabel += 4 - LenLabel % 4; fseek(fid,LenLabel,SEEK_CUR); } - if (FlagMissing) + if (FlagMissing) c2 += fread(MISSINGS+ns,1,8,fid); - + if (type != -1) ns++; } NS = ns; mxArray **R = (mxArray**) mxMalloc(NS * sizeof(mxArray*)); - /* ToDo: + /* ToDo: EXTRACT data */ @@ -298,12 +298,12 @@ for (uint32_t k = 0; k < NS; k++) { mxSetField(POutput[0], 0, ListOfVarNames[k], R[k]); } - + if (MISSINGS) free(MISSINGS); if (VarNames) free(VarNames); if (ListOfVarNames) free(ListOfVarNames); if (H2) free(H2); - } + } if (TYPE == SPSS) { /* @@ -323,15 +323,15 @@ - Data record. */ ; - } - else if ((H0[0]==113 || H0[0]==114) && (H0[1]==1 || H0[1]==2) && H0[2]==1 && H0[3]==0) { + } + else if ((H0[0]>=0x6e || H0[0]<=114) && (H0[1]==1 || H0[1]==2) && H0[2]==1 && H0[3]==0) { /* STATA File Format - http://www.stata.com/help.cgi?dta + http://www.stata.com/help.cgi?dta http://www.stata.com/help.cgi?dta_113 */ TYPE = STATA; - // Header 119 bytes + // Header 119 bytes LittleEndian = H0[1]==2; if (LittleEndian) { NS = l_endian_u16(*(uint16_t*)(H0+4)); @@ -342,65 +342,65 @@ M = b_endian_u32(*(uint32_t*)(H0+6)); } - // Descriptors - int fmtlen = (H0[0]==113) ? 12 : 49; + // Descriptors + int fmtlen = (H0[0]==113) ? 12 : 49; fseek(fid,109,SEEK_SET); size_t HeadLen2 = 2+NS*(1+33+2+fmtlen+33+81); char *H1 = (char*)malloc(HeadLen2); - fread(H1,1,HeadLen2,fid); + HeadLen2 = fread(H1,1,HeadLen2,fid); // expansion fields char typ; int32_t len,c; char flagSWAP = (((__BYTE_ORDER == __BIG_ENDIAN) && LittleEndian) || ((__BYTE_ORDER == __LITTLE_ENDIAN) && !LittleEndian)); - do { + do { fread(&typ,1,1,fid); fread(&len,4,1,fid); - if (flagSWAP) bswap_32(len); + if (flagSWAP) bswap_32(len); fseek(fid,len,SEEK_CUR); - } while (len); + } while (len); uint8_t *typlist = (uint8_t*)H1; /* char *varlist = H1+NS; char *srtlist; - char *fmtlist = H1+NS*36+2; - char *lbllist = H1+NS*(36+fmtlen)+2; + char *fmtlist = H1+NS*36+2; + char *lbllist = H1+NS*(36+fmtlen)+2; */ - + mxArray **R = (mxArray**) mxMalloc(NS*sizeof(mxArray*)); size_t *bi = (size_t*) malloc((NS+1)*sizeof(size_t*)); - const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); + const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); bi[0] = 0; for (size_t k = 0; k < NS; k++) { size_t sz; ListOfVarNames[k] = H1+NS+33*k; switch (typlist[k]) { - case 0xfb: sz = 1; break; - case 0xfc: sz = 2; break; - case 0xfd: sz = 4; break; - case 0xfe: sz = 4; break; + case 0xfb: sz = 1; break; + case 0xfc: sz = 2; break; + case 0xfd: sz = 4; break; + case 0xfe: sz = 4; break; case 0xff: sz = 8; break; otherwise: sz = typlist[k]; - } + } bi[k+1] = bi[k]+sz; } - - // data + + // data uint8_t *data = (uint8_t *) malloc(bi[NS] * M); fread(data, bi[NS], M, fid); - + char *f = (char*)malloc(bi[NS]+1); for (size_t k = 0; k < NS; k++) { switch (typlist[k]) { - case 0xfb: - R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); + case 0xfb: + R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); for (size_t m = 0; m < M; m++) { int8_t d = *(int8_t*)(data+bi[k]+m*bi[NS]); ((double*)mxGetData(R[k]))[m] = (d>100) ? NaN : d; } - break; - case 0xfc: - R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); + break; + case 0xfc: + R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); if (flagSWAP) for (size_t m = 0; m < M; m++) { int16_t d = (int16_t) bswap_16(*(uint16_t*)(data+bi[k]+m*bi[NS])); ((double*)mxGetData(R[k]))[m] = (d>32740) ? NaN : d; @@ -409,9 +409,9 @@ int16_t d = *(int16_t*)(data+bi[k]+m*bi[NS]); ((double*)mxGetData(R[k]))[m] = (d>32740) ? NaN : d; } - break; - case 0xfd: - R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); + break; + case 0xfd: + R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); if (flagSWAP) for (size_t m = 0; m < M; m++) { int32_t d = (int32_t)bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS])); ((double*)mxGetData(R[k]))[m] = (d>2147483620) ? NaN : d; @@ -420,20 +420,20 @@ int32_t d = *(int32_t*)(data+bi[k]+m*bi[NS]); ((double*)mxGetData(R[k]))[m] = (d>2147483620) ? NaN : d; } - break; - case 0xfe: - R[k] = mxCreateNumericMatrix(M, 1, mxSINGLE_CLASS, mxREAL); + break; + case 0xfe: + R[k] = mxCreateNumericMatrix(M, 1, mxSINGLE_CLASS, mxREAL); if (flagSWAP) for (size_t m = 0; m < M; m++) { - ((uint32_t*)mxGetData(R[k]))[m] = bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS]));; + ((uint32_t*)mxGetData(R[k]))[m] = bswap_32(*(uint32_t*)(data+bi[k]+m*bi[NS]));; } else for (size_t m = 0; m < M; m++) { - ((uint32_t*)mxGetData(R[k]))[m] = *(uint32_t*)(data+bi[k]+m*bi[NS]); + ((uint32_t*)mxGetData(R[k]))[m] = *(uint32_t*)(data+bi[k]+m*bi[NS]); } - break; - case 0xff: - R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); + break; + case 0xff: + R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); if (flagSWAP) for (size_t m = 0; m < M; m++) { - ((uint64_t*)mxGetData(R[k]))[m] = bswap_64(*(uint64_t*)(data+bi[k]+m*bi[NS])); + ((uint64_t*)mxGetData(R[k]))[m] = bswap_64(*(uint64_t*)(data+bi[k]+m*bi[NS])); } else for (size_t m = 0; m < M; m++) { ((uint64_t*)mxGetData(R[k]))[m] = *(uint64_t*)(data+bi[k]+m*bi[NS]); @@ -446,13 +446,13 @@ memcpy(f, data+bi[k]+m*bi[NS], sz); f[sz] = 0; mxSetCell(R[k], m, mxCreateString(f)); - } - } + } + } } - if (f) free(f); + if (f) free(f); if (H1) free(H1); if (bi) free(bi); - + /* convert into output */ POutput[0] = mxCreateStructMatrix(1, 1, NS, ListOfVarNames); for (size_t k = 0; k < NS; k++) { @@ -466,23 +466,23 @@ /* ARFF */ - TYPE = ARFF; + TYPE = ARFF; rewind(fid); char *H1 = NULL; count = 0; - size_t ns = 0; + size_t ns = 0; char *vartyp = NULL; char **datestr = NULL; - const char **ListOfVarNames = NULL; + const char **ListOfVarNames = NULL; mxArray **R = NULL; size_t m = 0; - + while (!feof(fid)) { HeadLen0 = max(1024,HeadLen0*2); H1 = (char*)realloc(H1,HeadLen0); count += fread(H1+count,1,HeadLen0-count-1,fid); - } + } H1[count] = 0; switch (H1[count-1]) { @@ -490,21 +490,21 @@ case 0x0d: H1[count] = 0; break; - default: + default: H1[count] = 0x0a; } H1[count+1] = 0; char *line = strtok(H1,"\x0a\0x0d"); - int status = 0; + int status = 0; while (line) { - if (!strncmpi(line,"@relation",9)) { + if (!strncmpi(line,"@relation",9)) { status = 1; - } + } - else if (status == 1 && !strncmpi(line,"@attribute",10)) { + else if (status == 1 && !strncmpi(line,"@attribute",10)) { if (ns<=NS) { ns = max(16, ns*2); ListOfVarNames = (const char**)realloc(ListOfVarNames,ns*sizeof(char*)); @@ -519,27 +519,27 @@ line[k++]=0; while (isspace(line[k])) k++; p2 = line+k; - + ListOfVarNames[NS] = p1; if (!strncmpi(p2,"numeric",7)) { - vartyp[NS] = 1; - } - else if (!strncmpi(p2,"integer",7)) { - vartyp[NS] = 2; + vartyp[NS] = 1; + } + else if (!strncmpi(p2,"integer",7)) { + vartyp[NS] = 2; } - else if (!strncmpi(p2,"real",4)) { - vartyp[NS] = 3; + else if (!strncmpi(p2,"real",4)) { + vartyp[NS] = 3; } - else if (!strncmpi(p2,"string",6)) { - vartyp[NS] = 4; + else if (!strncmpi(p2,"string",6)) { + vartyp[NS] = 4; } else if (!strncmpi(p2,"{",1)) { - vartyp[NS] = 5; - } - else if (!strncmpi(p2,"date",4)) { - vartyp[NS] = 6; + vartyp[NS] = 5; + } + else if (!strncmpi(p2,"date",4)) { + vartyp[NS] = 6; datestr = (char**)realloc(datestr,(NS+1)*sizeof(char*)); - p2+=4; + p2+=4; while (isspace(*p2)) p2++; datestr[NS] = p2; if (p2[0]==34) { @@ -549,51 +549,51 @@ } } else if (!strncmpi(p2,"relational",10)) { - vartyp[NS] = 7; + vartyp[NS] = 7; } - else vartyp[NS] = 99; - + else vartyp[NS] = 99; + NS++; - } + } - else if (status == 1 && !strncmpi(line,"@data",5)) { + else if (status == 1 && !strncmpi(line,"@data",5)) { status = 2; - char *p = line; - while (*p) p++; // goto end of current line + char *p = line; + while (*p) p++; // goto end of current line p++; // skip \x00 - M = 0; + M = 0; while (*p) { if (p[0]==0x0a || p[0]==0x0d) { // count number of <CR> M++; - // skip next char (deals with <CR><NL>) - p+=2; + // skip next char (deals with <CR><NL>) + p+=2; } else p++; } for (size_t k=0; k<NS; k++) { - if (vartyp[k]==4 || vartyp[k]==5) + if (vartyp[k]==4 || vartyp[k]==5) R[k] = mxCreateCellMatrix(M, 1); else R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); - } + } } - + else if (status == 2) { - size_t p = 0,k; - for (ns = 0; ns<NS; ns++) { - // read next token - while (isspace(line[p])) p++; + size_t p = 0,k; + for (ns = 0; ns<NS; ns++) { + // read next token + while (isspace(line[p])) p++; if (line[p]==39) { p++; k=p; while (line[k]!=39 && line[k]) k++; // if (!line[k]) ; // error line[k++] = 0; - } + } else k=p; - while (line[k] != ',' && line[k] != 0) k++; + while (line[k] != ',' && line[k] != 0) k++; line[k] = 0; if (vartyp[ns] < 4) { @@ -607,7 +607,7 @@ size_t kk[6],n=0, N=strlen(datestr[ns]); char T0[6][5]; char ix = 0; - struct tm t; + struct tm t; for (n=0; n < N; n++) { switch (datestr[ns][n]) { @@ -629,13 +629,13 @@ case 's': ix = 5; break; - default: - ix = 99; - } + default: + ix = 99; + } if (ix < 6) { T0[ix][kk[ix]++] = line[p+n]; - } + } } for (n=0; n<6; n++) { T0[n][kk[n]] = 0; @@ -650,11 +650,11 @@ *(mxGetPr(R[ns])+m) = tm_time2gdf_time(&t); } p = k+1; - } + } m++; } line = strtok(NULL, "\x0a\x0d"); - } + } /* convert into output */ POutput[0] = mxCreateStructMatrix(1, 1, NS, ListOfVarNames); @@ -666,49 +666,49 @@ if (vartyp) free(vartyp); if (datestr) free(datestr); if (H1) free(H1); - } + } else if (!memcmp(H0,"HEADER RECORD*******LIBRARY HEADER RECORD!!!!!!!000000000000000000000000000000",78)) { /* SAS Transport file format (XPORT) */ - TYPE = SASXPT; - + TYPE = SASXPT; + /* TODO: sanity checks */ - char tmp[5]; - memcpy(tmp,H0+7*80+54,4); + char tmp[5]; + memcpy(tmp,H0+7*80+54,4); tmp[4] = 0; NS = atoi(tmp); - + char *tmp2; - sz2 = strtoul(H0+4*80-6, &tmp2, 10); - + sz2 = strtoul(H0+4*80-6, &tmp2, 10); + HeadLen2 = NS*sz2; - if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; + if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; /* read namestr header, and header line "OBS" */ H2 = (char*) realloc(H2, HeadLen2+81); - count += fread(H2,1,HeadLen2+80,fid); + count += fread(H2,1,HeadLen2+80,fid); - /* size of single record */ + /* size of single record */ size_t pos=0, recsize = 0, POS = 0; - for (size_t k = 0; k < NS; k++) + for (size_t k = 0; k < NS; k++) recsize += b_endian_u16(*(int16_t*)(H2+k*sz2+4)); - /* read data section */ - size_t szData = 0; - uint8_t *Data = NULL; + /* read data section */ + size_t szData = 0; + uint8_t *Data = NULL; while (!feof(fid)) { size_t szNew = max(16,szData*2); Data = (uint8_t*)realloc(Data,szNew); szData += fread(Data+szData,1,szNew-szData,fid); } - - M = szData/recsize; + + M = szData/recsize; mxArray **R = (mxArray**) mxMalloc(NS*sizeof(mxArray*)); - const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); + const char **ListOfVarNames = (const char**)malloc(NS * sizeof(char*)); char *VarNames = (char*)malloc(NS * 9); for (size_t k = 0; k < NS; k++) { @@ -718,26 +718,26 @@ int n = k*sz2+8; int flagDate = (!memcmp(H2+n+48,"DATE ",8) || !memcmp(H2+n+48,"MONNAME ",8)); do { - VarNames[pos++] = H2[n]; - } while (isalnum(H2[++n]) && (n < k*sz2+16)); - + VarNames[pos++] = H2[n]; + } while (isalnum(H2[++n]) && (n < k*sz2+16)); + VarNames[pos++] = 0; if ((*(int16_t*)(H2+k*sz2)) == b_endian_u16(1) && (*(int16_t*)(H2+k*sz2+4)) == b_endian_u16(8) ) { // numerical data - R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); + R[k] = mxCreateDoubleMatrix(M, 1, mxREAL); for (size_t m=0; m<M; m++) { double d = xpt2d(b_endian_u64(*(uint64_t*)(Data+m*recsize+POS))); // if (flagDate) d += 715876; // add number of days from 0000-Jan-01 to 1960-Jan-01 *(mxGetPr(R[k])+m) = d; - + } } else if ((*(int16_t*)(H2+k*sz2)) == b_endian_u16(2)) { - // character string + // character string R[k] = mxCreateCellMatrix(M, 1); char *f = (char*)malloc(maxlen+1); for (size_t m=0; m<M; m++) { @@ -754,29 +754,29 @@ for (size_t k = 0; k < NS; k++) { mxSetField(POutput[0], 0, ListOfVarNames[k], R[k]); } - + if (VarNames) free(VarNames); if (ListOfVarNames) free(ListOfVarNames); - if (Data) free(Data); + if (Data) free(Data); /* end of reading SAS format */ } - + else { fclose(fid); mexErrMsgTxt("file format not supported"); - return; + return; } - + } // if (Mode[0]=='w' || Mode[0]=='a' ) { if (Mode[0]=='w') { - - NS += mxGetNumberOfFields(PInputs[2]); - // generate default (fixed) header + NS += mxGetNumberOfFields(PInputs[2]); + + // generate default (fixed) header if (Mode[0]=='w') { memset(H0,' ',80*8); memcpy(H0,L1,strlen(L1)); @@ -788,61 +788,61 @@ memcpy(H0+80*7,L8,strlen(L8)); } - + time_t t; - time(&t); + time(&t); char tt[20]; strftime(tt, 17, DATEFORMAT, localtime(&t)); - memcpy(H0+80*2-16,tt,16); - memcpy(H0+80*2,tt,16); - memcpy(H0+80*5+8,fn,min(8,strcspn(fn,".\x00"))); - memcpy(H0+80*5+32,"XPTOPEN.MEX (OCTAVE/MATLAB)",27); - memcpy(H0+80*6-16,tt,16); - memcpy(H0+80*6,tt,16); - + memcpy(H0+80*2-16,tt,16); + memcpy(H0+80*2,tt,16); + memcpy(H0+80*5+8,fn,min(8,strcspn(fn,".\x00"))); + memcpy(H0+80*5+32,"XPTOPEN.MEX (OCTAVE/MATLAB)",27); + memcpy(H0+80*6-16,tt,16); + memcpy(H0+80*6,tt,16); + char tmp[17]; - sprintf(tmp,"%04i", NS); // number of variables + sprintf(tmp,"%04i", NS); // number of variables memcpy(H0+80*7+54, tmp, 4); - + if (sz2==0) sz2 = 140; - if (sz2 < 136) + if (sz2 < 136) mexErrMsgTxt("error XPTOPEN: incorrect length of namestr field"); /* generate variable NAMESTR header */ HeadLen2 = NS*sz2; - if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; + if (HeadLen2 % 80) HeadLen2 = (HeadLen2 / 80 + 1) * 80; H2 = (char*) realloc(H2,HeadLen2); memset(H2,0,HeadLen2); - + mwIndex M = 0; mxArray **F = (mxArray**) mxMalloc(NS*sizeof(mxArray*)); char **Fstr = (char**) malloc(NS*sizeof(char*)); size_t *MAXLEN = (size_t*) malloc(NS*sizeof(size_t*)); for (int16_t k = 0; k < NS; k++) { Fstr[k] = NULL; - MAXLEN[k]=0; + MAXLEN[k]=0; F[k] = mxGetFieldByNumber(PInputs[2],0,k); if (k==0) M = mxGetM(F[k]); else if (M != mxGetM(F[k])) { - if (H2) free(H2); - if (F) free(F); + if (H2) free(H2); + if (F) free(F); mexErrMsgTxt("Error XPTOPEN: number of elements (rows) do not fit !!!"); } - - if (mxIsChar(F[k])) { + + if (mxIsChar(F[k])) { *(int16_t*)(H2+k*sz2) = b_endian_u16(2); *(int16_t*)(H2+k*sz2+4) = b_endian_u16(mxGetN(F[k])); } else if (mxIsCell(F[k])) { - size_t maxlen = 0; - for (mwIndex m = 0; m<M; m++) { - mxArray *f = mxGetCell(F[k],m); + size_t maxlen = 0; + for (mwIndex m = 0; m<M; m++) { + mxArray *f = mxGetCell(F[k],m); if (mxIsChar(f) || mxIsEmpty(f)) { size_t len = mxGetNumberOfElements(f); if (maxlen<len) maxlen = len; - } + } } - Fstr[k] = (char*) malloc(maxlen+1); + Fstr[k] = (char*) malloc(maxlen+1); *(int16_t*)(H2+k*sz2) = b_endian_u16(2); *(int16_t*)(H2+k*sz2+4) = b_endian_u16(maxlen); MAXLEN[k] = maxlen; @@ -850,7 +850,7 @@ else { *(int16_t*)(H2+k*sz2) = b_endian_u16(1); *(int16_t*)(H2+k*sz2+4) = b_endian_u16(8); - } + } *(int16_t*)(H2+k*sz2+6) = b_endian_u16(k); strncpy(H2+k*sz2+8,mxGetFieldNameByNumber(PInputs[2],k),8); } @@ -866,9 +866,9 @@ // numeric uint64_t u64 = b_endian_u64(d2xpt(*(mxGetPr(F[k])+m))); count += fwrite(&u64, 1, 8, fid); - } + } -/* else if (mxIsChar(F[k])) { +/* else if (mxIsChar(F[k])) { *(int16_t*)(H2+k*sz2) = b_endian_u16(2); *(int16_t*)(H2+k*sz2+4) = b_endian_u16(mxGetN(F[k])); } @@ -877,37 +877,37 @@ size_t maxlen = MAXLEN[k]; mxArray *f = mxGetCell(F[k],m); mxGetString(f, Fstr[k], maxlen+1); - count += fwrite(Fstr[k], 1, maxlen, fid); + count += fwrite(Fstr[k], 1, maxlen, fid); } } } /* - // padding to full multiple of 80 byte: + // padding to full multiple of 80 byte: // FIXME: this might introduce spurios sample values char d = count%80; - while (d--) fwrite("\x20",1,1,fid); + while (d--) fwrite("\x20",1,1,fid); */ - // free memory - for (size_t k=0; k<NS; k++) if (Fstr[k]) free(Fstr[k]); - if (Fstr) free(Fstr); - if (MAXLEN) free(MAXLEN); - Fstr = NULL; + // free memory + for (size_t k=0; k<NS; k++) if (Fstr[k]) free(Fstr[k]); + if (Fstr) free(Fstr); + if (MAXLEN) free(MAXLEN); + Fstr = NULL; } - fclose(fid); - - if (H2) free(H2); + fclose(fid); + + if (H2) free(H2); H2 = NULL; - - return; + + return; } /* - XPT2D converts from little-endian IBM to little-endian IEEE format + XPT2D converts from little-endian IBM to little-endian IEEE format */ double xpt2d(uint64_t x) { - // x is little-endian 64bit IBM floating point format + // x is little-endian 64bit IBM floating point format char c = *((char*)&x+7) & 0x7f; uint64_t u = x; *((char*)&u+7)=0; @@ -918,33 +918,33 @@ #elif __BYTE_ORDER==__LITTLE_ENDIAN -#if DEBUG +#if DEBUG mexPrintf("xpt2d(%016Lx): [0x%x]\n",x,c); #endif - // missing values - if ((c==0x2e || c==0x5f || (c>0x40 && c<0x5b)) && !u ) + // missing values + if ((c==0x2e || c==0x5f || (c>0x40 && c<0x5b)) && !u ) return(NaN); - + int s,e; s = *(((char*)&x) + 7) & 0x80; // sign e = (*(((char*)&x) + 7) & 0x7f) - 64; // exponent - *(((char*)&x) + 7) = 0; // mantisse x + *(((char*)&x) + 7) = 0; // mantisse x -#if DEBUG +#if DEBUG mexPrintf("%x %x %016Lx\n",s,e,x); -#endif +#endif double y = ldexp(x, e*4-56); if (s) return(-y); else return( y); -#endif +#endif } /* - D2XPT converts from little-endian IEEE to little-endian IBM format + D2XPT converts from little-endian IEEE to little-endian IBM format */ uint64_t d2xpt(double x) { @@ -958,29 +958,29 @@ #elif __BYTE_ORDER==__LITTLE_ENDIAN - if (x != x) return(0x2eLL << 56); // NaN - not a number + if (x != x) return(0x2eLL << 56); // NaN - not a number if (fabs(x) == 1.0/0.0) return(0x5fLL << 56); // +-infinity - if (x == 0.0) return(0); + if (x == 0.0) return(0); - if (x > 0.0) s=0; + if (x > 0.0) s=0; else s=1; - x = frexp(x,&e); + x = frexp(x,&e); -#if DEBUG +#if DEBUG mexPrintf("d2xpt(%f)\n",x); -#endif +#endif // see http://old.nabble.com/Re%3A-IBM-integer-and-double-formats-p20428979.html m = *(uint64_t*) &x; *(((char*)&m) + 6) &= 0x0f; // - if (e) *(((char*)&m) + 6) |= 0x10; // reconstruct implicit leading '1' for normalized numbers + if (e) *(((char*)&m) + 6) |= 0x10; // reconstruct implicit leading '1' for normalized numbers m <<= (3-(-e & 3)); *(((char*)&m) + 7) = s ? 0x80 : 0; e = (e + (-e & 3)) / 4 + 64; - - if (e >= 128) return(0x5f); // overflow + + if (e >= 128) return(0x5f); // overflow if (e < 0) { uint64_t h = 1<<(4*-e - 1); m = m / (2*h) + (m & h && m & (3*h-1) ? 1 : 0); @@ -988,32 +988,32 @@ } return (((uint64_t)e)<<56 | m); -#endif +#endif -} +} double tm_time2gdf_time(struct tm *t) { - /* based Octave's datevec.m - it referes Peter Baum's algorithm at http://vsg.cape.com/~pbaum/date/date0.htm - but the link is not working anymore as of 2008-12-03. + /* based Octave's datevec.m + it referes Peter Baum's algorithm at http://vsg.cape.com/~pbaum/date/date0.htm + but the link is not working anymore as of 2008-12-03. Other links to Peter Baum's algorithm are http://www.rexswain.com/b2mmddyy.rex http://www.dpwr.net/forums/index.php?s=ecfa72e38be61327403126e23aeea7e5&showtopic=4309 */ - + int Y,M,s; //h,m, - double D; - - D = t->tm_mday; - M = t->tm_mon+1; + double D; + + D = t->tm_mday; + M = t->tm_mon+1; Y = t->tm_year+1900; - + // Set start of year to March by moving Jan. and Feb. to previous year. // Correct for months > 12 by moving to subsequent years. Y += fix ((M-14.0)/12); - + const int monthstart[] = {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; // Lookup number of days since start of the current year. D += monthstart[t->tm_mon % 12] + 60; @@ -1023,9 +1023,9 @@ D += 365*Y + floor (Y/4) - floor (Y/100) + floor (Y/400); // Add fraction representing current second of the day. - s = t->tm_hour*3600 + t->tm_min*60 + t->tm_sec; + s = t->tm_hour*3600 + t->tm_min*60 + t->tm_sec; - // s -= timezone; + // s -= timezone; return(D + s/86400.0); }