NeXus  4.4.3
 All Data Structures Files Functions Variables Typedefs Macros Pages
nxxml.c
Go to the documentation of this file.
1 /*
2  * This is the implementation file for the XML file driver
3  * for NeXus
4  *
5  * Copyright (C) 2006 Mark Koennecke
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  * For further information, see <http://www.nexusformat.org>
22  */
23 
24 #include <nxconfig.h>
25 
26 #ifdef WITH_MXML
27 
28 #include <stdio.h>
29 #include <assert.h>
30 #include <stdint.h>
31 #include <mxml.h>
32 #include <napi.h>
33 #include <napi_internal.h>
34 #include <nxxml.h>
35 #include "nxio.h"
36 #include "nxdataset.h"
37 
38 #ifdef _MSC_VER
39 #define snprintf _snprintf
40 #endif /* _MSC_VER */
41 
42 extern void *NXpData;
43 extern int validNXName(const char* name, int allow_colon); /* from napi.c */
44 char *nxitrim(char *str); /* from napi.c */
45 
46 /*----------------------- our data structures --------------------------
47  One might wonder why a node stack is still needed even if this API
48  operates on top of a tree API. The reason for this are the links.
49  Following a link on any NXopenpath, data means a jump through the
50  whole tree. In order to correctly return from such adventures,
51  a stack is needed. Moreover we need it in order to keep track of the
52  state of search operations.
53 
54  The true NXroot node is always at stack[0]. The root in the data
55  structure is the ?xml element. The latter one is needed to store
56  the tree.
57 -----------------------------------------------------------------------*/
58 typedef struct {
59  mxml_node_t *current;
60  mxml_node_t *currentChild;
61  int currentAttribute;
62  int options;
63 }xmlStack;
64 
65 /*
66  * Freddie Akeroyd, 19/03/2008
67  *
68  * Add in support for table style data writing - this is
69  * indicated internally via the XMLSTACK_OPTION_TABLE flag
70  * and separates the dimensions and data into separate nodes contained
71  * in DIMS_NODE_NAME and DATA_NODE_NAME. This is a first commit and
72  * involves some code duplication that will need to be cleaned up later.
73  * Also writing in table style is only enabled for 1D arrays as
74  * I haven't done slab writing yet which the nexus test program uses
75  * for writing 2D arrays.
76  *
77  * Table output is enabled by opening a file with (NXACC_CREATEXML | NXACC_TABLE)
78  *
79  * See http://trac.nexusformat.org/code/ticket/111 for further details
80  */
81 #define XMLSTACK_OPTION_TABLE 0x1
84 /*---------------------------------------------------------------------*/
85 typedef struct {
86  mxml_node_t *root; /* root node */
87  int readOnly; /* read only flag */
88  int tableStyle;
89  int stackPointer; /* stack pointer */
90  char filename[1024]; /* file name, for NXflush, NXclose */
91  xmlStack stack[NXMAXSTACK]; /* stack */
92 }XMLNexus, *pXMLNexus;
93 /*===================== support functions ===============================*/
94 extern char *stptok(char *s, char *tok, size_t toklen, char *brk);
95 /*----------------------------------------------------------------------*/
96 static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target){
97  mxml_node_t *node = NULL;
98  mxml_node_t *testNode = NULL;
99  char path[132], *pPtr;
100 
101  pPtr = (char *)target + 1;
102  node = xmlHandle->stack[0].current;
103  while((pPtr = stptok(pPtr,path,131,"/")) != NULL){
104  /*
105  search for group node
106  */
107  testNode = mxmlFindElement(node,node,NULL,"name",path,MXML_DESCEND_FIRST);
108  if(testNode == NULL){
109  /*
110  it can still be a data node
111  */
112  testNode = mxmlFindElement(node,node,path,NULL,NULL,MXML_DESCEND_FIRST);
113  }
114  if(testNode == NULL){
115  NXReportError("Cannot follow broken link");
116  return NULL;
117  } else {
118  node = testNode;
119  }
120  }
121  return node;
122 }
123 /*==================== file functions ===================================*/
124 static void errorCallbackForMxml(const char *txt){
125  NXReportError((char *)txt);
126 }
127 /*-----------------------------------------------------------------------*/
128 NXstatus NXXopen(CONSTCHAR *filename, NXaccess am,
129  NXhandle* pHandle) {
130  pXMLNexus xmlHandle = NULL;
131  FILE *fp = NULL;
132  char *time_buffer = NULL;
133  mxml_node_t *current;
134 
135  /*
136  allocate data
137  */
138  xmlHandle = (pXMLNexus)malloc(sizeof(XMLNexus));
139  if(!xmlHandle){
140  NXReportError( "Out of memory allocating XML file handle");
141  return NX_ERROR;
142  }
143  memset(xmlHandle,0,sizeof(XMLNexus));
144 
145  /*
146  initialize mxml XML parser
147  */
148  mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback);
150  mxmlSetErrorCallback(errorCallbackForMxml);
151 
152  xmlHandle->tableStyle = ((am & NXACC_TABLE) ? 1 : 0);
153  /*
154  open file
155  */
156  strncpy(xmlHandle->filename,filename,1023);
157  switch(am & NXACCMASK_REMOVEFLAGS){
158  case NXACC_READ:
159  xmlHandle->readOnly = 1;
160  case NXACC_RDWR:
161  fp = fopen(filename,"r");
162  if(fp == NULL){
163  NXReportError("Failed to open file:");
164  NXReportError((char *)filename);
165  free(xmlHandle);
166  return NX_ERROR;
167  }
168  xmlHandle->root = mxmlLoadFile(NULL,fp,nexusTypeCallback);
169  xmlHandle->stack[0].current = mxmlFindElement(xmlHandle->root,
170  xmlHandle->root,
171  "NXroot",
172  NULL,NULL,
173  MXML_DESCEND);
174  xmlHandle->stack[0].currentChild = NULL;
175  xmlHandle->stack[0].currentAttribute = 0;
176  xmlHandle->stack[0].options = 0;
177  fclose(fp);
178  break;
179  case NXACC_CREATEXML:
180  xmlHandle->root = mxmlNewElement(NULL,
181  "?xml version=\"1.0\" encoding=\"UTF-8\"?");
182  current = mxmlNewElement(xmlHandle->root,"NXroot");
183  mxmlElementSetAttr(current,"NeXus_version",NEXUS_VERSION);
184  mxmlElementSetAttr(current,"XML_version","mxml");
185  mxmlElementSetAttr(current,"NX_class","NXroot");
186  mxmlElementSetAttr(current,"file_name",filename);
187  mxmlElementSetAttr(current,"xmlns", NEXUS_SCHEMA_NAMESPACE);
188  mxmlElementSetAttr(current,"xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
189  mxmlElementSetAttr(current,"xsi:schemaLocation",
190  NEXUS_SCHEMA_NAMESPACE " " NEXUS_SCHEMA_URL);
191  time_buffer = NXIformatNeXusTime();
192  if(time_buffer != NULL){
193  mxmlElementSetAttr(current,"file_time",time_buffer);
194  free(time_buffer);
195  }
196  xmlHandle->stack[0].current = current;
197  xmlHandle->stack[0].currentChild = NULL;
198  xmlHandle->stack[0].currentAttribute = 0;
199  xmlHandle->stack[0].options = 0;
200  break;
201  default:
202  NXReportError("Bad access parameter specified in NXXopen");
203  return NX_ERROR;
204  }
205  if(xmlHandle->stack[0].current == NULL){
207  "No NXroot element in XML-file, no NeXus-XML file");
208  return NX_ERROR;
209  }
210 
211  *pHandle = xmlHandle;
212  return NX_OK;
213 }
214 /*----------------------------------------------------------------------*/
215 NXstatus NXXclose (NXhandle* fid){
216  pXMLNexus xmlHandle = NULL;
217  FILE *fp = NULL;
218 
219  xmlHandle = (pXMLNexus)*fid;
220  assert(xmlHandle);
221 
222  if(xmlHandle->readOnly == 0) {
223  fp = fopen(xmlHandle->filename,"w");
224  if(fp == NULL){
225  NXReportError("Failed to open NeXus XML file for writing");
226  return NX_ERROR;
227  }
228  mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback);
229  fclose(fp);
230  }
231  mxmlDelete(xmlHandle->root);
232  free(xmlHandle);
233  *fid = NULL;
234  return NX_OK;
235 }
236 /*----------------------------------------------------------------------*/
237 NXstatus NXXflush(NXhandle *fid){
238  pXMLNexus xmlHandle = NULL;
239  FILE *fp = NULL;
240 
241  xmlHandle = (pXMLNexus)*fid;
242  assert(xmlHandle);
243 
244  if(xmlHandle->readOnly == 0) {
245  fp = fopen(xmlHandle->filename,"w");
246  if(fp == NULL){
247  NXReportError("Failed to open NeXus XML file for writing");
248  return NX_ERROR;
249  }
250  mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback);
251  fclose(fp);
252  }
253  return NX_OK;
254 }
255 /*=======================================================================
256  Group functions
257 =========================================================================*/
258 NXstatus NXXmakegroup (NXhandle fid, CONSTCHAR *name,
259  CONSTCHAR *nxclass){
260  char buffer[256];
261  pXMLNexus xmlHandle = NULL;
262  mxml_node_t *newGroup = NULL;
263 
264  xmlHandle = (pXMLNexus)fid;
265  assert(xmlHandle);
266 
267  if (!validNXName(name, 0))
268  {
269  sprintf(buffer, "ERROR: invalid characters in group name \"%s\"", name);
270  NXReportError(buffer);
271  return NX_ERROR;
272  }
273  if ( strlen(nxclass) == 0 ) /* xml node must have a name */
274  {
275  nxclass = "NXcollection";
276  }
277 
278  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
279  NXReportError("Close dataset before trying to create a group");
280  return NX_ERROR;
281  }
282 
283  newGroup = mxmlNewElement(xmlHandle->stack[xmlHandle->stackPointer].current,
284  nxclass);
285  if(!newGroup){
286  NXReportError("failed to allocate new group");
287  return NX_ERROR;
288  }
289  mxmlElementSetAttr(newGroup,"name",name);
290  return NX_OK;
291 }
292 /*----------------------------------------------------------------------*/
293 static mxml_node_t *searchGroupLinks(pXMLNexus xmlHandle, CONSTCHAR *name,
294  CONSTCHAR *nxclass){
295  mxml_node_t *linkNode = NULL;
296  mxml_node_t *current;
297  mxml_node_t *test = NULL;
298  const char *linkTarget;
299  const char *linkName = NULL;
300 
301  current = xmlHandle->stack[xmlHandle->stackPointer].current;
302  linkNode = current;
303  while((linkNode = mxmlFindElement(linkNode,current,"NAPIlink",NULL,NULL,
304  MXML_DESCEND_FIRST)) != NULL){
305  linkTarget = mxmlElementGetAttr(linkNode,"target");
306  test = getLinkTarget(xmlHandle,linkTarget);
307  if(test != NULL){
308  if(strcmp(test->value.element.name,nxclass) == 0){
309  if(strcmp(mxmlElementGetAttr(test,"name"),name) == 0){
310  return test;
311  }
312  }
313  }
314  /*
315  test for named links
316  */
317  linkName = mxmlElementGetAttr(linkNode,"name");
318  if(test != NULL && linkName != NULL){
319  if(strcmp(test->value.element.name,nxclass) == 0){
320  if(strcmp(linkName, name) == 0){
321  return test;
322  }
323  }
324  }
325  }
326  return NULL;
327 }
328 /*------------------------------------------------------------------------*/
329 NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name,
330  CONSTCHAR *nxclass){
331  pXMLNexus xmlHandle = NULL;
332  mxml_node_t *newGroup = NULL;
333  char error[1024];
334 
335  xmlHandle = (pXMLNexus)fid;
336  assert(xmlHandle);
337 
338  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
339  NXReportError("Close dataset before trying to open a group");
340  return NX_ERROR;
341  }
342  if ( strlen(nxclass) == 0 ) /* xml node must have a name */
343  {
344  nxclass = "NXcollection";
345  }
346  newGroup = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current,
347  xmlHandle->stack[xmlHandle->stackPointer].current,
348  nxclass,
349  "name",
350  name,
351  MXML_DESCEND_FIRST);
352  if(newGroup == NULL){
353  newGroup = searchGroupLinks(xmlHandle,name,nxclass);
354  }
355  if(!newGroup){
356  snprintf(error,1023,"Failed to open %s, %s",name,nxclass);
357  NXReportError(error);
358  return NX_ERROR;
359  }
360  xmlHandle->stackPointer++;
361  xmlHandle->stack[xmlHandle->stackPointer].current = newGroup;
362  xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL;
363  xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0;
364  xmlHandle->stack[xmlHandle->stackPointer].options = 0;
365  return NX_OK;
366 }
367 /*----------------------------------------------------------------------*/
368 NXstatus NXXclosegroup (NXhandle fid){
369  pXMLNexus xmlHandle = NULL;
370 
371  xmlHandle = (pXMLNexus)fid;
372  assert(xmlHandle);
373 
374  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
375  /*
376  silently fix this
377  */
378  NXXclosedata(fid);
379  }
380  if(xmlHandle->stackPointer > 0){
381  xmlHandle->stackPointer--;
382  }
383  return NX_OK;
384 }
385 /*=========================================================================
386  dataset functions
387 =========================================================================*/
388 NXstatus NXXcompmakedata64 (NXhandle fid, CONSTCHAR *name,
389  int datatype,
390  int rank,
391  int64_t dimensions[],
392  int compress_type, int64_t chunk_size[]){
393  /*
394  compression does not relly make sense with XML
395  */
396  return NXXmakedata64(fid,name,datatype,rank,dimensions);
397 }
398 /*-----------------------------------------------------------------------*/
399 static char *buildTypeString(int datatype, int rank, int64_t dimensions[]){
400  char *typestring = NULL;
401  char pNumber[20];
402  int i;
403 
404  /*
405  allocate data
406  */
407  typestring = (char *)malloc(132*sizeof(char));
408  if(!typestring){
409  NXReportError("Failed to allocate typestring");
410  return NULL;
411  }
412  memset(typestring,0,132*sizeof(char));
413 
414  getNumberText(datatype,typestring,130);
415  if(rank > 1 || datatype == NX_CHAR || dimensions[0] > 1) {
416  strcat(typestring,"[");
417  snprintf(pNumber,19,"%lld", (long long)dimensions[0]);
418  strncat(typestring,pNumber,130-strlen(typestring));
419  for(i = 1; i < rank; i++){
420  snprintf(pNumber,19,",%lld", (long long)dimensions[i]);
421  strncat(typestring,pNumber,130-strlen(typestring));
422  }
423  strcat(typestring,"]");
424  }
425  return typestring;
426 }
427 
428 /*------------------------------------------------------------------------*/
429 NXstatus NXXmakedatatable64 (NXhandle fid,
430  CONSTCHAR *name, int datatype,
431  int rank, int64_t dimensions[]){
432  pXMLNexus xmlHandle = NULL;
433  mxml_node_t *dataNode = NULL, *dataNodeRoot = NULL, *dimsNode = NULL, *dimsNodeRoot = NULL;
434  mxml_node_t *newData = NULL;
435  mxml_node_t *current;
436  char *typestring;
437  int i, ndata;
438  char buffer[256];
439  static int64_t one = 1;
440 
441  xmlHandle = (pXMLNexus)fid;
442  assert(xmlHandle);
443  if (!validNXName(name, 0))
444  {
445  sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name);
446  NXReportError(buffer);
447  return NX_ERROR;
448  }
449 
450  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
451  NXReportError("Close dataset before trying to create a dataset");
452  return NX_ERROR;
453  }
454  if(dimensions[0] < 0){
455  dimensions[0] = 1;
456  }
457 
458  current = xmlHandle->stack[xmlHandle->stackPointer].current;
459 
460  dimsNodeRoot = mxmlFindElement(current, current, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST);
461  if (dimsNodeRoot == NULL)
462  {
463  dimsNodeRoot = mxmlNewElement(current, DIMS_NODE_NAME);
464  }
465  dimsNode = mxmlNewElement(dimsNodeRoot, name);
466  mxmlNewOpaque(dimsNode, "");
467  typestring = buildTypeString(datatype,rank,dimensions);
468  if(typestring != NULL){
469  mxmlElementSetAttr(dimsNode,TYPENAME,typestring);
470  free(typestring);
471  } else {
472  NXReportError("Failed to allocate typestring");
473  return NX_ERROR;
474  }
475  ndata = 1;
476  for(i=0; i<rank; i++)
477  {
478  ndata *= dimensions[i];
479  }
480  dataNodeRoot = current;
481  for(i=0; i<ndata; i++)
482  {
483  dataNodeRoot = mxmlFindElement(dataNodeRoot, current, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) );
484  if (dataNodeRoot == NULL)
485  {
486  dataNodeRoot = mxmlNewElement(current, DATA_NODE_NAME);
487  }
488  dataNode = mxmlNewElement(dataNodeRoot,name);
489  newData = (mxml_node_t *)malloc(sizeof(mxml_node_t));
490  if(!newData){
491  NXReportError("Failed to allocate space for dataset");
492  return NX_ERROR;
493  }
494  memset(newData,0,sizeof(mxml_node_t));
495  mxmlAdd(dataNode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, newData);
496  newData->type = MXML_CUSTOM;
497 /* newData->value.custom.data = createNXDataset(rank,datatype,dimensions); */
498  newData->value.custom.data = createNXDataset(1,datatype,&one);
499  if(!newData->value.custom.data){
500  NXReportError("Failed to allocate space for dataset");
501  return NX_ERROR;
502  }
503  newData->value.custom.destroy = destroyDataset;
504  }
505  return NX_OK;
506 }
507 
508 NXstatus NXXmakedata64 (NXhandle fid,
509  CONSTCHAR *name, int datatype,
510  int rank, int64_t dimensions[]){
511  pXMLNexus xmlHandle = NULL;
512  mxml_node_t *dataNode = NULL;
513  mxml_node_t *newData = NULL;
514  mxml_node_t *current;
515  char *typestring;
516  char buffer[256];
517 
518 
519  xmlHandle = (pXMLNexus)fid;
520  assert(xmlHandle);
521  if (!validNXName(name, 0))
522  {
523  sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name);
524  NXReportError(buffer);
525  return NX_ERROR;
526  }
527 
528  if (xmlHandle->tableStyle && datatype != NX_CHAR && dimensions[0] != NX_UNLIMITED && rank == 1)
529  {
530  return NXXmakedatatable64(fid,name,datatype,rank,dimensions);
531  }
532 
533  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
534  NXReportError("Close dataset before trying to create a dataset");
535  return NX_ERROR;
536  }
537  if(dimensions[0] < 0){
538  dimensions[0] = 1;
539  }
540 
541  current = xmlHandle->stack[xmlHandle->stackPointer].current;
542  dataNode = mxmlNewElement(current,name);
543  typestring = buildTypeString(datatype,rank,dimensions);
544  if(typestring != NULL){
545  mxmlElementSetAttr(dataNode,TYPENAME,typestring);
546  free(typestring);
547  } else {
548  NXReportError("Failed to allocate typestring");
549  return NX_ERROR;
550  }
551  /*
552  NX_CHAR maps to MXML_OPAQUE datasets
553  */
554  if(datatype == NX_CHAR){
555  newData = mxmlNewOpaque(dataNode,"");
556  return NX_OK;
557  } else {
558  newData = (mxml_node_t *)malloc(sizeof(mxml_node_t));
559  if(!newData){
560  NXReportError("Failed to allocate space for dataset");
561  return NX_ERROR;
562  }
563  memset(newData,0,sizeof(mxml_node_t));
564  mxmlAdd(dataNode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, newData);
565  newData->type = MXML_CUSTOM;
566  newData->value.custom.data = createNXDataset(rank,datatype,dimensions);
567  if(!newData->value.custom.data){
568  NXReportError("Failed to allocate space for dataset");
569  return NX_ERROR;
570  }
571  newData->value.custom.destroy = destroyDataset;
572  }
573  return NX_OK;
574 }
575 /*----------------------------------------------------------------------*/
576 static mxml_node_t *searchSDSLinks(pXMLNexus xmlHandle, CONSTCHAR *name){
577  mxml_node_t *linkNode = NULL;
578  mxml_node_t *current;
579  mxml_node_t *test = NULL;
580  const char *linkTarget;
581  const char *linkName = NULL;
582 
583  current = xmlHandle->stack[xmlHandle->stackPointer].current;
584  linkNode = current;
585  while((linkNode = mxmlFindElement(linkNode,current,"NAPIlink",NULL,NULL,
586  MXML_DESCEND_FIRST)) != NULL){
587  linkTarget = mxmlElementGetAttr(linkNode,"target");
588  test = getLinkTarget(xmlHandle,linkTarget);
589  if(test != NULL){
590  if(strcmp(test->value.element.name,name) == 0){
591  return test;
592  }
593  }
594  /*
595  test for named links
596  */
597  linkName = mxmlElementGetAttr(linkNode,"name");
598  if(test != NULL && linkName != NULL){
599  if(strcmp(linkName,name) == 0){
600  return test;
601  }
602  }
603  }
604  return NULL;
605 }
606 /*-----------------------------------------------------------------------*/
607 NXstatus NXXopendatatable (NXhandle fid, CONSTCHAR *name){
608  pXMLNexus xmlHandle = NULL;
609  mxml_node_t *dataNode = NULL, *dimsNode = NULL;
610  char error[1024];
611 
612  xmlHandle = (pXMLNexus)fid;
613  assert(xmlHandle);
614 
615 
616  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
617  /*
618  silently fix this
619  */
620  xmlHandle->stackPointer--;
621  if(xmlHandle->stackPointer < 0){
622  xmlHandle->stackPointer = 0;
623  }
624  }
625 
626  dimsNode = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current,
627  xmlHandle->stack[xmlHandle->stackPointer].current,
629  NULL,
630  NULL,
631  MXML_DESCEND_FIRST);
632 
633  if(!dimsNode){
634  snprintf(error,1023,"Failed to open dataset %s",name);
635  NXReportError(error);
636  return NX_ERROR;
637  }
638 
639  dataNode = mxmlFindElement(dimsNode,
640  dimsNode,
641  name,
642  NULL,
643  NULL,
644  MXML_DESCEND_FIRST);
645  if(dataNode == NULL){
646  dataNode = searchSDSLinks(xmlHandle,name);
647  }
648  if(!dataNode){
649  snprintf(error,1023,"Failed to open dataset %s",name);
650  NXReportError(error);
651  return NX_ERROR;
652  }
653  xmlHandle->stackPointer++;
654  xmlHandle->stack[xmlHandle->stackPointer].current = dataNode;
655  xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL;
656  xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0;
657  xmlHandle->stack[xmlHandle->stackPointer].options = XMLSTACK_OPTION_TABLE;
658  return NX_OK;
659 }
660 
661 
662 NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name){
663  pXMLNexus xmlHandle = NULL;
664  mxml_node_t *dataNode = NULL, *current = NULL;
665  char error[1024];
666 
667  xmlHandle = (pXMLNexus)fid;
668  assert(xmlHandle);
669 
670  /* is this a table style node ? */
671  current = xmlHandle->stack[xmlHandle->stackPointer].current;
672  dataNode = mxmlFindElement(current,
673  current,
675  NULL,
676  NULL,
677  MXML_DESCEND_FIRST);
678  if (dataNode != NULL)
679  {
680  dataNode = mxmlFindElement(dataNode,
681  dataNode,
682  name,
683  NULL,
684  NULL,
685  MXML_DESCEND_FIRST);
686  }
687  if (dataNode != NULL)
688  {
689  return NXXopendatatable(fid, name);
690  }
691 
692  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
693  /*
694  silently fix this
695  */
696  xmlHandle->stackPointer--;
697  if(xmlHandle->stackPointer < 0){
698  xmlHandle->stackPointer = 0;
699  }
700  }
701 
702  dataNode = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current,
703  xmlHandle->stack[xmlHandle->stackPointer].current,
704  name,
705  NULL,
706  NULL,
707  MXML_DESCEND_FIRST);
708  if(dataNode == NULL){
709  dataNode = searchSDSLinks(xmlHandle,name);
710  }
711  if(!dataNode){
712  snprintf(error,1023,"Failed to open dataset %s",name);
713  NXReportError(error);
714  return NX_ERROR;
715  }
716  xmlHandle->stackPointer++;
717  xmlHandle->stack[xmlHandle->stackPointer].current = dataNode;
718  xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL;
719  xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0;
720  xmlHandle->stack[xmlHandle->stackPointer].options = 0;
721  return NX_OK;
722 }
723 /*----------------------------------------------------------------------*/
724 
725 NXstatus NXXclosedata (NXhandle fid){
726  pXMLNexus xmlHandle = NULL;
727 
728  xmlHandle = (pXMLNexus)fid;
729  assert(xmlHandle);
730 
731  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
732  if(xmlHandle->stackPointer > 0){
733  xmlHandle->stackPointer--;
734  }
735  return NX_OK;
736  }
737  return NX_OK;
738 }
739 /*----------------------------------------------------------------------*/
740 static mxml_node_t *findData(mxml_node_t *node){
741  mxml_node_t *baby = node;
742 
743  while( (baby = mxmlWalkNext(baby,node,MXML_DESCEND_FIRST)) != NULL){
744  if(baby->type == MXML_OPAQUE || baby->type == MXML_CUSTOM){
745  return baby;
746  }
747  }
748  return NULL;
749 }
750 
751 /* we only havv to deal with non-character data here */
752 NXstatus NXXputdatatable (NXhandle fid, const void *data){
753  pXMLNexus xmlHandle = NULL;
754  mxml_node_t *userData = NULL;
755  mxml_node_t *current = NULL;
756  mxml_node_t *nodeRoot = NULL;
757  mxml_node_t *dataNodeRoot = NULL;
758  mxml_node_t *dataNode = NULL;
759  const char* name;
760  pNXDS dataset;
761  int i, offset, length;
762  xmlHandle = (pXMLNexus)fid;
763  assert(xmlHandle);
764  /* current points at the Idims node as done in NXXopendatatable */
765  current = xmlHandle->stack[xmlHandle->stackPointer].current;
766  name = current->value.element.name;
767  /* we want to walk all Idata nodes and set name */
768  nodeRoot = current->parent->parent;
769  dataNodeRoot = nodeRoot;
770  offset = 0;
771  for(i=0; dataNodeRoot != NULL; i++)
772  {
773  dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) );
774  if (dataNodeRoot != NULL)
775  {
776  dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST);
777  if (dataNode != NULL)
778  {
779  userData = findData(dataNode);
780  assert(userData != NULL);
781  dataset = (pNXDS)userData->value.custom.data;
782  assert(dataset);
783  length = getNXDatasetByteLength(dataset);
784  memcpy(dataset->u.ptr,(char*)data + offset,length);
785  offset += length;
786  }
787  }
788  }
789  return NX_OK;
790 }
791 
792 /*------------------------------------------------------------------------*/
793 NXstatus NXXputdata (NXhandle fid, const void *data){
794  pXMLNexus xmlHandle = NULL;
795  mxml_node_t *userData = NULL;
796  mxml_node_t *current = NULL;
797  pNXDS dataset;
798  int i, length, type, rank;
799  int64_t dim[NX_MAXRANK];
800  char *pPtr = NULL;
801 
802  xmlHandle = (pXMLNexus)fid;
803  assert(xmlHandle);
804 
805  if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE)
806  {
807  return NXXputdatatable(fid,data);
808  }
809 
810  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
811  NXReportError("No dataset open");
812  return NX_ERROR;
813  }
814 
815  current = xmlHandle->stack[xmlHandle->stackPointer].current;
816  userData = findData(current);
817  assert(userData != NULL);
818  if(userData->type == MXML_OPAQUE){
819  /*
820  Text data. We have to make sure that the text is \0 terminated.
821  Some language bindings do not ensure that this is the case.
822  */
823  if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){
824  length = 1;
825  for(i=0; i<rank; i++)
826  {
827  length *= dim[i];
828  }
829  /* we seem to have trouble reading an empty node back (no userData), so make sure we have at least a single space present even for empty strings */
830  if (length == 0)
831  {
832  mxmlSetOpaque(userData," ");
833  }
834  else
835  {
836  pPtr = (char *)malloc((length+1)*sizeof(char));
837  if(pPtr != NULL){
838  memcpy(pPtr,data,length);
839  pPtr[length] = '\0';
840  mxmlSetOpaque(userData,(const char *)pPtr);
841  free(pPtr);
842  }
843  }
844  }
845  else
846  {
847  NXReportError("Unable to determine size of character dataset");
848  return NX_ERROR;
849  }
850  } else {
851  dataset = (pNXDS)userData->value.custom.data;
852  assert(dataset);
853  length = getNXDatasetByteLength(dataset);
854  memcpy(dataset->u.ptr,data,length);
855  }
856  return NX_OK;
857 }
858 
859 NXstatus NXXgetdatatable (NXhandle fid, void *data){
860  pXMLNexus xmlHandle = NULL;
861  mxml_node_t *userData = NULL;
862  mxml_node_t *current = NULL;
863  mxml_node_t *nodeRoot = NULL;
864  mxml_node_t *dataNodeRoot = NULL;
865  mxml_node_t *dataNode = NULL;
866  const char* name;
867  pNXDS dataset;
868  int i, offset, length;
869  xmlHandle = (pXMLNexus)fid;
870  assert(xmlHandle);
871 
872  /* current points at the Idims node as done in NXXopendatatable */
873  current = xmlHandle->stack[xmlHandle->stackPointer].current;
874  name = current->value.element.name;
875  /* we want to walk all Idata nodes and set name */
876  nodeRoot = current->parent->parent;
877  dataNodeRoot = nodeRoot;
878  offset = 0;
879  for(i=0; dataNodeRoot != NULL; i++)
880  {
881  dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) );
882  if (dataNodeRoot != NULL)
883  {
884  dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST);
885  if (dataNode != NULL)
886  {
887  userData = findData(dataNode);
888  assert(userData != NULL);
889  dataset = (pNXDS)userData->value.custom.data;
890  assert(dataset);
891  length = getNXDatasetByteLength(dataset);
892  memcpy((char*)data + offset, dataset->u.ptr, length);
893  offset += length;
894  }
895  }
896  }
897  return NX_OK;
898 }
899 
900 
901 /*------------------------------------------------------------------------*/
902 NXstatus NXXgetdata (NXhandle fid, void *data){
903  pXMLNexus xmlHandle = NULL;
904  mxml_node_t *userData = NULL;
905  mxml_node_t *current = NULL;
906  pNXDS dataset;
907  int i, length, type, rank;
908  int64_t dim[NX_MAXRANK];
909 
910  xmlHandle = (pXMLNexus)fid;
911  assert(xmlHandle);
912 
913  if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE)
914  {
915  return NXXgetdatatable(fid,data);
916  }
917 
918  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
919  NXReportError("No dataset open");
920  return NX_ERROR;
921  }
922 
923  current = xmlHandle->stack[xmlHandle->stackPointer].current;
924  userData = findData(current);
925  assert(userData != NULL);
926  if(userData->type == MXML_OPAQUE){
927  /*
928  text data
929  */
930  if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){
931  length = 1;
932  for(i=0; i<rank; i++)
933  {
934  length *= dim[i];
935  }
936  strncpy((char *)data,userData->value.opaque,length);
937  } else {
938  strcpy((char *)data,nxitrim(userData->value.opaque));
939  }
940 
941  } else {
942  dataset = (pNXDS)userData->value.custom.data;
943  assert(dataset);
944  length = getNXDatasetByteLength(dataset);
945  memcpy(data,dataset->u.ptr,length);
946  }
947  return NX_OK;
948 }
949 /*------------------------------------------------------------------------*/
950 NXstatus NXXgetinfo64 (NXhandle fid, int *rank,
951  int64_t dimension[], int *iType){
952  pXMLNexus xmlHandle = NULL;
953  mxml_node_t *userData = NULL;
954  mxml_node_t *current = NULL;
955  pNXDS dataset;
956  int myRank, i;
957  const char *attr = NULL;
958 
959  xmlHandle = (pXMLNexus)fid;
960  assert(xmlHandle);
961 
962  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
963  NXReportError("No dataset open");
964  return NX_ERROR;
965  }
966 
967  current = xmlHandle->stack[xmlHandle->stackPointer].current;
968  userData = findData(current);
969  assert(userData != NULL);
970  if(userData->type == MXML_OPAQUE){
971  /*
972  text data
973  */
974  attr = mxmlElementGetAttr(current, TYPENAME);
975  if(attr == NULL){
976  *rank = 1;
977  *iType = NX_CHAR;
978  dimension[0]= strlen(userData->value.opaque);
979  } else {
980  *iType = translateTypeCode(attr, "");
981  analyzeDim(attr,rank,dimension,iType);
982  if (dimension[0] == -1) /* 1D strings are NX_CHAR not NX_CHAR[] so length will not be correct */
983  {
984  dimension[0] = strlen(userData->value.opaque);
985  }
986 
987  }
988  } else {
989  dataset = (pNXDS)userData->value.custom.data;
990  assert(dataset);
991  myRank = getNXDatasetRank(dataset);
992  *rank = myRank;
993  *iType = getNXDatasetType(dataset);
994  for(i = 0; i < myRank; i++){
995  dimension[i] = getNXDatasetDim(dataset,i);
996  }
997  }
998  return NX_OK;
999 }
1000 /*---------------------------------------------------------------------
1001  clone the dataset and set the data pointer. This in order to use
1002  the addressing and type conversion implemented in nxdataset
1003 ---------------------------------------------------------------------*/
1004 static pNXDS makeSlabData(pNXDS dataset, const void *data, const int64_t size[]){
1005  pNXDS slabData = NULL;
1006  int rank, i;
1007 
1008  slabData = (pNXDS)malloc(sizeof(NXDS));
1009  if(slabData == NULL){
1010  return NULL;
1011  }
1012 
1013  rank = getNXDatasetRank(dataset);
1014  slabData->rank = rank;
1015  slabData->dim = (int64_t *)malloc(rank*sizeof(int64_t));
1016  for(i = 0; i < rank; i++){
1017  slabData->dim[i] = size[i];
1018  }
1019  slabData->type = getNXDatasetType(dataset);
1020  slabData->u.ptr = (void*)data;
1021  slabData->magic = dataset->magic;
1022  return slabData;
1023 }
1024 /*--------------------------------------------------------------------
1025  This goes by recursion
1026 ----------------------------------------------------------------------*/
1027 static void putSlabData(pNXDS dataset, pNXDS slabData, int dim,
1028  const int64_t start[],
1029  int64_t sourcePos[], int64_t targetPos[]){
1030  int64_t i, rank, length;
1031 
1032  rank = getNXDatasetRank(slabData);
1033  length = getNXDatasetDim(slabData,dim);
1034  if(dim != rank-1){
1035  for(i = 0; i < length; i++){
1036  targetPos[dim] = start[dim] +i;
1037  sourcePos[dim] = i;
1038  putSlabData(dataset,slabData, dim+1,start,
1039  sourcePos,targetPos);
1040  }
1041  } else {
1042  for(i = 0; i < length; i++){
1043  targetPos[dim] = start[dim] +i;
1044  sourcePos[dim] = i;
1045  putNXDatasetValue(dataset,targetPos,
1046  getNXDatasetValue(slabData,sourcePos));
1047  }
1048  }
1049 }
1050 /*----------------------------------------------------------------------
1051  This is in order to support unlimited dimensions along the first axis
1052  -----------------------------------------------------------------------*/
1053 static int checkAndExtendDataset(mxml_node_t *node, pNXDS dataset,
1054  const int64_t start[], const int64_t size[]){
1055  int64_t dim0, byteLength;
1056  void *oldData = NULL;
1057  char *typestring = NULL;
1058 
1059  dim0 = start[0] + size[0];
1060  if(dim0 > dataset->dim[0]){
1061  byteLength = getNXDatasetByteLength(dataset);
1062  oldData = dataset->u.ptr;
1063  dataset->dim[0] = dim0;
1064  dataset->u.ptr = malloc(getNXDatasetByteLength(dataset));
1065  if(dataset->u.ptr == NULL){
1066  return 0;
1067  }
1068  memset(dataset->u.ptr,0,getNXDatasetByteLength(dataset));
1069  memcpy(dataset->u.ptr,oldData,byteLength);
1070  free(oldData);
1071  typestring = buildTypeString(dataset->type,dataset->rank,dataset->dim);
1072  if(typestring != NULL){
1073  mxmlElementSetAttr(node,TYPENAME,typestring);
1074  free(typestring);
1075  } else {
1076  NXReportError("Failed to allocate typestring");
1077  return 0;
1078  }
1079  }
1080  return 1;
1081 }
1082 
1083 NXstatus NXXputslabtable (NXhandle fid, const void *data,
1084  const int64_t iStart[], const int64_t iSize[]){
1085  return NX_OK;
1086 }
1087 /*----------------------------------------------------------------------*/
1088 NXstatus NXXputslab64 (NXhandle fid, const void *data,
1089  const int64_t iStart[], const int64_t iSize[]){
1090 
1091  pXMLNexus xmlHandle = NULL;
1092  mxml_node_t *userData = NULL;
1093  mxml_node_t *current = NULL;
1094  pNXDS dataset, slabData;
1095  int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK];
1096  int status;
1097 
1098  xmlHandle = (pXMLNexus)fid;
1099  assert(xmlHandle);
1100 
1101  if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE)
1102  {
1103  return NXXputslabtable(fid,data,iStart,iSize);
1104  }
1105 
1106  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1107  NXReportError("No dataset open");
1108  return NX_ERROR;
1109  }
1110 
1111  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1112  userData = findData(current);
1113  assert(userData != NULL);
1114  if(userData->type == MXML_OPAQUE){
1115  NXReportError("This API does not support slabs on text data");
1116  return NX_ERROR;
1117  }
1118  dataset = (pNXDS)userData->value.custom.data;
1119  assert(dataset);
1120 
1121  status = checkAndExtendDataset(current,dataset,iStart,iSize);
1122  if(status == 0){
1123  NXReportError("Out of memory extending dataset");
1124  return NX_ERROR;
1125  }
1126 
1127  slabData = makeSlabData(dataset, data, iSize);
1128  if(slabData == NULL){
1129  NXReportError("Failed to allocate slab data");
1130  return NX_ERROR;
1131  }
1132 
1133 
1134  putSlabData(dataset,slabData,0,iStart,sourcePos,targetPos);
1135  free(slabData->dim);
1136  free(slabData);
1137 
1138  return NX_OK;
1139 }
1140 /*--------------------------------------------------------------------
1141  This goes by recursion
1142 ----------------------------------------------------------------------*/
1143 static void getSlabData(pNXDS dataset, pNXDS slabData, int dim,
1144  const int64_t start[],
1145  int64_t sourcePos[],int64_t targetPos[]){
1146  int64_t i, rank, length;
1147 
1148  rank = getNXDatasetRank(slabData);
1149  length = getNXDatasetDim(slabData,dim);
1150  if(dim != rank-1){
1151  for(i = 0; i < length; i++){
1152  sourcePos[dim] = start[dim] +i;
1153  targetPos[dim] = i;
1154  getSlabData(dataset,slabData, dim+1,start,
1155  sourcePos,targetPos);
1156  }
1157  } else {
1158  for(i = 0; i < length; i++){
1159  sourcePos[dim] = start[dim] +i;
1160  targetPos[dim] = i;
1161  putNXDatasetValue(slabData,targetPos,
1162  getNXDatasetValue(dataset,sourcePos));
1163  }
1164  }
1165 }
1166 /*----------------------------------------------------------------------*/
1167 NXstatus NXXgetslab64 (NXhandle fid, void *data,
1168  const int64_t iStart[], const int64_t iSize[]){
1169  pXMLNexus xmlHandle = NULL;
1170  mxml_node_t *userData = NULL;
1171  mxml_node_t *current = NULL;
1172  pNXDS dataset, slabData;
1173  int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK];
1174 
1175  xmlHandle = (pXMLNexus)fid;
1176  assert(xmlHandle);
1177 
1178  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1179  NXReportError("No dataset open");
1180  return NX_ERROR;
1181  }
1182 
1183  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1184  userData = findData(current);
1185  assert(userData != NULL);
1186  if(userData->type == MXML_OPAQUE){
1187  NXReportError("This API does not support slabs on text data");
1188  return NX_ERROR;
1189  }
1190  dataset = (pNXDS)userData->value.custom.data;
1191  assert(dataset);
1192  slabData = makeSlabData(dataset, data, iSize);
1193  if(slabData == NULL){
1194  NXReportError("Failed to allocate slab data");
1195  return NX_ERROR;
1196  }
1197  getSlabData(dataset,slabData,0,iStart,sourcePos,targetPos);
1198  free(slabData->dim);
1199  free(slabData);
1200 
1201  return NX_OK;
1202 }
1203 /*----------------------------------------------------------------------*/
1204 static NXstatus NXXsetnumberformat(NXhandle fid,
1205  int type, char *format){
1206  pXMLNexus xmlHandle = NULL;
1207  mxml_node_t *current = NULL;
1208  mxml_node_t *userData = NULL;
1209  pNXDS dataset;
1210 
1211  xmlHandle = (pXMLNexus)fid;
1212  assert(xmlHandle);
1213 
1214  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1215  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1216  userData = findData(current);
1217  assert(userData != NULL);
1218  if(userData->type == MXML_OPAQUE){
1219  return NX_OK;
1220  }
1221  dataset = (pNXDS)userData->value.custom.data;
1222  assert(dataset);
1223  if(dataset->format != NULL){
1224  free(dataset->format);
1225  }
1226  dataset->format = strdup(format);
1227  } else {
1228  setNumberFormat(type, format);
1229  }
1230  return NX_OK;
1231 }
1232 /*============================ Attributes ============================*/
1233 static char *formatAttributeData(const void *data, int datalen, int iType){
1234  int intData = 0;
1235  long iValue = -99999;
1236  double dValue = -1e38;
1237  char type[20];
1238  char *number;
1239 
1240 
1241  if(iType == NX_CHAR){
1242 /* data may not be NULL terminated */
1243  number = (char*)malloc((datalen+1) * sizeof(char));
1244  memcpy(number, data, datalen * sizeof(char));
1245  number[datalen] = '\0';
1246  return number;
1247  }
1248 
1249  number = (char *)malloc(132*sizeof(char));
1250  if(!number){
1251  NXReportError("Failed to allocate attribute number buffer");
1252  return NULL;
1253  }
1254 
1255  if(datalen > 1){
1256  return NULL;
1257  }
1258  type[0] = '\0';
1259  switch(iType){
1260  case NX_INT32:
1261  iValue = ((int *)data)[0];
1262  intData = 1;
1263  strcpy(type,"NX_INT32:");
1264  break;
1265  case NX_UINT32:
1266  iValue = ((unsigned int *)data)[0];
1267  intData = 1;
1268  strcpy(type,"NX_UINT32:");
1269  break;
1270  case NX_INT16:
1271  iValue = ((short *)data)[0];
1272  intData = 1;
1273  strcpy(type,"NX_INT16:");
1274  break;
1275  case NX_UINT16:
1276  iValue = ((unsigned short *)data)[0];
1277  intData = 1;
1278  strcpy(type,"NX_UINT16:");
1279  break;
1280  case NX_INT8:
1281  iValue = (int)((char *)data)[0];
1282  intData = 1;
1283  strcpy(type,"NX_INT8:");
1284  break;
1285  case NX_UINT8:
1286  intData = 1;
1287  iValue = (int)((unsigned char *)data)[0];
1288  strcpy(type,"NX_UINT8:");
1289  break;
1290  case NX_FLOAT32:
1291  dValue = ((float *)data)[0];
1292  strcpy(type,"NX_FLOAT32:");
1293  intData = 0;
1294  break;
1295  case NX_FLOAT64:
1296  dValue = ((double *)data)[0];
1297  strcpy(type,"NX_FLOAT64:");
1298  intData = 0;
1299  break;
1300  }
1301  if(intData){
1302  snprintf(number,79,"%s%ld",type,iValue);
1303  } else {
1304  snprintf(number,79,"%s%f",type,dValue);
1305  }
1306  return number;
1307 }
1308 /*---------------------------------------------------------------------*/
1309 NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, const void *data,
1310  int datalen, int iType){
1311  char buffer[256];
1312  pXMLNexus xmlHandle = NULL;
1313  mxml_node_t *current = NULL;
1314  char *numberData = NULL;
1315 
1316  xmlHandle = (pXMLNexus)fid;
1317  assert(xmlHandle);
1318  if (!validNXName(name, 1))
1319  {
1320  sprintf(buffer, "ERROR: invalid characters in attribute name \"%s\"", name);
1321  NXReportError(buffer);
1322  return NX_ERROR;
1323  }
1324 
1325  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1326  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1327  if(strcmp(name,TYPENAME) == 0){
1328  NXReportError("type is a reserved attribute name, rejected");
1329  return NX_ERROR;
1330  }
1331  }
1332 
1333  numberData = formatAttributeData(data,datalen,iType);
1334  if(numberData == NULL){
1335  NXReportError("This API does not support non number arrays");
1336  return NX_ERROR;
1337  } else {
1338  mxmlElementSetAttr(current,name,numberData);
1339  free(numberData);
1340  }
1341  return NX_OK;
1342 }
1343 /*--------------------------------------------------------------------------*/
1344 NXstatus NXXgetattr (NXhandle fid, const char *name,
1345  void *data, int* datalen, int* iType){
1346  pXMLNexus xmlHandle = NULL;
1347  mxml_node_t *current = NULL;
1348  const char *attribute = NULL;
1349  char error[1024];
1350  const char *attData = NULL;
1351  int nx_type;
1352 
1353  xmlHandle = (pXMLNexus)fid;
1354  assert(xmlHandle);
1355 
1356  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1357 
1358  attribute = mxmlElementGetAttr(current,name);
1359  if(!attribute){
1360  snprintf(error,1023,"Attribute %s not found", name);
1361  NXReportError(error);
1362  return NX_ERROR;
1363  }
1364  nx_type = translateTypeCode((char *)attribute, ":");
1365  if(nx_type < 0) {
1366  /*
1367  no type code == text attribute
1368  */
1369  nx_type = NX_CHAR;
1370  } else {
1371  /*
1372  We need to find the number after the type code. However, there is
1373  the complication of the datatype type attribute ...
1374  */
1375  if(strcmp(name,TYPENAME) == 0){
1376  nx_type = NX_CHAR;
1377  } else {
1378  attData = strchr(attribute,(int)':');
1379  if(attData == NULL){
1380  snprintf(error,1023,"ERROR: bad attribute string, : missing for attribute \"%s\"", name);
1381  NXReportError(error);
1382  return NX_ERROR;
1383  }
1384  attData++;
1385  }
1386  }
1387  *iType = nx_type;
1388  switch(nx_type){
1389  case NX_CHAR:
1390  /* enforce NULL termination regardless of length of datalen */
1391  strncpy((char *)data, attribute, *datalen-1);
1392  ((char*)data)[*datalen-1] = '\0';
1393  /* *datalen = strlen(attribute); */
1394  *datalen = strlen((char*)data);
1395  *iType = NX_CHAR;
1396  break;
1397  case NX_INT32:
1398  ((int *)data)[0] = atoi(attData);
1399  *datalen = 1;
1400  break;
1401  case NX_UINT32:
1402  ((unsigned int *)data)[0] = atoi(attData);
1403  *datalen = 1;
1404  break;
1405  case NX_INT16:
1406  ((short *)data)[0] = atoi(attData);
1407  *datalen = 1;
1408  break;
1409  case NX_UINT16:
1410  ((unsigned short *)data)[0] = atoi(attData);
1411  *datalen = 1;
1412  break;
1413  case NX_INT8:
1414  ((char *)data)[0] = atoi(attData);
1415  *datalen = 1;
1416  break;
1417  case NX_UINT8:
1418  ((unsigned char *)data)[0] = atoi(attData);
1419  *datalen = 1;
1420  break;
1421  case NX_FLOAT32:
1422  ((float *)data)[0] = atof(attData);
1423  *datalen = 1;
1424  break;
1425  case NX_FLOAT64:
1426  ((double *)data)[0] = atof(attData);
1427  *datalen = 1;
1428  break;
1429  }
1430 
1431  return NX_OK;
1432 }
1433 
1434 /* find the next node, ignoring Idata */
1435 static mxml_node_t* find_node(mxml_node_t* node, int next)
1436 {
1437  int done = 0;
1438  mxml_node_t* parent_next = NULL; /* parent to use if we are in an Idims search */
1439  if (node == NULL)
1440  {
1441  return NULL;
1442  }
1443  if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) )
1444  {
1445  parent_next = node->parent->next;
1446  }
1447  else
1448  {
1449  parent_next = NULL;
1450  }
1451  if (next)
1452  {
1453  if (node->next != NULL)
1454  {
1455  node = node->next;
1456  }
1457  else
1458  {
1459  node = parent_next;
1460  }
1461  }
1462  while(node != NULL && !done)
1463  {
1464  if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) )
1465  {
1466  parent_next = node->parent->next;
1467  }
1468  else
1469  {
1470  parent_next = NULL;
1471  }
1472  if ( (node->type != MXML_ELEMENT) || !strcmp(node->value.element.name, DATA_NODE_NAME) )
1473  {
1474  if (node->next != NULL)
1475  {
1476  node = node->next;
1477  }
1478  else
1479  {
1480  node = parent_next;
1481  }
1482  continue;
1483  }
1484  if (!strcmp(node->value.element.name, DIMS_NODE_NAME))
1485  {
1486  node = node->child;
1487  continue;
1488  }
1489  done = 1;
1490  }
1491  return node;
1492 }
1493 
1494 /*====================== search functions =================================*/
1495 NXstatus NXXgetnextentry (NXhandle fid,NXname name,
1496  NXname nxclass, int *datatype){
1497  pXMLNexus xmlHandle = NULL;
1498  mxml_node_t *next = NULL, *userData, *node = NULL;
1499  int stackPtr;
1500  const char *target = NULL, *attname = NULL;
1501  pNXDS dataset;
1502  char pBueffel[256];
1503  const char *linkName = NULL;
1504 
1505  xmlHandle = (pXMLNexus)fid;
1506  assert(xmlHandle);
1507 
1508  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1509  /*
1510  be nice to user: silently fix this problem
1511  */
1512  NXXclosedata(fid);
1513  }
1514 
1515  stackPtr = xmlHandle->stackPointer;
1516  if(xmlHandle->stack[stackPtr].currentChild == NULL){
1517  /*
1518  initialization of search
1519  */
1520  node = find_node(xmlHandle->stack[stackPtr].current->child, 0);
1521  } else {
1522  /*
1523  proceed
1524  */
1525  node = find_node(xmlHandle->stack[stackPtr].currentChild, 1);
1526  }
1527  xmlHandle->stack[stackPtr].currentChild = node;
1528  next = node;
1529  if(next == NULL){
1530  return NX_EOD;
1531  }
1532  if(strcmp(next->value.element.name,"NAPIlink") == 0){
1533  target = mxmlElementGetAttr(next,"target");
1534  linkName = mxmlElementGetAttr(next,"name");
1535  if(target == NULL){
1536  NXReportError("Corrupted file, NAPIlink without target");
1537  return NX_ERROR;
1538  }
1539  next = getLinkTarget(xmlHandle,target);
1540  if(next == NULL){
1541  NXReportError("Corrupted file, broken link");
1542  return NX_ERROR;
1543  }
1544  }
1545 
1546  if(isDataNode(next)){
1547  strcpy(name,next->value.element.name);
1548  strcpy(nxclass,"SDS");
1549  userData = findData(next);
1550  if(userData == NULL){
1551  snprintf(pBueffel,255,"Corrupted file, userData for %s not found",
1552  name);
1553  NXReportError(pBueffel);
1554  return NX_ERROR;
1555  }
1556  if(userData->type == MXML_OPAQUE){
1557  *datatype = NX_CHAR;
1558  } else {
1559  dataset = (pNXDS)userData->value.custom.data;
1560  assert(dataset);
1561  *datatype = getNXDatasetType(dataset);
1562  }
1563  } else {
1564  strcpy(nxclass,next->value.element.name);
1565  attname = mxmlElementGetAttr(next,"name");
1566  strcpy(name,attname);
1567  }
1568  /*
1569  this is for named links
1570  */
1571  if(linkName != NULL){
1572  strcpy(name,linkName);
1573  }
1574  return NX_OK;
1575 }
1576 /*----------------------------------------------------------------------*/
1577 extern NXstatus NXXinitgroupdir(NXhandle fid){
1578  pXMLNexus xmlHandle = NULL;
1579  int stackPtr;
1580 
1581  xmlHandle = (pXMLNexus)fid;
1582  assert(xmlHandle);
1583 
1584  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1585  NXReportError("Cannot search datasets");
1586  return NX_ERROR;
1587  }
1588 
1589  stackPtr = xmlHandle->stackPointer;
1590  xmlHandle->stack[stackPtr].currentChild = NULL;
1591  return NX_OK;
1592 }
1593 /*-------------------------------------------------------------------------*/
1594 NXstatus NXXgetnextattr (NXhandle fid, NXname pName,
1595  int *iLength, int *iType){
1596  pXMLNexus xmlHandle = NULL;
1597  mxml_node_t *current = NULL;
1598  int stackPtr, currentAtt, nx_type;
1599  char *attVal;
1600 
1601  xmlHandle = (pXMLNexus)fid;
1602  assert(xmlHandle);
1603 
1604  stackPtr = xmlHandle->stackPointer;
1605 
1606  current = xmlHandle->stack[stackPtr].current;
1607  currentAtt = xmlHandle->stack[stackPtr].currentAttribute;
1608  if(currentAtt >=
1609  current->value.element.num_attrs ){
1610  xmlHandle->stack[stackPtr].currentAttribute = 0;
1611  return NX_EOD;
1612  }
1613 
1614  /*
1615  hide group name attribute
1616  */
1617  if(strcmp(current->value.element.attrs[currentAtt].name,"name") == 0
1618  && !isDataNode(current) ){
1619  xmlHandle->stack[stackPtr].currentAttribute++;
1620  return NXXgetnextattr(fid,pName,iLength,iType);
1621  }
1622 
1623  /*
1624  hide type attribute
1625  */
1626  if(strcmp(current->value.element.attrs[currentAtt].name,TYPENAME) == 0
1627  && isDataNode(current)){
1628  xmlHandle->stack[stackPtr].currentAttribute++;
1629  return NXXgetnextattr(fid,pName,iLength,iType);
1630  }
1631 
1632  strcpy(pName,current->value.element.attrs[currentAtt].name);
1633  attVal = current->value.element.attrs[currentAtt].value;
1634  nx_type = translateTypeCode((char *)attVal, ":");
1635  if(nx_type < 0 || strcmp(pName,TYPENAME) == 0){
1636  /*
1637  no type == NX_CHAR
1638  */
1639  *iLength = strlen(attVal);
1640  *iType = NX_CHAR;
1641  } else {
1642  *iLength = 1;
1643  *iType = nx_type;
1644  }
1645 
1646  xmlHandle->stack[stackPtr].currentAttribute++;
1647  return NX_OK;
1648 }
1649 /*-------------------------------------------------------------------------*/
1650 extern NXstatus NXXinitattrdir(NXhandle fid){
1651  pXMLNexus xmlHandle = NULL;
1652  int stackPtr;
1653 
1654  xmlHandle = (pXMLNexus)fid;
1655  assert(xmlHandle);
1656 
1657  stackPtr = xmlHandle->stackPointer;
1658  xmlHandle->stack[stackPtr].currentAttribute = 0;
1659  return NX_OK;
1660 }
1661 /*-------------------------------------------------------------------------*/
1662 NXstatus NXXgetgroupinfo (NXhandle fid, int *iN,
1663  NXname pName, NXname pClass){
1664  pXMLNexus xmlHandle = NULL;
1665  mxml_node_t *node = NULL, *child = NULL;
1666  mxml_node_t *current = NULL;
1667  const char *nameAtt = NULL;
1668  int childCount;
1669 
1670  xmlHandle = (pXMLNexus)fid;
1671  assert(xmlHandle);
1672 
1673  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1674  NXReportError("No group open");
1675  return NX_ERROR;
1676  }
1677  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1678 
1679  nameAtt = mxmlElementGetAttr(current,"name");
1680  if(nameAtt != NULL){
1681  strcpy(pName,nameAtt);
1682  }
1683  strcpy(pClass,current->value.element.name);
1684 
1685 /* count all child nodes, but need to ignore DATA_NODE_NAME and
1686  * descend into DIMS_NODE_NAME
1687  */
1688  childCount = 0;
1689  node = current->child;
1690  while(node != NULL)
1691  {
1692  if (!strcmp(node->value.element.name, DATA_NODE_NAME))
1693  {
1694  ; /* names also exist in DIMS_NODE_NAME so do nothing here */
1695  }
1696  else if (!strcmp(node->value.element.name, DIMS_NODE_NAME))
1697  {
1698  child = node->child;
1699  while(child != NULL)
1700  {
1701  /* not sure why this check is needed, but you double count otherwise */
1702  if (child->type == MXML_ELEMENT)
1703  {
1704  childCount++;
1705  }
1706  child = child->next;
1707  }
1708  }
1709  else
1710  {
1711  childCount++;
1712  }
1713  node = node->next;
1714  }
1715  *iN = childCount;
1716  return NX_OK;
1717 }
1718 /*----------------------------------------------------------------------*/
1719 NXstatus NXXgetattrinfo (NXhandle fid, int *iN){
1720  pXMLNexus xmlHandle = NULL;
1721  mxml_node_t *current = NULL;
1722  int stackPtr, skip;
1723 
1724  xmlHandle = (pXMLNexus)fid;
1725  assert(xmlHandle);
1726 
1727  stackPtr = xmlHandle->stackPointer;
1728 
1729  current = xmlHandle->stack[stackPtr].current;
1730 
1731  /*
1732  hide type and group name attributes
1733  */
1734  skip=0;
1735  if(isDataNode(current)) {
1736  /* data nodes may have type */
1737  if(mxmlElementGetAttr(current,TYPENAME) != NULL) skip=1;
1738  } else {
1739  /* group nodes (except root) have name */
1740  if(mxmlElementGetAttr(current,"name") != NULL) skip=1;
1741  }
1742  *iN = current->value.element.num_attrs - skip;
1743  return NX_OK;
1744 }
1745 /*================= Linking functions =================================*/
1746 static int countPathChars(mxml_node_t *path[], int stackPtr){
1747  int count = 1;
1748  const char *name = NULL;
1749 
1750  while(stackPtr >= 0) {
1751  if(isDataNode(path[stackPtr])){
1752  count += strlen(path[stackPtr]->value.element.name);
1753  } else {
1754  name = mxmlElementGetAttr(path[stackPtr],"name");
1755  if(name != NULL){
1756  count += strlen(name);
1757  }
1758  }
1759  stackPtr--;
1760  count += 1;
1761  }
1762  return count;
1763 }
1764 /*-------------------------------------------------------------------*/
1765 static char *buildPathString(mxml_node_t *path[], int stackPtr){
1766  int count = 0;
1767  const char *name = NULL;
1768  char *pathString = NULL;
1769 
1770  count = countPathChars(path,stackPtr);
1771  pathString = (char *)malloc((count+10)*sizeof(char));
1772  if(pathString == NULL){
1773  return NULL;
1774  }
1775  memset(pathString,0,(count+10)*sizeof(char));
1776 
1777  while(stackPtr >= 0) {
1778  if(isDataNode(path[stackPtr])){
1779  strcat(pathString,"/");
1780  strcat(pathString,path[stackPtr]->value.element.name);
1781  } else {
1782  name = mxmlElementGetAttr(path[stackPtr],"name");
1783  if(name != NULL){
1784  strcat(pathString,"/");
1785  strcat(pathString,name);
1786  }
1787  }
1788  stackPtr--;
1789  }
1790  return pathString;
1791 }
1792 /*--------------------------------------------------------------------*/
1793 static char *findLinkPath(mxml_node_t *node){
1794  mxml_node_t **path = NULL;
1795  int stackPtr;
1796  mxml_node_t *current = NULL;
1797  char *result = NULL;
1798 
1799  path = (mxml_node_t **)malloc(NXMAXSTACK*sizeof(mxml_node_t *));
1800  if(path == NULL){
1801  NXReportError("ERROR: out of memory following link path");
1802  return NULL;
1803  }
1804  memset(path,0,NXMAXSTACK*sizeof(mxml_node_t *));
1805 
1806  /*
1807  first path: walk up the tree untill NXroot is found
1808  */
1809  current = node;
1810  stackPtr = 0;
1811  while(current != NULL &&
1812  strcmp(current->value.element.name,"NXroot") != 0){
1813  path[stackPtr] = current;
1814  stackPtr++;
1815  current = current->parent;
1816  }
1817  stackPtr--;
1818 
1819  /*
1820  path now contains the nodes to the root node in reverse order.
1821  From this build the path string
1822  */
1823  result = buildPathString(path,stackPtr);
1824  free(path);
1825  return result;
1826 }
1827 /*--------------------------------------------------------------------*/
1828 NXstatus NXXgetdataID (NXhandle fid, NXlink* sRes){
1829  pXMLNexus xmlHandle = NULL;
1830  mxml_node_t *current = NULL;
1831  char *linkPath = NULL;
1832 
1833  xmlHandle = (pXMLNexus)fid;
1834  assert(xmlHandle);
1835 
1836  if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1837  return NX_ERROR;
1838  }
1839  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1840 
1841  linkPath = findLinkPath(current);
1842  if(!linkPath){
1843  NXReportError("Failed to allocate link path string");
1844  return NX_ERROR;
1845  }
1846  strncpy(sRes->targetPath,linkPath,1023);
1847  free(linkPath);
1848  return NX_OK;
1849 }
1850 /*--------------------------------------------------------------------*/
1851 NXstatus NXXgetgroupID (NXhandle fid, NXlink* sRes){
1852  pXMLNexus xmlHandle = NULL;
1853  mxml_node_t *current = NULL;
1854  char *linkPath = NULL;
1855 
1856  xmlHandle = (pXMLNexus)fid;
1857  assert(xmlHandle);
1858 
1859  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1860  NXReportError("No group open");
1861  return NX_ERROR;
1862  }
1863  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1864 
1865  if(xmlHandle->stackPointer == 0){
1866  return NX_ERROR;
1867  }
1868 
1869  linkPath = findLinkPath(current);
1870  if(!linkPath){
1871  NXReportError("Failed to allocate link path string");
1872  return NX_ERROR;
1873  }
1874  strncpy(sRes->targetPath,linkPath,1023);
1875  free(linkPath);
1876  return NX_OK;
1877 }
1878 
1879 /*-----------------------------------------------------------------------*/
1880  NXstatus NXXprintlink (NXhandle fid, NXlink* sLink)
1881  {
1882  pXMLNexus xmlHandle = NULL;
1883  xmlHandle = (pXMLNexus)fid;
1884  assert(xmlHandle);
1885 
1886  printf("XML link: target=\"%s\"\n", sLink->targetPath);
1887  return NX_OK;
1888  }
1889 
1890 /*-----------------------------------------------------------------------*/
1891 NXstatus NXXmakelink (NXhandle fid, NXlink* sLink){
1892  pXMLNexus xmlHandle = NULL;
1893  mxml_node_t *current = NULL, *linkNode = NULL;
1894  mxml_node_t *linkedNode = NULL;
1895 
1896  xmlHandle = (pXMLNexus)fid;
1897  assert(xmlHandle);
1898 
1899  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1900  NXReportError("No group to link to open");
1901  return NX_ERROR;
1902  }
1903  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1904  linkNode = mxmlNewElement(current,"NAPIlink");
1905  if(!linkNode){
1906  NXReportError("Failed to allocate new link element");
1907  return NX_ERROR;
1908  }
1909  mxmlElementSetAttr(linkNode,"target",sLink->targetPath);
1910  linkedNode = getLinkTarget(xmlHandle,sLink->targetPath);
1911  if(linkedNode != NULL){
1912  mxmlElementSetAttr(linkedNode,"target",sLink->targetPath);
1913  }
1914  return NX_OK;
1915 }
1916 
1917 /*-----------------------------------------------------------------------*/
1918 NXstatus NXXmakenamedlink (NXhandle fid, CONSTCHAR *name, NXlink* sLink){
1919  pXMLNexus xmlHandle = NULL;
1920  mxml_node_t *current = NULL, *linkNode = NULL;
1921  mxml_node_t *linkedNode = NULL;
1922  char buffer[256];
1923 
1924  xmlHandle = (pXMLNexus)fid;
1925  assert(xmlHandle);
1926  if (!validNXName(name, 0))
1927  {
1928  sprintf(buffer, "ERROR: invalid characters in link name \"%s\"", name);
1929  NXReportError(buffer);
1930  return NX_ERROR;
1931  }
1932 
1933  if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){
1934  NXReportError("No group to link to open");
1935  return NX_ERROR;
1936  }
1937  current = xmlHandle->stack[xmlHandle->stackPointer].current;
1938  linkNode = mxmlNewElement(current,"NAPIlink");
1939  if(!linkNode){
1940  NXReportError("Failed to allocate new link element");
1941  return NX_ERROR;
1942  }
1943  mxmlElementSetAttr(linkNode,"target",sLink->targetPath);
1944  mxmlElementSetAttr(linkNode,"name",name);
1945  linkedNode = getLinkTarget(xmlHandle,sLink->targetPath);
1946  if(linkedNode != NULL){
1947  mxmlElementSetAttr(linkedNode,"target",sLink->targetPath);
1948  }
1949  return NX_OK;
1950 }
1951 /*----------------------------------------------------------------------*/
1952 NXstatus NXXsameID (NXhandle fileid, NXlink* pFirstID,
1953  NXlink* pSecondID){
1954  if(strcmp(pFirstID->targetPath,pSecondID->targetPath) == 0) {
1955  return NX_OK;
1956  } else {
1957  return NX_ERROR;
1958  }
1959 }
1960 
1961 /*--------------------------------------------------------------------*/
1962 
1963 int NXXcompress(NXhandle fid, int comp){
1964  /* that will throw an exception in the Java API, errors have to be fatal */
1965  /* NXReportError("NXcompress is deprecated, IGNORED"); */
1966  return NX_OK;
1967 }
1968 
1969 /*--------------------------------------------------------------------*/
1970 NXstatus NXXputattra(NXhandle handle, CONSTCHAR* name, const void* data, const int rank, const int dim[], const int iType)
1971 {
1972  if (rank > 1) {
1973  NXReportError("This is an XML file, there is only rudimentary support for attribute arrays wirh rank <=1");
1974  return NX_ERROR;
1975  }
1976 
1977  return NXXputattr(handle, name, data, dim[0], iType);
1978 }
1979 
1980 /*--------------------------------------------------------------------*/
1981 NXstatus NXXgetnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
1982 {
1983  NXstatus ret = NXXgetnextattr(handle, pName, dim, iType);
1984  if (ret != NX_OK) return ret;
1985  (*rank) = 1;
1986  if (dim[0] <= 1 ) (*rank) = 0;
1987  return NX_OK;
1988 }
1989 
1990 /*--------------------------------------------------------------------*/
1991 NXstatus NXXgetattra(NXhandle handle, const char* name, void* data)
1992 {
1993  NXReportError("This is an XML file, attribute array API is not supported here");
1994  return NX_ERROR;
1995 }
1996 
1997 /*--------------------------------------------------------------------*/
1998 NXstatus NXXgetattrainfo(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
1999 {
2000  NXReportError("This is an XML file, attribute array API is not supported here");
2001  return NX_ERROR;
2002 }
2003 
2004 /*----------------------------------------------------------------------*/
2005 void NXXassignFunctions(pNexusFunction fHandle){
2006  fHandle->nxclose=NXXclose;
2007  fHandle->nxreopen=NULL;
2008  fHandle->nxflush=NXXflush;
2009  fHandle->nxmakegroup=NXXmakegroup;
2010  fHandle->nxopengroup=NXXopengroup;
2011  fHandle->nxclosegroup=NXXclosegroup;
2012  fHandle->nxmakedata64=NXXmakedata64;
2014  fHandle->nxcompress=NXXcompress;
2015  fHandle->nxopendata=NXXopendata;
2016  fHandle->nxclosedata=NXXclosedata;
2017  fHandle->nxputdata=NXXputdata;
2018  fHandle->nxputattr=NXXputattr;
2019  fHandle->nxputslab64=NXXputslab64;
2020  fHandle->nxgetdataID=NXXgetdataID;
2021  fHandle->nxmakelink=NXXmakelink;
2022  fHandle->nxmakenamedlink=NXXmakenamedlink;
2023  fHandle->nxgetdata=NXXgetdata;
2024  fHandle->nxgetinfo64=NXXgetinfo64;
2026  fHandle->nxgetslab64=NXXgetslab64;
2027  fHandle->nxgetnextattr=NXXgetnextattr;
2028  fHandle->nxgetattr=NXXgetattr;
2029  fHandle->nxgetattrinfo=NXXgetattrinfo;
2030  fHandle->nxgetgroupID=NXXgetgroupID;
2032  fHandle->nxsameID=NXXsameID;
2034  fHandle->nxinitattrdir=NXXinitattrdir;
2035  fHandle->nxsetnumberformat=NXXsetnumberformat;
2036  fHandle->nxprintlink=NXXprintlink;
2037  fHandle->nxnativeexternallink=NULL;
2038  fHandle->nxputattra = NXXputattra;
2039  fHandle->nxgetnextattra = NXXgetnextattra;
2040  fHandle->nxgetattra = NXXgetattra;
2041  fHandle->nxgetattrainfo = NXXgetattrainfo;
2042 }
2043 
2044 #endif /*NXXML*/
NXstatus(* nxgetinfo64)(NXhandle handle, int *rank, int64_t dimension[], int *datatype)
Definition: napi_internal.h:61
NXstatus(* nxgetdataID)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:57
NXstatus(* nxmakedata64)(NXhandle handle, CONSTCHAR *label, int datatype, int rank, int64_t dim[])
Definition: napi_internal.h:48
NXstatus NXXputattra(NXhandle handle, CONSTCHAR *name, const void *data, const int rank, const int dim[], const int iType)
int getNXDatasetRank(pNXDS dataset)
Definition: nxdataset.c:108
int rank
Definition: nxdataset.h:19
NXstatus NXXgetnextentry(NXhandle fid, NXname name, NXname nxclass, int *datatype)
int64_t * dim
Definition: nxdataset.h:21
NXstatus NXXgetnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
NXstatus(* nxinitgroupdir)(NXhandle handle)
Definition: napi_internal.h:73
int getNXDatasetType(pNXDS dataset)
Definition: nxdataset.c:131
NXstatus(* nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType)
Definition: napi_internal.h:64
NXstatus NXXgetslab64(NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[])
pNXDS createNXDataset(int rank, int typecode, int64_t dim[])
Definition: nxdataset.c:36
NXstatus(* nxgetattrinfo)(NXhandle handle, int *no_items)
Definition: napi_internal.h:69
mxml_type_t nexusTypeCallback(mxml_node_t *parent)
NXstatus NXXgetattrinfo(NXhandle fid, int *iN)
NXstatus NXXgetattra(NXhandle handle, const char *name, void *data)
NXstatus NXXputattr(NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType)
NXstatus(* nxgetnextattra)(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi_internal.h:65
void analyzeDim(const char *typeString, int *rank, int64_t *iDim, int *type)
char * nexusWriteCallback(mxml_node_t *node)
NXstatus NXXgetattrainfo(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
void initializeNumberFormats()
int getNXDatasetDim(pNXDS dataset, int which)
Definition: nxdataset.c:118
NXstatus(* nxclose)(NXhandle *pHandle)
Definition: napi_internal.h:43
NXstatus(* nxputattr)(NXhandle handle, CONSTCHAR *name, const void *data, int iDataLen, int iType)
Definition: napi_internal.h:54
NXstatus(* nxcompmakedata64)(NXhandle handle, CONSTCHAR *label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[])
Definition: napi_internal.h:49
#define NX_INT8
Definition: nxdataset.h:41
int isDataNode(mxml_node_t *node)
void setNumberFormat(int dataType, char *formatString)
NXstatus NXXgetgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass)
NXstatus NXXmakelink(NXhandle fid, NXlink *sLink)
char * format
Definition: nxdataset.h:22
NXstatus NXXopengroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass)
NXstatus NXXinitattrdir(NXhandle handle)
NXstatus(* nxgetgroupinfo)(NXhandle handle, int *no_items, NXname name, NXname nxclass)
Definition: napi_internal.h:71
NXstatus NXXprintlink(NXhandle fid, NXlink *sLink)
#define NX_FLOAT64
Definition: nxdataset.h:40
NXstatus(* nxputdata)(NXhandle handle, const void *data)
Definition: napi_internal.h:53
NXstatus NXXmakedata64(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int64_t dimensions[])
NXstatus(* nxgetdata)(NXhandle handle, void *data)
Definition: napi_internal.h:60
NXstatus(* nxprintlink)(NXhandle handle, NXlink *link)
Definition: napi_internal.h:76
void * ptr
Definition: nxdataset.h:24
NXstatus(* nxputslab64)(NXhandle handle, const void *data, const int64_t start[], const int64_t size[])
Definition: napi_internal.h:56
#define NX_UINT8
Definition: nxdataset.h:42
NXstatus(* nxmakegroup)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
Definition: napi_internal.h:45
double getNXDatasetValue(pNXDS dataset, int64_t pos[])
Definition: nxdataset.c:180
NXstatus NXXputdata(NXhandle fid, const void *data)
NXstatus NXXinitgroupdir(NXhandle handle)
NXstatus NXXflush(NXhandle *pHandle)
NXstatus NXXsameID(NXhandle fileid, NXlink *pFirstID, NXlink *pSecondID)
NXstatus(* nxgetattra)(NXhandle handle, const char *name, void *data)
Definition: napi_internal.h:67
#define DATA_NODE_NAME
Definition: nxio.h:33
NXstatus(* nxmakenamedlink)(NXhandle handle, CONSTCHAR *newname, NXlink *pLink)
Definition: napi_internal.h:59
int nexusLoadCallback(mxml_node_t *node, const char *buffer)
#define NX_FLOAT32
Definition: nxdataset.h:39
NXstatus(* nxflush)(NXhandle *pHandle)
Definition: napi_internal.h:44
int magic
Definition: nxdataset.h:18
NXstatus(* nxopengroup)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
Definition: napi_internal.h:46
union pNXDS::@0 u
int getNXDatasetByteLength(pNXDS dataset)
Definition: nxdataset.c:157
NXstatus(* nxmakelink)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:58
NXstatus(* nxcompress)(NXhandle handle, int compr_type)
Definition: napi_internal.h:50
int translateTypeCode(const char *code, const char *term)
void NXXassignFunctions(pNexusFunction fHandle)
NXstatus NXXgetgroupID(NXhandle fid, NXlink *sRes)
NXstatus(* nxopendata)(NXhandle handle, CONSTCHAR *label)
Definition: napi_internal.h:51
NXstatus(* nxgetattrainfo)(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi_internal.h:68
NXstatus(* nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int *datatype)
Definition: napi_internal.h:62
NXstatus NXXclosegroup(NXhandle fid)
NXstatus NXXopendata(NXhandle fid, CONSTCHAR *name)
NXstatus(* nxgetslab64)(NXhandle handle, void *data, const int64_t start[], const int64_t size[])
Definition: napi_internal.h:63
NXstatus NXXcompmakedata64(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int64_t dimensions[], int compress_type, int64_t chunk_size[])
NXstatus NXXgetnextattr(NXhandle handle, NXname pName, int *iLength, int *iType)
NXstatus NXXgetattr(NXhandle fid, const char *name, void *data, int *datalen, int *iType)
NXstatus NXXgetdata(NXhandle fid, void *data)
NXstatus(* nxsameID)(NXhandle handle, NXlink *pFirstID, NXlink *pSecondID)
Definition: napi_internal.h:72
NXstatus NXXclosedata(NXhandle fid)
void getNumberText(int nx_type, char *typestring, int typeLen)
void destroyDataset(void *data)
#define NX_MAXRANK
Definition: nxdataset.h:51
#define TYPENAME
This file contains functions necessary to perform XML-I/O for NeXus with the mxml-library.
Definition: nxio.h:30
NXstatus(* nxputattra)(NXhandle handle, CONSTCHAR *name, const void *data, const int rank, const int dim[], const int iType)
Definition: napi_internal.h:55
NXstatus(* nxreopen)(NXhandle pOrigHandle, NXhandle *pNewHandle)
Definition: napi_internal.h:42
void NXReportError(char *string)
Definition: napi.c:305
NXstatus NXXgetinfo64(NXhandle fid, int *rank, int64_t dimension[], int *iType)
char * nxitrim(char *str)
Definition: napi.c:1206
#define NX_UINT16
Definition: nxdataset.h:44
NXstatus(* nxclosedata)(NXhandle handle)
Definition: napi_internal.h:52
char * stptok(const char *s, char *tok, size_t toklen, char *brk)
Definition: stptok.c:17
NXstatus NXXgetdataID(NXhandle fid, NXlink *sRes)
NXstatus(* nxclosegroup)(NXhandle handle)
Definition: napi_internal.h:47
NXstatus(* nxnativeexternallink)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *externalfile, CONSTCHAR *remotetarget)
Definition: napi_internal.h:77
NXstatus NXXputslab64(NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[])
int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value)
Definition: nxdataset.c:267
NXstatus NXXopen(CONSTCHAR *filename, NXaccess access_method, NXhandle *pHandle)
#define DIMS_NODE_NAME
Definition: nxio.h:32
char * NXIformatNeXusTime()
Definition: napi.c:1973
int validNXName(const char *name, int allow_colon)
valid NeXus names
Definition: napi.c:151
int type
Definition: nxdataset.h:20
#define NX_CHAR
Definition: nxdataset.h:49
NXstatus NXXclose(NXhandle *pHandle)
NXstatus(* nxinitattrdir)(NXhandle handle)
Definition: napi_internal.h:74
#define NX_UINT32
Definition: nxdataset.h:46
const char * NXwhitespaceCallback(mxml_node_t *node, int where)
#define NX_INT32
Definition: nxdataset.h:45
NXstatus(* nxgetattr)(NXhandle handle, const char *name, void *data, int *iDataLen, int *iType)
Definition: napi_internal.h:66
#define NX_INT16
Definition: nxdataset.h:43
NXstatus(* nxsetnumberformat)(NXhandle handle, int type, char *format)
Definition: napi_internal.h:75
NXstatus(* nxgetgroupID)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:70
NXstatus NXXmakegroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass)