/* * Copyright 1996, University Corporation for Atmospheric Research * See netcdf/COPYRIGHT file for copying and redistribution conditions. */ #include "config.h" #include #include #include #ifdef _MSC_VER #include #endif #include "netcdf.h" /* Common utilities related to filters. */ /* Forward */ static int gettype(const int q0, const int q1, int* unsignedp); /**************************************************/ /* Parse a filter spec string into a filter id + a vector of unsigned ints. @param spec0 - a string containing the spec as a sequence of constants separated by commas. @param idp - store the parsed filter id here @param nparamsp - store number of parsed filter params here @param paramsp - store the vector of parsed filter params here @return 1 if parse succeeded, 0 otherwise. */ EXTERNL int NC_parsefilterspec(const char* spec, unsigned int* idp, size_t* nparamsp, unsigned int** paramsp) { int stat = NC_NOERR; int sstat; /* for scanf */ char* p; char* sdata = NULL; unsigned int id; size_t count; /* no. of comma delimited params */ size_t nparams; /* final no. of unsigned ints */ size_t len; int i; unsigned int* ulist = NULL; unsigned char mem[8]; /* to convert to network byte order */ if(spec == NULL || strlen(spec) == 0) goto fail; sdata = strdup(spec); /* Count number of parameters + id and delimit */ p=sdata; for(count=0;;count++) { char* q = strchr(p,','); if(q == NULL) break; *q++ = '\0'; p = q; } count++; /* for final piece */ if(count == 0) goto fail; /* no id and no parameters */ /* Extract the filter id */ p = sdata; sstat = sscanf(p,"%u",&id); if(sstat != 1) goto fail; /* skip past the filter id */ p = p + strlen(p) + 1; count--; /* Allocate the max needed space; *2 in case the params are all doubles */ ulist = (unsigned int*)malloc(sizeof(unsigned int)*(count)*2); if(ulist == NULL) goto fail; /* walk and convert */ nparams = 0; /* actual count */ for(i=0;i 2 => we might have a two letter tag */ q = (p + len) - 2; type = gettype(*q,*(q+1),&isunsigned); break; } /* Now parse */ switch (type) { case 'b': case 's': case 'i': /* special case for a positive integer;for back compatibility.*/ if(!isnegative) sstat = sscanf(p,"%u",&val32u); else sstat = sscanf(p,"%d",(int*)&val32u); if(sstat != 1) goto fail; switch(type) { case 'b': val32u = (val32u & 0xFF); break; case 's': val32u = (val32u & 0xFFFF); break; } ulist[nparams++] = val32u; break; case 'f': sstat = sscanf(p,"%lf",&vald); if(sstat != 1) goto fail; valf = (float)vald; ulist[nparams++] = *(unsigned int*)&valf; break; case 'd': sstat = sscanf(p,"%lf",&vald); if(sstat != 1) goto fail; /* convert to network byte order */ memcpy(mem,&vald,sizeof(mem)); #ifdef WORDS_BIGENDIAN NC_byteswap8(mem); /* convert big endian to little endian */ #endif vector = (unsigned int*)mem; ulist[nparams++] = vector[0]; ulist[nparams++] = vector[1]; break; case 'l': /* long long */ if(isunsigned) sstat = sscanf(p,"%llu",&val64u); else sstat = sscanf(p,"%lld",(long long*)&val64u); if(sstat != 1) goto fail; /* convert to network byte order */ memcpy(mem,&val64u,sizeof(mem)); #ifdef WORDS_BIGENDIAN NC_byteswap8(mem); /* convert big endian to little endian */ #endif vector = (unsigned int*)mem; ulist[nparams++] = vector[0]; ulist[nparams++] = vector[1]; break; default: goto fail; } p = p + strlen(p) + 1; /* move to next param */ } /* Now return results */ if(idp) *idp = id; if(nparamsp) *nparamsp = nparams; if(paramsp) { *paramsp = ulist; ulist = NULL; /* avoid duplicate free */ } done: if(sdata) free(sdata); if(ulist) free(ulist); return stat; fail: stat = NC_EFILTER; goto done; } /* Look at q0 and q1) to determine type */ static int gettype(const int q0, const int q1, int* isunsignedp) { int type = 0; int isunsigned = 0; char typechar; isunsigned = (q0 == 'u' || q0 == 'U'); if(q1 == '\0') typechar = q0; /* we were given only a single char */ else if(isunsigned) typechar = q1; /* we have something like Ux as the tag */ else typechar = q1; /* look at last char for tag */ switch (typechar) { case 'f': case 'F': case '.': type = 'f'; break; /* float */ case 'd': case 'D': type = 'd'; break; /* double */ case 'b': case 'B': type = 'b'; break; /* byte */ case 's': case 'S': type = 's'; break; /* short */ case 'l': case 'L': type = 'l'; break; /* long long */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': type = 'i'; break; case 'u': case 'U': type = 'i'; isunsigned = 1; break; /* unsigned int */ case '\0': type = 'i'; break; default: break; } if(isunsignedp) *isunsignedp = isunsigned; return type; } #ifdef WORDS_BIGENDIAN /* Byte swap an 8-byte integer in place */ EXTERNL void NC_byteswap8(unsigned char* mem) { unsigned char c; c = mem[0]; mem[0] = mem[7]; mem[7] = c; c = mem[1]; mem[1] = mem[6]; mem[6] = c; c = mem[2]; mem[2] = mem[5]; mem[5] = c; c = mem[3]; mem[3] = mem[4]; mem[4] = c; } #endif