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


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed