#include "netcdf.h" #include "api.h" #include #include #define MAX_ATT 32 #define NC_TYPE 'NC' #pragma warning(disable: 4018) #pragma warning(disable: 4244) class zsRegPrimitive { public: zsRegPrimitive(const char* name, int type, void* func) { api_add_primitive(name, type, func); } }; class zsNetcdf { public: int ncid; }; ///////////////////////////////////////////////////////////////////// void input_error(void* caller) { api_runtime_error(caller, "bad arguments"); } void cdf_check_error(void* caller, int status) { if (status != NC_NOERR) api_runtime_error(caller, nc_strerror(status)); } void cdf_destroy(void* ptr) { zsNetcdf *o = (zsNetcdf*)ptr; nc_close(o->ncid); delete o; } ///////////////////////////////////////////////////////////////////// void* cdf_open(void *caller, int nargs, void** args) { if (nargs < 1) input_error(caller); const char *fname = api_get_string(caller, args[0]); const char *mode = "r"; int ncid; if (nargs > 1) mode = api_get_string(caller, args[1]); if (mode[0] == 'w' || mode[0] == 'W') cdf_check_error(caller, nc_open(fname, NC_WRITE, &ncid)); else if (mode[0] == 'c' || mode[0] == 'C') cdf_check_error(caller, nc_create(fname, NC_NOCLOBBER, &ncid)); else cdf_check_error(caller, nc_open(fname, NC_NOWRITE, &ncid)); zsNetcdf *o = new zsNetcdf; o->ncid = ncid; return api_create_user(caller, o, 0, cdf_destroy, NC_TYPE); } static zsRegPrimitive nc0("netcdf", 0, cdf_open); void* cdf_close(void *caller, int nargs, void** args) { if (nargs < 1) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); nc_close(o->ncid); o->ncid = 0; return 0; } static zsRegPrimitive nc0a("close", NC_TYPE, cdf_close); void* cdf_version(void *caller, int nargs, void** args) { return api_create_string(caller, (char*)nc_inq_libvers()); } static zsRegPrimitive nc1("version", NC_TYPE, cdf_version); void* cdf_defdim(void *caller, int nargs, void** args) { if (nargs < 3) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string (caller, args[1]); int n = api_get_integer(caller, args[2]); nc_redef(o->ncid); int varid; if (n > 0) cdf_check_error(caller, nc_def_dim(o->ncid, name, n, &varid)); else cdf_check_error(caller, nc_def_dim(o->ncid, name, NC_UNLIMITED, &varid)); return api_create_integer(caller, varid); } static zsRegPrimitive nc2("defdim", NC_TYPE, cdf_defdim); void* cdf_defvar(void *caller, int nargs, void** args) { if (nargs < 4 || nargs-3 > NC_MAX_VAR_DIMS) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); const char *type = api_get_string(caller, args[2]); nc_type nc; if (!strcmp(type, "char")) nc = NC_CHAR; else if (!strcmp(type, "byte")) nc = NC_BYTE; else if (!strcmp(type, "uchar")) nc = NC_BYTE; else if (!strcmp(type, "short")) nc = NC_SHORT; else if (!strcmp(type, "int")) nc = NC_INT; else if (!strcmp(type, "float")) nc = NC_FLOAT; else if (!strcmp(type, "double")) nc = NC_DOUBLE; else input_error(caller); int dimid[NC_MAX_VAR_DIMS]; for (int i = 3; i < nargs; i++) dimid[i-3] = api_get_integer(caller, args[i]); nc_redef(o->ncid); int varid; cdf_check_error(caller, nc_def_var(o->ncid, name, nc, nargs-3, dimid, &varid)); return api_create_integer(caller, varid); } static zsRegPrimitive nc3("defvar", NC_TYPE, cdf_defvar); void* cdf_defined(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); int varid, status; status = nc_inq_varid(o->ncid, name, &varid); if (status != NC_NOERR) return api_create_integer(caller, 1); return api_create_integer(caller, 0); } static zsRegPrimitive nc4("defined", NC_TYPE, cdf_defined); size_t get_var_size(void *caller, int ncid, const char*name, int &varid, nc_type &type, int &ndim, int dimid[]) { cdf_check_error(caller, nc_inq_varid (ncid, name, &varid)); cdf_check_error(caller, nc_inq_vartype (ncid, varid, &type)); cdf_check_error(caller, nc_inq_varndims(ncid, varid, &ndim)); cdf_check_error(caller, nc_inq_vardimid(ncid, varid, dimid)); size_t m, size = 1; for (int i = 0; i < ndim; i++) { cdf_check_error(caller, nc_inq_dimlen(ncid, dimid[i], &m)); size *= m; } return size; } void* cdf_size(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); nc_type type; int varid, ndim, dimid[NC_MAX_VAR_DIMS]; nc_enddef(o->ncid); size_t size = get_var_size(caller, o->ncid, name, varid, type, ndim, dimid); void *arr = api_create_array(caller, 3); api_set_array_object(caller, arr, "0", api_create_integer(caller, size)); switch (type) { case NC_BYTE: case NC_CHAR: api_set_array_object(caller, arr, "1", api_create_integer(caller, 1)); break; case NC_SHORT: api_set_array_object(caller, arr, "1", api_create_integer(caller, sizeof(short))); break; case NC_INT: api_set_array_object(caller, arr, "1", api_create_integer(caller, sizeof(int))); break; case NC_FLOAT: api_set_array_object(caller, arr, "1", api_create_integer(caller, sizeof(float))); break; case NC_DOUBLE: api_set_array_object(caller, arr, "1", api_create_integer(caller, sizeof(double))); break; default: input_error(caller); } return arr; } static zsRegPrimitive nc5("size", NC_TYPE, cdf_size); inline check_space(void* caller, size_t n, int esize, size_t m, int tsize) { if (n != m || esize != tsize) api_runtime_error(caller, "un-equal data-memory space"); } void* cdf_getvar(void *caller, int nargs, void** args) { if (nargs < 5) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string (caller, args[1]); void *ptr = api_get_ptr (caller, args[2]); size_t n = api_get_integer(caller, args[3]); int esize = api_get_integer(caller, args[4]); nc_type type; int i, k, varid, ndim, dimid[NC_MAX_VAR_DIMS]; size_t size = get_var_size(caller, o->ncid, name, varid, type, ndim, dimid); nc_enddef(o->ncid); if (nargs > 6) { size_t start[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; for (i = 0; i < ndim; i++) { start[i] = 0; count[i] = 1; } size = 1; for (i = 6, k = 0; i < nargs && k < ndim; i+=2, k++) { start[k] = api_get_integer(caller, args[i-1]); count[k] = api_get_integer(caller, args[i ]); size *= count[k]; } switch (type) { case NC_BYTE: check_space(caller, n, esize, size, 1); cdf_check_error(caller, nc_get_vara_uchar(o->ncid, varid, start, count, (unsigned char*)ptr)); break; case NC_CHAR: check_space(caller, n, esize, size, 1); cdf_check_error(caller, nc_get_vara_schar(o->ncid, varid, start, count, (signed char*)ptr)); break; case NC_SHORT: check_space(caller, n, esize, size, sizeof(short)); cdf_check_error(caller, nc_get_vara_short(o->ncid, varid, start, count, (short*)ptr)); break; case NC_INT: check_space(caller, n, esize, size, sizeof(int)); cdf_check_error(caller, nc_get_vara_int(o->ncid, varid, start, count, (int*)ptr)); break; case NC_FLOAT: check_space(caller, n, esize, size, sizeof(float)); cdf_check_error(caller, nc_get_vara_float(o->ncid, varid, start, count, (float*)ptr)); break; case NC_DOUBLE: check_space(caller, n, esize, size, sizeof(double)); cdf_check_error(caller, nc_get_vara_double(o->ncid, varid, start, count, (double*)ptr)); break; default: input_error(caller); } } else { switch (type) { case NC_BYTE: check_space(caller, n, esize, size, 1); cdf_check_error(caller, nc_get_var_uchar(o->ncid, varid, (unsigned char*)ptr)); break; case NC_CHAR: check_space(caller, n, esize, size, 1); cdf_check_error(caller, nc_get_var_schar(o->ncid, varid, (signed char*)ptr)); break; case NC_SHORT: check_space(caller, n, esize, size, sizeof(short)); cdf_check_error(caller, nc_get_var_short(o->ncid, varid, (short*)ptr)); break; case NC_INT: check_space(caller, n, esize, size, sizeof(int)); cdf_check_error(caller, nc_get_var_int(o->ncid, varid, (int*)ptr)); break; case NC_FLOAT: check_space(caller, n, esize, size, sizeof(float)); cdf_check_error(caller, nc_get_var_float(o->ncid, varid, (float*)ptr)); break; case NC_DOUBLE: check_space(caller, n, esize, size, sizeof(double)); cdf_check_error(caller, nc_get_var_double(o->ncid, varid, (double*)ptr)); break; default: input_error(caller); } } return 0; } static zsRegPrimitive nc6("getvar", NC_TYPE, cdf_getvar); void* cdf_putvar(void *caller, int nargs, void** args) { if (nargs < 3) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); void *ptr = api_get_ptr (caller, args[2]); nc_type type; int i, k, varid, ndim, dimid[NC_MAX_VAR_DIMS]; get_var_size(caller, o->ncid, name, varid, type, ndim, dimid); nc_enddef(o->ncid); if (nargs > 4) { size_t start[NC_MAX_VAR_DIMS], count[NC_MAX_VAR_DIMS]; for (i = 0; i < ndim; i++) { start[i] = 0; count[i] = 1; } for (i = 4, k = 0; i < nargs && k < ndim; i+=2, k++) { start[k] = api_get_integer(caller, args[i-1]); count[k] = api_get_integer(caller, args[i ]); } switch (type) { case NC_BYTE: cdf_check_error(caller, nc_put_vara_uchar(o->ncid, varid, start, count, (unsigned char*)ptr)); break; case NC_CHAR: cdf_check_error(caller, nc_put_vara_schar(o->ncid, varid, start, count, (signed char*)ptr)); break; case NC_SHORT: cdf_check_error(caller, nc_put_vara_short(o->ncid, varid, start, count, (short*)ptr)); break; case NC_INT: cdf_check_error(caller, nc_put_vara_int(o->ncid, varid, start, count, (int*)ptr)); break; case NC_FLOAT: cdf_check_error(caller, nc_put_vara_float(o->ncid, varid, start, count, (float*)ptr)); break; case NC_DOUBLE: cdf_check_error(caller, nc_put_vara_double(o->ncid, varid, start, count, (double*)ptr)); break; default: input_error(caller); } } else { switch (type) { case NC_BYTE: cdf_check_error(caller, nc_put_var_uchar(o->ncid, varid, (unsigned char*)ptr)); break; case NC_CHAR: cdf_check_error(caller, nc_put_var_schar(o->ncid, varid, (signed char*)ptr)); break; case NC_SHORT: cdf_check_error(caller, nc_put_var_short(o->ncid, varid, (short*)ptr)); break; case NC_INT: cdf_check_error(caller, nc_put_var_int(o->ncid, varid, (int*)ptr)); break; case NC_FLOAT: cdf_check_error(caller, nc_put_var_float(o->ncid, varid, (float*)ptr)); break; case NC_DOUBLE: cdf_check_error(caller, nc_put_var_double(o->ncid, varid, (double*)ptr)); break; default: input_error(caller); } } return 0; } static zsRegPrimitive nc7("putvar", NC_TYPE, cdf_putvar); void* cdf_getatt(void *caller, int nargs, void** args) { if (nargs < 3) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *var = api_get_string(caller, args[1]); const char *att = api_get_string(caller, args[2]); int i, varid; nc_type type; size_t size; nc_enddef(o->ncid); cdf_check_error(caller, nc_inq_varid(o->ncid, var, &varid)); cdf_check_error(caller, nc_inq_att(o->ncid, varid, att, &type, &size)); double ptr[MAX_ATT]; char buf[64]; if (type != NC_CHAR && size > MAX_ATT) api_runtime_error(caller, "attribute too long"); switch(type) { case NC_CHAR: { char *p = new char[size +1]; cdf_check_error(caller, nc_get_att_text(o->ncid, varid, att, p)); p[size] = 0; void *ret = api_create_string(caller, p); delete[] p; return ret; } case NC_BYTE: { cdf_check_error(caller, nc_get_att_uchar(o->ncid, varid, att, (unsigned char*)ptr)); if (size == 1) return api_create_integer(caller, ((unsigned char*)ptr)[0]); void *arr = api_create_array(caller, size+1); for (i = 0; i < size; i++) { sprintf(buf, "%d", i); api_set_array_object(caller, arr, buf, api_create_integer(caller, ((unsigned char*)ptr)[i])); } return arr; } case NC_SHORT: { cdf_check_error(caller, nc_get_att_short(o->ncid, varid, att, (short*)ptr)); if (size == 1) return api_create_integer(caller, ((short*)ptr)[0]); void *arr = api_create_array(caller, size+1); for (i = 0; i < size; i++) { sprintf(buf, "%d", i); api_set_array_object(caller, arr, buf, api_create_integer(caller, ((short*)ptr)[i])); } return arr; } case NC_INT: { cdf_check_error(caller, nc_get_att_int(o->ncid, varid, att, (int*)ptr)); if (size == 1) return api_create_integer(caller, ((int*)ptr)[0]); void *arr = api_create_array(caller, size+1); for (i = 0; i < size; i++) { sprintf(buf, "%d", i); api_set_array_object(caller, arr, buf, api_create_integer(caller, ((int*)ptr)[i])); } return arr; } case NC_FLOAT: { cdf_check_error(caller, nc_get_att_float(o->ncid, varid, att, (float*)ptr)); if (size == 1) return api_create_real(caller, ((float*)ptr)[0]); void *arr = api_create_array(caller, size+1); for (i = 0; i < size; i++) { sprintf(buf, "%d", i); api_set_array_object(caller, arr, buf, api_create_real(caller, ((float*)ptr)[i])); } return arr; } case NC_DOUBLE: { cdf_check_error(caller, nc_get_att_double(o->ncid, varid, att, (double*)ptr)); if (size == 1) return api_create_real(caller, ((double*)ptr)[0]); void *arr = api_create_array(caller, size+1); for (i = 0; i < size; i++) { sprintf(buf, "%d", i); api_set_array_object(caller, arr, buf, api_create_real(caller, ((double*)ptr)[i])); } return arr; } default: input_error(caller); } return 0; } static zsRegPrimitive nc8("getatt", NC_TYPE, cdf_getatt); void* cdf_putatt(void *caller, int nargs, void** args) { if (nargs < 4) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); const char *att = api_get_string(caller, args[2]); nc_redef(o->ncid); if (strlen(name) < 1) { if (api_is_string(args[3])) { const char *str = api_get_string(caller, args[3]); cdf_check_error(caller, nc_put_att_text(o->ncid, NC_GLOBAL, att, strlen(str), str)); return 0; } input_error(caller); } int varid; cdf_check_error(caller, nc_inq_varid(o->ncid, name, &varid)); nc_del_att(o->ncid, varid, att); if (api_is_string(args[3])) { const char *str = api_get_string(caller, args[3]); cdf_check_error(caller, nc_put_att_text(o->ncid, varid, att, strlen(str), str)); return 0; } int n = nargs - 3; if (n > MAX_ATT) api_runtime_error(caller, "attribute too long"); if (api_is_integer(args[3])) { int data[MAX_ATT]; for (int i = 0; i < n; i++) data[i] = api_get_integer(caller, args[i+3]); cdf_check_error(caller, nc_put_att_int(o->ncid, varid, att, NC_INT, n, data)); return 0; } if (api_is_real(args[3])) { double data[MAX_ATT]; for (int i = 0; i < n; i++) data[i] = api_get_real(caller, args[i+3]); cdf_check_error(caller, nc_put_att_double(o->ncid, varid, att, NC_DOUBLE, n, data)); return 0; } api_runtime_error(caller, "un-supported attribute type"); return 0; } static zsRegPrimitive nc9("putatt", NC_TYPE, cdf_putatt); void* cdf_inqdim(void *caller, int nargs, void** args) { if (nargs < 1) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); int i, unlimited, nvar, ndim, ngatt; size_t len; char name[NC_MAX_NAME]; cdf_check_error(caller, nc_inq(o->ncid, &ndim, &nvar, &ngatt, &unlimited)); void *arr = api_create_array(caller, ndim+1); for (i = 0; i < ndim; i++) { cdf_check_error(caller, nc_inq_dim(o->ncid, i, name, &len)); api_set_array_object(caller, arr, name, api_create_integer(caller, len)); if (i == unlimited) api_set_array_object(caller, arr, "unlimited", api_create_string(caller, name)); } return arr; } static zsRegPrimitive nc10("inqdim", NC_TYPE, cdf_inqdim); void* cdf_inqvar(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); int j, ndim, natt, dimid[NC_MAX_VAR_DIMS]; nc_type type; char name[NC_MAX_NAME]; cdf_check_error(caller, nc_inq_var(o->ncid, api_get_integer(caller, args[1]), name, &type, &ndim, dimid, &natt)); void *arr = api_create_array(caller, ndim+3); api_set_array_object(caller, arr, "name", api_create_string(caller, name)); api_set_array_object(caller, arr, "ndim", api_create_integer(caller, ndim)); switch(type) { case NC_CHAR: api_set_array_object(caller, arr, "type", api_create_string(caller, "char")); break; case NC_BYTE: api_set_array_object(caller, arr, "type", api_create_string(caller, "byte")); break; case NC_SHORT: api_set_array_object(caller, arr, "type", api_create_string(caller, "short")); break; case NC_INT: api_set_array_object(caller, arr, "type", api_create_string(caller, "int")); break; case NC_FLOAT: api_set_array_object(caller, arr, "type", api_create_string(caller, "float")); break; case NC_DOUBLE: api_set_array_object(caller, arr, "type", api_create_string(caller, "double")); break; default: api_set_array_object(caller, arr, "type", api_create_string(caller, "unknown")); break; } if (ndim > 0) { char key[64]; for (j = 0; j < ndim; j++) { cdf_check_error(caller, nc_inq_dimname(o->ncid, dimid[j], name)); sprintf(key, "dim%d", j); api_set_array_object(caller, arr, key, api_create_string(caller, name)); } } return arr; } static zsRegPrimitive nc11("inqvar", NC_TYPE, cdf_inqvar); void get_attributes(void* caller, int ncid, FILE *f, const int ivar, const char* space); void *get_attributes2(void* caller, int ncid, const int ivar); void* cdf_inqatt(void *caller, int nargs, void** args) { if (nargs < 2) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); const char *name = api_get_string(caller, args[1]); if (strcmp(name, "GLOBAL") == 0) return get_attributes2(caller, o->ncid, NC_GLOBAL); int varid; cdf_check_error(caller, nc_inq_varid (o->ncid, name, &varid)); return get_attributes2(caller, o->ncid, varid); } static zsRegPrimitive nc12("inqatt", NC_TYPE, cdf_inqatt); void* cdf_info(void *caller, int nargs, void** args) { if (nargs < 1) input_error(caller); zsNetcdf *o = (zsNetcdf*)api_get_user(caller, args[0], NC_TYPE); int ncid = o->ncid; FILE *f = stdout; if (nargs > 1) f = fopen(api_get_string(caller, args[1]), "w"); if (!f) f = stdout; // dimensions int i, unlimited, nvar, ndim, ngatt; size_t len, dim[NC_MAX_VAR_DIMS]; char name[NC_MAX_NAME]; fprintf(f, "Dimensions:\n"); cdf_check_error(caller, nc_inq(ncid, &ndim, &nvar, &ngatt, &unlimited)); for (i = 0; i < ndim; i++) { cdf_check_error(caller, nc_inq_dim(ncid, i, name, &len)); dim[i] = len; if (unlimited == i) fprintf(f, " %s = %d (unlimited)\n", name, len); else fprintf(f, " %s = %d\n", name, len); } // variables fprintf(f, "\nVariables:\n"); for (i = 0; i < nvar; i++) { int natt, ndim, dimid[NC_MAX_VAR_DIMS]; nc_type type; cdf_check_error(caller, nc_inq_var(ncid, i, name, &type, &ndim, dimid, &natt)); switch(type) { case NC_CHAR: fprintf(f, " char"); break; case NC_BYTE: fprintf(f, " byte"); break; case NC_SHORT: fprintf(f, " short"); break; case NC_INT: fprintf(f, " int"); break; case NC_FLOAT: fprintf(f, " float"); break; case NC_DOUBLE: fprintf(f, " doule"); break; default: fprintf(f, " unknown"); break; } fprintf(f, " %s", name); if (ndim > 0) { for (int j = 0; j < ndim; j++) { cdf_check_error(caller, nc_inq_dimname(ncid, dimid[j], name)); if (j == 0) fprintf(f, "(%s", name); else fprintf(f, ", %s", name); } fprintf(f, ")"); } fprintf(f, "\n"); get_attributes(caller, ncid, f, i, " "); fprintf(f, "\n"); } // global attributes fprintf(f, "Global attributes:\n"); get_attributes(caller, ncid, f, NC_GLOBAL, " "); fflush(f); if (f != stdout) fclose(f); return 0; } static zsRegPrimitive nc15("info", NC_TYPE, cdf_info); void get_attributes(void* caller, int ncid, FILE *f, const int ivar, const char* space) { int i, status, natt; char name[NC_MAX_NAME]; cdf_check_error(caller, nc_inq_varnatts(ncid, ivar, &natt)); for (i = 0; i < natt; i++) { nc_type type; size_t j, len; cdf_check_error(caller, nc_inq_attname(ncid, ivar, i, name)); cdf_check_error(caller, nc_inq_att(ncid, ivar, name, &type, &len)); char *buff = new char[len * sizeof(double)]; fprintf(f, "%s%s:", space, name); switch(type) { case NC_CHAR: status = nc_get_att_text(ncid, ivar, name, buff); if (status == NC_NOERR) { buff[len] = 0; fprintf(f, " %s", buff); } break; case NC_BYTE: status = nc_get_att_uchar(ncid, ivar, name, (unsigned char*)buff); if (status == NC_NOERR) { for (j = 0; j < len; j++) fprintf(f, " %d", ((unsigned char*)buff)[j]); } break; case NC_SHORT: status = nc_get_att_short(ncid, ivar, name, (short*)buff); if (status == NC_NOERR) { for (j = 0; j < len; j++) fprintf(f, " %d", ((short*)buff)[j]); } break; case NC_INT: status = nc_get_att_int(ncid, ivar, name, (int*)buff); if (status == NC_NOERR) { for (j = 0; j < len; j++) fprintf(f, " %d", ((int*)buff)[j]); } break; case NC_FLOAT: status = nc_get_att_float(ncid, ivar, name, (float*)buff); if (status == NC_NOERR) { for (j = 0; j < len; j++) fprintf(f, " %e", ((float*)buff)[j]); } break; case NC_DOUBLE: status = nc_get_att_double(ncid, ivar, name, (double*)buff); if (status == NC_NOERR) { for (j = 0; j < len; j++) fprintf(f, " %e", ((double*)buff)[j]); } break; default: delete[] buff; api_runtime_error(caller, "nnknown data type"); } delete[] buff; fprintf(f, "\n"); cdf_check_error(caller, status); } fflush(stdout); } void *get_attributes2(void* caller, int ncid, const int ivar) { int i, status, natt; char name[NC_MAX_NAME]; cdf_check_error(caller, nc_inq_varnatts(ncid, ivar, &natt)); void *arr = api_create_array(caller, natt); for (i = 0; i < natt; i++) { nc_type type; size_t j, len; cdf_check_error(caller, nc_inq_attname(ncid, ivar, i, name)); cdf_check_error(caller, nc_inq_att(ncid, ivar, name, &type, &len)); char *buff = new char[len * sizeof(double)]; switch(type) { case NC_CHAR: status = nc_get_att_text(ncid, ivar, name, buff); if (status == NC_NOERR) { buff[len] = 0; api_set_array_object(caller, arr, name, api_create_string(caller, buff)); } break; case NC_BYTE: status = nc_get_att_uchar(ncid, ivar, name, (unsigned char*)buff); if (status == NC_NOERR) { if (len == 1) { api_set_array_object(caller, arr, name, api_create_integer(caller, ((unsigned char*)buff)[0])); } else { void *arr2 = api_create_array(caller, len); for (j = 0; j < len; j++) { api_set_array_object2(caller, arr2, j, api_create_integer(caller, ((unsigned char*)buff)[j])); } api_set_array_object(caller, arr, name, arr2); } } break; case NC_SHORT: status = nc_get_att_short(ncid, ivar, name, (short*)buff); if (status == NC_NOERR) { if (len == 1) { api_set_array_object(caller, arr, name, api_create_integer(caller, ((short*)buff)[0])); } else { void *arr2 = api_create_array(caller, len); for (j = 0; j < len; j++) { api_set_array_object2(caller, arr2, j, api_create_integer(caller, ((short*)buff)[j])); } api_set_array_object(caller, arr, name, arr2); } } break; case NC_INT: status = nc_get_att_int(ncid, ivar, name, (int*)buff); if (status == NC_NOERR) { if (len == 1) { api_set_array_object(caller, arr, name, api_create_integer(caller, ((int*)buff)[0])); } else { void *arr2 = api_create_array(caller, len); for (j = 0; j < len; j++) { api_set_array_object2(caller, arr2, j, api_create_integer(caller, ((int*)buff)[j])); } api_set_array_object(caller, arr, name, arr2); } } break; case NC_FLOAT: status = nc_get_att_float(ncid, ivar, name, (float*)buff); if (status == NC_NOERR) { if (len == 1) { api_set_array_object(caller, arr, name, api_create_integer(caller, ((float*)buff)[0])); } else { void *arr2 = api_create_array(caller, len); for (j = 0; j < len; j++) { api_set_array_object2(caller, arr2, j, api_create_real(caller, ((float*)buff)[j])); } api_set_array_object(caller, arr, name, arr2); } } break; case NC_DOUBLE: status = nc_get_att_double(ncid, ivar, name, (double*)buff); if (status == NC_NOERR) { if (len == 1) { api_set_array_object(caller, arr, name, api_create_integer(caller, ((double*)buff)[0])); } else { void *arr2 = api_create_array(caller, len); for (j = 0; j < len; j++) { api_set_array_object2(caller, arr2, j, api_create_real(caller, ((double*)buff)[j])); } api_set_array_object(caller, arr, name, arr2); } } break; default: delete[] buff; api_runtime_error(caller, "unknown data type"); } delete[] buff; cdf_check_error(caller, status); } return arr; }