/* * gcc nv3h_read_gz.c -shared -Bsymbolic -I/zshare/rsi/idl_6.3/external/include -L/zshare/rsi/idl_6.3/bin/bin.linux.x86_64 -lidl -o nv3h_read_gz.so -fPIC -lz -ldl * * requires zlib 1.2.5 for gzbuffer -- will check for right version */ #include #include #include #include #include #include #include "idl_export.h" char *chomp(char *s) { char *ss = s; while(*s && *s != '\n' && *s != '\r') s++; *s = '\0'; return ss; } IDL_VPTR IDL_CDECL nv3h_read(int argc, IDL_VPTR argv[], char *argk) { IDL_MEMINT dims[IDL_MAX_ARRAY_DIM]; int status; struct stat st_buf; void *dlhandle; int (*fn)(gzFile, int); char *zlibfile = "libz.so.1"; char *zliberror; char messages[8192]; char *filename = IDL_VarGetString(argv[0]); char *fname; double *buffer; IDL_VPTR vpTmp = NULL; IDL_VPTR vpPlainArgs[3]; gzFile *myFp; char *line = malloc(sizeof(char) * 32768); ssize_t len = 0; double val; int nVals = 0; size_t size; char *endline = NULL; //char **comments = NULL; IDL_STRING *comments; static IDL_VPTR silent; static IDL_VPTR nx, ny; static IDL_VPTR commentPtr; char *lineptr = NULL; long dataPosition = 0; long totalDataElements = 0; int longestComment = 0; int nComments = 0; int longestData = 0; int nData = 0; // make sure it's a file we can read status = stat(filename, &st_buf); if (status != 0) { // first see if adding .gz finds it strcpy(line, filename); strcat(line, ".gz"); status = stat(line, &st_buf); fname = strdup(line); line[0] = '\0'; } else { fname = strdup(filename); } if (status != 0) { free(line); sprintf(messages, "Error: Cannot read %s\n", fname); free(fname); IDL_Message(IDL_M_NAMED_GENERIC,IDL_MSG_RET, messages); return IDL_GettmpLong(0); } if (!(S_ISREG (st_buf.st_mode))) { free(line); sprintf(messages, "Error: Not a regular file: %s\n", fname); free(fname); IDL_Message(IDL_M_NAMED_GENERIC,IDL_MSG_RET, messages); return IDL_GettmpLong(0); } if ((myFp = gzopen(fname, "rb")) == NULL) { free(line); sprintf(messages, "Error: Cannot open %s.", fname); IDL_Message(IDL_M_NAMED_GENERIC,IDL_MSG_RET, messages); return IDL_GettmpLong(0); } dlhandle = dlopen("libz.so.1", RTLD_LAZY); fn = dlsym(dlhandle, "gzbuffer"); if (((zliberror = dlerror()) == NULL) && dlhandle) { // I know I should use (*fn)(...) here but I know gzbuffer exists gzbuffer(myFp, 131070); dlclose(dlhandle); } IDL_StoreScalarZero(argv[1], IDL_TYP_LONG); IDL_ENSURE_SCALAR(argv[0]); IDL_EXCLUDE_EXPR(argv[1]); while ((gzgets(myFp, line, 32768)) != NULL) { len = strlen(line); if (*line != ';') { nData++; if (len > longestData) { dataPosition = gztell(myFp); } longestData = (len > longestData) ? len : longestData; } else { nComments++; longestComment = (len > longestComment) ? len : longestComment; } } gzseek(myFp, dataPosition-longestData, SEEK_SET); gzgets(myFp, line, 32768); lineptr = line; // find the number of data values per record while ((val = strtod(lineptr, &endline)) || (endline != lineptr)) { nVals++; lineptr = endline; } totalDataElements = nVals * nData; // dims[0] = totalDataElements; dims[0] = nVals; dims[1] = nData; static IDL_KW_PAR kw_pars[] = { IDL_KW_FAST_SCAN, {"COMMENTS", IDL_TYP_STRING,1,IDL_KW_OUT,0,IDL_CHARA(commentPtr)}, {"NX", IDL_TYP_LONG,1,IDL_KW_OUT|IDL_KW_ZERO,0,IDL_CHARA(nx)}, {"NY", IDL_TYP_LONG,1,IDL_KW_OUT|IDL_KW_ZERO,0,IDL_CHARA(ny)}, {"SILENT", IDL_TYP_LONG,1,IDL_KW_VIN,0,IDL_CHARA(silent)}, {NULL} }; IDL_KWCleanup(IDL_KW_MARK); IDL_KWGetParams(argc, argv, argk, kw_pars, vpPlainArgs, 1); if (commentPtr) IDL_StoreScalarZero(commentPtr, IDL_TYP_STRING); if (nx) { vpTmp = IDL_GettmpLong(nVals); IDL_VarCopy(vpTmp, nx); } if (ny) { vpTmp = IDL_GettmpLong(nData); IDL_VarCopy(vpTmp, ny); } buffer = (double *)IDL_MakeTempArray(IDL_TYP_DOUBLE,2, dims, IDL_ARR_INI_NOP, &vpTmp); IDL_VarCopy(vpTmp,argv[1]); dims[0] = nComments; dims[1] = 0; comments = (IDL_STRING *) IDL_MakeTempArray(IDL_TYP_STRING,1,dims, IDL_ARR_INI_NOP, &vpTmp); if (commentPtr) IDL_VarCopy(vpTmp, commentPtr); gzseek(myFp, 0, SEEK_SET); while ((gzgets(myFp, line, 32768)) != NULL) { len = strlen(line); lineptr = line; if (*line != ';') { while ((val = strtod(lineptr, &endline)) || (endline != lineptr)) { *buffer++ = val; lineptr = endline; } } else { IDL_StrStore(comments++,chomp(line)); } } free(line); free(fname); line = NULL; gzclose(myFp); IDL_KWCleanup(IDL_KW_CLEAN); return IDL_GettmpLong(1); } int IDL_Load(void) { static IDL_SYSFUN_DEF2 function_addr[] = { { nv3h_read, "NV3H_READ_GZ", 2, 2, IDL_SYSFUN_DEF_F_KEYWORDS }, }; IDL_SysRtnAdd(function_addr, TRUE, 1); return IDL_TRUE; }