ncdf4a13/libsrc/dim.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 /* $Id: dim.c,v 1.74 2004/07/29 05:25:00 russ Exp $ */
00006 
00007 #include "nc.h"
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <assert.h>
00011 #include "ncx.h"
00012 #include "fbits.h"
00013 
00014 /*
00015  * Free dim
00016  * Formerly
00017 NC_free_dim(dim)
00018  */
00019 void
00020 free_NC_dim(NC_dim *dimp)
00021 {
00022         if(dimp == NULL)
00023                 return;
00024         free_NC_string(dimp->name);
00025         free(dimp);
00026 }
00027 
00028 
00029 NC_dim *
00030 new_x_NC_dim(NC_string *name)
00031 {
00032         NC_dim *dimp;
00033 
00034         dimp = (NC_dim *) malloc(sizeof(NC_dim));
00035         if(dimp == NULL)
00036                 return NULL;
00037 
00038         dimp->name = name;
00039         dimp->size = 0;
00040 
00041         return(dimp);
00042 }
00043 
00044 
00045 /*
00046  * Formerly
00047 NC_new_dim(const char *name, long size)
00048  */
00049 static NC_dim *
00050 new_NC_dim(const char *name, size_t size)
00051 {
00052         NC_string *strp;
00053         NC_dim *dimp;
00054 
00055         strp = new_NC_string(strlen(name), name);
00056         if(strp == NULL)
00057                 return NULL;
00058 
00059         dimp = new_x_NC_dim(strp);
00060         if(dimp == NULL)
00061         {
00062                 free_NC_string(strp);
00063                 return NULL;
00064         }
00065 
00066         dimp->size = size;
00067 
00068         return(dimp);
00069 }
00070 
00071 
00072 static NC_dim *
00073 dup_NC_dim(const NC_dim *dimp)
00074 {
00075         return new_NC_dim(dimp->name->cp, dimp->size);
00076 }
00077 
00078 /*
00079  * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension.
00080  * Return dimid or -1 on not found.
00081  * *dimpp is set to the appropriate NC_dim.
00082  * The loop structure is odd. In order to parallelize,
00083  * we moved a clearer 'break' inside the loop body to the loop test.
00084  */
00085 int
00086 find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
00087 {
00088         assert(ncap != NULL);
00089 
00090         if(ncap->nelems == 0)
00091                 return -1;
00092 
00093         {
00094         int dimid = 0;
00095         NC_dim **loc = ncap->value;
00096 
00097         for(; (size_t) dimid < ncap->nelems
00098                          && (*loc)->size != NC_UNLIMITED; dimid++, loc++)
00099         {
00100                 /*EMPTY*/
00101         }
00102         if(dimid >= ncap->nelems)
00103                 return(-1); /* not found */
00104         /* else, normal return */
00105         if(dimpp != NULL)
00106                 *dimpp = *loc;
00107         return dimid;
00108         }
00109 }
00110 
00111 
00112 /*
00113  * Step thru NC_DIMENSION array, seeking match on name.
00114  * Return dimid or -1 on not found.
00115  * *dimpp is set to the appropriate NC_dim.
00116  * The loop structure is odd. In order to parallelize,
00117  * we moved a clearer 'break' inside the loop body to the loop test.
00118  */
00119 static int
00120 NC_finddim(const NC_dimarray *ncap, const char *name, NC_dim **dimpp)
00121 {
00122 
00123         assert(ncap != NULL);
00124 
00125         if(ncap->nelems == 0)
00126                 return -1;
00127 
00128         {
00129         size_t slen = strlen(name);
00130         int dimid = 0;
00131         NC_dim **loc = (NC_dim **) ncap->value;
00132 
00133         for(; (size_t) dimid < ncap->nelems
00134                         && (strlen((*loc)->name->cp) != slen
00135                                 || strncmp((*loc)->name->cp, name, slen) != 0);
00136                  dimid++, loc++)
00137         {
00138                 /*EMPTY*/
00139         }
00140         if(dimid >= ncap->nelems)
00141                 return(-1); /* not found */
00142         /* else, normal return */
00143         if(dimpp != NULL)
00144                         *dimpp = *loc;
00145         return(dimid);
00146         }
00147 }
00148 
00149 
00150 /* dimarray */
00151 
00152 
00153 /*
00154  * Free the stuff "in" (referred to by) an NC_dimarray.
00155  * Leaves the array itself allocated.
00156  */
00157 void
00158 free_NC_dimarrayV0(NC_dimarray *ncap)
00159 {
00160         assert(ncap != NULL);
00161 
00162         if(ncap->nelems == 0)
00163                 return;
00164 
00165         assert(ncap->value != NULL);
00166 
00167         {
00168                 NC_dim **dpp = ncap->value;
00169                 NC_dim *const *const end = &dpp[ncap->nelems];
00170                 for( /*NADA*/; dpp < end; dpp++)
00171                 {
00172                         free_NC_dim(*dpp);
00173                         *dpp = NULL;
00174                 }
00175         }
00176         ncap->nelems = 0;
00177 }
00178 
00179 
00180 /*
00181  * Free NC_dimarray values.
00182  * formerly
00183 NC_free_array()
00184  */
00185 void
00186 free_NC_dimarrayV(NC_dimarray *ncap)
00187 {
00188         assert(ncap != NULL);
00189         
00190         if(ncap->nalloc == 0)
00191                 return;
00192 
00193         assert(ncap->value != NULL);
00194 
00195         free_NC_dimarrayV0(ncap);
00196 
00197         free(ncap->value);
00198         ncap->value = NULL;
00199         ncap->nalloc = 0;
00200 }
00201 
00202 
00203 int
00204 dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref)
00205 {
00206         int status = NC_NOERR;
00207 
00208         assert(ref != NULL);
00209         assert(ncap != NULL);
00210 
00211         if(ref->nelems != 0)
00212         {
00213                 const size_t sz = ref->nelems * sizeof(NC_dim *);
00214                 ncap->value = (NC_dim **) malloc(sz);
00215                 if(ncap->value == NULL)
00216                         return NC_ENOMEM;
00217                 (void) memset(ncap->value, 0, sz);
00218                 ncap->nalloc = ref->nelems;
00219         }
00220 
00221         ncap->nelems = 0;
00222         {
00223                 NC_dim **dpp = ncap->value;
00224                 const NC_dim **drpp = (const NC_dim **)ref->value;
00225                 NC_dim *const *const end = &dpp[ref->nelems];
00226                 for( /*NADA*/; dpp < end; drpp++, dpp++, ncap->nelems++)
00227                 {
00228                         *dpp = dup_NC_dim(*drpp);
00229                         if(*dpp == NULL)
00230                         {
00231                                 status = NC_ENOMEM;
00232                                 break;
00233                         }
00234                 }
00235         }
00236 
00237         if(status != NC_NOERR)
00238         {
00239                 free_NC_dimarrayV(ncap);
00240                 return status;
00241         }
00242 
00243         assert(ncap->nelems == ref->nelems);
00244 
00245         return NC_NOERR;
00246 }
00247 
00248 
00249 /*
00250  * Add a new handle on the end of an array of handles
00251  * Formerly
00252 NC_incr_array(array, tail)
00253  */
00254 static int
00255 incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
00256 {
00257         NC_dim **vp;
00258 
00259         assert(ncap != NULL);
00260 
00261         if(ncap->nalloc == 0)
00262         {
00263                 assert(ncap->nelems == 0);
00264                 vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *));
00265                 if(vp == NULL)
00266                         return NC_ENOMEM;
00267                 ncap->value = vp;
00268                 ncap->nalloc = NC_ARRAY_GROWBY;
00269         }
00270         else if(ncap->nelems +1 > ncap->nalloc)
00271         {
00272                 vp = (NC_dim **) realloc(ncap->value,
00273                         (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *));
00274                 if(vp == NULL)
00275                         return NC_ENOMEM;
00276                 ncap->value = vp;
00277                 ncap->nalloc += NC_ARRAY_GROWBY;
00278         }
00279 
00280         if(newelemp != NULL)
00281         {
00282                 ncap->value[ncap->nelems] = newelemp;
00283                 ncap->nelems++;
00284         }
00285         return NC_NOERR;
00286 }
00287 
00288 
00289 NC_dim *
00290 elem_NC_dimarray(const NC_dimarray *ncap, size_t elem)
00291 {
00292         assert(ncap != NULL);
00293                 /* cast needed for braindead systems with signed size_t */
00294         if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
00295                 return NULL;
00296 
00297         assert(ncap->value != NULL);
00298 
00299         return ncap->value[elem];
00300 }
00301 
00302 
00303 /* Public */
00304 
00305 int
00306 nc_def_dim(int ncid, const char *name, size_t size, int *dimidp)
00307 {
00308         int status;
00309         NC *ncp;
00310         int dimid;
00311         NC_dim *dimp;
00312 
00313         status = NC_check_id(ncid, &ncp); 
00314         if(status != NC_NOERR)
00315                 return status;
00316 
00317         if(!NC_indef(ncp))
00318                 return NC_ENOTINDEFINE;
00319 
00320         status = NC_check_name(name);
00321         if(status != NC_NOERR)
00322                 return status;
00323 
00324         if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) {
00325             /* CDF2 format and LFS */
00326             if(size > X_UINT_MAX - 3) /* "- 3" handles rounded-up size */
00327                 return NC_EDIMSIZE;
00328         } else {
00329             /* CDF1 format */
00330             if(size > X_INT_MAX - 3)
00331                 return NC_EDIMSIZE;
00332         }
00333 
00334         if(size == NC_UNLIMITED)
00335         {
00336                 dimid = find_NC_Udim(&ncp->dims, &dimp);
00337                 if(dimid != -1)
00338                 {
00339                         assert(dimid != -1);
00340                         return NC_EUNLIMIT;
00341                 }
00342         }
00343 
00344         if(ncp->dims.nelems >= NC_MAX_DIMS)
00345                 return NC_EMAXDIMS;
00346 
00347         dimid = NC_finddim(&ncp->dims, name, &dimp);
00348         if(dimid != -1)
00349                 return NC_ENAMEINUSE;
00350         
00351         dimp = new_NC_dim(name, size);
00352         if(dimp == NULL)
00353                 return NC_ENOMEM;
00354         status = incr_NC_dimarray(&ncp->dims, dimp);
00355         if(status != NC_NOERR)
00356         {
00357                 free_NC_dim(dimp);
00358                 return status;
00359         }
00360 
00361         if(dimidp != NULL)
00362                 *dimidp = (int)ncp->dims.nelems -1;
00363         return NC_NOERR;
00364 }
00365 
00366 
00367 int
00368 nc_inq_dimid(int ncid, const char *name, int *dimid_ptr)
00369 {
00370         int status;
00371         NC *ncp;
00372         int dimid;
00373 
00374         status = NC_check_id(ncid, &ncp); 
00375         if(status != NC_NOERR)
00376                 return status;
00377 
00378         dimid = NC_finddim(&ncp->dims, name, NULL);
00379 
00380         if(dimid == -1)
00381                 return NC_EBADDIM;
00382 
00383         *dimid_ptr = dimid;
00384         return NC_NOERR;
00385 }
00386 
00387 
00388 int
00389 nc_inq_dim(int ncid, int dimid, char *name, size_t *sizep)
00390 {
00391         int status;
00392         NC *ncp;
00393         NC_dim *dimp;
00394 
00395         status = NC_check_id(ncid, &ncp); 
00396         if(status != NC_NOERR)
00397                 return status;
00398 
00399         dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00400         if(dimp == NULL)
00401                 return NC_EBADDIM;
00402 
00403         if(name != NULL)
00404         {
00405                 (void)strncpy(name, dimp->name->cp, 
00406                         dimp->name->nchars);
00407                 name[dimp->name->nchars] = 0;
00408         }
00409         if(sizep != 0)
00410         {
00411                 if(dimp->size == NC_UNLIMITED)
00412                         *sizep = NC_get_numrecs(ncp);
00413                 else
00414                         *sizep = dimp->size;    
00415         }
00416         return NC_NOERR;
00417 }
00418 
00419 
00420 int 
00421 nc_inq_dimname(int ncid, int dimid, char *name)
00422 {
00423         int status;
00424         NC *ncp;
00425         NC_dim *dimp;
00426 
00427         status = NC_check_id(ncid, &ncp); 
00428         if(status != NC_NOERR)
00429                 return status;
00430 
00431         dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00432         if(dimp == NULL)
00433                 return NC_EBADDIM;
00434 
00435         if(name != NULL)
00436         {
00437                 (void)strncpy(name, dimp->name->cp, 
00438                         dimp->name->nchars);
00439                 name[dimp->name->nchars] = 0;
00440         }
00441 
00442         return NC_NOERR;
00443 }
00444 
00445 
00446 int 
00447 nc_inq_dimlen(int ncid, int dimid, size_t *lenp)
00448 {
00449         int status;
00450         NC *ncp;
00451         NC_dim *dimp;
00452 
00453         status = NC_check_id(ncid, &ncp); 
00454         if(status != NC_NOERR)
00455                 return status;
00456 
00457         dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00458         if(dimp == NULL)
00459                 return NC_EBADDIM;
00460 
00461         if(lenp != 0)
00462         {
00463                 if(dimp->size == NC_UNLIMITED)
00464                         *lenp = NC_get_numrecs(ncp);
00465                 else
00466                         *lenp = dimp->size;     
00467         }
00468         return NC_NOERR;
00469 }
00470 
00471 
00472 int
00473 nc_rename_dim( int ncid, int dimid, const char *newname)
00474 {
00475         int status;
00476         NC *ncp;
00477         int existid;
00478         NC_dim *dimp;
00479 
00480         status = NC_check_id(ncid, &ncp); 
00481         if(status != NC_NOERR)
00482                 return status;
00483 
00484         if(NC_readonly(ncp))
00485                 return NC_EPERM;
00486 
00487         status = NC_check_name(newname);
00488         if(status != NC_NOERR)
00489                 return status;
00490 
00491         existid = NC_finddim(&ncp->dims, newname, &dimp);
00492         if(existid != -1)
00493                 return NC_ENAMEINUSE;
00494 
00495         dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
00496         if(dimp == NULL)
00497                 return NC_EBADDIM;
00498 
00499         if(NC_indef(ncp))
00500         {
00501                 NC_string *old = dimp->name;
00502                 NC_string *newStr = new_NC_string(strlen(newname), newname);
00503                 if(newStr == NULL)
00504                         return NC_ENOMEM;
00505                 dimp->name = newStr;
00506                 free_NC_string(old);
00507                 return NC_NOERR;
00508         }
00509 
00510         /* else, not in define mode */
00511 
00512         status = set_NC_string(dimp->name, newname);
00513         if(status != NC_NOERR)
00514                 return status;
00515 
00516         set_NC_hdirty(ncp);
00517 
00518         if(NC_doHsync(ncp))
00519         {
00520                 status = NC_sync(ncp);
00521                 if(status != NC_NOERR)
00522                         return status;
00523         }
00524 
00525         return NC_NOERR;
00526 }

Generated on Thu Mar 16 18:10:09 2006 for nco by  doxygen 1.4.4