Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

var.c

Go to the documentation of this file.
00001 /*
00002  *      Copyright 1996, University Corporation for Atmospheric Research
00003  *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
00004  */
00005 
00006 #include "nc.h"
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <assert.h>
00010 #include "ncx.h"
00011 #include "rnd.h"
00012 
00013 
00014 /*
00015  * Free var
00016  * Formerly
00017 NC_free_var(var)
00018  */
00019 void
00020 free_NC_var(NC_var *varp)
00021 {
00022         if(varp == NULL)
00023                 return;
00024         free_NC_attrarrayV(&varp->attrs);
00025         free_NC_string(varp->name);
00026         free(varp);
00027 }
00028 
00029 
00030 /* 
00031  * Common code for new_NC_var() 
00032  * and ncx_get_NC_var()
00033  */
00034 NC_var *
00035 new_x_NC_var(
00036         NC_string *strp,
00037         size_t ndims)
00038 {
00039         NC_var *varp;
00040         const size_t o1 = M_RNDUP(ndims * sizeof(int));
00041         const size_t o2 = M_RNDUP(ndims * sizeof(size_t));
00042         const size_t sz =  M_RNDUP(sizeof(NC_var)) +
00043                  o1 + o2 + ndims * sizeof(size_t);
00044 
00045         varp = (NC_var *) malloc(sz);
00046         if(varp == NULL )
00047                 return NULL;
00048         (void) memset(varp, 0, sz);
00049 
00050         varp->name = strp;
00051         varp->ndims = ndims;
00052 
00053         if(ndims != 0)
00054         {
00055                 /*
00056                  * NOTE: lint may complain about the next 3 lines:
00057                  * "pointer cast may result in improper alignment".
00058                  * We use the M_RNDUP() macro to get the proper alignment.
00059                  */
00060                 varp->dimids = (int *)((char *)varp + M_RNDUP(sizeof(NC_var)));
00061                 varp->shape = (size_t *)((char *)varp->dimids + o1);
00062                 varp->dsizes = (size_t *)((char *)varp->shape + o2);
00063         }
00064 
00065         varp->xsz = 0;
00066         varp->len = 0;
00067         varp->begin = 0;
00068 
00069         return varp;
00070 }
00071 
00072 
00073 /*
00074  * Formerly
00075 NC_new_var()
00076  */
00077 static NC_var *
00078 new_NC_var(const char *name, nc_type type,
00079         size_t ndims, const int *dimids)
00080 {
00081         NC_string *strp;
00082         NC_var *varp;
00083 
00084         strp = new_NC_string(strlen(name), name);
00085         if(strp == NULL)
00086                 return NULL;
00087 
00088         varp = new_x_NC_var(strp, ndims);
00089         if(varp == NULL )
00090         {
00091                 free_NC_string(strp);
00092                 return NULL;
00093         }
00094         
00095         varp->type = type;
00096 
00097         if( ndims != 0 && dimids != NULL)
00098                 (void) memcpy(varp->dimids, dimids, ndims * sizeof(int));
00099 
00100         return(varp);
00101 }
00102 
00103 
00104 static NC_var *
00105 dup_NC_var(const NC_var *rvarp)
00106 {
00107         NC_var *varp = new_NC_var(rvarp->name->cp, rvarp->type,
00108                  rvarp->ndims, rvarp->dimids);
00109         if(varp == NULL)
00110                 return NULL;
00111 
00112         
00113         if(dup_NC_attrarrayV(&varp->attrs, &rvarp->attrs) != NC_NOERR)
00114         {
00115                 free_NC_var(varp);
00116                 return NULL;
00117         }
00118 
00119         (void) memcpy(varp->shape, rvarp->shape,
00120                          rvarp->ndims * sizeof(size_t));
00121         (void) memcpy(varp->dsizes, rvarp->dsizes,
00122                          rvarp->ndims * sizeof(size_t));
00123         varp->xsz = rvarp->xsz;
00124         varp->len = rvarp->len;
00125         varp->begin = rvarp->begin;
00126 
00127         return varp;
00128 }
00129 
00130 
00131 /* vararray */
00132 
00133 
00134 /*
00135  * Free the stuff "in" (referred to by) an NC_vararray.
00136  * Leaves the array itself allocated.
00137  */
00138 void
00139 free_NC_vararrayV0(NC_vararray *ncap)
00140 {
00141         assert(ncap != NULL);
00142 
00143         if(ncap->nelems == 0)
00144                 return;
00145 
00146         assert(ncap->value != NULL);
00147 
00148         {
00149                 NC_var **vpp = ncap->value;
00150                 NC_var *const *const end = &vpp[ncap->nelems];
00151                 for( /*NADA*/; vpp < end; vpp++)
00152                 {
00153                         free_NC_var(*vpp);
00154                         *vpp = NULL;
00155                 }
00156         }
00157         ncap->nelems = 0;
00158 }
00159 
00160 
00161 /*
00162  * Free NC_vararray values.
00163  * formerly
00164 NC_free_array()
00165  */
00166 void
00167 free_NC_vararrayV(NC_vararray *ncap)
00168 {
00169         assert(ncap != NULL);
00170         
00171         if(ncap->nalloc == 0)
00172                 return;
00173 
00174         assert(ncap->value != NULL);
00175 
00176         free_NC_vararrayV0(ncap);
00177 
00178         free(ncap->value);
00179         ncap->value = NULL;
00180         ncap->nalloc = 0;
00181 }
00182 
00183 
00184 int
00185 dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref)
00186 {
00187         int status = NC_NOERR;
00188 
00189         assert(ref != NULL);
00190         assert(ncap != NULL);
00191 
00192         if(ref->nelems != 0)
00193         {
00194                 const size_t sz = ref->nelems * sizeof(NC_var *);
00195                 ncap->value = (NC_var **) malloc(sz);
00196                 if(ncap->value == NULL)
00197                         return NC_ENOMEM;
00198                 (void) memset(ncap->value, 0, sz);
00199                 ncap->nalloc = ref->nelems;
00200         }
00201 
00202         ncap->nelems = 0;
00203         {
00204                 NC_var **vpp = ncap->value;
00205                 const NC_var **drpp = (const NC_var **)ref->value;
00206                 NC_var *const *const end = &vpp[ref->nelems];
00207                 for( /*NADA*/; vpp < end; drpp++, vpp++, ncap->nelems++)
00208                 {
00209                         *vpp = dup_NC_var(*drpp);
00210                         if(*vpp == NULL)
00211                         {
00212                                 status = NC_ENOMEM;
00213                                 break;
00214                         }
00215                 }
00216         }
00217 
00218         if(status != NC_NOERR)
00219         {
00220                 free_NC_vararrayV(ncap);
00221                 return status;
00222         }
00223 
00224         assert(ncap->nelems == ref->nelems);
00225 
00226         return NC_NOERR;
00227 }
00228 
00229 
00230 /*
00231  * Add a new handle on the end of an array of handles
00232  * Formerly
00233 NC_incr_array(array, tail)
00234  */
00235 static int
00236 incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp)
00237 {
00238         NC_var **vp;
00239 
00240         assert(ncap != NULL);
00241 
00242         if(ncap->nalloc == 0)
00243         {
00244                 assert(ncap->nelems == 0);
00245                 vp = (NC_var **) malloc(NC_ARRAY_GROWBY * sizeof(NC_var *));
00246                 if(vp == NULL)
00247                         return NC_ENOMEM;
00248                 ncap->value = vp;
00249                 ncap->nalloc = NC_ARRAY_GROWBY;
00250         }
00251         else if(ncap->nelems +1 > ncap->nalloc)
00252         {
00253                 vp = (NC_var **) realloc(ncap->value,
00254                         (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *));
00255                 if(vp == NULL)
00256                         return NC_ENOMEM;
00257                 ncap->value = vp;
00258                 ncap->nalloc += NC_ARRAY_GROWBY;
00259         }
00260 
00261         if(newelemp != NULL)
00262         {
00263                 ncap->value[ncap->nelems] = newelemp;
00264                 ncap->nelems++;
00265         }
00266         return NC_NOERR;
00267 }
00268 
00269 
00270 static NC_var *
00271 elem_NC_vararray(const NC_vararray *ncap, size_t elem)
00272 {
00273         assert(ncap != NULL);
00274                 /* cast needed for braindead systems with signed size_t */
00275         if(ncap->nelems == 0 || (unsigned long)elem >= ncap->nelems)
00276                 return NULL;
00277 
00278         assert(ncap->value != NULL);
00279 
00280         return ncap->value[elem];
00281 }
00282 
00283 
00284 /* End vararray per se */
00285 
00286 
00287 /*
00288  * Step thru NC_VARIABLE array, seeking match on name.
00289  * Return varid or -1 on not found.
00290  * *varpp is set to the appropriate NC_var.
00291  * Formerly (sort of)
00292 NC_hvarid
00293  */
00294 int
00295 NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp)
00296 {
00297         NC_var **loc;
00298         size_t slen;
00299         int varid;
00300 
00301         assert(ncap != NULL);
00302 
00303         if(ncap->nelems == 0)
00304                 return -1;
00305 
00306         loc = (NC_var **) ncap->value;
00307 
00308         slen = strlen(name);
00309 
00310         for(varid = 0; (size_t) varid < ncap->nelems; varid++, loc++)
00311         {
00312                 if(strlen((*loc)->name->cp) == slen &&
00313                         strncmp((*loc)->name->cp, name, slen) == 0)
00314                 {
00315                         if(varpp != NULL)
00316                                 *varpp = *loc;
00317                         return(varid); /* Normal return */
00318                 }
00319         }
00320         return(-1); /* not found */
00321 }
00322 
00323 /* 
00324  * For a netcdf type
00325  *  return the size of one element in the external representation.
00326  * Note that arrays get rounded up to X_ALIGN boundaries.
00327  * Formerly
00328 NC_xtypelen
00329  * See also ncx_len()
00330  */
00331 size_t
00332 ncx_szof(nc_type type)
00333 {
00334         switch(type){
00335         case NC_BYTE:
00336         case NC_CHAR:
00337                 return(1);
00338         case NC_SHORT :
00339                 return(2);
00340         case NC_INT:
00341                 return X_SIZEOF_INT;
00342         case NC_FLOAT:
00343                 return X_SIZEOF_FLOAT;
00344         case NC_DOUBLE : 
00345                 return X_SIZEOF_DOUBLE;
00346         }
00347         /* default */
00348         assert("ncx_szof invalid type" == 0);
00349         return 0;
00350 }
00351 
00352 
00353 /*
00354  * 'compile' the shape and len of a variable
00355  *  Formerly
00356 NC_var_shape(var, dims)
00357  */
00358 int
00359 NC_var_shape(NC_var *varp, const NC_dimarray *dims)
00360 {
00361         size_t *shp, *dsp, *op;
00362         int *ip;
00363         const NC_dim *dimp;
00364         size_t product = 1;
00365         
00366         varp->xsz = ncx_szof(varp->type);
00367 
00368         if(varp->ndims == 0)
00369         {
00370                 goto out;
00371         }
00372 
00373         /*
00374          * use the user supplied dimension indices
00375          * to determine the shape
00376          */
00377         for(ip = varp->dimids, op = varp->shape
00378                 ; ip < &varp->dimids[varp->ndims]; ip++, op++)
00379         {
00380                 if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) )
00381                         return NC_EBADDIM;
00382                 
00383                 dimp = elem_NC_dimarray(dims, (size_t)*ip);
00384                 *op = dimp->size;
00385                 if(*op == NC_UNLIMITED && ip != varp->dimids)
00386                         return NC_EUNLIMPOS;
00387         }
00388 
00389         /* 
00390          * Compute the dsizes
00391          */
00392                                 /* ndims is > 0 here */
00393         for(shp = varp->shape + varp->ndims -1,
00394                                 dsp = varp->dsizes + varp->ndims -1;
00395                         shp >= varp->shape;
00396                         shp--, dsp--)
00397         {
00398                 if(!(shp == varp->shape && IS_RECVAR(varp)))
00399                         product *= *shp;
00400                 *dsp = product;
00401         }
00402 
00403 
00404 out :
00405         varp->len = product * varp->xsz;
00406         switch(varp->type) {
00407         case NC_BYTE :
00408         case NC_CHAR :
00409         case NC_SHORT :
00410                 if( varp->len%4 != 0 )
00411                 {
00412                         varp->len += 4 - varp->len%4; /* round up */
00413         /*              *dsp += 4 - *dsp%4; */
00414                 }
00415                 break;
00416         default:
00417                 /* already aligned */
00418                 break;
00419         }
00420 #if 0
00421         arrayp("\tshape", varp->ndims, varp->shape);
00422         arrayp("\tdsizes", varp->ndims, varp->dsizes);
00423 #endif
00424         return NC_NOERR;
00425 }
00426 
00427 
00428 /*
00429  * Given valid ncp and varid, return var
00430  *  else NULL on error
00431  * Formerly
00432 NC_hlookupvar()
00433  */
00434 NC_var *
00435 NC_lookupvar(NC *ncp, int varid)
00436 {
00437         NC_var *varp;
00438 
00439         if(varid == NC_GLOBAL)
00440         {
00441                 /* Global is error in this context */
00442                 return(NULL);
00443         }
00444 
00445         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00446         if(varp == NULL)
00447         {
00448                 return NULL;
00449         }
00450 
00451         assert(varp != NULL);
00452 
00453         return(varp);
00454 }
00455 
00456 
00457 /* Public */
00458 
00459 int
00460 nc_def_var( int ncid, const char *name, nc_type type,
00461          int ndims, const int *dimids, int *varidp)
00462 {
00463         int status;
00464         NC *ncp;
00465         int varid;
00466         NC_var *varp;
00467 
00468         status = NC_check_id(ncid, &ncp); 
00469         if(status != NC_NOERR)
00470                 return status;
00471 
00472         if(!NC_indef(ncp))
00473         {
00474                 return NC_ENOTINDEFINE;
00475         }
00476 
00477         status = NC_check_name(name);
00478         if(status != NC_NOERR)
00479                 return status;
00480 
00481         status = nc_cktype(type);
00482         if(status != NC_NOERR)
00483                 return status;
00484 
00485                 /* cast needed for braindead systems with signed size_t */
00486         if((unsigned long) ndims > X_INT_MAX) /* Backward compat */
00487         {
00488                 return NC_EINVAL;
00489         } 
00490 
00491         if(ncp->vars.nelems >= NC_MAX_VARS)
00492         {
00493                 return NC_EMAXVARS;
00494         }
00495 
00496         varid = NC_findvar(&ncp->vars, name, &varp);
00497         if(varid != -1)
00498         {
00499                 return NC_ENAMEINUSE;
00500         }
00501         
00502         varp = new_NC_var(name, type, ndims, dimids);
00503         if(varp == NULL)
00504                 return NC_ENOMEM;
00505 
00506         status = NC_var_shape(varp, &ncp->dims);
00507         if(status != NC_NOERR)
00508         {
00509                 free_NC_var(varp);
00510                 return status;
00511         }
00512 
00513         status = incr_NC_vararray(&ncp->vars, varp);
00514         if(status != NC_NOERR)
00515         {
00516                 free_NC_var(varp);
00517                 return status;
00518         }
00519 
00520         if(varidp != NULL)
00521                 *varidp = (int)ncp->vars.nelems -1; /* varid */
00522         return NC_NOERR;
00523 }
00524 
00525 
00526 int
00527 nc_inq_varid(int ncid, const char *name, int *varid_ptr)
00528 {
00529         int status;
00530         NC *ncp;
00531         NC_var *varp;
00532         int varid;
00533 
00534         status = NC_check_id(ncid, &ncp); 
00535         if(status != NC_NOERR)
00536                 return status;
00537 
00538         varid = NC_findvar(&ncp->vars, name, &varp);
00539         if(varid == -1)
00540         {
00541                 return NC_ENOTVAR;
00542         }
00543 
00544         *varid_ptr = varid;
00545         return NC_NOERR;
00546 }
00547 
00548 
00549 int
00550 nc_inq_var(int ncid,
00551         int varid,
00552         char *name,
00553         nc_type *typep,
00554         int *ndimsp,
00555         int *dimids,
00556         int *nattsp)
00557 {
00558         int status;
00559         NC *ncp;
00560         NC_var *varp;
00561         size_t ii;
00562 
00563         status = NC_check_id(ncid, &ncp); 
00564         if(status != NC_NOERR)
00565                 return status;
00566 
00567         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00568         if(varp == NULL)
00569                 return NC_ENOTVAR;
00570 
00571         if(name != NULL)
00572         {
00573                 (void) strncpy(name, varp->name->cp, varp->name->nchars);
00574                 name[varp->name->nchars] = 0;
00575         }
00576 
00577         if(typep != 0)
00578                 *typep = varp->type;
00579         if(ndimsp != 0)
00580         {
00581                 *ndimsp = (int) varp->ndims;
00582         }
00583         if(dimids != 0)
00584         {
00585                 for(ii = 0; ii < varp->ndims; ii++)
00586                 {
00587                         dimids[ii] = varp->dimids[ii];
00588                 }
00589         }
00590         if(nattsp != 0)
00591         {
00592                 *nattsp = (int) varp->attrs.nelems;
00593         }
00594 
00595         return NC_NOERR;
00596 }
00597 
00598 
00599 int 
00600 nc_inq_varname(int ncid, int varid, char *name)
00601 {
00602         int status;
00603         NC *ncp;
00604         NC_var *varp;
00605 
00606         status = NC_check_id(ncid, &ncp); 
00607         if(status != NC_NOERR)
00608                 return status;
00609 
00610         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00611         if(varp == NULL)
00612                 return NC_ENOTVAR;
00613 
00614         if(name != NULL)
00615         {
00616                 (void) strncpy(name, varp->name->cp, varp->name->nchars);
00617                 name[varp->name->nchars] = 0;
00618         }
00619 
00620         return NC_NOERR;
00621 }
00622 
00623 int 
00624 nc_inq_vartype(int ncid, int varid, nc_type *typep)
00625 {
00626         int status;
00627         NC *ncp;
00628         NC_var *varp;
00629 
00630         status = NC_check_id(ncid, &ncp); 
00631         if(status != NC_NOERR)
00632                 return status;
00633 
00634         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00635         if(varp == NULL)
00636                 return NC_ENOTVAR;
00637 
00638         if(typep != 0)
00639                 *typep = varp->type;
00640 
00641         return NC_NOERR;
00642 }
00643 
00644 int 
00645 nc_inq_varndims(int ncid, int varid, int *ndimsp)
00646 {
00647         int status;
00648         NC *ncp;
00649         NC_var *varp;
00650 
00651         status = NC_check_id(ncid, &ncp); 
00652         if(status != NC_NOERR)
00653                 return status;
00654 
00655         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00656         if(varp == NULL)
00657                 return NC_ENOTVAR; /* TODO: is this the right error code? */
00658 
00659         if(ndimsp != 0)
00660         {
00661                 *ndimsp = (int) varp->ndims;
00662         }
00663 
00664         return NC_NOERR;
00665 }
00666 
00667 
00668 int 
00669 nc_inq_vardimid(int ncid, int varid, int *dimids)
00670 {
00671         int status;
00672         NC *ncp;
00673         NC_var *varp;
00674         size_t ii;
00675 
00676         status = NC_check_id(ncid, &ncp); 
00677         if(status != NC_NOERR)
00678                 return status;
00679 
00680         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00681         if(varp == NULL)
00682                 return NC_ENOTVAR; /* TODO: is this the right error code? */
00683 
00684         if(dimids != 0)
00685         {
00686                 for(ii = 0; ii < varp->ndims; ii++)
00687                 {
00688                         dimids[ii] = varp->dimids[ii];
00689                 }
00690         }
00691 
00692         return NC_NOERR;
00693 }
00694 
00695 
00696 int 
00697 nc_inq_varnatts(int ncid, int varid, int *nattsp)
00698 {
00699         int status;
00700         NC *ncp;
00701         NC_var *varp;
00702 
00703         if(varid == NC_GLOBAL)
00704                 return  nc_inq_natts(ncid, nattsp);
00705 
00706         status = NC_check_id(ncid, &ncp); 
00707         if(status != NC_NOERR)
00708                 return status;
00709 
00710         varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
00711         if(varp == NULL)
00712                 return NC_ENOTVAR; /* TODO: is this the right error code? */
00713 
00714         if(nattsp != 0)
00715         {
00716                 *nattsp = (int) varp->attrs.nelems;
00717         }
00718 
00719         return NC_NOERR;
00720 }
00721 
00722 int
00723 nc_rename_var(int ncid, int varid, const char *newname)
00724 {
00725         int status;
00726         NC *ncp;
00727         NC_var *varp;
00728         NC_string *old, *newStr;
00729         int other;
00730 
00731         status = NC_check_id(ncid, &ncp); 
00732         if(status != NC_NOERR)
00733                 return status;
00734 
00735         if(NC_readonly(ncp))
00736         {
00737                 return NC_EPERM;
00738         }
00739 
00740         status = NC_check_name(newname);
00741         if(status != NC_NOERR)
00742                 return status;
00743 
00744         /* check for name in use */
00745         other = NC_findvar(&ncp->vars, newname, &varp);
00746         if(other != -1)
00747         {
00748                 return NC_ENAMEINUSE;
00749         }
00750         
00751         varp = NC_lookupvar(ncp, varid);
00752         if(varp == NULL)
00753         {
00754                 /* invalid varid */
00755                 return NC_ENOTVAR; /* TODO: is this the right error code? */
00756         }
00757 
00758         old = varp->name;
00759         if(NC_indef(ncp))
00760         {
00761                 newStr = new_NC_string(strlen(newname),newname);
00762                 if(newStr == NULL)
00763                         return(-1);
00764                 varp->name = newStr;
00765                 free_NC_string(old);
00766                 return NC_NOERR;
00767         }
00768 
00769         /* else, not in define mode */
00770         status = set_NC_string(varp->name, newname);
00771         if(status != NC_NOERR)
00772                 return status;
00773 
00774         set_NC_hdirty(ncp);
00775 
00776         if(NC_doHsync(ncp))
00777         {
00778                 status = NC_sync(ncp);
00779                 if(status != NC_NOERR)
00780                         return status;
00781         }
00782 
00783         return NC_NOERR;
00784 }
 

Powered by Plone

This site conforms to the following standards: