source: XIOS/trunk/extern/src_netcdf4/dim.c @ 409

Last change on this file since 409 was 409, checked in by ymipsl, 11 years ago

Add improved nectdf internal library src

YM

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1/*
2 *      Copyright 1996, University Corporation for Atmospheric Research
3 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
4 */
5/* $Id: dim.c,v 1.83 2010/05/25 17:54:15 dmh Exp $ */
6
7#include "nc.h"
8#include <stdlib.h>
9#include <string.h>
10#include <assert.h>
11#include "ncx.h"
12#include "fbits.h"
13#include "utf8proc.h"
14
15/*
16 * Free dim
17 * Formerly
18NC_free_dim(dim)
19 */
20void
21free_NC_dim(NC_dim *dimp)
22{
23        if(dimp == NULL)
24                return;
25        free_NC_string(dimp->name);
26        free(dimp);
27}
28
29
30NC_dim *
31new_x_NC_dim(NC_string *name)
32{
33        NC_dim *dimp;
34
35        dimp = (NC_dim *) malloc(sizeof(NC_dim));
36        if(dimp == NULL)
37                return NULL;
38
39        dimp->name = name;
40        dimp->hash = hash_fast(name->cp, strlen(name->cp));
41        dimp->size = 0;
42
43        return(dimp);
44}
45
46
47/*
48 * Formerly
49NC_new_dim(const char *uname, long size)
50 */
51static NC_dim *
52new_NC_dim(const char *uname, size_t size)
53{
54        NC_string *strp;
55        NC_dim *dimp;
56
57        char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
58        if(name == NULL)
59            return NULL;
60        strp = new_NC_string(strlen(name), name);
61        free(name);
62        if(strp == NULL)
63                return NULL;
64
65        dimp = new_x_NC_dim(strp);
66        if(dimp == NULL)
67        {
68                free_NC_string(strp);
69                return NULL;
70        }
71
72        dimp->size = size;
73
74        return(dimp);
75}
76
77
78static NC_dim *
79dup_NC_dim(const NC_dim *dimp)
80{
81        return new_NC_dim(dimp->name->cp, dimp->size);
82}
83
84/*
85 * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension.
86 * Return dimid or -1 on not found.
87 * *dimpp is set to the appropriate NC_dim.
88 * The loop structure is odd. In order to parallelize,
89 * we moved a clearer 'break' inside the loop body to the loop test.
90 */
91int
92find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
93{
94        assert(ncap != NULL);
95
96        if(ncap->nelems == 0)
97                return -1;
98
99        {
100        int dimid = 0;
101        NC_dim **loc = ncap->value;
102
103        for(; (size_t) dimid < ncap->nelems
104                         && (*loc)->size != NC_UNLIMITED; dimid++, loc++)
105        {
106                /*EMPTY*/
107        }
108        if(dimid >= ncap->nelems)
109                return(-1); /* not found */
110        /* else, normal return */
111        if(dimpp != NULL)
112                *dimpp = *loc;
113        return dimid;
114        }
115}
116
117
118/*
119 * Step thru NC_DIMENSION array, seeking match on uname.
120 * Return dimid or -1 on not found.
121 * *dimpp is set to the appropriate NC_dim.
122 * The loop structure is odd. In order to parallelize,
123 * we moved a clearer 'break' inside the loop body to the loop test.
124 */
125static int
126NC_finddim(const NC_dimarray *ncap, const char *uname, NC_dim **dimpp)
127{
128
129   int dimid;
130   uint32_t shash;
131   NC_dim ** loc;
132   char *name;
133
134   assert(ncap != NULL);
135
136   if(ncap->nelems == 0)
137      return -1;
138
139   {
140      dimid = 0;
141      loc = (NC_dim **) ncap->value;
142      /* normalized version of uname */
143      name = (char *)utf8proc_NFC((const unsigned char *)uname);
144      if(name == NULL)
145         return NC_ENOMEM;
146      shash = hash_fast(name, strlen(name));
147
148      for(; (size_t) dimid < ncap->nelems
149             && ((*loc)->hash != shash
150                 || strncmp((*loc)->name->cp, name, strlen(name)) != 0);
151          dimid++, loc++)
152      {
153         /*EMPTY*/
154      }
155      free(name);
156      if(dimid >= ncap->nelems)
157         return(-1); /* not found */
158      /* else, normal return */
159      if(dimpp != NULL)
160         *dimpp = *loc;
161      return(dimid);
162   }
163}
164
165
166/* dimarray */
167
168
169/*
170 * Free the stuff "in" (referred to by) an NC_dimarray.
171 * Leaves the array itself allocated.
172 */
173void
174free_NC_dimarrayV0(NC_dimarray *ncap)
175{
176        assert(ncap != NULL);
177
178        if(ncap->nelems == 0)
179                return;
180
181        assert(ncap->value != NULL);
182
183        {
184                NC_dim **dpp = ncap->value;
185                NC_dim *const *const end = &dpp[ncap->nelems];
186                for( /*NADA*/; dpp < end; dpp++)
187                {
188                        free_NC_dim(*dpp);
189                        *dpp = NULL;
190                }
191        }
192        ncap->nelems = 0;
193}
194
195
196/*
197 * Free NC_dimarray values.
198 * formerly
199NC_free_array()
200 */
201void
202free_NC_dimarrayV(NC_dimarray *ncap)
203{
204        assert(ncap != NULL);
205       
206        if(ncap->nalloc == 0)
207                return;
208
209        assert(ncap->value != NULL);
210
211        free_NC_dimarrayV0(ncap);
212
213        free(ncap->value);
214        ncap->value = NULL;
215        ncap->nalloc = 0;
216}
217
218
219int
220dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref)
221{
222        int status = NC_NOERR;
223
224        assert(ref != NULL);
225        assert(ncap != NULL);
226
227        if(ref->nelems != 0)
228        {
229                const size_t sz = ref->nelems * sizeof(NC_dim *);
230                ncap->value = (NC_dim **) malloc(sz);
231                if(ncap->value == NULL)
232                        return NC_ENOMEM;
233                (void) memset(ncap->value, 0, sz);
234                ncap->nalloc = ref->nelems;
235        }
236
237        ncap->nelems = 0;
238        {
239                NC_dim **dpp = ncap->value;
240                const NC_dim **drpp = (const NC_dim **)ref->value;
241                NC_dim *const *const end = &dpp[ref->nelems];
242                for( /*NADA*/; dpp < end; drpp++, dpp++, ncap->nelems++)
243                {
244                        *dpp = dup_NC_dim(*drpp);
245                        if(*dpp == NULL)
246                        {
247                                status = NC_ENOMEM;
248                                break;
249                        }
250                }
251        }
252
253        if(status != NC_NOERR)
254        {
255                free_NC_dimarrayV(ncap);
256                return status;
257        }
258
259        assert(ncap->nelems == ref->nelems);
260
261        return NC_NOERR;
262}
263
264
265/*
266 * Add a new handle on the end of an array of handles
267 * Formerly
268NC_incr_array(array, tail)
269 */
270static int
271incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
272{
273        NC_dim **vp;
274
275        assert(ncap != NULL);
276
277        if(ncap->nalloc == 0)
278        {
279                assert(ncap->nelems == 0);
280                vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *));
281                if(vp == NULL)
282                        return NC_ENOMEM;
283                ncap->value = vp;
284                ncap->nalloc = NC_ARRAY_GROWBY;
285        }
286        else if(ncap->nelems +1 > ncap->nalloc)
287        {
288                vp = (NC_dim **) realloc(ncap->value,
289                        (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *));
290                if(vp == NULL)
291                        return NC_ENOMEM;
292                ncap->value = vp;
293                ncap->nalloc += NC_ARRAY_GROWBY;
294        }
295
296        if(newelemp != NULL)
297        {
298                ncap->value[ncap->nelems] = newelemp;
299                ncap->nelems++;
300        }
301        return NC_NOERR;
302}
303
304
305NC_dim *
306elem_NC_dimarray(const NC_dimarray *ncap, size_t elem)
307{
308        assert(ncap != NULL);
309                /* cast needed for braindead systems with signed size_t */
310        if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
311                return NULL;
312
313        assert(ncap->value != NULL);
314
315        return ncap->value[elem];
316}
317
318
319/* Public */
320
321int
322NC3_def_dim(int ncid, const char *name, size_t size, int *dimidp)
323{
324        int status;
325        NC *ncp;
326        int dimid;
327        NC_dim *dimp;
328
329        status = NC_check_id(ncid, &ncp); 
330        if(status != NC_NOERR)
331                return status;
332
333        if(!NC_indef(ncp))
334                return NC_ENOTINDEFINE;
335
336        status = NC_check_name(name);
337        if(status != NC_NOERR)
338                return status;
339
340        if ((ncp->flags & NC_64BIT_OFFSET) && sizeof(off_t) > 4) {
341            /* CDF2 format and LFS */
342            if(size > X_UINT_MAX - 3) /* "- 3" handles rounded-up size */
343                return NC_EDIMSIZE;
344        } else {
345            /* CDF1 format */
346            if(size > X_INT_MAX - 3)
347                return NC_EDIMSIZE;
348        }
349
350        if(size == NC_UNLIMITED)
351        {
352                dimid = find_NC_Udim(&ncp->dims, &dimp);
353                if(dimid != -1)
354                {
355                        assert(dimid != -1);
356                        return NC_EUNLIMIT;
357                }
358        }
359
360        if(ncp->dims.nelems >= NC_MAX_DIMS)
361                return NC_EMAXDIMS;
362
363        dimid = NC_finddim(&ncp->dims, name, &dimp);
364        if(dimid != -1)
365                return NC_ENAMEINUSE;
366       
367        dimp = new_NC_dim(name, size);
368        if(dimp == NULL)
369                return NC_ENOMEM;
370        status = incr_NC_dimarray(&ncp->dims, dimp);
371        if(status != NC_NOERR)
372        {
373                free_NC_dim(dimp);
374                return status;
375        }
376
377        if(dimidp != NULL)
378                *dimidp = (int)ncp->dims.nelems -1;
379        return NC_NOERR;
380}
381
382
383int
384NC3_inq_dimid(int ncid, const char *name, int *dimid_ptr)
385{
386        int status;
387        NC *ncp;
388        int dimid;
389
390        status = NC_check_id(ncid, &ncp); 
391        if(status != NC_NOERR)
392                return status;
393
394        dimid = NC_finddim(&ncp->dims, name, NULL);
395
396        if(dimid == -1)
397                return NC_EBADDIM;
398
399        if (dimid_ptr)
400           *dimid_ptr = dimid;
401        return NC_NOERR;
402}
403
404int
405NC3_inq_dim(int ncid, int dimid, char *name, size_t *sizep)
406{
407        int status;
408        NC *ncp;
409        NC_dim *dimp;
410
411        status = NC_check_id(ncid, &ncp); 
412        if(status != NC_NOERR)
413                return status;
414
415        dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
416        if(dimp == NULL)
417                return NC_EBADDIM;
418
419        if(name != NULL)
420        {
421                (void)strncpy(name, dimp->name->cp, 
422                        dimp->name->nchars);
423                name[dimp->name->nchars] = 0;
424        }
425        if(sizep != NULL)
426        {
427                if(dimp->size == NC_UNLIMITED)
428                        *sizep = NC_get_numrecs(ncp);
429                else
430                        *sizep = dimp->size;   
431        }
432        return NC_NOERR;
433}
434
435int
436NC3_rename_dim( int ncid, int dimid, const char *unewname)
437{
438        int status;
439        NC *ncp;
440        int existid;
441        NC_dim *dimp;
442        char *newname;          /* normalized */
443
444        status = NC_check_id(ncid, &ncp); 
445        if(status != NC_NOERR)
446                return status;
447
448        if(NC_readonly(ncp))
449                return NC_EPERM;
450
451        status = NC_check_name(unewname);
452        if(status != NC_NOERR)
453                return status;
454
455        existid = NC_finddim(&ncp->dims, unewname, &dimp);
456        if(existid != -1)
457                return NC_ENAMEINUSE;
458
459        dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
460        if(dimp == NULL)
461                return NC_EBADDIM;
462
463        newname = (char *)utf8proc_NFC((const unsigned char *)unewname);
464        if(newname == NULL)
465            return NC_ENOMEM;
466        if(NC_indef(ncp))
467        {
468                NC_string *old = dimp->name;
469                NC_string *newStr = new_NC_string(strlen(newname), newname);
470                free(newname);
471                if(newStr == NULL)
472                        return NC_ENOMEM;
473                dimp->name = newStr;
474                dimp->hash = hash_fast(newStr->cp, strlen(newStr->cp));
475                free_NC_string(old);
476                return NC_NOERR;
477        }
478
479        /* else, not in define mode */
480
481        status = set_NC_string(dimp->name, newname);
482        dimp->hash = hash_fast(newname, strlen(newname));
483        free(newname);
484        if(status != NC_NOERR)
485                return status;
486
487        set_NC_hdirty(ncp);
488
489        if(NC_doHsync(ncp))
490        {
491                status = NC_sync(ncp);
492                if(status != NC_NOERR)
493                        return status;
494        }
495
496        return NC_NOERR;
497}
Note: See TracBrowser for help on using the repository browser.