Skip to content

Instantly share code, notes, and snippets.

@radiofreejohn
Created January 11, 2012 02:12
Show Gist options
  • Save radiofreejohn/1592535 to your computer and use it in GitHub Desktop.
Save radiofreejohn/1592535 to your computer and use it in GitHub Desktop.
IDL dlm to read formatted ASCII files
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <zlib.h>
#include <dlfcn.h>
#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 (calling program may strip .gz from filename)
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(zlibfile, 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] = 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;
}
/* required metadata file: nv3h_read_gz.dlm
MODULE nv3h_read_gz
DESCRIPTION Read super big NV3H files
VERSION 1.0
SOURCE John Clover, UC San Diego.
BUILD_DATE Jan, 6 2011
FUNCTION nv3h_read_gz 2 2 KEYWORDS
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment