PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/other/netcdf_write_matrix/src/cxx/netcdf.cpp

http://github.com/jbeezley/wrf-fire
C++ | 1208 lines | 1065 code | 119 blank | 24 comment | 213 complexity | b1b9b42fdb4822e19d11ef596ede93dd MD5 | raw file
Possible License(s): AGPL-1.0
  1. /*********************************************************************
  2. * Copyright 1992, University Corporation for Atmospheric Research
  3. * See netcdf/README file for copying and redistribution conditions.
  4. *
  5. * Purpose: Implements class interface for netCDF over C interface
  6. *
  7. * $Header: /upc/share/CVS/netcdf-3/cxx/netcdf.cpp,v 1.11 2005/11/05 01:39:52 ed Exp $
  8. *********************************************************************/
  9. #include <config.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include "netcdfcpp.h"
  13. #ifndef TRUE
  14. #define TRUE 1
  15. #define FALSE 0
  16. #endif
  17. static const int ncGlobal = NC_GLOBAL; // psuedo-variable for global attributes
  18. static const int ncBad = -1; // failure return for netCDF C interface
  19. NcFile::~NcFile( void )
  20. {
  21. (void) close();
  22. }
  23. NcBool NcFile::is_valid( void ) const
  24. {
  25. return the_id != ncBad;
  26. }
  27. int NcFile::num_dims( void ) const
  28. {
  29. int num = 0;
  30. if (is_valid())
  31. ncinquire(the_id, &num, 0, 0, 0);
  32. return num;
  33. }
  34. int NcFile::num_vars( void ) const
  35. {
  36. int num = 0;
  37. if (is_valid())
  38. ncinquire(the_id, 0, &num, 0, 0);
  39. return num;
  40. }
  41. int NcFile::num_atts( void ) const
  42. {
  43. int num = 0;
  44. if (is_valid())
  45. ncinquire(the_id, 0, 0, &num, 0);
  46. return num;
  47. }
  48. NcDim* NcFile::get_dim( NcToken name ) const
  49. {
  50. int dimid = ncdimid(the_id, name);
  51. return get_dim(dimid);
  52. }
  53. NcVar* NcFile::get_var( NcToken name ) const
  54. {
  55. int varid = ncvarid(the_id, name);
  56. return get_var(varid);
  57. }
  58. NcAtt* NcFile::get_att( NcToken aname ) const
  59. {
  60. return is_valid() ? globalv->get_att(aname) : 0;
  61. }
  62. NcDim* NcFile::get_dim( int i ) const
  63. {
  64. if (! is_valid() || i < 0 || i >= num_dims())
  65. return 0;
  66. return dimensions[i];
  67. }
  68. NcVar* NcFile::get_var( int i ) const
  69. {
  70. if (! is_valid() || i < 0 || i >= num_vars())
  71. return 0;
  72. return variables[i];
  73. }
  74. NcAtt* NcFile::get_att( int n ) const
  75. {
  76. return is_valid() ? globalv->get_att(n) : 0;
  77. }
  78. NcDim* NcFile::rec_dim( ) const
  79. {
  80. if (! is_valid())
  81. return 0;
  82. int recdim;
  83. ncinquire(the_id, 0, 0, 0, &recdim);
  84. if (recdim == -1)
  85. return 0;
  86. return get_dim(recdim);
  87. }
  88. NcDim* NcFile::add_dim(NcToken name, long size)
  89. {
  90. if (!is_valid() || !define_mode())
  91. return 0;
  92. int n = num_dims();
  93. NcDim* dimp = new NcDim(this, name, size);
  94. dimensions[n] = dimp; // for garbage collection on close()
  95. return dimp;
  96. }
  97. NcDim* NcFile::add_dim(NcToken name)
  98. {
  99. return add_dim(name, NC_UNLIMITED);
  100. }
  101. // To create scalar, 1-dimensional, ..., 5-dimensional variables, just supply
  102. // as many dimension arguments as necessary
  103. NcVar* NcFile::add_var(NcToken name, NcType type, // scalar to 5D var
  104. const NcDim* dim0,
  105. const NcDim* dim1,
  106. const NcDim* dim2,
  107. const NcDim* dim3,
  108. const NcDim* dim4)
  109. {
  110. if (!is_valid() || !define_mode())
  111. return 0;
  112. int dims[5];
  113. int ndims = 0;
  114. if (dim0) {
  115. ndims++;
  116. dims[0] = dim0->id();
  117. if (dim1) {
  118. ndims++;
  119. dims[1] = dim1->id();
  120. if (dim2) {
  121. ndims++;
  122. dims[2] = dim2->id();
  123. if (dim3) {
  124. ndims++;
  125. dims[3] = dim3->id();
  126. if (dim4) {
  127. ndims++;
  128. dims[4] = dim4->id();
  129. }
  130. }
  131. }
  132. }
  133. }
  134. int n = num_vars();
  135. NcVar* varp =
  136. new NcVar(this, ncvardef(the_id, name, (nc_type) type, ndims, dims));
  137. variables[n] = varp;
  138. return varp;
  139. }
  140. // For variables with more than 5 dimensions, use n-dimensional interface
  141. // with vector of dimensions.
  142. NcVar* NcFile::add_var(NcToken name, NcType type, int ndims, const NcDim** dims)
  143. {
  144. if (!is_valid() || !define_mode())
  145. return 0;
  146. int* dimids = new int[ndims];
  147. for (int i=0; i < ndims; i++)
  148. dimids[i] = dims[i]->id();
  149. int n = num_vars();
  150. NcVar* varp =
  151. new NcVar(this, ncvardef(the_id, name, (nc_type) type, ndims, dimids));
  152. variables[n] = varp;
  153. delete [] dimids;
  154. return varp;
  155. }
  156. #define NcFile_add_scalar_att(TYPE) \
  157. NcBool NcFile::add_att(NcToken aname, TYPE val) \
  158. { \
  159. return globalv->add_att(aname, val); \
  160. }
  161. NcFile_add_scalar_att(char)
  162. NcFile_add_scalar_att(ncbyte)
  163. NcFile_add_scalar_att(short)
  164. NcFile_add_scalar_att(int)
  165. NcFile_add_scalar_att(long)
  166. NcFile_add_scalar_att(float)
  167. NcFile_add_scalar_att(double)
  168. NcFile_add_scalar_att(const char*)
  169. #define NcFile_add_vector_att(TYPE) \
  170. NcBool NcFile::add_att(NcToken aname, int n, const TYPE* val) \
  171. { \
  172. return globalv->add_att(aname, n, val); \
  173. }
  174. NcFile_add_vector_att(char)
  175. NcFile_add_vector_att(ncbyte)
  176. NcFile_add_vector_att(short)
  177. NcFile_add_vector_att(int)
  178. NcFile_add_vector_att(long)
  179. NcFile_add_vector_att(float)
  180. NcFile_add_vector_att(double)
  181. NcBool NcFile::set_fill( FillMode a_mode )
  182. {
  183. if (ncsetfill(the_id, a_mode) != ncBad) {
  184. the_fill_mode = a_mode;
  185. return TRUE;
  186. }
  187. return FALSE;
  188. }
  189. NcFile::FillMode NcFile::get_fill( void ) const
  190. {
  191. return the_fill_mode;
  192. }
  193. NcFile::FileFormat NcFile::get_format( void ) const
  194. {
  195. int the_format;
  196. nc_inq_format(the_id, &the_format);
  197. switch (the_format) {
  198. case NC_FORMAT_CLASSIC:
  199. return Classic;
  200. case NC_FORMAT_64BIT:
  201. return Offset64Bits;
  202. case NC_FORMAT_NETCDF4:
  203. return Netcdf4;
  204. case NC_FORMAT_NETCDF4_CLASSIC:
  205. return Netcdf4Classic;
  206. default:
  207. return BadFormat;
  208. }
  209. }
  210. NcBool NcFile::sync( void )
  211. {
  212. if (!data_mode())
  213. return 0;
  214. if (ncsync(the_id) == ncBad)
  215. return 0;
  216. int i;
  217. for (i = 0; i < num_dims(); i++) {
  218. if (dimensions[i]->is_valid()) {
  219. dimensions[i]->sync();
  220. } else { // someone else added a new dimension
  221. dimensions[i] = new NcDim(this,i);
  222. }
  223. }
  224. for (i = 0; i < num_vars(); i++) {
  225. if (variables[i]->is_valid()) {
  226. variables[i]->sync();
  227. } else { // someone else added a new variable
  228. variables[i] = new NcVar(this,i);
  229. }
  230. }
  231. return 1;
  232. }
  233. NcBool NcFile::close( void )
  234. {
  235. int i;
  236. if (the_id == ncBad)
  237. return 0;
  238. for (i = 0; i < num_dims(); i++)
  239. delete dimensions[i];
  240. for (i = 0; i < num_vars(); i++)
  241. delete variables[i];
  242. delete [] dimensions;
  243. delete [] variables;
  244. delete globalv;
  245. int old_id = the_id;
  246. the_id = ncBad;
  247. return ncclose(old_id) != ncBad;
  248. }
  249. NcBool NcFile::abort( void )
  250. {
  251. return ncabort(the_id) != ncBad;
  252. }
  253. NcBool NcFile::define_mode( void )
  254. {
  255. if (! is_valid())
  256. return FALSE;
  257. if (in_define_mode)
  258. return TRUE;
  259. if (ncredef(the_id) == ncBad)
  260. return FALSE;
  261. in_define_mode = 1;
  262. return TRUE;
  263. }
  264. NcBool NcFile::data_mode( void )
  265. {
  266. if (! is_valid())
  267. return FALSE;
  268. if (! in_define_mode)
  269. return TRUE;
  270. if (ncendef(the_id) == ncBad)
  271. return FALSE;
  272. in_define_mode = 0;
  273. return TRUE;
  274. }
  275. int NcFile::id( void ) const
  276. {
  277. return the_id;
  278. }
  279. NcFile::NcFile( const char* path, FileMode fmode,
  280. size_t* chunksizeptr, size_t initialsize, FileFormat fformat )
  281. {
  282. NcError err(NcError::silent_nonfatal); // constructor must not fail
  283. int mode = NC_NOWRITE;
  284. the_fill_mode = Fill;
  285. int status;
  286. // If the user wants a 64-bit offset format, set that flag.
  287. if (fformat == Offset64Bits)
  288. mode |= NC_64BIT_OFFSET;
  289. #ifdef USE_NETCDF4
  290. else if (fformat == Netcdf4)
  291. mode |= NC_NETCDF4;
  292. else if (fformat == Netcdf4Classic)
  293. mode |= NC_NETCDF4|NC_CLASSIC_MODEL;
  294. #endif
  295. switch (fmode) {
  296. case Write:
  297. mode = NC_WRITE;
  298. /*FALLTHRU*/
  299. case ReadOnly:
  300. // use netcdf-3 interface to permit specifying tuning parameter
  301. status = nc__open(path, mode, chunksizeptr, &the_id);
  302. if(status != NC_NOERR)
  303. {
  304. nc_advise("ncopen", status, "filename \"%s\"", path);
  305. the_id = -1;
  306. }
  307. in_define_mode = 0;
  308. break;
  309. case New:
  310. mode = NC_NOCLOBBER;
  311. /*FALLTHRU*/
  312. case Replace:
  313. // use netcdf-3 interface to permit specifying tuning parameters
  314. status = nc__create(path, mode, initialsize,
  315. chunksizeptr, &the_id);
  316. if(status != NC_NOERR)
  317. {
  318. nc_advise("nccreate", status, "filename \"%s\"", path);
  319. the_id = -1;
  320. }
  321. in_define_mode = 1;
  322. break;
  323. default:
  324. the_id = ncBad;
  325. in_define_mode = 0;
  326. break;
  327. }
  328. if (is_valid()) {
  329. dimensions = new NcDim*[MAX_NC_DIMS];
  330. variables = new NcVar*[MAX_NC_VARS];
  331. int i;
  332. for (i = 0; i < num_dims(); i++)
  333. dimensions[i] = new NcDim(this, i);
  334. for (i = 0; i < num_vars(); i++)
  335. variables[i] = new NcVar(this, i);
  336. globalv = new NcVar(this, ncGlobal);
  337. } else {
  338. dimensions = 0;
  339. variables = 0;
  340. globalv = 0;
  341. }
  342. }
  343. NcToken NcDim::name( void ) const
  344. {
  345. return the_name;
  346. }
  347. long NcDim::size( void ) const
  348. {
  349. long sz = 0;
  350. if (the_file)
  351. ncdiminq(the_file->id(), the_id, (char*)0, &sz);
  352. return sz;
  353. }
  354. NcBool NcDim::is_valid( void ) const
  355. {
  356. return the_file->is_valid() && the_id != ncBad;
  357. }
  358. NcBool NcDim::is_unlimited( void ) const
  359. {
  360. if (!the_file)
  361. return FALSE;
  362. int recdim;
  363. ncinquire(the_file->id(), 0, 0, 0, &recdim);
  364. return the_id == recdim;
  365. }
  366. NcBool NcDim::rename(NcToken newname)
  367. {
  368. if (strlen(newname) > strlen(the_name)) {
  369. if (! the_file->define_mode())
  370. return FALSE;
  371. }
  372. NcBool ret = ncdimrename(the_file->id(), the_id, newname) != ncBad;
  373. if (ret) {
  374. delete [] the_name;
  375. the_name = new char[1 + strlen(newname)];
  376. strcpy(the_name, newname);
  377. }
  378. return ret;
  379. }
  380. int NcDim::id( void ) const
  381. {
  382. return the_id;
  383. }
  384. NcBool NcDim::sync(void)
  385. {
  386. char nam[MAX_NC_NAME];
  387. if (the_name) {
  388. delete [] the_name;
  389. }
  390. if (the_file && ncdiminq(the_file->id(), the_id, nam, 0) != ncBad) {
  391. the_name = new char[strlen(nam) + 1];
  392. strcpy(the_name, nam);
  393. return TRUE;
  394. }
  395. the_name = 0;
  396. return FALSE;
  397. }
  398. NcDim::NcDim(NcFile* nc, int id)
  399. : the_file(nc), the_id(id)
  400. {
  401. char nam[MAX_NC_NAME];
  402. if (the_file && ncdiminq(the_file->id(), the_id, nam, 0) != ncBad) {
  403. the_name = new char[strlen(nam) + 1];
  404. strcpy(the_name, nam);
  405. } else {
  406. the_name = 0;
  407. }
  408. }
  409. NcDim::NcDim(NcFile* nc, NcToken name, long sz)
  410. : the_file(nc)
  411. {
  412. the_id = ncdimdef(the_file->id(), name, sz);
  413. if (the_id != ncBad) {
  414. the_name = new char[strlen(name) + 1];
  415. strcpy(the_name, name);
  416. } else {
  417. the_name = 0;
  418. }
  419. }
  420. NcDim::~NcDim( void )
  421. {
  422. delete [] the_name;
  423. }
  424. #define Nc_as(TYPE) name2(as_,TYPE)
  425. #define NcTypedComponent_as(TYPE) \
  426. TYPE NcTypedComponent::Nc_as(TYPE)( long n ) const \
  427. { \
  428. NcValues* tmp = values(); \
  429. TYPE rval = tmp->Nc_as(TYPE)(n); \
  430. delete tmp; \
  431. return rval; \
  432. }
  433. NcTypedComponent_as(ncbyte)
  434. NcTypedComponent_as(char)
  435. NcTypedComponent_as(short)
  436. NcTypedComponent_as(int)
  437. NcTypedComponent_as(nclong)
  438. NcTypedComponent_as(long)
  439. NcTypedComponent_as(float)
  440. NcTypedComponent_as(double)
  441. char* NcTypedComponent::as_string( long n ) const
  442. {
  443. NcValues* tmp = values();
  444. char* rval = tmp->as_string(n);
  445. delete tmp;
  446. return rval;
  447. }
  448. NcTypedComponent::NcTypedComponent ( NcFile* nc )
  449. : the_file(nc)
  450. {}
  451. NcValues* NcTypedComponent::get_space( long numVals ) const
  452. {
  453. NcValues* valp;
  454. if (numVals < 1)
  455. numVals = num_vals();
  456. switch (type()) {
  457. case ncFloat:
  458. valp = new NcValues_float(numVals);
  459. break;
  460. case ncDouble:
  461. valp = new NcValues_double(numVals);
  462. break;
  463. case ncInt:
  464. valp = new NcValues_int(numVals);
  465. break;
  466. case ncShort:
  467. valp = new NcValues_short(numVals);
  468. break;
  469. case ncByte:
  470. case ncChar:
  471. valp = new NcValues_char(numVals);
  472. break;
  473. case ncNoType:
  474. default:
  475. valp = 0;
  476. }
  477. return valp;
  478. }
  479. NcVar::~NcVar( void )
  480. {
  481. delete[] the_cur;
  482. delete[] cur_rec;
  483. delete[] the_name;
  484. }
  485. NcToken NcVar::name( void ) const
  486. {
  487. return the_name;
  488. }
  489. NcType NcVar::type( void ) const
  490. {
  491. nc_type typ;
  492. ncvarinq(the_file->id(), the_id, 0, &typ, 0, 0, 0);
  493. return (NcType) typ;
  494. }
  495. NcBool NcVar::is_valid( void ) const
  496. {
  497. return the_file->is_valid() && the_id != ncBad;
  498. }
  499. int NcVar::num_dims( void ) const
  500. {
  501. int ndim;
  502. ncvarinq(the_file->id(), the_id, 0, 0, &ndim, 0, 0);
  503. return ndim;
  504. }
  505. // The i-th dimension for this variable
  506. NcDim* NcVar::get_dim( int i ) const
  507. {
  508. int ndim;
  509. int dims[MAX_NC_DIMS];
  510. if(ncvarinq(the_file->id(), the_id, 0, 0, &ndim, dims, 0) == ncBad ||
  511. i < 0 || i >= ndim)
  512. return 0;
  513. return the_file->get_dim(dims[i]);
  514. }
  515. long* NcVar::edges( void ) const // edge lengths (dimension sizes)
  516. {
  517. long* evec = new long[num_dims()];
  518. for(int i=0; i < num_dims(); i++)
  519. evec[i] = get_dim(i)->size();
  520. return evec;
  521. }
  522. int NcVar::num_atts( void ) const // handles variable and global atts
  523. {
  524. int natt = 0;
  525. if (the_file->is_valid())
  526. if (the_id == ncGlobal)
  527. natt = the_file->num_atts();
  528. else
  529. ncvarinq(the_file->id(), the_id, 0, 0, 0, 0, &natt);
  530. return natt;
  531. }
  532. NcAtt* NcVar::get_att( NcToken aname ) const
  533. {
  534. NcAtt* att = new NcAtt(the_file, this, aname);
  535. if (! att->is_valid()) {
  536. delete att;
  537. return 0;
  538. }
  539. return att;
  540. }
  541. NcAtt* NcVar::get_att( int n ) const
  542. {
  543. if (n < 0 || n >= num_atts())
  544. return 0;
  545. NcToken aname = attname(n);
  546. NcAtt* ap = get_att(aname);
  547. delete [] (char*)aname;
  548. return ap;
  549. }
  550. long NcVar::num_vals( void ) const
  551. {
  552. long prod = 1;
  553. for (int d = 0; d < num_dims(); d++)
  554. prod *= get_dim(d)->size();
  555. return prod;
  556. }
  557. NcValues* NcVar::values( void ) const
  558. {
  559. int ndims = num_dims();
  560. long crnr[MAX_NC_DIMS];
  561. long edgs[MAX_NC_DIMS];
  562. for (int i = 0; i < ndims; i++) {
  563. crnr[i] = 0;
  564. edgs[i] = get_dim(i)->size();
  565. }
  566. NcValues* valp = get_space();
  567. if (ncvarget(the_file->id(), the_id, crnr, edgs, valp->base()) == ncBad)
  568. return 0;
  569. return valp;
  570. }
  571. int NcVar::dim_to_index(NcDim *rdim)
  572. {
  573. for (int i=0; i < num_dims() ; i++) {
  574. if (strcmp(get_dim(i)->name(),rdim->name()) == 0) {
  575. return i;
  576. }
  577. }
  578. // we should fail and gripe about it here....
  579. return -1;
  580. }
  581. void NcVar::set_rec(NcDim *rdim, long slice)
  582. {
  583. int i = dim_to_index(rdim);
  584. // we should fail and gripe about it here....
  585. if (slice >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
  586. return;
  587. cur_rec[i] = slice;
  588. return;
  589. }
  590. void NcVar::set_rec(long rec)
  591. {
  592. // Since we can't ask for the record dimension here
  593. // just assume [0] is it.....
  594. set_rec(get_dim(0),rec);
  595. return;
  596. }
  597. NcValues* NcVar::get_rec(void)
  598. {
  599. return get_rec(get_dim(0), cur_rec[0]);
  600. }
  601. NcValues* NcVar::get_rec(long rec)
  602. {
  603. return get_rec(get_dim(0), rec);
  604. }
  605. NcValues* NcVar::get_rec(NcDim* rdim, long slice)
  606. {
  607. int idx = dim_to_index(rdim);
  608. long size = num_dims();
  609. long* start = new long[size];
  610. for (int i=1; i < size ; i++) start[i] = 0;
  611. start[idx] = slice;
  612. NcBool result = set_cur(start);
  613. if (! result ) {
  614. delete [] start;
  615. return 0;
  616. }
  617. long* edge = edges();
  618. edge[idx] = 1;
  619. NcValues* valp = get_space(rec_size(rdim));
  620. if (ncvarget(the_file->id(), the_id, start, edge, valp->base()) == ncBad) {
  621. delete [] start;
  622. delete [] edge;
  623. delete valp;
  624. return 0;
  625. }
  626. delete [] start;
  627. delete [] edge;
  628. return valp;
  629. }
  630. #define NcVar_put_rec(TYPE) \
  631. NcBool NcVar::put_rec( const TYPE* vals) \
  632. { \
  633. return put_rec(get_dim(0), vals, cur_rec[0]); \
  634. } \
  635. \
  636. NcBool NcVar::put_rec( NcDim *rdim, const TYPE* vals) \
  637. { \
  638. int idx = dim_to_index(rdim); \
  639. return put_rec(rdim, vals, cur_rec[idx]); \
  640. } \
  641. \
  642. NcBool NcVar::put_rec( const TYPE* vals, \
  643. long rec) \
  644. { \
  645. return put_rec(get_dim(0), vals, rec); \
  646. } \
  647. \
  648. NcBool NcVar::put_rec( NcDim* rdim, const TYPE* vals, \
  649. long slice) \
  650. { \
  651. int idx = dim_to_index(rdim); \
  652. long size = num_dims(); \
  653. long* start = new long[size]; \
  654. for (int i=1; i < size ; i++) start[i] = 0; \
  655. start[idx] = slice; \
  656. NcBool result = set_cur(start); \
  657. delete [] start; \
  658. if (! result ) \
  659. return FALSE; \
  660. \
  661. long* edge = edges(); \
  662. edge[idx] = 1; \
  663. result = put(vals, edge); \
  664. delete [] edge; \
  665. return result; \
  666. }
  667. NcVar_put_rec(ncbyte)
  668. NcVar_put_rec(char)
  669. NcVar_put_rec(short)
  670. NcVar_put_rec(int)
  671. NcVar_put_rec(long)
  672. NcVar_put_rec(float)
  673. NcVar_put_rec(double)
  674. long NcVar::rec_size(void) {
  675. return rec_size(get_dim(0));
  676. }
  677. long NcVar::rec_size(NcDim *rdim) {
  678. int idx = dim_to_index(rdim);
  679. long size = 1;
  680. long* edge = edges();
  681. for( int i = 0 ; i<num_dims() ; i++) {
  682. if (i != idx) {
  683. size *= edge[i];
  684. }
  685. }
  686. delete [] edge;
  687. return size;
  688. }
  689. #define NcVar_get_index(TYPE) \
  690. long NcVar::get_index(const TYPE* key) \
  691. { \
  692. return get_index(get_dim(0), key); \
  693. } \
  694. \
  695. long NcVar::get_index(NcDim *rdim, const TYPE* key) \
  696. { \
  697. if (type() != NcTypeEnum(TYPE)) \
  698. return -1; \
  699. if (! the_file->data_mode()) \
  700. return -1; \
  701. int idx = dim_to_index(rdim); \
  702. long maxrec = get_dim(idx)->size(); \
  703. long maxvals = rec_size(rdim); \
  704. NcValues* val; \
  705. int validx; \
  706. for (long j=0; j<maxrec; j++) { \
  707. val = get_rec(rdim,j); \
  708. if (val == NULL) return -1; \
  709. for (validx = 0; validx < maxvals; validx++) { \
  710. if (key[validx] != val->as_ ## TYPE(validx)) break; \
  711. } \
  712. delete val; \
  713. if (validx == maxvals) return j; \
  714. } \
  715. return -1; \
  716. }
  717. NcVar_get_index(ncbyte)
  718. NcVar_get_index(char)
  719. NcVar_get_index(short)
  720. NcVar_get_index(nclong)
  721. NcVar_get_index(long)
  722. NcVar_get_index(float)
  723. NcVar_get_index(double)
  724. #define NcVar_put_array(TYPE) \
  725. NcBool NcVar::put( const TYPE* vals, \
  726. long edge0, \
  727. long edge1, \
  728. long edge2, \
  729. long edge3, \
  730. long edge4) \
  731. { \
  732. if (type() != NcTypeEnum(TYPE)) \
  733. return FALSE; \
  734. if (! the_file->data_mode()) \
  735. return FALSE; \
  736. long count[5]; \
  737. count[0] = edge0; \
  738. count[1] = edge1; \
  739. count[2] = edge2; \
  740. count[3] = edge3; \
  741. count[4] = edge4; \
  742. for (int i = 0; i < 5; i++) { \
  743. if (count[i]) { \
  744. if (num_dims() < i) \
  745. return FALSE; \
  746. } else \
  747. break; \
  748. } \
  749. long start[5]; \
  750. for (int j = 0; j < 5; j++) { \
  751. start[j] = the_cur[j]; \
  752. } \
  753. return ncvarput(the_file->id(), the_id, start, count, vals) != ncBad; \
  754. }
  755. NcVar_put_array(ncbyte)
  756. NcVar_put_array(char)
  757. NcVar_put_array(short)
  758. NcVar_put_array(int)
  759. NcVar_put_array(long)
  760. NcVar_put_array(float)
  761. NcVar_put_array(double)
  762. #define NcVar_put_nd_array(TYPE) \
  763. NcBool NcVar::put( const TYPE* vals, const long* count ) \
  764. { \
  765. if (type() != NcTypeEnum(TYPE)) \
  766. return FALSE; \
  767. if (! the_file->data_mode()) \
  768. return FALSE; \
  769. long start[MAX_NC_DIMS]; \
  770. for (int i = 0; i < num_dims(); i++) \
  771. start[i] = the_cur[i]; \
  772. return ncvarput(the_file->id(), the_id, start, count, vals) != ncBad; \
  773. }
  774. NcVar_put_nd_array(ncbyte)
  775. NcVar_put_nd_array(char)
  776. NcVar_put_nd_array(short)
  777. NcVar_put_nd_array(int)
  778. NcVar_put_nd_array(long)
  779. NcVar_put_nd_array(float)
  780. NcVar_put_nd_array(double)
  781. #define NcVar_get_array(TYPE) \
  782. NcBool NcVar::get( TYPE* vals, \
  783. long edge0, \
  784. long edge1, \
  785. long edge2, \
  786. long edge3, \
  787. long edge4) const \
  788. { \
  789. if (type() != NcTypeEnum(TYPE)) \
  790. return FALSE; \
  791. if (! the_file->data_mode()) \
  792. return FALSE; \
  793. long count[5]; \
  794. count[0] = edge0; \
  795. count[1] = edge1; \
  796. count[2] = edge2; \
  797. count[3] = edge3; \
  798. count[4] = edge4; \
  799. for (int i = 0; i < 5; i++) { \
  800. if (count[i]) { \
  801. if (num_dims() < i) \
  802. return FALSE; \
  803. } else \
  804. break; \
  805. } \
  806. static long start[5] = {0, 0, 0, 0, 0}; \
  807. for (int j = 0; j < 5; j++) { \
  808. start[j] = the_cur[j]; \
  809. } \
  810. return ncvarget(the_file->id(), the_id, start, count, vals) != ncBad; \
  811. }
  812. NcVar_get_array(ncbyte)
  813. NcVar_get_array(char)
  814. NcVar_get_array(short)
  815. NcVar_get_array(int)
  816. NcVar_get_array(long)
  817. NcVar_get_array(float)
  818. NcVar_get_array(double)
  819. #define NcVar_get_nd_array(TYPE) \
  820. NcBool NcVar::get( TYPE* vals, const long* count ) const \
  821. { \
  822. if (type() != NcTypeEnum(TYPE)) \
  823. return FALSE; \
  824. if (! the_file->data_mode()) \
  825. return FALSE; \
  826. long start[MAX_NC_DIMS]; \
  827. for (int i = 0; i < num_dims(); i++) \
  828. start[i] = the_cur[i]; \
  829. return ncvarget(the_file->id(), the_id, start, count, vals) != ncBad; \
  830. }
  831. NcVar_get_nd_array(ncbyte)
  832. NcVar_get_nd_array(char)
  833. NcVar_get_nd_array(short)
  834. NcVar_get_nd_array(int)
  835. NcVar_get_nd_array(long)
  836. NcVar_get_nd_array(float)
  837. NcVar_get_nd_array(double)
  838. // If no args, set cursor to all zeros. Else set initial elements of cursor
  839. // to args provided, rest to zeros.
  840. NcBool NcVar::set_cur(long c0, long c1, long c2, long c3, long c4)
  841. {
  842. long t[6];
  843. t[0] = c0;
  844. t[1] = c1;
  845. t[2] = c2;
  846. t[3] = c3;
  847. t[4] = c4;
  848. t[5] = -1;
  849. for(int j = 0; j < 6; j++) { // find how many parameters were used
  850. int i;
  851. if (t[j] == -1) {
  852. if (num_dims() < j)
  853. return FALSE; // too many for variable's dimensionality
  854. for (i = 0; i < j; i++) {
  855. if (t[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
  856. return FALSE; // too big for dimension
  857. the_cur[i] = t[i];
  858. }
  859. for(i = j; i < num_dims(); i++)
  860. the_cur[i] = 0;
  861. return TRUE;
  862. }
  863. }
  864. return TRUE;
  865. }
  866. NcBool NcVar::set_cur(long* cur)
  867. {
  868. for(int i = 0; i < num_dims(); i++) {
  869. if (cur[i] >= get_dim(i)->size() && ! get_dim(i)->is_unlimited())
  870. return FALSE;
  871. the_cur[i] = cur[i];
  872. }
  873. return TRUE;
  874. }
  875. #define NcVar_add_scalar_att(TYPE) \
  876. NcBool NcVar::add_att(NcToken aname, TYPE val) \
  877. { \
  878. if (! the_file->define_mode()) \
  879. return FALSE; \
  880. if (ncattput(the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE), \
  881. 1, &val) == ncBad) \
  882. return FALSE; \
  883. return TRUE; \
  884. } \
  885. NcVar_add_scalar_att(char)
  886. NcVar_add_scalar_att(ncbyte)
  887. NcVar_add_scalar_att(short)
  888. NcVar_add_scalar_att(int)
  889. NcVar_add_scalar_att(long)
  890. NcVar_add_scalar_att(double)
  891. NcBool NcVar::add_att(NcToken aname, float val)
  892. {
  893. if (! the_file->define_mode())
  894. return FALSE;
  895. float fval = (float) val; // workaround for bug, val passed as double??
  896. if (ncattput(the_file->id(), the_id, aname, (nc_type) ncFloat,
  897. 1, &fval) == ncBad)
  898. return FALSE;
  899. return TRUE;
  900. }
  901. NcBool NcVar::add_att(NcToken aname, const char* val)
  902. {
  903. if (! the_file->define_mode())
  904. return FALSE;
  905. if (ncattput(the_file->id(), the_id, aname, (nc_type) ncChar,
  906. strlen(val), val) == ncBad)
  907. return FALSE;
  908. return TRUE;
  909. }
  910. #define NcVar_add_vector_att(TYPE) \
  911. NcBool NcVar::add_att(NcToken aname, int len, const TYPE* vals) \
  912. { \
  913. if (! the_file->define_mode()) \
  914. return FALSE; \
  915. if (ncattput(the_file->id(), the_id, aname, (nc_type) NcTypeEnum(TYPE), \
  916. len, vals) == ncBad) \
  917. return FALSE; \
  918. return TRUE; \
  919. }
  920. NcVar_add_vector_att(char)
  921. NcVar_add_vector_att(ncbyte)
  922. NcVar_add_vector_att(short)
  923. NcVar_add_vector_att(int)
  924. NcVar_add_vector_att(long)
  925. NcVar_add_vector_att(float)
  926. NcVar_add_vector_att(double)
  927. NcBool NcVar::rename(NcToken newname)
  928. {
  929. if (strlen(newname) > strlen(the_name)) {
  930. if (! the_file->define_mode())
  931. return FALSE;
  932. }
  933. NcBool ret = ncvarrename(the_file->id(), the_id, newname) != ncBad;
  934. if (ret) {
  935. delete [] the_name;
  936. the_name = new char [1 + strlen(newname)];
  937. strcpy(the_name, newname);
  938. }
  939. return ret;
  940. }
  941. int NcVar::id( void ) const
  942. {
  943. return the_id;
  944. }
  945. NcBool NcVar::sync(void)
  946. {
  947. if (the_name) {
  948. delete [] the_name;
  949. }
  950. if (the_cur) {
  951. delete [] the_cur;
  952. }
  953. if (cur_rec) {
  954. delete [] cur_rec;
  955. }
  956. char nam[MAX_NC_NAME];
  957. if (the_file
  958. && ncvarinq(the_file->id(), the_id, nam, 0, 0, 0, 0) != ncBad) {
  959. the_name = new char[1 + strlen(nam)];
  960. strcpy(the_name, nam);
  961. } else {
  962. the_name = 0;
  963. return FALSE;
  964. }
  965. init_cur();
  966. return TRUE;
  967. }
  968. NcVar::NcVar(NcFile* nc, int id)
  969. : NcTypedComponent(nc), the_id(id)
  970. {
  971. char nam[MAX_NC_NAME];
  972. if (the_file
  973. && ncvarinq(the_file->id(), the_id, nam, 0, 0, 0, 0) != ncBad) {
  974. the_name = new char[1 + strlen(nam)];
  975. strcpy(the_name, nam);
  976. } else {
  977. the_name = 0;
  978. }
  979. init_cur();
  980. }
  981. int NcVar::attnum( NcToken attrname ) const
  982. {
  983. int num;
  984. for(num=0; num < num_atts(); num++) {
  985. char aname[MAX_NC_NAME];
  986. ncattname(the_file->id(), the_id, num, aname);
  987. if (strcmp(aname, attrname) == 0)
  988. break;
  989. }
  990. return num; // num_atts() if no such attribute
  991. }
  992. NcToken NcVar::attname( int attnum ) const // caller must delete[]
  993. {
  994. if (attnum < 0 || attnum >= num_atts())
  995. return 0;
  996. char aname[MAX_NC_NAME];
  997. if (ncattname(the_file->id(), the_id, attnum, aname) == ncBad)
  998. return 0;
  999. char* rname = new char[1 + strlen(aname)];
  1000. strcpy(rname, aname);
  1001. return rname;
  1002. }
  1003. void NcVar::init_cur( void )
  1004. {
  1005. the_cur = new long[MAX_NC_DIMS]; // *** don't know num_dims() yet?
  1006. cur_rec = new long[MAX_NC_DIMS]; // *** don't know num_dims() yet?
  1007. for(int i = 0; i < MAX_NC_DIMS; i++) {
  1008. the_cur[i] = 0; cur_rec[i] = 0; }
  1009. }
  1010. NcAtt::NcAtt(NcFile* nc, const NcVar* var, NcToken name)
  1011. : NcTypedComponent(nc), the_variable(var)
  1012. {
  1013. the_name = new char[1 + strlen(name)];
  1014. strcpy(the_name, name);
  1015. }
  1016. NcAtt::NcAtt(NcFile* nc, NcToken name)
  1017. : NcTypedComponent(nc), the_variable(NULL)
  1018. {
  1019. the_name = new char[1 + strlen(name)];
  1020. strcpy(the_name, name);
  1021. }
  1022. NcAtt::~NcAtt( void )
  1023. {
  1024. delete [] the_name;
  1025. }
  1026. NcToken NcAtt::name( void ) const
  1027. {
  1028. return the_name;
  1029. }
  1030. NcType NcAtt::type( void ) const
  1031. {
  1032. nc_type typ;
  1033. ncattinq(the_file->id(), the_variable->id(), the_name, &typ, 0);
  1034. return (NcType) typ;
  1035. }
  1036. long NcAtt::num_vals( void ) const
  1037. {
  1038. int len;
  1039. ncattinq(the_file->id(), the_variable->id(), the_name, 0, &len);
  1040. return len;
  1041. }
  1042. NcBool NcAtt::is_valid( void ) const
  1043. {
  1044. return the_file->is_valid() &&
  1045. (the_variable->id() == NC_GLOBAL || the_variable->is_valid()) &&
  1046. ncattinq(the_file->id(), the_variable->id(), the_name, 0, 0) != ncBad;
  1047. }
  1048. NcValues* NcAtt::values( void ) const
  1049. {
  1050. NcValues* valp = get_space();
  1051. if (ncattget(the_file->id(),
  1052. the_variable->id(),
  1053. the_name,
  1054. valp->base()) == ncBad) {
  1055. delete valp;
  1056. return 0;
  1057. }
  1058. return valp;
  1059. }
  1060. NcBool NcAtt::rename(NcToken newname)
  1061. {
  1062. if (strlen(newname) > strlen(the_name)) {
  1063. if (! the_file->define_mode())
  1064. return FALSE;
  1065. }
  1066. return ncattrename(the_file->id(), the_variable->id(),
  1067. the_name, newname) != ncBad;
  1068. }
  1069. NcBool NcAtt::remove( void )
  1070. {
  1071. if (! the_file->define_mode())
  1072. return FALSE;
  1073. return ncattdel(the_file->id(), the_variable->id(), the_name) != ncBad;
  1074. }
  1075. NcError::NcError( Behavior b )
  1076. {
  1077. the_old_state = ncopts; // global variable in C interface
  1078. the_old_err = ncerr; // global variable in C interface
  1079. ncopts = (int) b;
  1080. }
  1081. NcError::~NcError( void )
  1082. {
  1083. ncopts = the_old_state;
  1084. ncerr = the_old_err;
  1085. }
  1086. int NcError::get_err( void ) // returns most recent error
  1087. {
  1088. return ncerr;
  1089. }