oc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. /* Copyright 2009, UCAR/Unidata and OPeNDAP, Inc.
  2. See the COPYRIGHT file for more information. */
  3. #include "config.h"
  4. #include <stdlib.h>
  5. #include <assert.h>
  6. #include <string.h>
  7. #include "oc.h"
  8. #include "ocinternal.h"
  9. #include "occontent.h"
  10. #include "ocdebug.h"
  11. #include "ocdump.h"
  12. #include "oclog.h"
  13. #include "occlientparams.h"
  14. #include "ochttp.h"
  15. #undef TRACK
  16. /**************************************************/
  17. static int ocinitialized = 0;
  18. /**************************************************/
  19. /* Track legal ids */
  20. #ifdef OC_FASTCONSISTENCY
  21. #define ocverify(object) ((object) != NULL && (*(object) == OCMAGIC)?1:0)
  22. #define ocassign(object) ((OCobject)(object))
  23. #define ocassignall(list)
  24. #else /*!OC_FASTCONSISTENCY*/
  25. static OClist* ocmap = NULL;
  26. static int
  27. ocverify(unsigned long object)
  28. {
  29. unsigned int i;
  30. void** map = (void**)oclistcontents(ocmap);
  31. unsigned int len = oclistlength(ocmap);
  32. #ifdef TRACK
  33. fprintf(stderr,"verify: %lu\n",object); fflush(stderr);
  34. #endif
  35. if(object > 0) {
  36. for(i=0;i<len;i++,map++) {
  37. if(*map == (void*)object) {
  38. return 1;
  39. }
  40. }
  41. }
  42. fprintf(stderr,"illegal object id: %lu\n",(unsigned long)object);
  43. fflush(stderr);
  44. return 0;
  45. }
  46. static OCobject
  47. ocassign(void* object)
  48. {
  49. #ifdef TRACK
  50. fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
  51. #endif
  52. oclistpush(ocmap,(ocelem)object);
  53. return (OCobject)object;
  54. }
  55. static void
  56. ocassignall(OClist* list)
  57. {
  58. unsigned int i;
  59. if(list != NULL)
  60. for(i=0;i<oclistlength(list);i++) {
  61. void* object = (void*)oclistget(list,i);
  62. #ifdef TRACK
  63. fprintf(stderr,"assign: %lu\n",(unsigned long)object); fflush(stderr);
  64. #endif
  65. oclistpush(ocmap,(ocelem)object);
  66. }
  67. }
  68. #endif /*!OC_FASTCONSISTENCY*/
  69. #define OCVERIFYX(T,s,x,r) if(!ocverify(x)) {return (r);}
  70. #define OCVERIFY(T,s,x) OCVERIFYX(T,s,x,OC_EINVAL)
  71. #define OCDEREF(T,s,x) (s)=(T)(x)
  72. /**************************************************/
  73. static int
  74. oc_initialize(void)
  75. {
  76. int status = OC_NOERR;
  77. #ifndef OC_FASTCONSISTENCY
  78. ocmap = oclistnew();
  79. oclistsetalloc(ocmap,1024);
  80. #endif
  81. status = ocinternalinitialize();
  82. ocinitialized = 1;
  83. return status;
  84. }
  85. /**************************************************/
  86. OCerror
  87. oc_open(const char* url, OCconnection* connp)
  88. {
  89. OCerror ocerr;
  90. OCstate* state;
  91. if(!ocinitialized) oc_initialize();
  92. ocerr = ocopen(&state,url);
  93. if(ocerr == OC_NOERR && connp) {
  94. *connp = (OCconnection)ocassign(state);
  95. }
  96. return ocerr;
  97. }
  98. OCerror
  99. oc_close(OCconnection conn)
  100. {
  101. OCstate* state;
  102. OCVERIFY(OCstate*,state,conn);
  103. OCDEREF(OCstate*,state,conn);
  104. occlose(state);
  105. return OC_NOERR;
  106. }
  107. /* Release/reclaim the tree of objects associated with a given root */
  108. OCerror
  109. oc_root_free(OCconnection conn, OCobject root0)
  110. {
  111. OCnode* root;
  112. OCVERIFY(OCnode*,root,root0);
  113. OCDEREF(OCnode*,root,root0);
  114. ocfreeroot(root);
  115. return OC_NOERR;
  116. }
  117. /* Return the # of OCobjects associated with a tree with specified root */
  118. unsigned int
  119. oc_inq_nobjects(OCconnection conn, OCobject root0)
  120. {
  121. OCnode* root;
  122. OClist* nodes;
  123. unsigned int nobjects;
  124. OCVERIFYX(OCnode*,root,root0,-1);
  125. OCDEREF(OCnode*,root,root0);
  126. if(root == NULL) return 0;
  127. root = root->root;
  128. if(root == NULL) return 0;
  129. nodes = root->tree->nodes;
  130. nobjects = oclistlength(nodes);
  131. return nobjects;
  132. }
  133. /* Return all the OCobjects associated with a tree with specified root */
  134. OCobject*
  135. oc_inq_objects(OCconnection conn, OCobject root0)
  136. {
  137. unsigned int i;
  138. OCnode* root;
  139. OClist* nodes;
  140. OCobject* objects = NULL;
  141. unsigned int nobjects;
  142. OCVERIFYX(OCnode*,root,root0,OCNULL);
  143. OCDEREF(OCnode*,root,root0);
  144. if(root == NULL) return NULL;
  145. root = root->root;
  146. if(root == NULL) return NULL;
  147. nodes = root->tree->nodes;
  148. nobjects = oclistlength(nodes);
  149. if(nodes != NULL && nobjects > 0) {
  150. size_t len = sizeof(OCobject)*(1+nobjects);
  151. objects = (OCobject*)ocmalloc(len);
  152. for(i=0;i<oclistlength(nodes);i++) {
  153. objects[i] = (OCobject)oclistget(nodes,i);
  154. }
  155. objects[nobjects] = OCNULL; /* null terminate */
  156. }
  157. return objects;
  158. }
  159. /* Return the text of the DDS or DAS as received from the server */
  160. /* Return NULL if no fetch was ever made. */
  161. const char*
  162. oc_inq_text(OCconnection conn, OCobject root0)
  163. {
  164. OCnode* root;
  165. OCVERIFYX(OCnode*,root,root0,NULL);
  166. OCDEREF(OCnode*,root,root0);
  167. if(root == NULL) return NULL;
  168. root = root->root;
  169. if(root == NULL) return NULL;
  170. return root->tree->text;
  171. }
  172. OCerror
  173. oc_inq_object(OCconnection conn,
  174. OCobject node0,
  175. char** namep,
  176. OCtype* objecttypep,
  177. OCtype* primitivetypep, /* if objecttype == OC_Primitive */
  178. OCobject* containerp,
  179. unsigned int* rankp,
  180. unsigned int* subnodesp,
  181. unsigned int* nattrp)
  182. {
  183. OCnode* node;
  184. OCVERIFY(OCnode*,node,node0);
  185. OCDEREF(OCnode*,node,node0);
  186. if(namep) *namep = nulldup(node->name);
  187. if(objecttypep) *objecttypep = node->octype;
  188. if(primitivetypep) *primitivetypep = node->etype;
  189. if(rankp) *rankp = node->array.rank;
  190. if(containerp) *containerp = (OCobject)node->container;
  191. if(subnodesp) *subnodesp = oclistlength(node->subnodes);
  192. if(nattrp) {
  193. if(node->octype == OC_Attribute) {
  194. *nattrp = oclistlength(node->att.values);
  195. } else {
  196. *nattrp = oclistlength(node->attributes);
  197. }
  198. }
  199. return OC_NOERR;
  200. }
  201. /* Useful accessor functions */
  202. OCerror
  203. oc_inq_name(OCconnection conn, OCobject node0, char** namep)
  204. {
  205. OCstate* state;
  206. OCnode* node;
  207. OCVERIFY(OCstate*,state,conn);
  208. OCDEREF(OCstate*,state,conn);
  209. OCVERIFY(OCnode*,node,node0);
  210. OCDEREF(OCnode*,node,node0);
  211. if(state == NULL || node == NULL) return OC_EINVAL;
  212. if(namep) *namep = nulldup(node->name);
  213. return OC_NOERR;
  214. }
  215. OCerror
  216. oc_inq_nsubnodes(OCconnection conn, OCobject node0, unsigned int* nsubnodesp)
  217. {
  218. OCnode* node;
  219. OCVERIFY(OCnode*,node,node0);
  220. OCDEREF(OCnode*,node,node0);
  221. if(nsubnodesp) *nsubnodesp = oclistlength(node->subnodes);
  222. return OC_NOERR;
  223. }
  224. OCerror
  225. oc_inq_primtype(OCconnection conn, OCobject node0, OCtype* typep)
  226. {
  227. OCnode* node;
  228. OCVERIFY(OCnode*,node,node0);
  229. OCDEREF(OCnode*,node,node0);
  230. if(typep) *typep = node->etype;
  231. return OC_NOERR;
  232. }
  233. /* Alias for oc_inq_class */
  234. OCerror
  235. oc_inq_type(OCconnection conn, OCobject node0, OCtype* typep)
  236. {
  237. return oc_inq_class(conn,node0,typep);
  238. }
  239. OCerror
  240. oc_inq_class(OCconnection conn, OCobject node0, OCtype* typep)
  241. {
  242. OCnode* node;
  243. OCVERIFY(OCnode*,node,node0);
  244. OCDEREF(OCnode*,node,node0);
  245. if(typep) *typep = node->octype;
  246. return OC_NOERR;
  247. }
  248. OCerror
  249. oc_inq_rank(OCconnection conn, OCobject node0, unsigned int* rankp)
  250. {
  251. OCnode* node;
  252. OCVERIFY(OCnode*,node,node0);
  253. OCDEREF(OCnode*,node,node0);
  254. if(rankp) *rankp = node->array.rank;
  255. return OC_NOERR;
  256. }
  257. OCerror
  258. oc_inq_nattr(OCconnection conn, OCobject node0, unsigned int* nattrp)
  259. {
  260. OCnode* node;
  261. OCVERIFY(OCnode*,node,node0);
  262. OCDEREF(OCnode*,node,node0);
  263. if(nattrp) {
  264. if(node->octype == OC_Attribute) {
  265. *nattrp = oclistlength(node->att.values);
  266. } else {
  267. *nattrp = oclistlength(node->attributes);
  268. }
  269. }
  270. return OC_NOERR;
  271. }
  272. OCerror
  273. oc_inq_root(OCconnection conn, OCobject node0, OCobject* rootp)
  274. {
  275. OCnode* node;
  276. OCVERIFY(OCnode*,node,node0);
  277. OCDEREF(OCnode*,node,node0);
  278. if(rootp) *rootp = (OCobject)node->root;
  279. return OC_NOERR;
  280. }
  281. OCerror
  282. oc_inq_container(OCconnection conn, OCobject node0, OCobject* containerp)
  283. {
  284. OCnode* node;
  285. OCVERIFY(OCnode*,node,node0);
  286. OCDEREF(OCnode*,node,node0);
  287. if(containerp) *containerp = (OCobject)node->container;
  288. return OC_NOERR;
  289. }
  290. /* Return the subnode objects, if any, for a given object */
  291. /* Caller must free returned list */
  292. OCerror
  293. oc_inq_subnodes(OCconnection conn, OCobject node0, OCobject** subnodesp)
  294. {
  295. OCnode* node;
  296. OCobject* subnodes = NULL;
  297. unsigned int len;
  298. OCVERIFY(OCnode*,node,node0);
  299. OCDEREF(OCnode*,node,node0);
  300. len = oclistlength(node->subnodes);
  301. if(len > 0) {
  302. unsigned int i;
  303. subnodes = (OCobject*)occalloc(sizeof(OCobject),len+1);
  304. for(i=0;i<len;i++) {
  305. OCnode* ocnode = (OCnode*)oclistget(node->subnodes,i);
  306. subnodes[i] = (OCobject)ocnode;
  307. }
  308. subnodes[len] = OCNULL; /* NULL terminate */
  309. }
  310. if(subnodesp) *subnodesp = subnodes;
  311. return OC_NOERR;
  312. }
  313. OCerror
  314. oc_inq_ith(OCconnection conn,
  315. OCobject node0, unsigned int index, OCobject* subnodeidp)
  316. {
  317. OCnode* node;
  318. OCobject subnodeid = OCNULL;
  319. unsigned int nsubnodes;
  320. OCVERIFY(OCnode*,node,node0);
  321. OCDEREF(OCnode*,node,node0);
  322. nsubnodes = oclistlength(node->subnodes);
  323. if(nsubnodes > 0 && index < nsubnodes) {
  324. subnodeid = (OCobject)oclistget(node->subnodes,index);
  325. } else
  326. return OC_EINVAL;
  327. if(subnodeidp) *subnodeidp = subnodeid;
  328. return OC_NOERR;
  329. }
  330. /* Return the dimension objects, if any, for a given object */
  331. /* Caller must free returned dimids */
  332. OCerror
  333. oc_inq_dimset(OCconnection conn, OCobject node0, OCobject** dimids)
  334. {
  335. OCnode* node;
  336. OCobject* dims = NULL;
  337. OCVERIFY(OCnode*,node,node0);
  338. OCDEREF(OCnode*,node,node0);
  339. if(node->array.rank > 0) {
  340. unsigned int i;
  341. dims = (OCobject*)occalloc(sizeof(OCobject),node->array.rank+1);
  342. for(i=0;i<node->array.rank;i++) {
  343. OCnode* dim = (OCnode*)oclistget(node->array.dimensions,i);
  344. dims[i] = (OCobject)dim;
  345. }
  346. dims[node->array.rank] = OCNULL;
  347. }
  348. if(dimids) *dimids = dims;
  349. return OC_NOERR;
  350. }
  351. OCerror
  352. oc_inq_ithdim(OCconnection conn, OCobject node0, unsigned int index, OCobject* dimidp)
  353. {
  354. OCnode* node;
  355. OCobject dimid = OCNULL;
  356. OCVERIFY(OCnode*,node,node0);
  357. OCDEREF(OCnode*,node,node0);
  358. if(node->array.rank > 0 && index < node->array.rank) {
  359. dimid = (OCobject)oclistget(node->array.dimensions,index);
  360. } else
  361. return OC_EINVAL;
  362. if(dimidp) *dimidp = dimid;
  363. return OC_NOERR;
  364. }
  365. OCerror
  366. oc_inq_dim(OCconnection conn, OCobject node0, size_t* sizep, char** namep)
  367. {
  368. OCnode* dim;
  369. OCVERIFY(OCnode*,dim,node0);
  370. OCDEREF(OCnode*,dim,node0);
  371. if(dim->octype != OC_Dimension) return OC_EINVAL;
  372. if(sizep) *sizep = dim->dim.declsize;
  373. if(namep) *namep = nulldup(dim->name);
  374. return OC_NOERR;
  375. }
  376. /* Obtain info about the ith attribute attached to a given DDS node*/
  377. /* This procedure returns the value as the original DAS string */
  378. OCerror
  379. oc_inq_attrstrings(OCconnection conn, OCobject node0, unsigned int i,
  380. char** namep, OCtype* octypep,
  381. unsigned int* nvaluesp, char*** stringsp)
  382. {
  383. OCnode* node;
  384. OCattribute* attr;
  385. unsigned int nattrs;
  386. OCVERIFY(OCnode*,node,node0);
  387. OCDEREF(OCnode*,node,node0);
  388. nattrs = oclistlength(node->attributes);
  389. if(i >= nattrs) return OC_EINVAL;
  390. attr = (OCattribute*)oclistget(node->attributes,i);
  391. if(namep) *namep = strdup(attr->name);
  392. if(octypep) *octypep = attr->etype;
  393. if(nvaluesp) *nvaluesp = attr->nvalues;
  394. if(stringsp) {
  395. if(attr->nvalues > 0) {
  396. size_t space = attr->nvalues * sizeof(char*);
  397. char** strings = ocmalloc(space);
  398. for(i=0;i<attr->nvalues;i++)
  399. strings[i] = nulldup(attr->values[i]);
  400. *stringsp = strings;
  401. } else
  402. *stringsp = NULL;
  403. }
  404. return OC_NOERR;
  405. }
  406. /* This procedure returns the value as the default binary value
  407. corresponding to the string value
  408. */
  409. OCerror
  410. oc_inq_attr(OCconnection conn, OCobject node0, unsigned int i,
  411. char** namep, OCtype* octypep, unsigned int* nvaluesp, void** valuesp)
  412. {
  413. OCnode* node;
  414. OCattribute* attr;
  415. unsigned int nattrs;
  416. OCVERIFY(OCnode*,node,node0);
  417. OCDEREF(OCnode*,node,node0);
  418. nattrs = oclistlength(node->attributes);
  419. if(i >= nattrs) return OC_EINVAL;
  420. attr = (OCattribute*)oclistget(node->attributes,i);
  421. if(namep) *namep = strdup(attr->name);
  422. if(octypep) *octypep = attr->etype;
  423. if(nvaluesp) *nvaluesp = attr->nvalues;
  424. if(valuesp && attr->nvalues > 0) {
  425. void* memory = NULL;
  426. memory = oclinearize(attr->etype,attr->nvalues,attr->values);
  427. *valuesp = memory;
  428. }
  429. return OC_NOERR;
  430. }
  431. /* Convenience function */
  432. void
  433. oc_attr_reclaim(OCtype etype, unsigned int nvalues, void* values)
  434. {
  435. if(nvalues == 0 || values == NULL) return;
  436. if(etype == OC_String || etype == OC_URL) {
  437. unsigned int i;
  438. char** strings = (char**)values;
  439. for(i=0;i<nvalues;i++) {ocfree(strings[i]);}
  440. }
  441. ocfree(values);
  442. }
  443. OCerror
  444. oc_inq_dasattr_nvalues(OCconnection conn, OCobject node0,
  445. unsigned int* nvaluesp)
  446. {
  447. OCnode* attr;
  448. OCVERIFY(OCnode*,attr,node0);
  449. OCDEREF(OCnode*,attr,node0);
  450. if(attr->octype != OC_Attribute) return OC_EINVAL;
  451. if(nvaluesp) *nvaluesp = oclistlength(attr->att.values);
  452. return OC_NOERR;
  453. }
  454. OCerror
  455. oc_inq_dasattr(OCconnection conn, OCobject node0, unsigned int i,
  456. OCtype* primtypep, char** valuep)
  457. {
  458. OCnode* attr;
  459. unsigned int nvalues;
  460. OCVERIFY(OCnode*,attr,node0);
  461. OCDEREF(OCnode*,attr,node0);
  462. if(attr->octype != OC_Attribute) return OC_EINVAL;
  463. nvalues = oclistlength(attr->att.values);
  464. if(i >= nvalues) return OC_EINVAL;
  465. if(valuep) *valuep = nulldup((char*)oclistget(attr->att.values,i));
  466. if(primtypep) *primtypep = attr->etype;
  467. return OC_NOERR;
  468. }
  469. /**************************************************/
  470. /* Fetch and parse a given class of DXD the server specified
  471. at open time, and using a specified set of constraints.
  472. Return the root node of the parsed tree of objects.
  473. */
  474. OCerror oc_fetch(OCconnection conn, const char* constraint,
  475. OCdxd dxdkind, OCobject* rootp)
  476. {
  477. return oc_fetchf(conn,constraint,dxdkind,0,rootp);
  478. }
  479. OCerror oc_fetchf(OCconnection conn, const char* constraint,
  480. OCdxd dxdkind, OCflags flags, OCobject* rootp)
  481. {
  482. OCstate* state;
  483. OCerror ocerr = OC_NOERR;
  484. OCnode* root;
  485. OCVERIFY(OCstate*,state,conn);
  486. OCDEREF(OCstate*,state,conn);
  487. ocerr = ocfetchf(state,constraint,dxdkind,flags,&root);
  488. if(ocerr) return ocerr;
  489. ocassignall(root->tree->nodes);
  490. if(rootp) *rootp = (OCobject)ocassign(root);
  491. return ocerr;
  492. }
  493. OCerror
  494. oc_data_root(OCconnection conn, OCobject root0, OCdata content0)
  495. {
  496. OCstate* state;
  497. OCnode* root;
  498. OCcontent* content;
  499. OCerror ocerr = OC_NOERR;
  500. OCVERIFY(OCstate*,state,conn);
  501. OCDEREF(OCstate*,state,conn);
  502. OCVERIFY(OCnode*,root,root0);
  503. OCDEREF(OCnode*,root,root0);
  504. OCVERIFY(OCcontent*,content,content0);
  505. OCDEREF(OCcontent*,content,content0);
  506. if(root->tree == NULL) {OCTHROWCHK((ocerr=OC_EINVAL)); goto fail;}
  507. ocerr = ocrootdata(state,root,content);
  508. fail:
  509. return ocerr;
  510. }
  511. OCdata
  512. oc_data_new(OCconnection conn)
  513. {
  514. OCstate* state;
  515. OCVERIFYX(OCstate*,state,conn,OCNULL);
  516. OCDEREF(OCstate*,state,conn);
  517. return (OCdata)ocassign(ocnewcontent(state));
  518. }
  519. OCerror
  520. oc_data_free(OCconnection conn, OCdata content0)
  521. {
  522. OCstate* state;
  523. OCcontent* content;
  524. if(content0 == OCNULL) return OC_NOERR;
  525. OCVERIFY(OCstate*,state,conn);
  526. OCDEREF(OCstate*,state,conn);
  527. OCVERIFY(OCcontent*,content,content0);
  528. OCDEREF(OCcontent*,content,content0);
  529. ocfreecontent(state,content);
  530. return OC_NOERR;
  531. }
  532. OCerror
  533. oc_data_ith(OCconnection conn, OCdata parentdata, size_t index, OCdata subdata)
  534. {
  535. OCstate* state;
  536. OCcontent* parent;
  537. OCcontent* child;
  538. OCerror ocerr = OC_NOERR;
  539. OCVERIFY(OCstate*,state,conn);
  540. OCDEREF(OCstate*,state,conn);
  541. OCVERIFY(OCcontent*,parent,parentdata);
  542. OCDEREF(OCcontent*,parent,parentdata);
  543. OCVERIFY(OCcontent*,child,subdata);
  544. OCDEREF(OCcontent*,child,subdata);
  545. ocerr = ocdataith(state,parent,index,child);
  546. return ocerr;
  547. }
  548. OCerror
  549. oc_data_get(OCconnection conn, OCdata currentcontent,
  550. void* memory, size_t memsize, size_t start, size_t count)
  551. {
  552. OCstate* state;
  553. OCcontent* current;
  554. OCerror ocerr = OC_NOERR;
  555. OCVERIFY(OCstate*,state,conn);
  556. OCDEREF(OCstate*,state,conn);
  557. OCVERIFY(OCcontent*,current,currentcontent);
  558. OCDEREF(OCcontent*,current,currentcontent);
  559. ocerr = ocgetcontent(state,current,memory,memsize,start,count);
  560. if(ocerr == OC_EDATADDS) ocdataddsmsg(state,current->tree);
  561. return ocerr;
  562. }
  563. OCerror
  564. oc_data_count(OCconnection conn, OCdata content0, size_t* sizep)
  565. {
  566. OCstate* state;
  567. OCcontent* current;
  568. OCerror ocerr = OC_NOERR;
  569. OCVERIFY(OCstate*,state,conn);
  570. OCDEREF(OCstate*,state,conn);
  571. OCVERIFY(OCcontent*,current,content0);
  572. OCDEREF(OCcontent*,current,content0);
  573. ocerr = ocdatacount(state, current, sizep);
  574. return ocerr;
  575. }
  576. OCerror
  577. oc_data_index(OCconnection conn, OCdata content0, size_t* sizep)
  578. {
  579. OCcontent* current;
  580. OCerror ocerr = OC_NOERR;
  581. OCVERIFY(OCcontent*,current,content0);
  582. OCDEREF(OCcontent*,current,content0);
  583. if(sizep)
  584. *sizep = (current->cache.valid ? current->cache.index : 0);
  585. return ocerr;
  586. }
  587. OCerror
  588. oc_data_object(OCconnection conn, OCdata content0, OCobject* op)
  589. {
  590. OCcontent* current;
  591. OCerror ocerr = OC_NOERR;
  592. OCVERIFY(OCcontent*,current,content0);
  593. OCDEREF(OCcontent*,current,content0);
  594. if(op) *op = (OCobject)current->node;
  595. return ocerr;
  596. }
  597. OCerror
  598. oc_data_mode(OCconnection conn, OCdata content0, OCmode* modep)
  599. {
  600. OCcontent* current;
  601. OCerror ocerr = OC_NOERR;
  602. OCVERIFY(OCcontent*,current,content0);
  603. OCDEREF(OCcontent*,current,content0);
  604. if(modep) *modep = current->mode;
  605. return ocerr;
  606. }
  607. /**************************************************/
  608. /* OCtype management */
  609. size_t oc_typesize(OCtype etype)
  610. {
  611. return octypesize(etype);
  612. }
  613. const char*
  614. oc_typetostring(OCtype octype)
  615. {
  616. return octypetoddsstring(octype);
  617. }
  618. OCerror
  619. oc_typeprint(OCtype etype, char* buf, size_t bufsize, void* value)
  620. {
  621. return octypeprint(etype,buf,bufsize,value);
  622. }
  623. /**************************************************/
  624. /* The oc_logXXX procedures are define in oclog.c */
  625. /**************************************************/
  626. /* Miscellaneous */
  627. const char*
  628. oc_errstring(int err)
  629. {
  630. return ocerrstring(err);
  631. }
  632. /* Get clientparameters from the URL */
  633. const char*
  634. oc_clientparam_get(OCconnection conn, const char* param)
  635. {
  636. OCstate* state;
  637. OCVERIFYX(OCstate*,state,conn,NULL);
  638. OCDEREF(OCstate*,state,conn);
  639. return ocparamlookup(state,param);
  640. }
  641. #ifdef OCIGNORE
  642. /* Delete client parameter
  643. return value:
  644. OC_NOERR => defined; deletion performed
  645. OC_EINVAL => not already defined
  646. */
  647. OCerror
  648. oc_clientparam_delete(OCconnection conn, const char* param)
  649. {
  650. OCstate* state;
  651. OCVERIFY(OCstate*,state,conn);
  652. OCDEREF(OCstate*,state,conn);
  653. return ocparamdelete(state->clientparams,param);
  654. }
  655. /* Insert client parameter
  656. return value:
  657. OC_NOERR => not already define; insertion performed
  658. OC_EINVAL => already defined
  659. */
  660. OCerror
  661. oc_clientparam_insert(OCconnection conn, const char* param, const char* value)
  662. {
  663. OCstate* state;
  664. OCVERIFY(OCstate*,state,conn);
  665. OCDEREF(OCstate*,state,conn);
  666. state->clientparams = dapparaminsert(state->clientparams,param,value);
  667. return OC_NOERR;
  668. }
  669. /* Replace client parameter
  670. return value:
  671. OC_NOERR => already define; replacement performed
  672. OC_EINVAL => not already defined
  673. */
  674. OCerror
  675. oc_clientparam_replace(OCconnection conn, const char* param, const char* value)
  676. {
  677. OCstate* state;
  678. OCVERIFY(OCstate*,state,conn);
  679. OCDEREF(OCstate*,state,conn);
  680. return dapparamreplace(state->clientparams,param,value);
  681. }
  682. #endif
  683. OCerror
  684. oc_dd(OCconnection conn, OCobject root0, int level)
  685. {
  686. OCstate* state;
  687. OCnode* root;
  688. OCVERIFY(OCstate*,state,conn);
  689. OCDEREF(OCstate*,state,conn);
  690. OCVERIFY(OCnode*,root,root0);
  691. OCDEREF(OCnode*,root,root0);
  692. ocdd(state,root,1,level);
  693. return OC_NOERR;
  694. }
  695. OCerror
  696. oc_ddnode(OCconnection conn, OCobject root0)
  697. {
  698. OCnode* root;
  699. OCVERIFY(OCnode*,root,root0);
  700. OCDEREF(OCnode*,root,root0);
  701. ocdumpnode(root);
  702. return OC_NOERR;
  703. }
  704. /* Merge a specified DAS into a specified DDS or DATADDS */
  705. OCerror
  706. oc_attach_das(OCconnection conn, OCobject dasroot, OCobject ddsroot)
  707. {
  708. OCstate* state;
  709. OCnode* das;
  710. OCnode* dds;
  711. OCVERIFY(OCstate*,state,conn);
  712. OCDEREF(OCstate*,state,conn);
  713. OCVERIFY(OCnode*,das,dasroot);
  714. OCDEREF(OCnode*,das,dasroot);
  715. OCVERIFY(OCnode*,dds,ddsroot);
  716. OCDEREF(OCnode*,dds,ddsroot);
  717. return ocddsdasmerge(state,das,dds);
  718. }
  719. #if 0
  720. /*
  721. I suppressed this operation because I realized that it
  722. appears to be impossible to implement correctly in general.
  723. It also exposes a flaw in the protocol.
  724. If I have a dds with two identical Grids, G1 and G2,
  725. and I ask for the projection ?G1.temp,G2.temp,
  726. then I get back a DATADDS with duplicated temp fields,
  727. which means the DATADDS is illegal. The problem is that
  728. the protocol throws away important scoping information
  729. about the fact that each temp field is part of a different
  730. grid.
  731. */
  732. /* Connect a specified DATADDS tree to a specified DDS tree */
  733. OCerror
  734. oc_attach_datadds(OCconnection conn, OCobject dataddsroot, OCobject ddsroot)
  735. {
  736. OCstate* state;
  737. OCnode* dxd;
  738. OCnode* dds;
  739. OCVERIFY(OCstate*,state,conn);
  740. OCDEREF(OCstate*,state,conn);
  741. OCVERIFY(OCnode*,dxd,dataddsroot);
  742. OCDEREF(OCnode*,dxd,dataddsroot);
  743. OCVERIFY(OCnode*,dds,ddsroot);
  744. OCDEREF(OCnode*,dds,ddsroot);
  745. /* get the true roots */
  746. dds = dds->root;
  747. dxd = dxd->root;
  748. if(dds == NULL || dxd == NULL) return OC_EBADID;
  749. /* correlate the DATADDS to the DDS */
  750. return occorrelate(dxd,dds);
  751. }
  752. /* Return the attached DATADDS object for a given DDS object */
  753. OCerror oc_inq_datadds(OCconnection conn, OCobject dds0, OCobject* dataddsp)
  754. {
  755. OCstate* state;
  756. OCnode* dds;
  757. OCVERIFY(OCstate*,state,conn);
  758. OCDEREF(OCstate*,state,conn);
  759. OCVERIFY(OCnode*,dds,dds0);
  760. OCDEREF(OCnode*,dds,dds0);
  761. if(dataddsp) *dataddsp = (OCobject)dds->datadds;
  762. return OC_NOERR;
  763. }
  764. #endif
  765. /**************************************************/
  766. OCerror
  767. oc_svcerrordata(OCconnection conn, char** codep,
  768. char** msgp, long* httpp)
  769. {
  770. OCstate* state;
  771. OCVERIFY(OCstate*,state,conn);
  772. OCDEREF(OCstate*,state,conn);
  773. return ocsvcerrordata(state,codep,msgp,httpp);
  774. }
  775. /**************************************************/
  776. /* Experimental: this is useful for the netcdf
  777. DRNO project.
  778. */
  779. /* New 10/31/2009: return the size (in bytes)
  780. of the fetched datadds.
  781. */
  782. OCerror
  783. oc_raw_xdrsize(OCconnection conn, OCobject root0, size_t* sizep)
  784. {
  785. OCnode* root;
  786. OCerror ocerr = OC_NOERR;
  787. OCVERIFY(OCnode*,root,root0);
  788. OCDEREF(OCnode*,root,root0);
  789. if(sizep == NULL) goto done;
  790. if(root->tree == NULL || root->tree->dxdclass != OCDATADDS)
  791. {OCTHROWCHK((ocerr=OC_EINVAL)); goto done;}
  792. if(sizep) *sizep = root->tree->data.datasize;
  793. done:
  794. return ocerr;
  795. }
  796. /* Resend a url as a head request to check the Last-Modified time */
  797. OCerror
  798. oc_update_lastmodified_data(OCconnection conn)
  799. {
  800. OCstate* state;
  801. OCVERIFY(OCstate*,state,conn);
  802. OCDEREF(OCstate*,state,conn);
  803. return ocupdatelastmodifieddata(state);
  804. }
  805. long
  806. oc_get_lastmodified_data(OCconnection conn)
  807. {
  808. OCstate* state;
  809. OCVERIFY(OCstate*,state,conn);
  810. OCDEREF(OCstate*,state,conn);
  811. return state->datalastmodified;
  812. }
  813. int
  814. oc_dumpnode(OCconnection conn, OCobject root0)
  815. {
  816. OCnode* root;
  817. OCerror ocerr = OC_NOERR;
  818. OCVERIFY(OCnode*,root,root0);
  819. OCDEREF(OCnode*,root,root0);
  820. ocdumpnode(root);
  821. return ocerr;
  822. }
  823. OCerror
  824. oc_ping(const char* url)
  825. {
  826. return ocping(url);
  827. }