attr.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. /* Do not edit this file. It is produced from the corresponding .m4 source */
  2. /*
  3. * Copyright 1996, University Corporation for Atmospheric Research
  4. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  5. */
  6. /* $Id: attr.m4,v 2.39 2010/05/26 18:11:08 dmh Exp $ */
  7. #include "nc.h"
  8. #include "ncdispatch.h"
  9. #include "nc3dispatch.h"
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <assert.h>
  13. #include "ncx.h"
  14. #include "fbits.h"
  15. #include "rnd.h"
  16. #include "utf8proc.h"
  17. /*
  18. * Free attr
  19. * Formerly
  20. NC_free_attr()
  21. */
  22. void
  23. free_NC_attr(NC_attr *attrp)
  24. {
  25. if(attrp == NULL)
  26. return;
  27. free_NC_string(attrp->name);
  28. free(attrp);
  29. }
  30. /*
  31. * How much space will 'nelems' of 'type' take in
  32. * external representation (as the values of an attribute)?
  33. */
  34. static size_t
  35. ncx_len_NC_attrV(nc_type type, size_t nelems)
  36. {
  37. switch(type) {
  38. case NC_BYTE:
  39. case NC_CHAR:
  40. return ncx_len_char(nelems);
  41. case NC_SHORT:
  42. return ncx_len_short(nelems);
  43. case NC_INT:
  44. return ncx_len_int(nelems);
  45. case NC_FLOAT:
  46. return ncx_len_float(nelems);
  47. case NC_DOUBLE:
  48. return ncx_len_double(nelems);
  49. default:
  50. assert("ncx_len_NC_attr bad type" == 0);
  51. }
  52. return 0;
  53. }
  54. NC_attr *
  55. new_x_NC_attr(
  56. NC_string *strp,
  57. nc_type type,
  58. size_t nelems)
  59. {
  60. NC_attr *attrp;
  61. const size_t xsz = ncx_len_NC_attrV(type, nelems);
  62. size_t sz = M_RNDUP(sizeof(NC_attr));
  63. assert(!(xsz == 0 && nelems != 0));
  64. sz += xsz;
  65. attrp = (NC_attr *) malloc(sz);
  66. if(attrp == NULL )
  67. return NULL;
  68. attrp->xsz = xsz;
  69. attrp->name = strp;
  70. attrp->type = type;
  71. attrp->nelems = nelems;
  72. if(xsz != 0)
  73. attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
  74. else
  75. attrp->xvalue = NULL;
  76. return(attrp);
  77. }
  78. /*
  79. * Formerly
  80. NC_new_attr(name,type,count,value)
  81. */
  82. static NC_attr *
  83. new_NC_attr(
  84. const char *uname,
  85. nc_type type,
  86. size_t nelems)
  87. {
  88. NC_string *strp;
  89. NC_attr *attrp;
  90. char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
  91. if(name == NULL)
  92. return NULL;
  93. assert(name != NULL && *name != 0);
  94. strp = new_NC_string(strlen(name), name);
  95. free(name);
  96. if(strp == NULL)
  97. return NULL;
  98. attrp = new_x_NC_attr(strp, type, nelems);
  99. if(attrp == NULL)
  100. {
  101. free_NC_string(strp);
  102. return NULL;
  103. }
  104. return(attrp);
  105. }
  106. static NC_attr *
  107. dup_NC_attr(const NC_attr *rattrp)
  108. {
  109. NC_attr *attrp = new_NC_attr(rattrp->name->cp,
  110. rattrp->type, rattrp->nelems);
  111. if(attrp == NULL)
  112. return NULL;
  113. (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
  114. return attrp;
  115. }
  116. /* attrarray */
  117. /*
  118. * Free the stuff "in" (referred to by) an NC_attrarray.
  119. * Leaves the array itself allocated.
  120. */
  121. void
  122. free_NC_attrarrayV0(NC_attrarray *ncap)
  123. {
  124. assert(ncap != NULL);
  125. if(ncap->nelems == 0)
  126. return;
  127. assert(ncap->value != NULL);
  128. {
  129. NC_attr **app = ncap->value;
  130. NC_attr *const *const end = &app[ncap->nelems];
  131. for( /*NADA*/; app < end; app++)
  132. {
  133. free_NC_attr(*app);
  134. *app = NULL;
  135. }
  136. }
  137. ncap->nelems = 0;
  138. }
  139. /*
  140. * Free NC_attrarray values.
  141. * formerly
  142. NC_free_array()
  143. */
  144. void
  145. free_NC_attrarrayV(NC_attrarray *ncap)
  146. {
  147. assert(ncap != NULL);
  148. if(ncap->nalloc == 0)
  149. return;
  150. assert(ncap->value != NULL);
  151. free_NC_attrarrayV0(ncap);
  152. free(ncap->value);
  153. ncap->value = NULL;
  154. ncap->nalloc = 0;
  155. }
  156. int
  157. dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
  158. {
  159. int status = NC_NOERR;
  160. assert(ref != NULL);
  161. assert(ncap != NULL);
  162. if(ref->nelems != 0)
  163. {
  164. const size_t sz = ref->nelems * sizeof(NC_attr *);
  165. ncap->value = (NC_attr **) malloc(sz);
  166. if(ncap->value == NULL)
  167. return NC_ENOMEM;
  168. (void) memset(ncap->value, 0, sz);
  169. ncap->nalloc = ref->nelems;
  170. }
  171. ncap->nelems = 0;
  172. {
  173. NC_attr **app = ncap->value;
  174. const NC_attr **drpp = (const NC_attr **)ref->value;
  175. NC_attr *const *const end = &app[ref->nelems];
  176. for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++)
  177. {
  178. *app = dup_NC_attr(*drpp);
  179. if(*app == NULL)
  180. {
  181. status = NC_ENOMEM;
  182. break;
  183. }
  184. }
  185. }
  186. if(status != NC_NOERR)
  187. {
  188. free_NC_attrarrayV(ncap);
  189. return status;
  190. }
  191. assert(ncap->nelems == ref->nelems);
  192. return NC_NOERR;
  193. }
  194. /*
  195. * Add a new handle on the end of an array of handles
  196. * Formerly
  197. NC_incr_array(array, tail)
  198. */
  199. static int
  200. incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
  201. {
  202. NC_attr **vp;
  203. assert(ncap != NULL);
  204. if(ncap->nalloc == 0)
  205. {
  206. assert(ncap->nelems == 0);
  207. vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
  208. if(vp == NULL)
  209. return NC_ENOMEM;
  210. ncap->value = vp;
  211. ncap->nalloc = NC_ARRAY_GROWBY;
  212. }
  213. else if(ncap->nelems +1 > ncap->nalloc)
  214. {
  215. vp = (NC_attr **) realloc(ncap->value,
  216. (ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
  217. if(vp == NULL)
  218. return NC_ENOMEM;
  219. ncap->value = vp;
  220. ncap->nalloc += NC_ARRAY_GROWBY;
  221. }
  222. if(newelemp != NULL)
  223. {
  224. ncap->value[ncap->nelems] = newelemp;
  225. ncap->nelems++;
  226. }
  227. return NC_NOERR;
  228. }
  229. NC_attr *
  230. elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
  231. {
  232. assert(ncap != NULL);
  233. /* cast needed for braindead systems with signed size_t */
  234. if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
  235. return NULL;
  236. assert(ncap->value != NULL);
  237. return ncap->value[elem];
  238. }
  239. /* End attarray per se */
  240. /*
  241. * Given ncp and varid, return ptr to array of attributes
  242. * else NULL on error
  243. */
  244. static NC_attrarray *
  245. NC_attrarray0( NC *ncp, int varid)
  246. {
  247. NC_attrarray *ap;
  248. if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
  249. {
  250. ap = &ncp->attrs;
  251. }
  252. else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
  253. {
  254. NC_var **vpp;
  255. vpp = (NC_var **)ncp->vars.value;
  256. vpp += varid;
  257. ap = &(*vpp)->attrs;
  258. } else {
  259. ap = NULL;
  260. }
  261. return(ap);
  262. }
  263. /*
  264. * Step thru NC_ATTRIBUTE array, seeking match on name.
  265. * return match or NULL if Not Found or out of memory.
  266. */
  267. NC_attr **
  268. NC_findattr(const NC_attrarray *ncap, const char *uname)
  269. {
  270. NC_attr **attrpp;
  271. size_t attrid;
  272. size_t slen;
  273. char *name;
  274. assert(ncap != NULL);
  275. if(ncap->nelems == 0)
  276. return NULL;
  277. attrpp = (NC_attr **) ncap->value;
  278. /* normalized version of uname */
  279. name = (char *)utf8proc_NFC((const unsigned char *)uname);
  280. if(name == NULL)
  281. return NULL; /* TODO: need better way to indicate no memory */
  282. slen = strlen(name);
  283. for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
  284. {
  285. if(strlen((*attrpp)->name->cp) == slen &&
  286. strncmp((*attrpp)->name->cp, name, slen) == 0)
  287. {
  288. free(name);
  289. return(attrpp); /* Normal return */
  290. }
  291. }
  292. free(name);
  293. return(NULL);
  294. }
  295. /*
  296. * Look up by ncid, varid and name, return NULL if not found
  297. */
  298. static int
  299. NC_lookupattr(int ncid,
  300. int varid,
  301. const char *name, /* attribute name */
  302. NC_attr **attrpp) /* modified on return */
  303. {
  304. int status;
  305. NC *ncp;
  306. NC_attrarray *ncap;
  307. NC_attr **tmp;
  308. status = NC_check_id(ncid, &ncp);
  309. if(status != NC_NOERR)
  310. return status;
  311. ncap = NC_attrarray0(ncp, varid);
  312. if(ncap == NULL)
  313. return NC_ENOTVAR;
  314. tmp = NC_findattr(ncap, name);
  315. if(tmp == NULL)
  316. return NC_ENOTATT;
  317. if(attrpp != NULL)
  318. *attrpp = *tmp;
  319. return ENOERR;
  320. }
  321. /* Public */
  322. int
  323. NC3_inq_attname(int ncid, int varid, int attnum, char *name)
  324. {
  325. int status;
  326. NC *ncp;
  327. NC_attrarray *ncap;
  328. NC_attr *attrp;
  329. status = NC_check_id(ncid, &ncp);
  330. if(status != NC_NOERR)
  331. return status;
  332. ncap = NC_attrarray0(ncp, varid);
  333. if(ncap == NULL)
  334. return NC_ENOTVAR;
  335. attrp = elem_NC_attrarray(ncap, (size_t)attnum);
  336. if(attrp == NULL)
  337. return NC_ENOTATT;
  338. (void) strncpy(name, attrp->name->cp, attrp->name->nchars);
  339. name[attrp->name->nchars] = 0;
  340. return NC_NOERR;
  341. }
  342. int
  343. NC3_inq_attid(int ncid, int varid, const char *name, int *attnump)
  344. {
  345. int status;
  346. NC *ncp;
  347. NC_attrarray *ncap;
  348. NC_attr **attrpp;
  349. status = NC_check_id(ncid, &ncp);
  350. if(status != NC_NOERR)
  351. return status;
  352. ncap = NC_attrarray0(ncp, varid);
  353. if(ncap == NULL)
  354. return NC_ENOTVAR;
  355. attrpp = NC_findattr(ncap, name);
  356. if(attrpp == NULL)
  357. return NC_ENOTATT;
  358. if(attnump != NULL)
  359. *attnump = (int)(attrpp - ncap->value);
  360. return NC_NOERR;
  361. }
  362. int
  363. NC3_inq_att(int ncid,
  364. int varid,
  365. const char *name, /* input, attribute name */
  366. nc_type *datatypep,
  367. size_t *lenp)
  368. {
  369. int status;
  370. NC_attr *attrp;
  371. status = NC_lookupattr(ncid, varid, name, &attrp);
  372. if(status != NC_NOERR)
  373. return status;
  374. if(datatypep != NULL)
  375. *datatypep = attrp->type;
  376. if(lenp != NULL)
  377. *lenp = attrp->nelems;
  378. return NC_NOERR;
  379. }
  380. int
  381. NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
  382. {
  383. int status;
  384. NC *ncp;
  385. NC_attrarray *ncap;
  386. NC_attr **tmp;
  387. NC_attr *attrp;
  388. NC_string *newStr, *old;
  389. char *newname; /* normalized version */
  390. /* sortof inline clone of NC_lookupattr() */
  391. status = NC_check_id(ncid, &ncp);
  392. if(status != NC_NOERR)
  393. return status;
  394. if(NC_readonly(ncp))
  395. return NC_EPERM;
  396. ncap = NC_attrarray0(ncp, varid);
  397. if(ncap == NULL)
  398. return NC_ENOTVAR;
  399. status = NC_check_name(unewname);
  400. if(status != NC_NOERR)
  401. return status;
  402. tmp = NC_findattr(ncap, name);
  403. if(tmp == NULL)
  404. return NC_ENOTATT;
  405. attrp = *tmp;
  406. /* end inline clone NC_lookupattr() */
  407. if(NC_findattr(ncap, unewname) != NULL)
  408. {
  409. /* name in use */
  410. return NC_ENAMEINUSE;
  411. }
  412. old = attrp->name;
  413. newname = (char *)utf8proc_NFC((const unsigned char *)unewname);
  414. if(newname == NULL)
  415. return NC_EBADNAME;
  416. if(NC_indef(ncp))
  417. {
  418. newStr = new_NC_string(strlen(newname), newname);
  419. free(newname);
  420. if( newStr == NULL)
  421. return NC_ENOMEM;
  422. attrp->name = newStr;
  423. free_NC_string(old);
  424. return NC_NOERR;
  425. }
  426. /* else */
  427. status = set_NC_string(old, newname);
  428. free(newname);
  429. if( status != NC_NOERR)
  430. return status;
  431. set_NC_hdirty(ncp);
  432. if(NC_doHsync(ncp))
  433. {
  434. status = NC_sync(ncp);
  435. if(status != NC_NOERR)
  436. return status;
  437. }
  438. return NC_NOERR;
  439. }
  440. int
  441. NC3_del_att(int ncid, int varid, const char *uname)
  442. {
  443. int status;
  444. NC *ncp;
  445. NC_attrarray *ncap;
  446. NC_attr **attrpp;
  447. NC_attr *old = NULL;
  448. int attrid;
  449. size_t slen;
  450. status = NC_check_id(ncid, &ncp);
  451. if(status != NC_NOERR)
  452. return status;
  453. if(!NC_indef(ncp))
  454. return NC_ENOTINDEFINE;
  455. ncap = NC_attrarray0(ncp, varid);
  456. if(ncap == NULL)
  457. return NC_ENOTVAR;
  458. {
  459. char *name = (char *)utf8proc_NFC((const unsigned char *)uname);
  460. if(name == NULL)
  461. return NC_ENOMEM;
  462. /* sortof inline NC_findattr() */
  463. slen = strlen(name);
  464. attrpp = (NC_attr **) ncap->value;
  465. for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
  466. {
  467. if( slen == (*attrpp)->name->nchars &&
  468. strncmp(name, (*attrpp)->name->cp, slen) == 0)
  469. {
  470. old = *attrpp;
  471. break;
  472. }
  473. }
  474. free(name);
  475. }
  476. if( (size_t) attrid == ncap->nelems )
  477. return NC_ENOTATT;
  478. /* end inline NC_findattr() */
  479. /* shuffle down */
  480. for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
  481. {
  482. *attrpp = *(attrpp + 1);
  483. attrpp++;
  484. }
  485. *attrpp = NULL;
  486. /* decrement count */
  487. ncap->nelems--;
  488. free_NC_attr(old);
  489. return NC_NOERR;
  490. }
  491. static int
  492. ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type)
  493. {
  494. switch(type) {
  495. case NC_CHAR:
  496. return NC_ECHAR;
  497. case NC_BYTE:
  498. return ncx_pad_putn_schar_uchar(xpp, nelems, tp);
  499. case NC_SHORT:
  500. return ncx_pad_putn_short_uchar(xpp, nelems, tp);
  501. case NC_INT:
  502. return ncx_putn_int_uchar(xpp, nelems, tp);
  503. case NC_FLOAT:
  504. return ncx_putn_float_uchar(xpp, nelems, tp);
  505. case NC_DOUBLE:
  506. return ncx_putn_double_uchar(xpp, nelems, tp);
  507. default:
  508. assert("ncx_pad_putn_Iuchar invalid type" == 0);
  509. }
  510. return NC_EBADTYPE;
  511. }
  512. static int
  513. ncx_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type)
  514. {
  515. switch(type) {
  516. case NC_CHAR:
  517. return NC_ECHAR;
  518. case NC_BYTE:
  519. return ncx_pad_getn_schar_uchar(xpp, nelems, tp);
  520. case NC_SHORT:
  521. return ncx_pad_getn_short_uchar(xpp, nelems, tp);
  522. case NC_INT:
  523. return ncx_getn_int_uchar(xpp, nelems, tp);
  524. case NC_FLOAT:
  525. return ncx_getn_float_uchar(xpp, nelems, tp);
  526. case NC_DOUBLE:
  527. return ncx_getn_double_uchar(xpp, nelems, tp);
  528. default:
  529. assert("ncx_pad_getn_Iuchar invalid type" == 0);
  530. }
  531. return NC_EBADTYPE;
  532. }
  533. static int
  534. ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type)
  535. {
  536. switch(type) {
  537. case NC_CHAR:
  538. return NC_ECHAR;
  539. case NC_BYTE:
  540. return ncx_pad_putn_schar_schar(xpp, nelems, tp);
  541. case NC_SHORT:
  542. return ncx_pad_putn_short_schar(xpp, nelems, tp);
  543. case NC_INT:
  544. return ncx_putn_int_schar(xpp, nelems, tp);
  545. case NC_FLOAT:
  546. return ncx_putn_float_schar(xpp, nelems, tp);
  547. case NC_DOUBLE:
  548. return ncx_putn_double_schar(xpp, nelems, tp);
  549. default:
  550. assert("ncx_pad_putn_Ischar invalid type" == 0);
  551. }
  552. return NC_EBADTYPE;
  553. }
  554. static int
  555. ncx_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type)
  556. {
  557. switch(type) {
  558. case NC_CHAR:
  559. return NC_ECHAR;
  560. case NC_BYTE:
  561. return ncx_pad_getn_schar_schar(xpp, nelems, tp);
  562. case NC_SHORT:
  563. return ncx_pad_getn_short_schar(xpp, nelems, tp);
  564. case NC_INT:
  565. return ncx_getn_int_schar(xpp, nelems, tp);
  566. case NC_FLOAT:
  567. return ncx_getn_float_schar(xpp, nelems, tp);
  568. case NC_DOUBLE:
  569. return ncx_getn_double_schar(xpp, nelems, tp);
  570. default:
  571. assert("ncx_pad_getn_Ischar invalid type" == 0);
  572. }
  573. return NC_EBADTYPE;
  574. }
  575. static int
  576. ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type)
  577. {
  578. switch(type) {
  579. case NC_CHAR:
  580. return NC_ECHAR;
  581. case NC_BYTE:
  582. return ncx_pad_putn_schar_short(xpp, nelems, tp);
  583. case NC_SHORT:
  584. return ncx_pad_putn_short_short(xpp, nelems, tp);
  585. case NC_INT:
  586. return ncx_putn_int_short(xpp, nelems, tp);
  587. case NC_FLOAT:
  588. return ncx_putn_float_short(xpp, nelems, tp);
  589. case NC_DOUBLE:
  590. return ncx_putn_double_short(xpp, nelems, tp);
  591. default:
  592. assert("ncx_pad_putn_Ishort invalid type" == 0);
  593. }
  594. return NC_EBADTYPE;
  595. }
  596. static int
  597. ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type)
  598. {
  599. switch(type) {
  600. case NC_CHAR:
  601. return NC_ECHAR;
  602. case NC_BYTE:
  603. return ncx_pad_getn_schar_short(xpp, nelems, tp);
  604. case NC_SHORT:
  605. return ncx_pad_getn_short_short(xpp, nelems, tp);
  606. case NC_INT:
  607. return ncx_getn_int_short(xpp, nelems, tp);
  608. case NC_FLOAT:
  609. return ncx_getn_float_short(xpp, nelems, tp);
  610. case NC_DOUBLE:
  611. return ncx_getn_double_short(xpp, nelems, tp);
  612. default:
  613. assert("ncx_pad_getn_Ishort invalid type" == 0);
  614. }
  615. return NC_EBADTYPE;
  616. }
  617. static int
  618. ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type)
  619. {
  620. switch(type) {
  621. case NC_CHAR:
  622. return NC_ECHAR;
  623. case NC_BYTE:
  624. return ncx_pad_putn_schar_int(xpp, nelems, tp);
  625. case NC_SHORT:
  626. return ncx_pad_putn_short_int(xpp, nelems, tp);
  627. case NC_INT:
  628. return ncx_putn_int_int(xpp, nelems, tp);
  629. case NC_FLOAT:
  630. return ncx_putn_float_int(xpp, nelems, tp);
  631. case NC_DOUBLE:
  632. return ncx_putn_double_int(xpp, nelems, tp);
  633. default:
  634. assert("ncx_pad_putn_Iint invalid type" == 0);
  635. }
  636. return NC_EBADTYPE;
  637. }
  638. static int
  639. ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type)
  640. {
  641. switch(type) {
  642. case NC_CHAR:
  643. return NC_ECHAR;
  644. case NC_BYTE:
  645. return ncx_pad_getn_schar_int(xpp, nelems, tp);
  646. case NC_SHORT:
  647. return ncx_pad_getn_short_int(xpp, nelems, tp);
  648. case NC_INT:
  649. return ncx_getn_int_int(xpp, nelems, tp);
  650. case NC_FLOAT:
  651. return ncx_getn_float_int(xpp, nelems, tp);
  652. case NC_DOUBLE:
  653. return ncx_getn_double_int(xpp, nelems, tp);
  654. default:
  655. assert("ncx_pad_getn_Iint invalid type" == 0);
  656. }
  657. return NC_EBADTYPE;
  658. }
  659. static int
  660. ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type)
  661. {
  662. switch(type) {
  663. case NC_CHAR:
  664. return NC_ECHAR;
  665. case NC_BYTE:
  666. return ncx_pad_putn_schar_float(xpp, nelems, tp);
  667. case NC_SHORT:
  668. return ncx_pad_putn_short_float(xpp, nelems, tp);
  669. case NC_INT:
  670. return ncx_putn_int_float(xpp, nelems, tp);
  671. case NC_FLOAT:
  672. return ncx_putn_float_float(xpp, nelems, tp);
  673. case NC_DOUBLE:
  674. return ncx_putn_double_float(xpp, nelems, tp);
  675. default:
  676. assert("ncx_pad_putn_Ifloat invalid type" == 0);
  677. }
  678. return NC_EBADTYPE;
  679. }
  680. static int
  681. ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type)
  682. {
  683. switch(type) {
  684. case NC_CHAR:
  685. return NC_ECHAR;
  686. case NC_BYTE:
  687. return ncx_pad_getn_schar_float(xpp, nelems, tp);
  688. case NC_SHORT:
  689. return ncx_pad_getn_short_float(xpp, nelems, tp);
  690. case NC_INT:
  691. return ncx_getn_int_float(xpp, nelems, tp);
  692. case NC_FLOAT:
  693. return ncx_getn_float_float(xpp, nelems, tp);
  694. case NC_DOUBLE:
  695. return ncx_getn_double_float(xpp, nelems, tp);
  696. default:
  697. assert("ncx_pad_getn_Ifloat invalid type" == 0);
  698. }
  699. return NC_EBADTYPE;
  700. }
  701. static int
  702. ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type)
  703. {
  704. switch(type) {
  705. case NC_CHAR:
  706. return NC_ECHAR;
  707. case NC_BYTE:
  708. return ncx_pad_putn_schar_double(xpp, nelems, tp);
  709. case NC_SHORT:
  710. return ncx_pad_putn_short_double(xpp, nelems, tp);
  711. case NC_INT:
  712. return ncx_putn_int_double(xpp, nelems, tp);
  713. case NC_FLOAT:
  714. return ncx_putn_float_double(xpp, nelems, tp);
  715. case NC_DOUBLE:
  716. return ncx_putn_double_double(xpp, nelems, tp);
  717. default:
  718. assert("ncx_pad_putn_Idouble invalid type" == 0);
  719. }
  720. return NC_EBADTYPE;
  721. }
  722. static int
  723. ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type)
  724. {
  725. switch(type) {
  726. case NC_CHAR:
  727. return NC_ECHAR;
  728. case NC_BYTE:
  729. return ncx_pad_getn_schar_double(xpp, nelems, tp);
  730. case NC_SHORT:
  731. return ncx_pad_getn_short_double(xpp, nelems, tp);
  732. case NC_INT:
  733. return ncx_getn_int_double(xpp, nelems, tp);
  734. case NC_FLOAT:
  735. return ncx_getn_float_double(xpp, nelems, tp);
  736. case NC_DOUBLE:
  737. return ncx_getn_double_double(xpp, nelems, tp);
  738. default:
  739. assert("ncx_pad_getn_Idouble invalid type" == 0);
  740. }
  741. return NC_EBADTYPE;
  742. }
  743. #ifdef IGNORE
  744. static int
  745. ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type)
  746. {
  747. switch(type) {
  748. case NC_CHAR:
  749. return NC_ECHAR;
  750. case NC_BYTE:
  751. return ncx_pad_putn_schar_long(xpp, nelems, tp);
  752. case NC_SHORT:
  753. return ncx_pad_putn_short_long(xpp, nelems, tp);
  754. case NC_INT:
  755. return ncx_putn_int_long(xpp, nelems, tp);
  756. case NC_FLOAT:
  757. return ncx_putn_float_long(xpp, nelems, tp);
  758. case NC_DOUBLE:
  759. return ncx_putn_double_long(xpp, nelems, tp);
  760. default:
  761. assert("ncx_pad_putn_Ilong invalid type" == 0);
  762. }
  763. return NC_EBADTYPE;
  764. }
  765. static int
  766. ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type)
  767. {
  768. switch(type) {
  769. case NC_CHAR:
  770. return NC_ECHAR;
  771. case NC_BYTE:
  772. return ncx_pad_getn_schar_long(xpp, nelems, tp);
  773. case NC_SHORT:
  774. return ncx_pad_getn_short_long(xpp, nelems, tp);
  775. case NC_INT:
  776. return ncx_getn_int_long(xpp, nelems, tp);
  777. case NC_FLOAT:
  778. return ncx_getn_float_long(xpp, nelems, tp);
  779. case NC_DOUBLE:
  780. return ncx_getn_double_long(xpp, nelems, tp);
  781. default:
  782. assert("ncx_pad_getn_Ilong invalid type" == 0);
  783. }
  784. return NC_EBADTYPE;
  785. }
  786. #endif
  787. static int
  788. ncx_pad_putn_Ilonglong(void **xpp, size_t nelems, const longlong *tp, nc_type type)
  789. {
  790. switch(type) {
  791. case NC_CHAR:
  792. return NC_ECHAR;
  793. case NC_BYTE:
  794. return ncx_pad_putn_schar_longlong(xpp, nelems, tp);
  795. case NC_SHORT:
  796. return ncx_pad_putn_short_longlong(xpp, nelems, tp);
  797. case NC_INT:
  798. return ncx_putn_int_longlong(xpp, nelems, tp);
  799. case NC_FLOAT:
  800. return ncx_putn_float_longlong(xpp, nelems, tp);
  801. case NC_DOUBLE:
  802. return ncx_putn_double_longlong(xpp, nelems, tp);
  803. default:
  804. assert("ncx_pad_putn_Ilonglong invalid type" == 0);
  805. }
  806. return NC_EBADTYPE;
  807. }
  808. static int
  809. ncx_pad_getn_Ilonglong(const void **xpp, size_t nelems, longlong *tp, nc_type type)
  810. {
  811. switch(type) {
  812. case NC_CHAR:
  813. return NC_ECHAR;
  814. case NC_BYTE:
  815. return ncx_pad_getn_schar_longlong(xpp, nelems, tp);
  816. case NC_SHORT:
  817. return ncx_pad_getn_short_longlong(xpp, nelems, tp);
  818. case NC_INT:
  819. return ncx_getn_int_longlong(xpp, nelems, tp);
  820. case NC_FLOAT:
  821. return ncx_getn_float_longlong(xpp, nelems, tp);
  822. case NC_DOUBLE:
  823. return ncx_getn_double_longlong(xpp, nelems, tp);
  824. default:
  825. assert("ncx_pad_getn_Ilonglong invalid type" == 0);
  826. }
  827. return NC_EBADTYPE;
  828. }
  829. /* Common dispatcher for put cases */
  830. static int
  831. dispatchput(void **xpp, size_t nelems, const void* tp,
  832. nc_type atype, nc_type memtype)
  833. {
  834. switch (memtype) {
  835. case NC_CHAR:
  836. return ncx_pad_putn_text(xpp,nelems, (char *)tp);
  837. case NC_BYTE:
  838. return ncx_pad_putn_Ischar(xpp, nelems, (schar*)tp, atype);
  839. case NC_SHORT:
  840. return ncx_pad_putn_Ishort(xpp, nelems, (short*)tp, atype);
  841. case NC_INT:
  842. return ncx_pad_putn_Iint(xpp, nelems, (int*)tp, atype);
  843. case NC_FLOAT:
  844. return ncx_pad_putn_Ifloat(xpp, nelems, (float*)tp, atype);
  845. case NC_DOUBLE:
  846. return ncx_pad_putn_Idouble(xpp, nelems, (double*)tp, atype);
  847. case NC_UBYTE: /*Synthetic*/
  848. return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tp, atype);
  849. case NC_INT64:
  850. return ncx_pad_putn_Ilonglong(xpp, nelems, (longlong*)tp, atype);
  851. case NC_NAT:
  852. return NC_EBADTYPE;
  853. default:
  854. break;
  855. }
  856. return NC_EBADTYPE;
  857. }
  858. int
  859. NC3_put_att(
  860. int ncid,
  861. int varid,
  862. const char *name,
  863. nc_type type,
  864. size_t nelems,
  865. const void *value,
  866. nc_type memtype)
  867. {
  868. int status;
  869. NC *ncp;
  870. NC_attrarray *ncap;
  871. NC_attr **attrpp;
  872. NC_attr *old = NULL;
  873. NC_attr *attrp;
  874. status = NC_check_id(ncid, &ncp);
  875. if(status != NC_NOERR)
  876. return status;
  877. if(NC_readonly(ncp))
  878. return NC_EPERM;
  879. ncap = NC_attrarray0(ncp, varid);
  880. if(ncap == NULL)
  881. return NC_ENOTVAR;
  882. status = nc_cktype(type);
  883. if(status != NC_NOERR)
  884. return status;
  885. if(memtype == NC_NAT) memtype = type;
  886. if(memtype != NC_CHAR && type == NC_CHAR)
  887. return NC_ECHAR;
  888. if(memtype == NC_CHAR && type != NC_CHAR)
  889. return NC_ECHAR;
  890. /* cast needed for braindead systems with signed size_t */
  891. if((unsigned long) nelems > X_INT_MAX) /* backward compat */
  892. return NC_EINVAL; /* Invalid nelems */
  893. if(nelems != 0 && value == NULL)
  894. return NC_EINVAL; /* Null arg */
  895. attrpp = NC_findattr(ncap, name);
  896. /* 4 cases: exists X indef */
  897. if(attrpp != NULL) { /* name in use */
  898. if(!NC_indef(ncp)) {
  899. const size_t xsz = ncx_len_NC_attrV(type, nelems);
  900. attrp = *attrpp; /* convenience */
  901. if(xsz > attrp->xsz) return NC_ENOTINDEFINE;
  902. /* else, we can reuse existing without redef */
  903. attrp->xsz = xsz;
  904. attrp->type = type;
  905. attrp->nelems = nelems;
  906. if(nelems != 0) {
  907. void *xp = attrp->xvalue;
  908. status = dispatchput(&xp, nelems, (const void*)value, type, memtype);
  909. }
  910. set_NC_hdirty(ncp);
  911. if(NC_doHsync(ncp)) {
  912. const int lstatus = NC_sync(ncp);
  913. /*
  914. * N.B.: potentially overrides NC_ERANGE
  915. * set by ncx_pad_putn_I$1
  916. */
  917. if(lstatus != ENOERR) return lstatus;
  918. }
  919. return status;
  920. }
  921. /* else, redefine using existing array slot */
  922. old = *attrpp;
  923. } else {
  924. if(!NC_indef(ncp)) return NC_ENOTINDEFINE;
  925. if(ncap->nelems >= NC_MAX_ATTRS) return NC_EMAXATTS;
  926. }
  927. status = NC_check_name(name);
  928. if(status != NC_NOERR) return status;
  929. attrp = new_NC_attr(name, type, nelems);
  930. if(attrp == NULL) return NC_ENOMEM;
  931. if(nelems != 0) {
  932. void *xp = attrp->xvalue;
  933. status = dispatchput(&xp, nelems, (const void*)value, type, memtype);
  934. }
  935. if(attrpp != NULL) {
  936. assert(old != NULL);
  937. *attrpp = attrp;
  938. free_NC_attr(old);
  939. } else {
  940. const int lstatus = incr_NC_attrarray(ncap, attrp);
  941. /*
  942. * N.B.: potentially overrides NC_ERANGE
  943. * set by ncx_pad_putn_I$1
  944. */
  945. if(lstatus != NC_NOERR) {
  946. free_NC_attr(attrp);
  947. return lstatus;
  948. }
  949. }
  950. return status;
  951. }
  952. int
  953. NC3_get_att(
  954. int ncid,
  955. int varid,
  956. const char *name,
  957. void *value,
  958. nc_type memtype)
  959. {
  960. int status;
  961. NC_attr *attrp;
  962. const void *xp;
  963. status = NC_lookupattr(ncid, varid, name, &attrp);
  964. if(status != NC_NOERR) return status;
  965. if(attrp->nelems == 0) return NC_NOERR;
  966. if(memtype == NC_NAT) memtype = attrp->type;
  967. if(memtype != NC_CHAR && attrp->type == NC_CHAR)
  968. return NC_ECHAR;
  969. if(memtype == NC_CHAR && attrp->type != NC_CHAR)
  970. return NC_ECHAR;
  971. xp = attrp->xvalue;
  972. switch (memtype) {
  973. case NC_CHAR:
  974. return ncx_pad_getn_text(&xp, attrp->nelems , (char *)value);
  975. case NC_BYTE:
  976. return ncx_pad_getn_Ischar(&xp,attrp->nelems,(schar*)value,attrp->type);
  977. case NC_SHORT:
  978. return ncx_pad_getn_Ishort(&xp,attrp->nelems,(short*)value,attrp->type);
  979. case NC_INT:
  980. return ncx_pad_getn_Iint(&xp,attrp->nelems,(int*)value,attrp->type);
  981. case NC_FLOAT:
  982. return ncx_pad_getn_Ifloat(&xp,attrp->nelems,(float*)value,attrp->type);
  983. case NC_DOUBLE:
  984. return ncx_pad_getn_Idouble(&xp,attrp->nelems,(double*)value,attrp->type);
  985. case NC_INT64:
  986. return ncx_pad_getn_Ilonglong(&xp,attrp->nelems,(longlong*)value,attrp->type);
  987. case NC_UBYTE: /* Synthetic */
  988. return ncx_pad_getn_Iuchar(&xp, attrp->nelems , (uchar *)value, attrp->type);
  989. case NC_NAT:
  990. return NC_EBADTYPE;
  991. default:
  992. break;
  993. }
  994. status = NC_EBADTYPE;
  995. return status;
  996. }