NeXus  4.4.3
 All Data Structures Files Functions Variables Typedefs Macros Pages
napi5.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------
2  NeXus - Neutron & X-ray Common Data Format
3 
4  Application Program Interface (HDF5) Routines
5 
6  Copyright (C) 1997-2014 NIAC
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 
22  For further information, see <http://www.nexusformat.org>
23 
24 ----------------------------------------------------------------------------*/
25 
26 #define H5Aiterate_vers 2
27 
28 #include <nxconfig.h>
29 
30 #ifdef WITH_HDF5
31 
32 #include <stdlib.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <time.h>
36 
37 #include "napi.h"
38 #include "napi_internal.h"
39 #include "napi5.h"
40 
41 #ifdef H5_VERSION_GE
42 #if !H5_VERSION_GE(1,8,0)
43 #error HDF5 Version must be 1.8.0 or higher
44 #endif
45 #endif
46 
47 #ifdef _MSC_VER
48 #define snprintf _snprintf
49 #endif /* _MSC_VER */
50 
51 #define NX_UNKNOWN_GROUP "" /* for when no NX_class attr */
52 
53 extern void *NXpData;
54 
55 typedef struct __NexusFile5 {
56  struct iStack5 {
57  char irefn[1024];
58  hid_t iVref;
59  hsize_t iCurrentIDX;
60  } iStack5[NXMAXSTACK];
61  struct iStack5 iAtt5;
62  hid_t iFID;
63  hid_t iCurrentG;
64  hid_t iCurrentD;
65  hid_t iCurrentS;
66  hid_t iCurrentT;
67  hid_t iCurrentA;
68  int iNX;
69  int iNXID;
70  int iStackPtr;
71  char *iCurrentLGG;
72  char *iCurrentLD;
73  char name_ref[1024];
74  char name_tmp[1024];
75  char iAccess[2];
76 } NexusFile5, *pNexusFile5;
77 
78 /* forward declaration of NX5closegroup in order to get rid of a nasty warning */
79 
80 NXstatus NX5closegroup(NXhandle fid);
81 
82 /*-------------------------------------------------------------------*/
83 
84 static pNexusFile5 NXI5assert(NXhandle fid)
85 {
86  pNexusFile5 pRes;
87 
88  assert(fid != NULL);
89  pRes = (pNexusFile5) fid;
90  assert(pRes->iNXID == NX5SIGNATURE);
91  return pRes;
92 }
93 
94 /*--------------------------------------------------------------------*/
95 
96 static void NXI5KillDir(pNexusFile5 self)
97 {
98  self->iStack5[self->iStackPtr].iCurrentIDX = 0;
99 }
100 
101 static herr_t readStringAttribute(hid_t attr, char **data)
102 {
103  herr_t iRet = 0;
104  hid_t atype = -1;
105  hid_t space;
106  int ndims;
107  hsize_t thedims[H5S_MAX_RANK], sdim;
108 
109  atype = H5Aget_type(attr);
110  sdim = H5Tget_size(atype);
111  space = H5Aget_space(attr);
112  ndims = H5Sget_simple_extent_dims(space, thedims, NULL);
113 
114  if (ndims == 0) {
115  if (H5Tis_variable_str(atype)) {
116  hid_t btype = H5Tget_native_type(atype, H5T_DIR_ASCEND);
117  iRet = H5Aread(attr, btype, data);
118  H5Tclose(btype);
119  } else {
120  *data = malloc(sdim+1);
121  iRet = H5Aread(attr, atype, *data);
122  (*data)[sdim] = '\0';
123  }
124  } else if (ndims == 1) {
125  int i;
126  char **strings;
127 
128  strings = (char **) malloc(thedims[0] * sizeof(char*));
129 
130  if (! H5Tis_variable_str(atype)) {
131  strings[0] = (char *) malloc(thedims[0] * sdim * sizeof(char));
132  for(i=1; i<thedims[0]; i++) {
133  strings[i] = strings[0] + i * sdim;
134  }
135  }
136 
137  iRet = H5Aread(attr, atype, strings[0]);
138  *data = calloc((sdim + 2) * thedims[0], sizeof(char));
139  for(i=0; i<thedims[0]; i++) {
140  if (i==0) {
141  strncpy(*data, strings[i], sdim);
142  } else {
143  strcat(*data, ", ");
144  strncat(*data, strings[i], sdim);
145  }
146  }
147  if (H5Tis_variable_str(atype)) {
148  H5Dvlen_reclaim(atype, space, H5P_DEFAULT, strings);
149  } else {
150  free(strings[0]);
151  }
152 
153  free(strings);
154  } else {
155  *data = strdup(" higher dimensional string array");
156  }
157 
158  H5Tclose(atype);
159  H5Sclose(space);
160  if (iRet < 0)
161  return NX_ERROR;
162  return NX_OK;
163 }
164 
165 static herr_t readStringAttributeN(hid_t attr, char *data, int maxlen)
166 {
167  herr_t iRet;
168  char *vdat = NULL;
169  iRet = readStringAttribute(attr, &vdat);
170  if (iRet >= 0) {
171  strncpy(data, vdat, maxlen);
172  free(vdat);
173  }
174  data[maxlen - 1] = '\0';
175  return iRet;
176 }
177 
178 /*--------------------------------------------------------------------*/
179 
180 static void NXI5KillAttDir(pNexusFile5 self)
181 {
182  self->iAtt5.iCurrentIDX = 0;
183 }
184 
185 /*---------------------------------------------------------------------*/
186 static void buildCurrentPath(pNexusFile5 self, char *pathBuffer,
187  int pathBufferLen)
188 {
189 
190  memset(pathBuffer, 0, pathBufferLen);
191  if (self->iCurrentG != 0) {
192  strcpy(pathBuffer, "/");
193  if ((int)strlen(self->name_ref) + 1 < pathBufferLen) {
194  strcat(pathBuffer, self->name_ref);
195  }
196  }
197  if (self->iCurrentD != 0) {
198  strcat(pathBuffer, "/");
199  if ((int)strlen(self->iCurrentLD) + (int)strlen(pathBuffer) <
200  pathBufferLen) {
201  strcat(pathBuffer, self->iCurrentLD);
202  }
203  }
204 }
205 
206  /* ----------------------------------------------------------------------
207 
208  Definition of NeXus API
209 
210  --------------------------------------------------------------------- */
211 
212 NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle * pNewHandle)
213 {
214  pNexusFile5 pNew = NULL, pOrig = NULL;
215  *pNewHandle = NULL;
216  pOrig = (pNexusFile5) pOrigHandle;
217  pNew = (pNexusFile5) malloc(sizeof(NexusFile5));
218  if (!pNew) {
219  NXReportError("ERROR: no memory to create File datastructure");
220  return NX_ERROR;
221  }
222  memset(pNew, 0, sizeof(NexusFile5));
223  pNew->iFID = H5Freopen(pOrig->iFID);
224  if (pNew->iFID <= 0) {
225  NXReportError("cannot clone file");
226  free(pNew);
227  return NX_ERROR;
228  }
229  strcpy(pNew->iAccess, pOrig->iAccess);
230  pNew->iNXID = NX5SIGNATURE;
231  pNew->iStack5[0].iVref = 0; /* root! */
232  *pNewHandle = (NXhandle) pNew;
233  return NX_OK;
234 }
235 
236 
237 /*---------------------------------------------------------------------
238  * private functions used in NX5open
239  */
240 
241 pNexusFile5 create_file_struct()
242 {
243  pNexusFile5 pNew = (pNexusFile5) malloc(sizeof(NexusFile5));
244  if (!pNew) {
246  ("ERROR: not enough memory to create file structure");
247  }
248  else{
249  memset(pNew, 0, sizeof(NexusFile5));
250  }
251 
252  return pNew;
253 }
254 
255 hid_t create_file_access_plist(CONSTCHAR *filename)
256 {
257  char pBuffer[512];
258  hid_t fapl = -1;
259 
260  /* create file access property list - required in all cases*/
261  if((fapl = H5Pcreate(H5P_FILE_ACCESS))<0){
262  sprintf(pBuffer,"Error: failed to create file access property "
263  "list for file %s",filename);
264  NXReportError(pBuffer);
265  return fapl;
266  }
267 
268  /* set file close policy - need this in all cases*/
269  if(H5Pset_fclose_degree(fapl, H5F_CLOSE_STRONG)<0){
270  sprintf(pBuffer,"Error: cannot set close policy for file "
271  "%s",filename);
272  NXReportError(pBuffer);
273  return fapl;
274  }
275 
276  return fapl;
277 }
278 
279 
280 herr_t set_file_cache(hid_t fapl,CONSTCHAR *filename)
281 {
282  char pBuffer[512];
283  int mdc_nelmts;
284  size_t rdcc_nelmts;
285  size_t rdcc_nbytes;
286  double rdcc_w0;
287  herr_t error = -1;
288 
289  error = H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts,
290  &rdcc_nbytes,&rdcc_w0);
291 
292  if(error < 0){
293  sprintf(pBuffer,"Error: cannot obtain HDF5 cache size"
294  " for file %s",filename);
295  NXReportError(pBuffer);
296  return error;
297  }
298 
299  rdcc_nbytes = (size_t) nx_cacheSize;
300  error = H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes,rdcc_w0);
301  if(error < 0){
302  sprintf(pBuffer,"Error: cannot set cache size "
303  "for file %s",filename);
304  NXReportError(pBuffer);
305  return error;
306  }
307  return error;
308 }
309 
310 herr_t set_str_attribute(hid_t parent_id,CONSTCHAR *name,CONSTCHAR *buffer)
311 {
312  char pBuffer[512];
313  hid_t attr_id;
314  hid_t space_id = H5Screate(H5S_SCALAR);
315  hid_t type_id = H5Tcopy(H5T_C_S1);
316 
317  H5Tset_size(type_id, strlen(buffer));
318 
319  attr_id = H5Acreate(parent_id,name,type_id,space_id,H5P_DEFAULT,
320  H5P_DEFAULT);
321  if (attr_id < 0) {
322  sprintf(pBuffer,"ERROR: failed to create %s attribute",name);
323  NXReportError(pBuffer);
324  return -1;
325  }
326 
327  if(H5Awrite(attr_id,type_id,buffer) < 0) {
328  sprintf(pBuffer,"ERROR: failed writting %s attribute");
329  NXReportError(pBuffer);
330  return -1;
331  }
332 
333  H5Tclose(type_id);
334  H5Sclose(space_id);
335  H5Aclose(attr_id);
336 
337  return 0;
338 }
339 
340 NXstatus NX5open(CONSTCHAR * filename, NXaccess am, NXhandle * pHandle)
341 {
342  hid_t root_id;
343  pNexusFile5 pNew = NULL;
344  char pBuffer[512];
345  char *time_buffer = NULL;
346  char version_nr[10];
347  unsigned int vers_major, vers_minor, vers_release, am1;
348  hid_t fapl = -1;
349 
350  *pHandle = NULL;
351 
352  if (H5get_libversion(&vers_major, &vers_minor, &vers_release) < 0) {
353  NXReportError("ERROR: cannot determine HDF5 library version");
354  return NX_ERROR;
355  }
356  if (vers_major == 1 && vers_minor < 8) {
357  NXReportError("ERROR: HDF5 library 1.8.0 or higher required");
358  return NX_ERROR;
359  }
360 
361  /* mask of any options for now */
362  am = (NXaccess) (am & NXACCMASK_REMOVEFLAGS);
363 
364  /* turn off the automatic HDF error handling */
365  H5Eset_auto(H5E_DEFAULT, NULL, NULL);
366 #ifdef USE_FTIME
367  struct timeb timeb_struct;
368 #endif
369 
370  /* create the new file structure */
371  if(!(pNew = create_file_struct())) return NX_ERROR;
372 
373  /* create the file access property list*/
374  if((fapl = create_file_access_plist(filename))<0)
375  {
376  free(pNew);
377  return NX_ERROR;
378  }
379 
380  /* start HDF5 interface */
381  if (am == NXACC_CREATE5) {
382 
383  /* set the cache size for the file */
384  if(set_file_cache(fapl,filename)<0) {
385  free(pNew);
386  return NX_ERROR;
387  }
388 
389  am1 = H5F_ACC_TRUNC;
390  pNew->iFID = H5Fcreate(filename, am1, H5P_DEFAULT, fapl);
391  } else {
392  if (am == NXACC_READ) am1 = H5F_ACC_RDONLY;
393  else am1 = H5F_ACC_RDWR;
394 
395  pNew->iFID = H5Fopen(filename, am1, fapl);
396  }
397 
398  if (fapl != -1) H5Pclose(fapl); /*close file access property list*/
399 
400  if (pNew->iFID <= 0) {
401  snprintf(pBuffer,sizeof(pBuffer)-1, "ERROR: cannot open file: %s", filename);
402  NXReportError(pBuffer);
403  free(pNew);
404  return NX_ERROR;
405  }
406 
407 /*
408  * need to create global attributes file_name file_time NeXus_version
409  * at some point for new files
410  */
411 
412  if(am == NXACC_CREATE5)
413  {
414  root_id = H5Gopen(pNew->iFID,"/",H5P_DEFAULT);
415  if(set_str_attribute(root_id,"NeXus_version",NEXUS_VERSION)<0) {
416  H5Gclose(root_id);
417  H5Fclose(pNew->iFID);
418  free(pNew);
419  return NX_ERROR;
420  }
421 
422  if(set_str_attribute(root_id,"file_name",filename)<0) {
423  H5Gclose(root_id);
424  H5Fclose(pNew->iFID);
425  free(pNew);
426  return NX_ERROR;
427  }
428 
429  sprintf(version_nr,"%d.%d.%d",vers_major,vers_minor,vers_release);
430  if(set_str_attribute(root_id,"HDF5_Version",version_nr)<0) {
431  H5Gclose(root_id);
432  H5Fclose(pNew->iFID);
433  free(pNew);
434  return NX_ERROR;
435  }
436 
437  time_buffer = NXIformatNeXusTime();
438  if (time_buffer != NULL){
439  if(set_str_attribute(root_id,"file_time",time_buffer)<0) {
440  H5Gclose(root_id);
441  H5Fclose(pNew->iFID);
442  free(pNew);
443  free(time_buffer);
444  return NX_ERROR;
445  }
446  free(time_buffer);
447  }
448 
449  /*finally we set the NXroot NX_class attribute*/
450  if(set_str_attribute(root_id,"NX_class","NXroot")<0) {
451  H5Gclose(root_id);
452  H5Fclose(pNew->iFID);
453  free(pNew);
454  return NX_ERROR;
455  }
456 
457  H5Gclose(root_id);
458  }
459 
460  /* Set HDFgroup access mode */
461  if (am1 == H5F_ACC_RDONLY) {
462  strcpy(pNew->iAccess, "r");
463  } else {
464  strcpy(pNew->iAccess, "w");
465  }
466  pNew->iNXID = NX5SIGNATURE;
467  pNew->iStack5[0].iVref = 0; /* root! */
468  *pHandle = (NXhandle) pNew;
469  return NX_OK;
470 }
471 
472  /* ------------------------------------------------------------------------- */
473 
474 NXstatus NX5close(NXhandle * fid)
475 {
476  pNexusFile5 pFile = NULL;
477  herr_t iRet;
478 
479  pFile = NXI5assert(*fid);
480 
481  iRet = 0;
482  /*
483  printf("HDF5 object count before close: %d\n",
484  H5Fget_obj_count(pFile->iFID,H5F_OBJ_ALL));
485  */
486  iRet = H5Fclose(pFile->iFID);
487 
488  /*
489  leave this here: it helps in debugging leakage problems
490  printf("HDF5 object count after close: %d\n",
491  H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ALL));
492  printf("HDF5 dataset count after close: %d\n",
493  H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATASET));
494  printf("HDF5 group count after close: %d\n",
495  H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_GROUP));
496  printf("HDF5 datatype count after close: %d\n",
497  H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATATYPE));
498  printf("HDF5 attribute count after close: %d\n",
499  H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ATTR));
500  */
501 
502  if (iRet < 0) {
503  NXReportError("ERROR: cannot close HDF file");
504  }
505  /* release memory */
506  NXI5KillDir(pFile);
507  if (pFile->iCurrentLGG != NULL) {
508  free(pFile->iCurrentLGG);
509  }
510  if (pFile->iCurrentLD != NULL) {
511  free(pFile->iCurrentLD);
512  }
513  free(pFile);
514  *fid = NULL;
515  H5garbage_collect();
516  return NX_OK;
517 }
518 
519  /*-----------------------------------------------------------------------*/
520 
521 NXstatus NX5makegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass)
522 {
523  pNexusFile5 pFile;
524  hid_t iRet;
525  hid_t iVID;
526  hid_t attr1, aid1, aid2;
527  char pBuffer[1024] = "";
528 
529  pFile = NXI5assert(fid);
530  /* create and configure the group */
531  if (pFile->iCurrentG == 0) {
532  snprintf(pBuffer, 1023, "/%s", name);
533  } else {
534  snprintf(pBuffer, 1023, "/%s/%s", pFile->name_ref, name);
535  }
536  iVID =
537  H5Gcreate(pFile->iFID, (const char *)pBuffer, H5P_DEFAULT,
538  H5P_DEFAULT, H5P_DEFAULT);
539  if (iVID < 0) {
540  NXReportError("ERROR: could not create Group");
541  return NX_ERROR;
542  }
543  aid2 = H5Screate(H5S_SCALAR);
544  aid1 = H5Tcopy(H5T_C_S1);
545  H5Tset_size(aid1, strlen(nxclass));
546  attr1 =
547  H5Acreate(iVID, "NX_class", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT);
548  if (attr1 < 0) {
549  NXReportError("ERROR: failed to store class name");
550  return NX_ERROR;
551  }
552  if (H5Awrite(attr1, aid1, (char *)nxclass) < 0) {
553  NXReportError("ERROR: failed to store class name");
554  return NX_ERROR;
555  }
556  /* close group */
557  iRet = H5Sclose(aid2);
558  iRet = H5Tclose(aid1);
559  iRet = H5Aclose(attr1);
560  iRet = H5Gclose(iVID);
561  return NX_OK;
562 }
563 
564  /*------------------------------------------------------------------------*/
565 
566 herr_t attr_check(hid_t loc_id, const char *member_name,
567  const H5A_info_t * unused, void *opdata)
568 {
569  char attr_name[8 + 1]; /* need to leave space for \0 as well */
570 
571  strcpy(attr_name, "NX_class");
572  return strstr(member_name, attr_name) ? 1 : 0;
573 }
574 
575  /*------------------------------------------------------------------------*/
576 NXstatus NX5opengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass)
577 {
578 
579  pNexusFile5 pFile;
580  hid_t attr1, atype, iVID;
581  herr_t iRet;
582  char pBuffer[1024];
583  char data[128];
584 
585  pFile = NXI5assert(fid);
586  if (pFile->iCurrentG == 0) {
587  strcpy(pBuffer, name);
588  } else {
589  sprintf(pBuffer, "%s/%s", pFile->name_tmp, name);
590  }
591  iVID = H5Gopen(pFile->iFID, (const char *)pBuffer, H5P_DEFAULT);
592  if (iVID < 0) {
593  sprintf(pBuffer, "ERROR: group %s does not exist",
594  pFile->name_tmp);
595  NXReportError(pBuffer);
596  return NX_ERROR;
597  }
598  pFile->iCurrentG = iVID;
599  strcpy(pFile->name_tmp, pBuffer);
600  strcpy(pFile->name_ref, pBuffer);
601 
602  if ((nxclass != NULL) && (strcmp(nxclass, NX_UNKNOWN_GROUP) != 0)) {
603  /* check group attribute */
604  iRet =
605  H5Aiterate(pFile->iCurrentG, H5_INDEX_CRT_ORDER,
606  H5_ITER_INC, 0, attr_check, NULL);
607  if (iRet < 0) {
609  ("ERROR: iterating through attribute list");
610  return NX_ERROR;
611  } else if (iRet == 1) {
612  /* group attribute was found */
613  } else {
614  /* no group attribute available */
615  NXReportError("ERROR: no group attribute available");
616  return NX_ERROR;
617  }
618  /* check contents of group attribute */
619  attr1 =
620  H5Aopen_by_name(pFile->iCurrentG, ".", "NX_class",
621  H5P_DEFAULT, H5P_DEFAULT);
622  if (attr1 < 0) {
624  ("ERROR: opening NX_class group attribute");
625  return NX_ERROR;
626  }
627  atype = H5Tcopy(H5T_C_S1);
628  H5Tset_size(atype, sizeof(data));
629  iRet = readStringAttributeN(attr1, data, sizeof(data));
630  if (strcmp(data, nxclass) == 0) {
631  /* test OK */
632  } else {
633  snprintf(pBuffer, sizeof(pBuffer),
634  "ERROR: group class is not identical: \"%s\" != \"%s\"",
635  data, nxclass);
636  NXReportError(pBuffer);
637  iRet = H5Tclose(atype);
638  iRet = H5Aclose(attr1);
639  return NX_ERROR;
640  }
641  iRet = H5Tclose(atype);
642  iRet = H5Aclose(attr1);
643  }
644 
645  /* maintain stack */
646  pFile->iStackPtr++;
647  pFile->iStack5[pFile->iStackPtr].iVref = pFile->iCurrentG;
648  strcpy(pFile->iStack5[pFile->iStackPtr].irefn, name);
649  pFile->iAtt5.iCurrentIDX = 0;
650  pFile->iCurrentD = 0;
651  if (pFile->iCurrentLGG != NULL) {
652  free(pFile->iCurrentLGG);
653  }
654  pFile->iCurrentLGG = strdup(name);
655  NXI5KillDir(pFile);
656  return NX_OK;
657 }
658 
659  /* ------------------------------------------------------------------- */
660 
661 NXstatus NX5closegroup(NXhandle fid)
662 {
663  pNexusFile5 pFile;
664  int i, ii;
665  char *uname = NULL;
666  char *u1name = NULL;
667 
668  pFile = NXI5assert(fid);
669  /* first catch the trivial case: we are at root and cannot get
670  deeper into a negative directory hierarchy (anti-directory)
671  */
672  if (pFile->iCurrentG == 0) {
673  NXI5KillDir(pFile);
674  return NX_OK;
675  } else {
676  /* close the current group and decrement name_ref */
677  H5Gclose(pFile->iCurrentG);
678  i = 0;
679  i = (int)strlen(pFile->iStack5[pFile->iStackPtr].irefn);
680  ii = (int)strlen(pFile->name_ref);
681  if (pFile->iStackPtr > 1) {
682  ii = ii - i - 1;
683  } else {
684  ii = ii - i;
685  }
686  if (ii > 0) {
687  uname = strdup(pFile->name_ref);
688  u1name = (char *)malloc((ii + 1) * sizeof(char));
689  memset(u1name, 0, ii);
690  for (i = 0; i < ii; i++) {
691  *(u1name + i) = *(uname + i);
692  }
693  *(u1name + i) = '\0';
694  /*
695  strncpy(u1name, uname, ii);
696  */
697  strcpy(pFile->name_ref, u1name);
698  strcpy(pFile->name_tmp, u1name);
699  free(uname);
700  free(u1name);
701  } else {
702  strcpy(pFile->name_ref, "");
703  strcpy(pFile->name_tmp, "");
704  }
705  NXI5KillDir(pFile);
706  pFile->iStackPtr--;
707  if (pFile->iStackPtr > 0) {
708  pFile->iCurrentG =
709  pFile->iStack5[pFile->iStackPtr].iVref;
710  } else {
711  pFile->iCurrentG = 0;
712  }
713  }
714  return NX_OK;
715 }
716 
717 /*-----------------------------------------------------------------------*/
718 static hid_t nxToHDF5Type(int datatype)
719 {
720  hid_t type;
721  if (datatype == NX_CHAR) {
722  type = H5T_C_S1;
723  } else if (datatype == NX_INT8) {
724  type = H5T_NATIVE_CHAR;
725  } else if (datatype == NX_UINT8) {
726  type = H5T_NATIVE_UCHAR;
727  } else if (datatype == NX_INT16) {
728  type = H5T_NATIVE_SHORT;
729  } else if (datatype == NX_UINT16) {
730  type = H5T_NATIVE_USHORT;
731  } else if (datatype == NX_INT32) {
732  type = H5T_NATIVE_INT;
733  } else if (datatype == NX_UINT32) {
734  type = H5T_NATIVE_UINT;
735  } else if (datatype == NX_INT64) {
736  type = H5T_NATIVE_INT64;
737  } else if (datatype == NX_UINT64) {
738  type = H5T_NATIVE_UINT64;
739  } else if (datatype == NX_FLOAT32) {
740  type = H5T_NATIVE_FLOAT;
741  } else if (datatype == NX_FLOAT64) {
742  type = H5T_NATIVE_DOUBLE;
743  } else {
744  NXReportError("ERROR: nxToHDF5Type: unknown type");
745  type = -1;
746  }
747  return type;
748 }
749 
750  /* --------------------------------------------------------------------- */
751 
752 NXstatus NX5compmakedata64(NXhandle fid, CONSTCHAR * name,
753  int datatype,
754  int rank, int64_t dimensions[],
755  int compress_type, int64_t chunk_size[])
756 {
757  hid_t datatype1, dataspace, iNew, dID;
758  herr_t iRet;
759  hid_t type, cparms = -1;
760  pNexusFile5 pFile;
761  char pBuffer[256];
762  int i;
763  size_t byte_zahl = 0;
764  hsize_t chunkdims[H5S_MAX_RANK];
765  hsize_t mydim[H5S_MAX_RANK], mydim1[H5S_MAX_RANK];
766  hsize_t size[H5S_MAX_RANK];
767  hsize_t maxdims[H5S_MAX_RANK];
768  int compress_level;
769  int unlimiteddim = 0;
770 
771  pFile = NXI5assert(fid);
772  if (pFile->iCurrentG <= 0) {
773  sprintf(pBuffer, "ERROR: no group open for makedata on %s",
774  name);
775  NXReportError(pBuffer);
776  return NX_ERROR;
777  }
778 
779  if (rank <= 0) {
780  sprintf(pBuffer, "ERROR: invalid rank specified %s", name);
781  NXReportError(pBuffer);
782  return NX_ERROR;
783  }
784 
785  type = nxToHDF5Type(datatype);
786 
787  /*
788  Check dimensions for consistency. Dimension may be -1
789  thus denoting an unlimited dimension.
790  */
791  for (i = 0; i < rank; i++) {
792  chunkdims[i] = chunk_size[i];
793  mydim[i] = dimensions[i];
794  maxdims[i] = dimensions[i];
795  size[i] = dimensions[i];
796  if (dimensions[i] <= 0) {
797  mydim[i] = 1;
798  maxdims[i] = H5S_UNLIMITED;
799  size[i] = 1;
800  unlimiteddim = 1;
801  } else {
802  mydim[i] = dimensions[i];
803  maxdims[i] = dimensions[i];
804  size[i] = dimensions[i];
805  }
806  }
807 
808  if (datatype == NX_CHAR) {
809  /*
810  * This assumes string lenght is in the last dimensions and
811  * the logic must be the same as used in NX5getslab and NX5getinfo
812  *
813  * search for tests on H5T_STRING
814  */
815  byte_zahl = (size_t) mydim[rank - 1];
816  for (i = 0; i < rank; i++) {
817  mydim1[i] = mydim[i];
818  if (dimensions[i] <= 0) {
819  mydim1[0] = 1;
820  maxdims[0] = H5S_UNLIMITED;
821  }
822  }
823  mydim1[rank - 1] = 1;
824  if (mydim[rank - 1] > 1) {
825  mydim[rank - 1] = maxdims[rank - 1] = size[rank - 1] =
826  1;
827  }
828  if (chunkdims[rank - 1] > 1) {
829  chunkdims[rank - 1] = 1;
830  }
831  dataspace = H5Screate_simple(rank, mydim1, maxdims);
832  } else {
833  if (unlimiteddim) {
834  dataspace = H5Screate_simple(rank, mydim, maxdims);
835  } else {
836  /* dataset creation */
837  dataspace = H5Screate_simple(rank, mydim, NULL);
838  }
839  }
840  datatype1 = H5Tcopy(type);
841  if (datatype == NX_CHAR) {
842  H5Tset_size(datatype1, byte_zahl);
843  /* H5Tset_strpad(H5T_STR_SPACEPAD); */
844  }
845  compress_level = 6;
846  if ((compress_type / 100) == NX_COMP_LZW) {
847  compress_level = compress_type % 100;
848  compress_type = NX_COMP_LZW;
849  }
850  if (compress_type == NX_COMP_LZW) {
851  cparms = H5Pcreate(H5P_DATASET_CREATE);
852  iNew = H5Pset_chunk(cparms, rank, chunkdims);
853  if (iNew < 0) {
854  NXReportError("ERROR: size of chunks could not be set");
855  return NX_ERROR;
856  }
857  H5Pset_shuffle(cparms); // mrt: improves compression
858  H5Pset_deflate(cparms, compress_level);
859  dID = H5Dcreate(pFile->iCurrentG, (char *)name, datatype1,
860  dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT);
861  } else if (compress_type == NX_COMP_NONE) {
862  if (unlimiteddim) {
863  cparms = H5Pcreate(H5P_DATASET_CREATE);
864  iNew = H5Pset_chunk(cparms, rank, chunkdims);
865  if (iNew < 0) {
867  ("ERROR: size of chunks could not be set");
868  return NX_ERROR;
869  }
870  dID =
871  H5Dcreate(pFile->iCurrentG, (char *)name, datatype1,
872  dataspace, H5P_DEFAULT, cparms,
873  H5P_DEFAULT);
874  } else {
875  dID =
876  H5Dcreate(pFile->iCurrentG, (char *)name, datatype1,
877  dataspace, H5P_DEFAULT, H5P_DEFAULT,
878  H5P_DEFAULT);
879  }
880  } else if (compress_type == NX_CHUNK) {
881  cparms = H5Pcreate(H5P_DATASET_CREATE);
882  iNew = H5Pset_chunk(cparms, rank, chunkdims);
883  if (iNew < 0) {
884  NXReportError("ERROR: size of chunks could not be set");
885  return NX_ERROR;
886  }
887  dID = H5Dcreate(pFile->iCurrentG, (char *)name, datatype1,
888  dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT);
889 
890  } else {
892  ("HDF5 doesn't support selected compression method! Dataset created without compression");
893  iRet =
894  H5Dcreate(pFile->iCurrentG, (char *)name, datatype1,
895  dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
896  }
897  if (dID < 0) {
898  NXReportError("ERROR: creating chunked dataset failed");
899  return NX_ERROR;
900  } else {
901  pFile->iCurrentD = dID;
902  }
903  if (unlimiteddim) {
904  iNew = H5Dset_extent(pFile->iCurrentD, size);
905  if (iNew < 0) {
906  sprintf(pBuffer, "ERROR: cannot create dataset %s",
907  name);
908  NXReportError(pBuffer);
909  return NX_ERROR;
910  }
911  }
912  if (cparms != -1) {
913  iRet = H5Pclose(cparms);
914  }
915  iRet = H5Sclose(dataspace);
916  iRet = H5Tclose(datatype1);
917  iRet = H5Dclose(pFile->iCurrentD);
918  pFile->iCurrentD = 0;
919  if (iRet < 0) {
920  NXReportError("ERROR: HDF cannot close dataset");
921  return NX_ERROR;
922  }
923  return NX_OK;
924 }
925 
926  /* --------------------------------------------------------------------- */
927 
928 NXstatus NX5makedata64(NXhandle fid, CONSTCHAR * name, int datatype,
929  int rank, int64_t dimensions[])
930 {
931  int64_t chunk_size[H5S_MAX_RANK];
932  int i;
933 
934  NXI5assert(fid);
935 
936  memset(chunk_size, 0, H5S_MAX_RANK * sizeof(int64_t));
937  memcpy(chunk_size, dimensions, rank * sizeof(int64_t));
938  for (i = 0; i < rank; i++) {
939  if (dimensions[i] == NX_UNLIMITED || dimensions[i] <= 0) {
940  chunk_size[i] = 1;
941  }
942  }
943  return NX5compmakedata64(fid, name, datatype, rank, dimensions,
944  NX_COMP_NONE, chunk_size);
945 }
946 
947  /* --------------------------------------------------------------------- */
948 
949 NXstatus NX5compress(NXhandle fid, int compress_type)
950 {
951  printf
952  (" NXcompress ERROR: NeXus API based on HDF5 doesn't support\n");
953  printf
954  (" NXcompress function! Using HDF5 library,\n");
955  printf
956  (" the NXcompmakedata function can be applied\n");
957  printf(" for compression of data!\n");
958  return NX_ERROR;
959 }
960 
961  /* --------------------------------------------------------------------- */
962 
963 NXstatus NX5opendata(NXhandle fid, CONSTCHAR * name)
964 {
965  pNexusFile5 pFile;
966  char pBuffer[256];
967 
968  pFile = NXI5assert(fid);
969  /* clear pending attribute directories first */
970  NXI5KillAttDir(pFile);
971 
972  /* find the ID number and open the dataset */
973  pFile->iCurrentD = H5Dopen(pFile->iCurrentG, name, H5P_DEFAULT);
974  if (pFile->iCurrentD < 0) {
975  sprintf(pBuffer,
976  "ERROR: dataset \"%s\" not found at this level", name);
977  NXReportError(pBuffer);
978  return NX_ERROR;
979  }
980  /* find the ID number of datatype */
981  pFile->iCurrentT = H5Dget_type(pFile->iCurrentD);
982  if (pFile->iCurrentT < 0) {
983  NXReportError("ERROR: error opening dataset");
984  pFile->iCurrentT = 0;
985  return NX_ERROR;
986  }
987  /* find the ID number of dataspace */
988  pFile->iCurrentS = H5Dget_space(pFile->iCurrentD);
989  if (pFile->iCurrentS < 0) {
990  NXReportError("ERROR:HDF error opening dataset");
991  pFile->iCurrentS = 0;
992  return NX_ERROR;
993  }
994  if (pFile->iCurrentLD != NULL) {
995  free(pFile->iCurrentLD);
996  }
997  pFile->iCurrentLD = strdup(name);
998  return NX_OK;
999 }
1000 
1001  /* ----------------------------------------------------------------- */
1002 
1003 NXstatus NX5closedata(NXhandle fid)
1004 {
1005  pNexusFile5 pFile;
1006  herr_t iRet;
1007 
1008  pFile = NXI5assert(fid);
1009  iRet = H5Sclose(pFile->iCurrentS);
1010  iRet = H5Tclose(pFile->iCurrentT);
1011  iRet = H5Dclose(pFile->iCurrentD);
1012  if (iRet < 0) {
1013  NXReportError("ERROR: cannot end access to dataset");
1014  return NX_ERROR;
1015  }
1016  pFile->iCurrentD = 0;
1017  return NX_OK;
1018 }
1019 
1020  /* ------------------------------------------------------------------- */
1021 
1022 NXstatus NX5putdata(NXhandle fid, const void *data)
1023 {
1024  pNexusFile5 pFile;
1025  herr_t iRet;
1026  int64_t myStart[H5S_MAX_RANK];
1027  int64_t mySize[H5S_MAX_RANK];
1028  hsize_t thedims[H5S_MAX_RANK], maxdims[H5S_MAX_RANK];
1029  int i, rank, unlimiteddim = 0;
1030 
1031  char pError[512] = "";
1032 
1033  pFile = NXI5assert(fid);
1034  rank = H5Sget_simple_extent_ndims(pFile->iCurrentS);
1035  if (rank < 0) {
1036  NXReportError("ERROR: Cannot determine dataset rank");
1037  return NX_ERROR;
1038  }
1039  iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims);
1040  if (iRet < 0) {
1041  NXReportError("ERROR: Cannot determine dataset dimensions");
1042  return NX_ERROR;
1043  }
1044  for (i = 0; i < rank; ++i) {
1045  myStart[i] = 0;
1046  mySize[i] = thedims[i];
1047  if (maxdims[i] == H5S_UNLIMITED) {
1048  unlimiteddim = 1;
1049  myStart[i] = thedims[i] + 1;
1050  mySize[i] = 1;
1051  }
1052  }
1053  /* If we are using putdata on an unlimied dimesnion dataset, assume we want to append one single new slab */
1054  if (unlimiteddim) {
1055  return NX5putslab64(fid, data, myStart, mySize);
1056  } else {
1057  iRet =
1058  H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, H5S_ALL,
1059  H5S_ALL, H5P_DEFAULT, data);
1060  if (iRet < 0) {
1061  snprintf(pError, sizeof(pError) - 1,
1062  "ERROR: failure to write data");
1063  NXReportError(pError);
1064  return NX_ERROR;
1065  }
1066  }
1067  return NX_OK;
1068 }
1069 
1070 /*------------------------------------------------------------------*/
1071 static hid_t getAttVID(pNexusFile5 pFile)
1072 {
1073  hid_t vid;
1074  if (pFile->iCurrentG == 0 && pFile->iCurrentD == 0) {
1075  /* global attribute */
1076  vid = H5Gopen(pFile->iFID, "/", H5P_DEFAULT);
1077  } else if (pFile->iCurrentD != 0) {
1078  /* dataset attribute */
1079  vid = pFile->iCurrentD;
1080  } else {
1081  /* group attribute */ ;
1082  vid = pFile->iCurrentG;
1083  }
1084  return vid;
1085 }
1086 
1087 /*---------------------------------------------------------------*/
1088 static void killAttVID(pNexusFile5 pFile, hid_t vid)
1089 {
1090  if (pFile->iCurrentG == 0 && pFile->iCurrentD == 0) {
1091  H5Gclose(vid);
1092  }
1093 }
1094 
1095  /* ------------------------------------------------------------------- */
1096 
1097 NXstatus NX5putattr(NXhandle fid, CONSTCHAR * name, const void *data,
1098  int datalen, int iType)
1099 {
1100  pNexusFile5 pFile;
1101  hid_t attr1, aid1, aid2;
1102  hid_t type;
1103  herr_t iRet;
1104  hid_t vid, attRet;
1105 
1106  pFile = NXI5assert(fid);
1107 
1108  type = nxToHDF5Type(iType);
1109 
1110  /* determine vid */
1111  vid = getAttVID(pFile);
1112  attRet = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT);
1113  if (attRet > 0) {
1114  H5Aclose(attRet);
1115  iRet = H5Adelete(vid, name);
1116  if (iRet < 0) {
1118  ("ERROR: old attribute cannot be removed! ");
1119  killAttVID(pFile, vid);
1120  return NX_ERROR;
1121  }
1122  }
1123  aid2 = H5Screate(H5S_SCALAR);
1124  aid1 = H5Tcopy(type);
1125  if (iType == NX_CHAR) {
1126  H5Tset_size(aid1, datalen);
1127  }
1128  attr1 = H5Acreate(vid, name, aid1, aid2, H5P_DEFAULT, H5P_DEFAULT);
1129  if (attr1 < 0) {
1130  NXReportError("ERROR: attribute cannot created! ");
1131  killAttVID(pFile, vid);
1132  return NX_ERROR;
1133  }
1134  if (H5Awrite(attr1, aid1, data) < 0) {
1135  NXReportError("ERROR: failed to store attribute ");
1136  killAttVID(pFile, vid);
1137  return NX_ERROR;
1138  }
1139  /* Close attribute dataspace */
1140  iRet = H5Tclose(aid1);
1141  iRet = H5Sclose(aid2);
1142  /* Close attribute */
1143  iRet = H5Aclose(attr1);
1144  killAttVID(pFile, vid);
1145  return NX_OK;
1146 }
1147 
1148  /* ------------------------------------------------------------------- */
1149 
1150 NXstatus NX5putslab64(NXhandle fid, const void *data, const int64_t iStart[],
1151  const int64_t iSize[])
1152 {
1153  pNexusFile5 pFile;
1154  int iRet, rank, i;
1155  hsize_t myStart[H5S_MAX_RANK];
1156  hsize_t mySize[H5S_MAX_RANK];
1157  hsize_t size[H5S_MAX_RANK], thedims[H5S_MAX_RANK],
1158  maxdims[H5S_MAX_RANK];
1159  hid_t filespace, dataspace;
1160  int unlimiteddim = 0;
1161 
1162  pFile = NXI5assert(fid);
1163  /* check if there is an Dataset open */
1164  if (pFile->iCurrentD == 0) {
1165  NXReportError("ERROR: no dataset open");
1166  return NX_ERROR;
1167  }
1168  rank = H5Sget_simple_extent_ndims(pFile->iCurrentS);
1169  if (rank < 0) {
1170  NXReportError("ERROR: cannot get rank");
1171  return NX_ERROR;
1172  }
1173  iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims);
1174  if (iRet < 0) {
1175  NXReportError("ERROR: cannot get dimensions");
1176  return NX_ERROR;
1177  }
1178 
1179  for (i = 0; i < rank; i++) {
1180  myStart[i] = iStart[i];
1181  mySize[i] = iSize[i];
1182  size[i] = iStart[i] + iSize[i];
1183  if (maxdims[i] == H5S_UNLIMITED) {
1184  unlimiteddim = 1;
1185  }
1186  }
1187  if (H5Tget_class(pFile->iCurrentT) == H5T_STRING) {
1188  mySize[rank - 1] = 1;
1189  myStart[rank - 1] = 0;
1190  size[rank - 1] = 1;
1191  }
1192  dataspace = H5Screate_simple(rank, mySize, NULL);
1193  if (unlimiteddim) {
1194  for (i = 0; i < rank; i++) {
1195  if (size[i] < thedims[i]) {
1196  size[i] = thedims[i];
1197  }
1198  }
1199  iRet = H5Dset_extent(pFile->iCurrentD, size);
1200  if (iRet < 0) {
1201  NXReportError("ERROR: extend slab failed");
1202  return NX_ERROR;
1203  }
1204 
1205  filespace = H5Dget_space(pFile->iCurrentD);
1206 
1207  /* define slab */
1208  iRet = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, myStart,
1209  NULL, mySize, NULL);
1210  /* deal with HDF errors */
1211  if (iRet < 0) {
1212  NXReportError("ERROR: selecting slab failed");
1213  return NX_ERROR;
1214  }
1215  /* write slab */
1216  iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace,
1217  filespace, H5P_DEFAULT, data);
1218  if (iRet < 0) {
1219  NXReportError("ERROR: writing slab failed");
1220  }
1221  /* update with new size */
1222  iRet = H5Sclose(pFile->iCurrentS);
1223  pFile->iCurrentS = filespace;
1224  } else {
1225  /* define slab */
1226  iRet =
1227  H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET,
1228  myStart, NULL, mySize, NULL);
1229  /* deal with HDF errors */
1230  if (iRet < 0) {
1231  NXReportError("ERROR: selecting slab failed");
1232  return NX_ERROR;
1233  }
1234  /* write slab */
1235  iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace,
1236  pFile->iCurrentS, H5P_DEFAULT, data);
1237  if (iRet < 0) {
1238  NXReportError("ERROR: writing slab failed");
1239  }
1240  }
1241  /* deal with HDF errors */
1242  iRet = H5Sclose(dataspace);
1243  if (iRet < 0) {
1244  NXReportError("ERROR: closing slab failed");
1245  return NX_ERROR;
1246  }
1247  return NX_OK;
1248 }
1249 
1250  /* ------------------------------------------------------------------- */
1251 
1252 NXstatus NX5getdataID(NXhandle fid, NXlink * sRes)
1253 {
1254  pNexusFile5 pFile;
1255  int datalen, type = NX_CHAR;
1256 
1257  pFile = NXI5assert(fid);
1258 
1259  /* we cannot return ID's when no datset is open */
1260  if (pFile->iCurrentD <= 0) {
1261  return NX_ERROR;
1262  }
1263 
1264  /*
1265  this means: if the item is already linked: use the target attribute else,
1266  the path to the current node
1267  */
1269  datalen = 1024;
1270  memset(&sRes->targetPath, 0, datalen * sizeof(char));
1271  if (NX5getattr(fid, "target", &sRes->targetPath, &datalen, &type) != NX_OK) {
1272  buildCurrentPath(pFile, sRes->targetPath, 1024);
1273  }
1275  sRes->linkType = 1;
1276  return NX_OK;
1277 }
1278 
1279 /* ------------------------------------------------------------------- */
1280 
1281 NXstatus NX5printlink(NXhandle fid, NXlink * sLink)
1282 {
1283  NXI5assert(fid);
1284  printf("HDF5 link: targetPath = \"%s\", linkType = \"%d\"\n",
1285  sLink->targetPath, sLink->linkType);
1286  return NX_OK;
1287 }
1288 
1289 /*--------------------------------------------------------------------*/
1290 static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink * sLink)
1291 {
1292  hid_t dataID, aid2, aid1, attID;
1293  herr_t status;
1294  char name[] = "target";
1295 
1296  /*
1297  set the target attribute
1298  */
1299  if (sLink->linkType > 0) {
1300  dataID = H5Dopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT);
1301  } else {
1302  dataID = H5Gopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT);
1303  }
1304  if (dataID < 0) {
1305  NXReportError("Internal error, path to link does not exist");
1306  return NX_ERROR;
1307  }
1308  status = H5Aopen_by_name(dataID, ".", name, H5P_DEFAULT, H5P_DEFAULT);
1309  if (status > 0) {
1310  H5Aclose(status);
1311  status = H5Adelete(dataID, name);
1312  if (status < 0) {
1313  return NX_OK;
1314  }
1315  }
1316  aid2 = H5Screate(H5S_SCALAR);
1317  aid1 = H5Tcopy(H5T_C_S1);
1318  H5Tset_size(aid1, strlen(sLink->targetPath));
1319  attID = H5Acreate(dataID, name, aid1, aid2, H5P_DEFAULT, H5P_DEFAULT);
1320  if (attID < 0) {
1321  return NX_OK;
1322  }
1323  status = H5Awrite(attID, aid1, sLink->targetPath);
1324  H5Tclose(aid1);
1325  H5Sclose(aid2);
1326  H5Aclose(attID);
1327  if (sLink->linkType > 0) {
1328  H5Dclose(dataID);
1329  } else {
1330  H5Gclose(dataID);
1331  }
1332  return NX_OK;
1333 }
1334 
1335 /*---------------------------------------------------------------------*/
1336 
1337 NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR * name, NXlink * sLink)
1338 {
1339  pNexusFile5 pFile;
1340  char linkTarget[1024];
1341 
1342  pFile = NXI5assert(fid);
1343  if (pFile->iCurrentG == 0) { /* root level, can not link here */
1344  return NX_ERROR;
1345  }
1346 
1347  /*
1348  build pathname to link from our current group and the name
1349  of the thing to link
1350  */
1351  if (strlen(pFile->name_ref) + strlen(name) + 2 < 1024) {
1352  strcpy(linkTarget, "/");
1353  strcat(linkTarget, pFile->name_ref);
1354  strcat(linkTarget, "/");
1355  strcat(linkTarget, name);
1356  } else {
1357  NXReportError("ERROR: path string to long");
1358  return NX_ERROR;
1359  }
1360 
1361  H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget,
1362  H5P_DEFAULT, H5P_DEFAULT);
1363 
1364  return NX5settargetattribute(pFile, sLink);
1365 }
1366 
1367 /* ------------------------------------------------------------------- */
1368 
1369 NXstatus NX5makelink(NXhandle fid, NXlink * sLink)
1370 {
1371  pNexusFile5 pFile;
1372  char linkTarget[1024];
1373  char *itemName = NULL;
1374 
1375  pFile = NXI5assert(fid);
1376  if (pFile->iCurrentG == 0) { /* root level, can not link here */
1377  return NX_ERROR;
1378  }
1379 
1380  /*
1381  locate name of the element to link
1382  */
1383  itemName = strrchr(sLink->targetPath, '/');
1384  if (itemName == NULL) {
1385  NXReportError("ERROR: bad link structure");
1386  return NX_ERROR;
1387  }
1388  itemName++;
1389 
1390  /*
1391  build pathname to link from our current group and the name
1392  of the thing to link
1393  */
1394  if (strlen(pFile->name_ref) + strlen(itemName) + 2 < 1024) {
1395  strcpy(linkTarget, "/");
1396  strcat(linkTarget, pFile->name_ref);
1397  strcat(linkTarget, "/");
1398  strcat(linkTarget, itemName);
1399  } else {
1400  NXReportError("ERROR: path string to long");
1401  return NX_ERROR;
1402  }
1403 
1404  H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget,
1405  H5P_DEFAULT, H5P_DEFAULT);
1406 
1407  return NX5settargetattribute(pFile, sLink);
1408 }
1409 
1410 /*----------------------------------------------------------------------*/
1411 
1412 NXstatus NX5flush(NXhandle * pHandle)
1413 {
1414  pNexusFile5 pFile = NULL;
1415  herr_t iRet;
1416 
1417  pFile = NXI5assert(*pHandle);
1418  if (pFile->iCurrentD != 0) {
1419  iRet = H5Fflush(pFile->iCurrentD, H5F_SCOPE_LOCAL);
1420  } else if (pFile->iCurrentG != 0) {
1421  iRet = H5Fflush(pFile->iCurrentG, H5F_SCOPE_LOCAL);
1422  } else {
1423  iRet = H5Fflush(pFile->iFID, H5F_SCOPE_LOCAL);
1424  }
1425  if (iRet < 0) {
1426  NXReportError("ERROR: The object cannot be flushed");
1427  return NX_ERROR;
1428  }
1429  return NX_OK;
1430 }
1431 
1432  /*-------------------------------------------------------------------------*/
1433 
1434  /* Operator function. */
1435 
1436 herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t * statbuf,
1437  void *op_data)
1438 {
1439  pinfo self = (pinfo) op_data;
1440  H5O_info_t object_info;
1441  H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
1442  switch ((object_info).type) {
1443  case H5O_TYPE_GROUP:
1444  self->iname = strdup(name);
1445  self->type = H5O_TYPE_GROUP;
1446  break;
1447  case H5O_TYPE_DATASET:
1448  self->iname = strdup(name);
1449  self->type = H5O_TYPE_DATASET;
1450  break;
1451  default:
1452  // TODO defaults to group. not what we would want?
1453  self->type = 0;
1454  break;
1455  }
1456  return 1;
1457 }
1458 
1459  /* --------------------------------------------------------------------- */
1460 
1461  /* Operator function. */
1462 
1463 herr_t group_info1(hid_t loc_id, const char *name, const H5L_info_t * statbuf,
1464  void *opdata)
1465 {
1466  int iNX = *((int *)opdata);
1467  H5O_info_t object_info;
1468  H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
1469  switch ((object_info).type) {
1470  case H5O_TYPE_GROUP:
1471  iNX++;
1472  *((int *)opdata) = iNX;
1473  break;
1474  case H5O_TYPE_DATASET:
1475  iNX++;
1476  *((int *)opdata) = iNX;
1477  break;
1478  default:
1479  break;
1480  }
1481  return 0;
1482 }
1483 
1484  /*-------------------------------------------------------------------------*/
1485 
1486 NXstatus NX5getgroupinfo_recurse(NXhandle fid, int *iN, NXname pName,
1487  NXname pClass)
1488 {
1489  pNexusFile5 pFile;
1490  hid_t atype, attr_id, grp;
1491  char data[64];
1492 
1493  pFile = NXI5assert(fid);
1494  /* check if there is a group open */
1495  if (pFile->iCurrentG == 0) {
1496  strcpy(pName, "root");
1497  strcpy(pClass, "NXroot");
1498  pFile->iNX = 0;
1499  grp = H5Gopen(pFile->iFID, "/", H5P_DEFAULT);
1500  H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1,
1501  &pFile->iNX);
1502  H5Gclose(grp);
1503  *iN = pFile->iNX;
1504  } else {
1505  strcpy(pName, pFile->name_ref);
1506  attr_id =
1507  H5Aopen_by_name(pFile->iCurrentG, ".", "NX_class",
1508  H5P_DEFAULT, H5P_DEFAULT);
1509  if (attr_id < 0) {
1510  strcpy(pClass, NX_UNKNOWN_GROUP);
1511  } else {
1512  atype = H5Tcopy(H5T_C_S1);
1513  H5Tset_size(atype, sizeof(data));
1514  readStringAttributeN(attr_id, data, sizeof(data));
1515  strcpy(pClass, data);
1516  pFile->iNX = 0;
1517  grp =
1518  H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT);
1519  H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0,
1520  group_info1, &pFile->iNX);
1521  H5Gclose(grp);
1522  *iN = pFile->iNX;
1523  H5Aclose(attr_id);
1524  }
1525  }
1526  return NX_OK;
1527 }
1528 
1529 /*---------------------------------------------------------------------------*/
1530 static int countObjectsInGroup(hid_t loc_id)
1531 {
1532  int count = 0;
1533  H5G_info_t numobj;
1534 
1535  herr_t status;
1536 
1537  status = H5Gget_info(loc_id, &numobj);
1538  if (status < 0) {
1540  ("Internal error, failed to retrieve no of objects");
1541  return 0;
1542  }
1543 
1544  count = (int)numobj.nlinks;
1545  return count;
1546 }
1547 
1548 /*----------------------------------------------------------------------------*/
1549 NXstatus NX5getgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass)
1550 {
1551  pNexusFile5 pFile;
1552  hid_t atype, attr_id, gid;
1553  char data[64];
1554 
1555  pFile = NXI5assert(fid);
1556  /* check if there is a group open */
1557  if (pFile->iCurrentG == 0) {
1558  strcpy(pName, "root");
1559  strcpy(pClass, "NXroot");
1560  gid = H5Gopen(pFile->iFID, "/", H5P_DEFAULT);
1561  *iN = countObjectsInGroup(gid);
1562  H5Gclose(gid);
1563  } else {
1564  strcpy(pName, pFile->name_ref);
1565  attr_id =
1566  H5Aopen_by_name(pFile->iCurrentG, ".", "NX_class",
1567  H5P_DEFAULT, H5P_DEFAULT);
1568  if (attr_id < 0) {
1569  strcpy(pClass, NX_UNKNOWN_GROUP);
1570  } else {
1571  atype = H5Tcopy(H5T_C_S1);
1572  H5Tset_size(atype, sizeof(data));
1573  readStringAttributeN(attr_id, data, sizeof(data));
1574  strcpy(pClass, data);
1575  H5Aclose(attr_id);
1576  }
1577  pFile->iNX = 0;
1578  *iN = countObjectsInGroup(pFile->iCurrentG);
1579  }
1580  return NX_OK;
1581 }
1582 
1583 /*-------------------------------------------------------------------------
1584  * Function: hdf5ToNXType
1585  *
1586  * Purpose: Convert a HDF5 class to a NeXus type; it handles the following HDF5 classes
1587  * H5T_STRING
1588  * H5T_INTEGER
1589  * H5T_FLOAT
1590  *
1591  * Return: the NeXus type
1592  *
1593  *-------------------------------------------------------------------------
1594  */
1595 static int hdf5ToNXType(H5T_class_t tclass, hid_t atype)
1596 {
1597  int iPtype = -1;
1598  size_t size;
1599  H5T_sign_t sign;
1600 
1601  if (tclass == H5T_STRING) {
1602  iPtype = NX_CHAR;
1603  } else if (tclass == H5T_INTEGER) {
1604  size = H5Tget_size(atype);
1605  sign = H5Tget_sign(atype);
1606  if (size == 1) {
1607  if (sign == H5T_SGN_2) {
1608  iPtype = NX_INT8;
1609  } else {
1610  iPtype = NX_UINT8;
1611  }
1612  } else if (size == 2) {
1613  if (sign == H5T_SGN_2) {
1614  iPtype = NX_INT16;
1615  } else {
1616  iPtype = NX_UINT16;
1617  }
1618  } else if (size == 4) {
1619  if (sign == H5T_SGN_2) {
1620  iPtype = NX_INT32;
1621  } else {
1622  iPtype = NX_UINT32;
1623  }
1624  } else if (size == 8) {
1625  if (sign == H5T_SGN_2) {
1626  iPtype = NX_INT64;
1627  } else {
1628  iPtype = NX_UINT64;
1629  }
1630  }
1631  } else if (tclass == H5T_FLOAT) {
1632  size = H5Tget_size(atype);
1633  if (size == 4) {
1634  iPtype = NX_FLOAT32;
1635  } else if (size == 8) {
1636  iPtype = NX_FLOAT64;
1637  }
1638  }
1639  if (iPtype == -1) {
1640  char message[80];
1641  snprintf(message, 79, "ERROR: hdf5ToNXtype: invalid type (%d)", tclass);
1642  NXReportError(message);
1643  }
1644 
1645  return iPtype;
1646 }
1647 
1648 /*--------------------------------------------------------------------------*/
1649 static hid_t h5MemType(hid_t atype)
1650 {
1651  hid_t memtype_id = -1;
1652  size_t size;
1653  H5T_sign_t sign;
1654  H5T_class_t tclass;
1655 
1656  tclass = H5Tget_class(atype);
1657 
1658  if (tclass == H5T_INTEGER) {
1659  size = H5Tget_size(atype);
1660  sign = H5Tget_sign(atype);
1661  if (size == 1) {
1662  if (sign == H5T_SGN_2) {
1663  memtype_id = H5T_NATIVE_INT8;
1664  } else {
1665  memtype_id = H5T_NATIVE_UINT8;
1666  }
1667  } else if (size == 2) {
1668  if (sign == H5T_SGN_2) {
1669  memtype_id = H5T_NATIVE_INT16;
1670  } else {
1671  memtype_id = H5T_NATIVE_UINT16;
1672  }
1673  } else if (size == 4) {
1674  if (sign == H5T_SGN_2) {
1675  memtype_id = H5T_NATIVE_INT32;
1676  } else {
1677  memtype_id = H5T_NATIVE_UINT32;
1678  }
1679  } else if (size == 8) {
1680  if (sign == H5T_SGN_2) {
1681  memtype_id = H5T_NATIVE_INT64;
1682  } else {
1683  memtype_id = H5T_NATIVE_UINT64;
1684  }
1685  }
1686  } else if (tclass == H5T_FLOAT) {
1687  size = H5Tget_size(atype);
1688  if (size == 4) {
1689  memtype_id = H5T_NATIVE_FLOAT;
1690  } else if (size == 8) {
1691  memtype_id = H5T_NATIVE_DOUBLE;
1692  }
1693  }
1694  if (memtype_id == -1) {
1695  NXReportError("ERROR: h5MemType: invalid type");
1696  }
1697  return memtype_id;
1698 }
1699 
1700  /*-------------------------------------------------------------------------*/
1701 
1702 NXstatus NX5getnextentry(NXhandle fid, NXname name, NXname nxclass,
1703  int *datatype)
1704 {
1705  pNexusFile5 pFile;
1706  hid_t grp, attr1, type, atype;
1707  herr_t iRet;
1708  int iPtype, i;
1709  hsize_t idx;
1710  H5T_class_t tclass;
1711  char data[128];
1712  char ph_name[1024];
1713  info_type op_data;
1714  herr_t iRet_iNX = -1;
1715  char pBuffer[256];
1716 
1717  pFile = NXI5assert(fid);
1718  op_data.iname = NULL;
1719 
1720  /*
1721  iterate to next entry in group list
1722  */
1723  idx = pFile->iStack5[pFile->iStackPtr].iCurrentIDX;
1724  if (strlen(pFile->name_ref) == 0) {
1725  /* root group */
1726  strcpy(pFile->name_ref, "/");
1727  }
1728  grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT);
1729  // index can be wrong here
1730  iRet =
1731  H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, &idx, nxgroup_info,
1732  &op_data);
1733  H5Gclose(grp);
1734  strcpy(nxclass, NX_UNKNOWN_GROUP);
1735 
1736  /*
1737  figure out the number of items in the current group. We need this in order to
1738  find out if we are at the end of the search.
1739  */
1740  if (pFile->iCurrentG == 0) {
1741  // if pFile->iCurrentG == 0 would not pFile->name_ref be "/" already, so we could skip that if statement ?
1742  pFile->iNX = 0;
1743  grp = H5Gopen(pFile->iFID, "/", H5P_DEFAULT);
1744  iRet_iNX =
1745  H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1,
1746  &pFile->iNX);
1747  H5Gclose(grp);
1748  } else {
1749  pFile->iNX = 0;
1750  grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT);
1751  // index can be wrong here
1752  iRet_iNX =
1753  H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1,
1754  &pFile->iNX);
1755  H5Gclose(grp);
1756  }
1757  if (idx == pFile->iNX) {
1758  // why 2?
1759  iRet_iNX = 2;
1760  }
1761 
1762  if (iRet > 0) {
1763  pFile->iStack5[pFile->iStackPtr].iCurrentIDX++;
1764  if (op_data.iname != NULL) {
1765  strcpy(name, op_data.iname);
1766  free(op_data.iname);
1767  } else {
1768  pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0;
1769  return NX_EOD;
1770  }
1771  if (op_data.type == H5O_TYPE_GROUP) {
1772  /*
1773  open group and find class name attribute
1774  */
1775  strcpy(ph_name, "");
1776  for (i = 1; i < (pFile->iStackPtr + 1); i++) {
1777  strcat(ph_name, pFile->iStack5[i].irefn);
1778  strcat(ph_name, "/");
1779  }
1780  strcat(ph_name, name);
1781  grp = H5Gopen(pFile->iFID, ph_name, H5P_DEFAULT);
1782  if (grp < 0) {
1783  sprintf(pBuffer,
1784  "ERROR: group %s does not exist",
1785  ph_name);
1786  NXReportError(pBuffer);
1787  return NX_ERROR;
1788  }
1789  attr1 =
1790  H5Aopen_by_name(grp, ".", "NX_class", H5P_DEFAULT,
1791  H5P_DEFAULT);
1792  if (attr1 < 0) {
1793  strcpy(nxclass, NX_UNKNOWN_GROUP);
1794  } else {
1795  type = H5T_C_S1;
1796  atype = H5Tcopy(type);
1797  H5Tset_size(atype, sizeof(data));
1798  iRet =
1799  readStringAttributeN(attr1, data,
1800  sizeof(data));
1801  strcpy(nxclass, data);
1802  H5Tclose(atype);
1803  H5Aclose(attr1);
1804  }
1805  H5Gclose(grp);
1806  } else if (op_data.type == H5O_TYPE_DATASET) {
1807  /*
1808  open dataset and find type
1809  */
1810  if (pFile->iCurrentG == 0) {
1811  grp = H5Dopen(pFile->iFID, name, H5P_DEFAULT);
1812  } else {
1813  grp = H5Dopen(pFile->iCurrentG, name, H5P_DEFAULT);
1814  }
1815  type = H5Dget_type(grp);
1816  atype = H5Tcopy(type);
1817  tclass = H5Tget_class(atype);
1818  iPtype = hdf5ToNXType(tclass, atype);
1819  *datatype = iPtype;
1820  strcpy(nxclass, "SDS");
1821  H5Tclose(atype);
1822  H5Tclose(type);
1823  H5Dclose(grp);
1824  }
1825  return NX_OK;
1826  } else {
1827  /*
1828  we are at the end of the search: clear the data structure and reset
1829  iCurrentIDX to 0
1830  */
1831  if (iRet_iNX == 2) {
1832  if (op_data.iname != NULL) {
1833  free(op_data.iname);
1834  }
1835  pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0;
1836  return NX_EOD;
1837  }
1838  if (op_data.iname != NULL) {
1839  free(op_data.iname);
1840  }
1841  NXReportError("ERROR: iterating through group not successful");
1842  return NX_ERROR;
1843  }
1844 }
1845 
1846  /*-------------------------------------------------------------------------*/
1847 
1848 NXstatus NX5getdata(NXhandle fid, void *data)
1849 {
1850  pNexusFile5 pFile;
1851  int i, iStart[H5S_MAX_RANK], status;
1852  hid_t memtype_id;
1853  H5T_class_t tclass;
1854  hsize_t ndims, dims[H5S_MAX_RANK];
1855  char **vstrdata = NULL;
1856 
1857  pFile = NXI5assert(fid);
1858  /* check if there is an Dataset open */
1859  if (pFile->iCurrentD == 0) {
1860  NXReportError("ERROR: no dataset open");
1861  return NX_ERROR;
1862  }
1863  ndims = H5Sget_simple_extent_dims(pFile->iCurrentS, dims, NULL);
1864 
1865  if (ndims == 0) { /* SCALAR dataset */
1866  hid_t datatype = H5Dget_type(pFile->iCurrentD);
1867  hid_t filespace = H5Dget_space(pFile->iCurrentD);
1868 
1869  tclass = H5Tget_class(datatype);
1870 
1871  if (H5Tis_variable_str(pFile->iCurrentT)) {
1872  char *strdata = calloc(512, sizeof(char));
1873  status =
1874  H5Dread(pFile->iCurrentD, datatype, H5S_ALL,
1875  H5S_ALL, H5P_DEFAULT, &strdata);
1876  if (status >= 0)
1877  strncpy(data, strdata, strlen(strdata));
1878  free(strdata);
1879  } else {
1880  memtype_id = H5Screate(H5S_SCALAR);
1881  H5Sselect_all(filespace);
1882  status =
1883  H5Dread(pFile->iCurrentD, datatype, memtype_id,
1884  filespace, H5P_DEFAULT, data);
1885  H5Sclose(memtype_id);
1886  }
1887 
1888  H5Sclose(filespace);
1889  H5Tclose(datatype);
1890  if (status < 0)
1891  return NX_ERROR;
1892  return NX_OK;
1893  }
1894 
1895  memset(iStart, 0, H5S_MAX_RANK * sizeof(int));
1896  /* map datatypes of other plateforms */
1897  tclass = H5Tget_class(pFile->iCurrentT);
1898  if (H5Tis_variable_str(pFile->iCurrentT)) {
1899  vstrdata = (char **)malloc((size_t) dims[0] * sizeof(char *));
1900  memtype_id = H5Tcopy(H5T_C_S1);
1901  H5Tset_size(memtype_id, H5T_VARIABLE);
1902  status = H5Dread(pFile->iCurrentD, memtype_id,
1903  H5S_ALL, H5S_ALL, H5P_DEFAULT, vstrdata);
1904  ((char *)data)[0] = '\0';
1905  if (status >= 0) {
1906  for (i = 0; i < dims[0]; ++i) {
1907  if (vstrdata[i] != NULL) {
1908  strcat((char *)data, vstrdata[i]);
1909  }
1910  }
1911  }
1912  H5Dvlen_reclaim(memtype_id, pFile->iCurrentS, H5P_DEFAULT,
1913  vstrdata);
1914  free(vstrdata);
1915  H5Tclose(memtype_id);
1916  } else if (tclass == H5T_STRING) {
1917  status = H5Dread(pFile->iCurrentD, pFile->iCurrentT,
1918  H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
1919  } else {
1920  memtype_id = h5MemType(pFile->iCurrentT);
1921  status = H5Dread(pFile->iCurrentD, memtype_id,
1922  H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
1923  }
1924  if (status < 0) {
1925  NXReportError("ERROR: failed to transfer dataset");
1926  return NX_ERROR;
1927  }
1928  return NX_OK;
1929 }
1930 
1931  /*-------------------------------------------------------------------------*/
1932 
1933 NXstatus NX5getinfo64(NXhandle fid, int *rank, int64_t dimension[], int *iType)
1934 {
1935  pNexusFile5 pFile;
1936  int i, iRank, mType;
1937  hsize_t myDim[H5S_MAX_RANK], vlen_bytes = 0, total_dims_size = 1;
1938  H5T_class_t tclass;
1939  hid_t memType;
1940  char *vlData = NULL;
1941 
1942  pFile = NXI5assert(fid);
1943  /* check if there is an Dataset open */
1944  if (pFile->iCurrentD == 0) {
1945  NXReportError("ERROR: no dataset open");
1946  return NX_ERROR;
1947  }
1948 
1949  /* read information */
1950  tclass = H5Tget_class(pFile->iCurrentT);
1951  mType = hdf5ToNXType(tclass, pFile->iCurrentT);
1952  iRank = H5Sget_simple_extent_dims (pFile->iCurrentS, myDim, NULL);
1953  if (iRank == 0) {
1954  iRank = 1; /* we pretend */
1955  myDim[0] = 1;
1956  } else {
1957  H5Sget_simple_extent_dims(pFile->iCurrentS, myDim, NULL);
1958  for (i = 0; i < iRank; ++i) {
1959  total_dims_size *= myDim[i];
1960  }
1961  }
1962  /* conversion to proper ints for the platform */
1963  *iType = (int)mType;
1964  if (tclass == H5T_STRING && myDim[iRank - 1] == 1) {
1965  if (H5Tis_variable_str(pFile->iCurrentT)) {
1966  /* this will not work for arrays of strings */
1967  memType = H5Tcopy(H5T_C_S1);
1968  H5Tset_size (memType, H5T_VARIABLE);
1969  H5Dread(pFile->iCurrentD, memType, H5S_ALL, H5S_ALL, H5P_DEFAULT, &vlData);
1970  if(vlData != NULL){
1971  myDim[iRank-1] = strlen(vlData) + 1;
1972  H5Dvlen_reclaim (memType, pFile->iCurrentS, H5P_DEFAULT, &vlData);
1973  }
1974  H5Tclose(memType);
1975  } else {
1976  myDim[iRank - 1] = H5Tget_size(pFile->iCurrentT);
1977  }
1978  }
1979  *rank = (int)iRank;
1980  for (i = 0; i < iRank; i++) {
1981  dimension[i] = (int64_t) myDim[i];
1982  }
1983  return NX_OK;
1984 }
1985 
1986  /*-------------------------------------------------------------------------*/
1987 
1988 NXstatus NX5getslab64(NXhandle fid, void *data, const int64_t iStart[],
1989  const int64_t iSize[])
1990 {
1991  pNexusFile5 pFile;
1992  hsize_t myStart[H5S_MAX_RANK];
1993  hsize_t mySize[H5S_MAX_RANK];
1994  hsize_t mStart[H5S_MAX_RANK];
1995  hid_t memspace, iRet;
1996  H5T_class_t tclass;
1997  hid_t memtype_id;
1998  char *tmp_data = NULL;
1999  char *data1;
2000  int i, iRank, mtype = 0;
2001 
2002  pFile = NXI5assert(fid);
2003  /* check if there is an Dataset open */
2004  if (pFile->iCurrentD == 0) {
2005  NXReportError("ERROR: no dataset open");
2006  return NX_ERROR;
2007  }
2008  tclass = H5Tget_class(pFile->iCurrentT);
2009  /* map datatypes of other platforms */
2010  if (tclass == H5T_STRING) {
2011  memtype_id = pFile->iCurrentT;
2012  } else {
2013  memtype_id = h5MemType(pFile->iCurrentT);
2014  }
2015 
2016  iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS);
2017 
2018  if (iRank == 0) {
2019  /* this is an unslabbale SCALAR */
2020  hid_t filespace = H5Dget_space(pFile->iCurrentD);
2021  memspace = H5Screate(H5S_SCALAR);
2022  H5Sselect_all(filespace);
2023  iRet =
2024  H5Dread(pFile->iCurrentD, memtype_id, memspace, filespace,
2025  H5P_DEFAULT, data);
2026  H5Sclose(filespace);
2027  } else {
2028 
2029  for (i = 0; i < iRank; i++) {
2030  myStart[i] = (hssize_t) iStart[i];
2031  mySize[i] = (hsize_t) iSize[i];
2032  mStart[i] = (hsize_t) 0;
2033  }
2034 
2035  /*
2036  * this does not work for multidimensional string arrays.
2037  */
2038  if (tclass == H5T_STRING) {
2039  mtype = NX_CHAR;
2040  if (mySize[0] == 1) {
2041  mySize[0] = H5Tget_size(pFile->iCurrentT);
2042  }
2043  tmp_data = (char *)malloc((size_t) mySize[0]);
2044  memset(tmp_data, 0, sizeof(mySize[0]));
2045  iRet =
2046  H5Sselect_hyperslab(pFile->iCurrentS,
2047  H5S_SELECT_SET, mStart, NULL,
2048  mySize, NULL);
2049  } else {
2050  iRet =
2051  H5Sselect_hyperslab(pFile->iCurrentS,
2052  H5S_SELECT_SET, myStart, NULL,
2053  mySize, NULL);
2054  }
2055  /* define slab */
2056  /* deal with HDF errors */
2057  if (iRet < 0) {
2058  NXReportError("ERROR: selecting slab failed");
2059  return NX_ERROR;
2060  }
2061 
2062  memspace = H5Screate_simple(iRank, mySize, NULL);
2063  iRet = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, mStart,
2064  NULL, mySize, NULL);
2065  if (iRet < 0) {
2066  NXReportError("ERROR: selecting memspace failed");
2067  return NX_ERROR;
2068  }
2069  /* read slab */
2070  if (mtype == NX_CHAR) {
2071  iRet =
2072  H5Dread(pFile->iCurrentD, memtype_id, H5S_ALL,
2073  H5S_ALL, H5P_DEFAULT, tmp_data);
2074  data1 = tmp_data + myStart[0];
2075  strncpy((char *)data, data1, (size_t) iSize[0]);
2076  free(tmp_data);
2077  } else {
2078  iRet =
2079  H5Dread(pFile->iCurrentD, memtype_id, memspace,
2080  pFile->iCurrentS, H5P_DEFAULT, data);
2081  }
2082  }
2083  /* cleanup */
2084  H5Sclose(memspace);
2085  H5Tclose(tclass);
2086 
2087  if (iRet < 0) {
2088  NXReportError("ERROR: reading slab failed");
2089  return NX_ERROR;
2090  }
2091  return NX_OK;
2092 }
2093 
2094  /*-------------------------------------------------------------------------*/
2095 
2096  /* Operator function. */
2097 
2098 herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t * unused,
2099  void *opdata)
2100 {
2101  *((char **)opdata) = strdup(name);
2102  return 1;
2103 }
2104 
2105 NXstatus NX5getnextattr(NXhandle fileid, NXname pName, int *iLength, int *iType)
2106 {
2107  int rank, status;
2108  int mydim[H5S_MAX_RANK];
2109 
2110  status = NX5getnextattra(fileid, pName, &rank, mydim, iType);
2111 
2112  if (status != NX_OK)
2113  return status;
2114 
2115  if (rank == 0 || (rank == 1 && mydim[0] == 1)) {
2116  *iLength = 1;
2117  return NX_OK;
2118  }
2119 
2120  if (rank == 1 && *iType == NX_CHAR) {
2121  *iLength = mydim[0];
2122  return NX_OK;
2123  }
2124 
2125  NXReportError("ERROR iterating through attributes found array attribute not understood by this api");
2126  return NX_ERROR;
2127 }
2128 
2129  /*-------------------------------------------------------------------------*/
2130 
2131 NXstatus NX5getattr(NXhandle fid, const char *name,
2132  void *data, int *datalen, int *iType)
2133 {
2134  pNexusFile5 pFile;
2135  int i;
2136  hid_t vid, iNew;
2137  hsize_t ndims, dims[H5S_MAX_RANK], totalsize;
2138  herr_t iRet;
2139  hid_t type, filespace;
2140  char pBuffer[256];
2141 
2142  pFile = NXI5assert(fid);
2143 
2144  type = nxToHDF5Type(*iType);
2145 
2146  vid = getAttVID(pFile);
2147  iNew = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT);
2148  if (iNew < 0) {
2149  sprintf(pBuffer, "ERROR: attribute \"%s\" not found", name);
2150  killAttVID(pFile, vid);
2151  NXReportError(pBuffer);
2152  return NX_ERROR;
2153  }
2154  pFile->iCurrentA = iNew;
2155  filespace = H5Aget_space(pFile->iCurrentA);
2156  totalsize = 1;
2157  ndims = H5Sget_simple_extent_dims(filespace, dims, NULL);
2158  for(i = 0; i < ndims; i++) {
2159  totalsize *= dims[i];
2160  }
2161  if (ndims != 0 && totalsize > 1) {
2162  NXReportError("ERROR: attribute arrays not supported by this api");
2163  return NX_ERROR;
2164  }
2165 
2166  /* finally read the data */
2167  if (type == H5T_C_S1) {
2168  iRet = readStringAttributeN(pFile->iCurrentA, data, *datalen);
2169  *datalen = (int)strlen((char *)data);
2170  } else {
2171  iRet = H5Aread(pFile->iCurrentA, type, data);
2172  *datalen = 1;
2173  }
2174 
2175  if (iRet < 0) {
2176  sprintf(pBuffer, "ERROR: could not read attribute data for \"%s\"", name);
2177  NXReportError(pBuffer);
2178  killAttVID(pFile, vid);
2179  return NX_ERROR;
2180  }
2181 
2182  H5Aclose(pFile->iCurrentA);
2183 
2184  killAttVID(pFile, vid);
2185  return NX_OK;
2186 }
2187 
2188  /*-------------------------------------------------------------------------*/
2189 
2190 NXstatus NX5getattrinfo(NXhandle fid, int *iN)
2191 {
2192  pNexusFile5 pFile;
2193  int idx;
2194  hid_t vid;
2195  H5O_info_t oinfo;
2196 
2197  pFile = NXI5assert(fid);
2198  idx = 0;
2199  *iN = idx;
2200 
2201  vid = getAttVID(pFile);
2202 
2203  H5Oget_info(vid, &oinfo);
2204  idx = oinfo.num_attrs;
2205  if (idx > 0) {
2206  if (pFile->iCurrentG > 0 && pFile->iCurrentD == 0) {
2207  *iN = idx - 1;
2208  } else {
2209  *iN = idx;
2210  }
2211  } else {
2212  *iN = 0;
2213  }
2214  killAttVID(pFile, vid);
2215  return NX_OK;
2216 }
2217 
2218  /*-------------------------------------------------------------------------*/
2219 NXstatus NX5getgroupID(NXhandle fileid, NXlink * sRes)
2220 {
2221  pNexusFile5 pFile;
2222  int datalen, type = NX_CHAR;
2223 
2224  pFile = NXI5assert(fileid);
2225  if (pFile->iCurrentG == 0) {
2226  return NX_ERROR;
2227  } else {
2228  /*
2229  this means: if the item is already linked: use the target attribute, else
2230  the path to the current node
2231  */
2233  datalen = 1024;
2234  memset(sRes->targetPath, 0, datalen * sizeof(char));
2235  if (NX5getattr
2236  (fileid, "target", sRes->targetPath, &datalen,
2237  &type) != NX_OK) {
2238  buildCurrentPath(pFile, sRes->targetPath, 1024);
2239  }
2241  sRes->linkType = 0;
2242  return NX_OK;
2243  }
2244  /* not reached */
2245  return NX_ERROR;
2246 }
2247 
2248  /* ------------------------------------------------------------------- */
2249 
2250 NXstatus NX5nativeexternallink(NXhandle fileid, const char *name,
2251  const char *externalfile,
2252  const char *remotetarget)
2253 {
2254  herr_t iRet;
2255  pNexusFile5 pFile;
2256  hid_t openwhere;
2257 
2258  pFile = NXI5assert(fileid);
2259 
2260  if (pFile->iCurrentG <= 0) {
2261  openwhere = pFile->iFID;
2262  } else {
2263  openwhere = pFile->iCurrentG;
2264  }
2265 
2266  iRet =
2267  H5Lcreate_external(externalfile, remotetarget, openwhere, name,
2268  H5P_DEFAULT, H5P_DEFAULT);
2269  if (iRet < 0) {
2270  NXReportError("ERROR: making external link failed");
2271  return NX_ERROR;
2272  }
2273  return NX_OK;
2274 }
2275 
2276  /* ------------------------------------------------------------------- */
2277 
2278 NXstatus NX5nativeinquirefile(NXhandle fileid, char *externalfile,
2279  const int filenamelen)
2280 {
2281  pNexusFile5 pFile;
2282  ssize_t name_size;
2283  hid_t openthing;
2284 
2285  pFile = NXI5assert(fileid);
2286  if (pFile->iCurrentD > 0) {
2287  openthing = pFile->iCurrentD;
2288  } else if (pFile->iCurrentG > 0) {
2289  openthing = pFile->iCurrentG;
2290  } else {
2291  openthing = pFile->iFID;
2292  }
2293 
2294  name_size = H5Fget_name(openthing, externalfile, filenamelen);
2295 
2296  // Check for failure again
2297  if (name_size < 0) {
2298  NXReportError("ERROR: retrieving file name");
2299  return NX_ERROR;
2300  }
2301  return NX_OK;
2302 }
2303 
2304  /* ------------------------------------------------------------------- */
2305 
2306 NXstatus NX5nativeisexternallink(NXhandle fileid, const char *name, char *url,
2307  const int urllen)
2308 {
2309  pNexusFile5 pFile;
2310  herr_t ret;
2311  H5L_info_t link_buff;
2312  char linkval_buff[1024];
2313  const char *filepath = NULL, *objpath = NULL;
2314  size_t val_size;
2315  hid_t openthing;
2316 
2317  pFile = NXI5assert(fileid);
2318  memset(url, 0, urllen);
2319 
2320  if (pFile->iCurrentG > 0) {
2321  openthing = pFile->iCurrentG;
2322  } else {
2323  openthing = pFile->iFID;
2324  }
2325 
2326  ret = H5Lget_info(openthing, name, &link_buff, H5P_DEFAULT);
2327  if (ret < 0 || link_buff.type != H5L_TYPE_EXTERNAL) {
2328  return NX_ERROR;
2329  }
2330 
2331  val_size = link_buff.u.val_size;
2332  if (val_size > sizeof(linkval_buff)) {
2333  NXReportError("ERROR: linkval_buff too small");
2334  return NX_ERROR;
2335  }
2336 
2337  ret = H5Lget_val(openthing, name, linkval_buff, val_size, H5P_DEFAULT);
2338  if (ret < 0) {
2339  NXReportError("ERROR: H5Lget_val failed");
2340  return NX_ERROR;
2341  }
2342 
2343  ret =
2344  H5Lunpack_elink_val(linkval_buff, val_size, NULL, &filepath,
2345  &objpath);
2346  if (ret < 0) {
2347  NXReportError("ERROR: H5Lunpack_elink_val failed");
2348  return NX_ERROR;
2349  }
2350 
2351  snprintf(url, urllen - 1, "nxfile://%s#%s", filepath, objpath);
2352  return NX_OK;
2353 
2354 }
2355 
2356 /* ------------------------------------------------------------------- */
2357 
2358 NXstatus NX5sameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID)
2359 {
2360  NXI5assert(fileid);
2361  if ((strcmp(pFirstID->targetPath, pSecondID->targetPath) == 0)) {
2362  return NX_OK;
2363  } else {
2364  return NX_ERROR;
2365  }
2366 }
2367 
2368 /*-------------------------------------------------------------------------*/
2369 
2370 NXstatus NX5initattrdir(NXhandle fid)
2371 {
2372  pNexusFile5 pFile;
2373 
2374  pFile = NXI5assert(fid);
2375  NXI5KillAttDir(pFile);
2376  return NX_OK;
2377 }
2378 
2379 /*-------------------------------------------------------------------------*/
2380 
2381 NXstatus NX5initgroupdir(NXhandle fid)
2382 {
2383  pNexusFile5 pFile;
2384 
2385  pFile = NXI5assert(fid);
2386  NXI5KillDir(pFile);
2387  return NX_OK;
2388 }
2389 
2390 /*------------------------------------------------------------------------*/
2391 NXstatus NX5putattra(NXhandle handle, CONSTCHAR* name, const void* data, const int rank, const int dim[], const int iType)
2392 {
2393  hid_t datatype1, dataspace;
2394  hid_t type, cparms = -1;
2395  pNexusFile5 pFile;
2396  char pBuffer[256];
2397  int i;
2398  hid_t vid, iATT;
2399  herr_t iRet;
2400  hsize_t mydim[H5S_MAX_RANK];
2401 
2402  pFile = NXI5assert(handle);
2403 
2404  for (i = 0; i < rank; i++) {
2405  mydim[i] = dim[i];
2406  }
2407 
2408  /* determine vid */
2409  vid = getAttVID(pFile);
2410  iATT = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT);
2411  if (iATT > 0) {
2412  H5Aclose(iATT);
2413  iRet = H5Adelete(vid, name);
2414  if (iRet < 0) {
2415  NXReportError("ERROR: old attribute cannot be removed! ");
2416  killAttVID(pFile, vid);
2417  return NX_ERROR;
2418  }
2419  }
2420 
2421  if (rank < 0) {
2422  sprintf(pBuffer, "ERROR: invalid rank specified %s", name);
2423  NXReportError(pBuffer);
2424  return NX_ERROR;
2425  }
2426 
2427  type = nxToHDF5Type(iType);
2428 
2429  datatype1 = H5Tcopy(type);
2430  if (iType == NX_CHAR) {
2431  H5Tset_size(datatype1, dim[rank-1]);
2432  dataspace = H5Screate_simple(rank-1, mydim, NULL);
2433  } else {
2434  dataspace = H5Screate_simple(rank, mydim, NULL);
2435  }
2436 
2437  iATT = H5Acreate(vid, (char *)name, datatype1,
2438  dataspace, H5P_DEFAULT, H5P_DEFAULT);
2439 
2440  if (iATT < 0) {
2441  NXReportError("ERROR: creating attribute failed");
2442  return NX_ERROR;
2443  } else {
2444  pFile->iCurrentA = iATT;
2445  }
2446  if (cparms != -1) {
2447  iRet = H5Pclose(cparms);
2448  }
2449 
2450  iRet = H5Awrite(pFile->iCurrentA, datatype1, data);
2451  if (iRet < 0) {
2452  NXReportError("ERROR: failure to write attribute");
2453  return NX_ERROR;
2454  }
2455 
2456  iRet = H5Sclose(dataspace);
2457  iRet = H5Tclose(datatype1);
2458  iRet = H5Aclose(pFile->iCurrentA);
2459  pFile->iCurrentA = 0;
2460  if (iRet < 0) {
2461  NXReportError("ERROR: HDF cannot close attribute");
2462  return NX_ERROR;
2463  }
2464 
2465  return NX_OK;
2466 }
2467 
2468 /*------------------------------------------------------------------------*/
2469 NXstatus NX5getnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
2470 {
2471  pNexusFile5 pFile;
2472  herr_t iRet;
2473  char *iname = NULL;
2474  hsize_t idx, intern_idx = -1;
2475  hid_t vid;
2476  H5O_info_t oinfo;
2477 
2478  pFile = NXI5assert(handle);
2479 
2480  vid = getAttVID(pFile);
2481 
2482  pName[0] = '\0';
2483  idx = pFile->iAtt5.iCurrentIDX;
2484  iRet = 0;
2485 
2486  H5Oget_info(vid, &oinfo);
2487  intern_idx = oinfo.num_attrs;
2488  if (intern_idx == idx) {
2489  killAttVID(pFile, vid);
2490  return NX_EOD;
2491  }
2492 
2493  if (intern_idx > idx) {
2494  iRet = H5Aiterate(vid, H5_INDEX_CRT_ORDER, H5_ITER_INC, &idx,
2495  attr_info, &iname);
2496  } else {
2497  iRet = 0;
2498  }
2499  intern_idx = -1;
2500  if (iRet < 0) {
2501  NXReportError("ERROR: iterating through attribute list");
2502  killAttVID(pFile, vid);
2503  return NX_ERROR;
2504  }
2505  pFile->iAtt5.iCurrentIDX++;
2506  if (iname != NULL) {
2507  if (strcmp(iname, "NX_class") == 0 && pFile->iCurrentG != 0
2508  && pFile->iCurrentD == 0) {
2509  /*
2510  skip NXclass attribute which is internal
2511  */
2512  free(iname);
2513  iname = NULL;
2514  killAttVID(pFile, vid);
2515  return NX5getnextattra(handle, pName, rank, dim, iType);
2516  }
2517  strcpy(pName, iname);
2518  free(iname);
2519  iname = NULL;
2520  } else {
2521  NXReportError("ERROR: encountered nameless attribute");
2522  killAttVID(pFile, vid);
2523  return NX_ERROR;
2524  }
2525 
2526  killAttVID(pFile, vid);
2527  return NX5getattrainfo(handle, pName, rank, dim, iType);
2528 }
2529 /*------------------------------------------------------------------------*/
2530 NXstatus NX5getattra(NXhandle handle, const char* name, void* data)
2531 {
2532  pNexusFile5 pFile;
2533  int i, iStart[H5S_MAX_RANK], status;
2534  hid_t vid;
2535  hid_t memtype_id, filespace, datatype;
2536  H5T_class_t tclass;
2537  hsize_t ndims, dims[H5S_MAX_RANK];
2538  htri_t is_vlen_str = 0; /* false */
2539  char **vstrdata = NULL;
2540 
2541  pFile = NXI5assert(handle);
2542 
2543  vid = getAttVID(pFile);
2544  pFile->iCurrentA = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT);
2545  if (pFile->iCurrentA < 0) {
2546  pFile->iCurrentA = 0;
2547  NXReportError("ERROR: unable to open attribute");
2548  return NX_ERROR;
2549  }
2550  filespace = H5Aget_space(pFile->iCurrentA);
2551  datatype = H5Aget_type(pFile->iCurrentA);
2552  ndims = H5Sget_simple_extent_dims(filespace, dims, NULL);
2553 
2554  is_vlen_str = H5Tis_variable_str(datatype);
2555  if (ndims == 0 && is_vlen_str) {
2556  /* this assumes a fixed size - is this dangerous? */
2557  char *strdata = calloc(512, sizeof(char));
2558  status = H5Aread(pFile->iCurrentA, H5S_ALL, &strdata);
2559  if (status >= 0)
2560  strncpy(data, strdata, strlen(strdata));
2561  free(strdata);
2562 
2563  H5Sclose(filespace);
2564  H5Tclose(datatype);
2565  if (status < 0)
2566  return NX_ERROR;
2567  return NX_OK;
2568  }
2569  tclass = H5Tget_class(datatype);
2570  /* stop gap kludge for fixed length strings */
2571  if (tclass == H5T_STRING && !is_vlen_str) {
2572  char *datatmp = NULL;
2573  status = readStringAttribute(pFile->iCurrentA, &datatmp);
2574  if (status < 0)
2575  return NX_ERROR;
2576  strcpy(data, datatmp);
2577  free(datatmp);
2578  return NX_OK;
2579  }
2580 
2581  memset(iStart, 0, H5S_MAX_RANK * sizeof(int));
2582  /* map datatypes of other plateforms */
2583  if (is_vlen_str) {
2584  vstrdata = (char **)malloc((size_t) dims[0] * sizeof(char *));
2585  memtype_id = H5Tcopy(H5T_C_S1);
2586  H5Tset_size(memtype_id, H5T_VARIABLE);
2587  status = H5Aread(pFile->iCurrentA, memtype_id, vstrdata);
2588  ((char *)data)[0] = '\0';
2589  if (status >= 0) {
2590  for (i = 0; i < dims[0]; ++i) {
2591  if (vstrdata[i] != NULL) {
2592  strcat((char *)data, vstrdata[i]);
2593  }
2594  }
2595  }
2596  H5Dvlen_reclaim(memtype_id, pFile->iCurrentS, H5P_DEFAULT,
2597  vstrdata);
2598  free(vstrdata);
2599  H5Tclose(memtype_id);
2600  } else if (tclass == H5T_STRING) {
2601  status = H5Aread(pFile->iCurrentA, datatype, data);
2602  } else {
2603  memtype_id = h5MemType(datatype);
2604  status = H5Aread(pFile->iCurrentA, memtype_id, data);
2605  }
2606  if (status < 0) {
2607  NXReportError("ERROR: failed to read attribute");
2608  return NX_ERROR;
2609  }
2610 return NX_OK;
2611 }
2612 /*------------------------------------------------------------------------*/
2613 NXstatus NX5getattrainfo(NXhandle handle, NXname name, int *rank, int dim[], int *iType)
2614 {
2615  pNexusFile5 pFile;
2616  int i, iRet, mType;
2617  hid_t vid;
2618  hid_t filespace, attrt, memtype;
2619  hsize_t myDim[H5S_MAX_RANK], myrank;
2620  H5T_class_t tclass;
2621  char *vlStr = NULL;
2622 
2623  pFile = NXI5assert(handle);
2624 
2625  vid = getAttVID(pFile);
2626  pFile->iCurrentA = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT);
2627  if (pFile->iCurrentA < 0) {
2628  pFile->iCurrentA = 0;
2629  NXReportError("ERROR: unable to open attribute");
2630  return NX_ERROR;
2631  }
2632 
2633  filespace = H5Aget_space(pFile->iCurrentA);
2634  myrank = H5Sget_simple_extent_ndims(filespace);
2635  iRet = H5Sget_simple_extent_dims(filespace, myDim, NULL);
2636  if (iRet < 0) {
2637  NXReportError("ERROR: Cannot determine attribute dimensions");
2638  return NX_ERROR;
2639  }
2640 
2641  /* read information */
2642  attrt = H5Aget_type(pFile->iCurrentA);
2643  tclass = H5Tget_class(attrt);
2644  mType = hdf5ToNXType(tclass, attrt);
2645 
2646  /* conversion to proper ints for the platform */
2647  *iType = (int)mType;
2648 
2649  if (tclass == H5T_STRING) {
2650  myrank++;
2651  if (H5Tis_variable_str(attrt)) {
2652  memtype = H5Tcopy (H5T_C_S1);
2653  H5Tset_size (memtype, H5T_VARIABLE);
2654  H5Aread(pFile->iCurrentA, memtype,&vlStr);
2655  if(vlStr != NULL){
2656  myDim[myrank - 1] = strlen(vlStr) +1;
2657  H5Dvlen_reclaim (memtype, pFile->iCurrentA, H5P_DEFAULT, &vlStr);
2658  }
2659  H5Tclose(memtype);
2660  } else {
2661  myDim[myrank - 1] = H5Tget_size(attrt);
2662  }
2663  } else if (myrank == 0) {
2664  myrank = 1; /* we pretend */
2665  myDim[0] = 1;
2666  }
2667 
2668  for (i = 0; i < myrank; i++) {
2669  dim[i] = (int) myDim[i];
2670  }
2671  *rank = (int) myrank;
2672 
2673  return NX_OK;
2674 }
2675 
2676 /*------------------------------------------------------------------------*/
2677 void NX5assignFunctions(pNexusFunction fHandle)
2678 {
2679  fHandle->nxclose = NX5close;
2680  fHandle->nxreopen = NX5reopen;
2681  fHandle->nxflush = NX5flush;
2682  fHandle->nxmakegroup = NX5makegroup;
2683  fHandle->nxopengroup = NX5opengroup;
2684  fHandle->nxclosegroup = NX5closegroup;
2685  fHandle->nxmakedata64 = NX5makedata64;
2687  fHandle->nxcompress = NX5compress;
2688  fHandle->nxopendata = NX5opendata;
2689  fHandle->nxclosedata = NX5closedata;
2690  fHandle->nxputdata = NX5putdata;
2691  fHandle->nxputattr = NX5putattr;
2692  fHandle->nxputslab64 = NX5putslab64;
2693  fHandle->nxgetdataID = NX5getdataID;
2694  fHandle->nxmakelink = NX5makelink;
2695  fHandle->nxmakenamedlink = NX5makenamedlink;
2696  fHandle->nxgetdata = NX5getdata;
2697  fHandle->nxgetinfo64 = NX5getinfo64;
2698  fHandle->nxgetnextentry = NX5getnextentry;
2699  fHandle->nxgetslab64 = NX5getslab64;
2700  fHandle->nxgetnextattr = NX5getnextattr;
2701  fHandle->nxgetattr = NX5getattr;
2702  fHandle->nxgetattrinfo = NX5getattrinfo;
2703  fHandle->nxgetgroupID = NX5getgroupID;
2704  fHandle->nxgetgroupinfo = NX5getgroupinfo;
2705  fHandle->nxsameID = NX5sameID;
2706  fHandle->nxinitgroupdir = NX5initgroupdir;
2707  fHandle->nxinitattrdir = NX5initattrdir;
2708  fHandle->nxprintlink = NX5printlink;
2709  fHandle->nxnativeexternallink = NX5nativeexternallink;
2710  fHandle->nxnativeinquirefile = NX5nativeinquirefile;
2711  fHandle->nxnativeisexternallink = NX5nativeisexternallink;
2712  fHandle->nxputattra = NX5putattra;
2713  fHandle->nxgetnextattra = NX5getnextattra;
2714  fHandle->nxgetattra = NX5getattra;
2715  fHandle->nxgetattrainfo = NX5getattrainfo;
2716 }
2717 
2718 #endif /* HDF5 */
NXstatus NX5getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType)
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 NX5opendata(NXhandle handle, CONSTCHAR *label)
NXstatus NX5printlink(NXhandle handle, NXlink *pLink)
void NXMEnableErrorReporting()
Definition: napi.c:375
NXstatus(* nxinitgroupdir)(NXhandle handle)
Definition: napi_internal.h:73
NXstatus NX5getnextentry(NXhandle handle, NXname name, NXname nxclass, int *datatype)
NXstatus NX5getattrinfo(NXhandle handle, int *no_items)
NXstatus(* nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType)
Definition: napi_internal.h:64
#define NX_INT64
Definition: nxdataset.h:47
NXstatus(* nxgetattrinfo)(NXhandle handle, int *no_items)
Definition: napi_internal.h:69
NXstatus NX5getattrainfo(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
NXstatus(* nxgetnextattra)(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi_internal.h:65
NXstatus NX5getattr(NXhandle handle, const char *name, void *data, int *iDataLen, int *iType)
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 NX5closedata(NXhandle handle)
NXstatus(* nxcompmakedata64)(NXhandle handle, CONSTCHAR *label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[])
Definition: napi_internal.h:49
NXstatus(* nxnativeinquirefile)(NXhandle handle, char *externalfile, const int filenamelength)
Definition: napi_internal.h:78
#define NX_INT8
Definition: nxdataset.h:41
NXstatus NX5putslab64(NXhandle handle, const void *data, const int64_t start[], const int64_t size[])
NXstatus NX5makegroup(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
NXstatus NX5putattra(NXhandle handle, CONSTCHAR *name, const void *data, const int rank, const int dim[], const int iType)
NXstatus(* nxgetgroupinfo)(NXhandle handle, int *no_items, NXname name, NXname nxclass)
Definition: napi_internal.h:71
void NX5assignFunctions(pNexusFunction fHandle)
#define NX_FLOAT64
Definition: nxdataset.h:40
NXstatus(* nxputdata)(NXhandle handle, const void *data)
Definition: napi_internal.h:53
NXstatus(* nxgetdata)(NXhandle handle, void *data)
Definition: napi_internal.h:60
NXstatus NX5closegroup(NXhandle handle)
NXstatus(* nxprintlink)(NXhandle handle, NXlink *link)
Definition: napi_internal.h:76
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
NXstatus NX5flush(NXhandle *pHandle)
NXstatus(* nxgetattra)(NXhandle handle, const char *name, void *data)
Definition: napi_internal.h:67
NXstatus(* nxmakenamedlink)(NXhandle handle, CONSTCHAR *newname, NXlink *pLink)
Definition: napi_internal.h:59
#define NX_FLOAT32
Definition: nxdataset.h:39
NXstatus(* nxflush)(NXhandle *pHandle)
Definition: napi_internal.h:44
NXstatus(* nxopengroup)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
Definition: napi_internal.h:46
NXstatus NX5initgroupdir(NXhandle handle)
NXstatus NX5open(CONSTCHAR *filename, NXaccess access_method, NXhandle *pHandle)
NXstatus(* nxmakelink)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:58
NXstatus(* nxcompress)(NXhandle handle, int compr_type)
Definition: napi_internal.h:50
NXstatus NX5makedata64(NXhandle handle, CONSTCHAR *label, int datatype, int rank, int64_t dim[])
#define NX5SIGNATURE
Definition: napi5.h:4
NXstatus NX5getgroupID(NXhandle handle, NXlink *pLink)
long nx_cacheSize
Definition: napi.c:248
NXstatus NX5putattr(NXhandle handle, CONSTCHAR *name, const void *data, int iDataLen, int iType)
NXstatus NX5compmakedata64(NXhandle handle, CONSTCHAR *label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[])
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(* nxgetslab64)(NXhandle handle, void *data, const int64_t start[], const int64_t size[])
Definition: napi_internal.h:63
NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle *pNewHandle)
NXstatus NX5getnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
NXstatus(* nxsameID)(NXhandle handle, NXlink *pFirstID, NXlink *pSecondID)
Definition: napi_internal.h:72
NXstatus NX5getgroupinfo(NXhandle handle, int *no_items, NXname name, NXname nxclass)
NXstatus NX5compress(NXhandle handle, int compr_type)
NXstatus NX5initattrdir(NXhandle handle)
NXstatus(* nxputattra)(NXhandle handle, CONSTCHAR *name, const void *data, const int rank, const int dim[], const int iType)
Definition: napi_internal.h:55
NXstatus NX5getslab64(NXhandle handle, void *data, const int64_t start[], const int64_t size[])
NXstatus(* nxreopen)(NXhandle pOrigHandle, NXhandle *pNewHandle)
Definition: napi_internal.h:42
void NXReportError(char *string)
Definition: napi.c:305
NXstatus NX5makelink(NXhandle handle, NXlink *pLink)
void NXMDisableErrorReporting()
Definition: napi.c:360
NXstatus NX5opengroup(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
#define NX_UINT16
Definition: nxdataset.h:44
NXstatus NX5putdata(NXhandle handle, const void *data)
NXstatus(* nxclosedata)(NXhandle handle)
Definition: napi_internal.h:52
NXstatus NX5getinfo64(NXhandle handle, int *rank, int64_t dimension[], int *datatype)
NXstatus(* nxclosegroup)(NXhandle handle)
Definition: napi_internal.h:47
NXstatus(* nxnativeexternallink)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *externalfile, CONSTCHAR *remotetarget)
Definition: napi_internal.h:77
herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *op_data)
NXstatus NX5getattra(NXhandle handle, const char *name, void *data)
char * NXIformatNeXusTime()
Definition: napi.c:1973
#define NX_CHAR
Definition: nxdataset.h:49
NXstatus NX5close(NXhandle *pHandle)
NXstatus(* nxinitattrdir)(NXhandle handle)
Definition: napi_internal.h:74
#define NX_UINT64
Definition: nxdataset.h:48
#define NX_UINT32
Definition: nxdataset.h:46
#define NX_INT32
Definition: nxdataset.h:45
NXstatus NX5getdata(NXhandle handle, void *data)
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(* nxnativeisexternallink)(NXhandle handle, CONSTCHAR *name, char *url, int urllen)
Definition: napi_internal.h:79
NXstatus NX5getdataID(NXhandle handle, NXlink *pLink)
NXstatus(* nxgetgroupID)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:70
herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata)