NeXus  4.4.3
 All Data Structures Files Functions Variables Typedefs Macros Pages
napi.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------
2  NeXus - Neutron & X-ray Common Data Format
3 
4  Application Program Interface Routines
5 
6  Copyright (C) 1997-2014 NeXus International Advisory Committee
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 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <time.h>
32 #include <stdarg.h>
33 
34 #include <napi.h>
35 #include <napi_internal.h>
36 #include <nxconfig.h>
37 #include "nxstack.h"
38 
39 /*---------------------------------------------------------------------
40  Recognized and handled napimount URLS
41  -----------------------------------------------------------------------*/
42 #define NXBADURL 0
43 #define NXFILE 1
44 
45 /*--------------------------------------------------------------------*/
46 /* static int iFortifyScope; */
47 /*----------------------------------------------------------------------
48  This is a section with code for searching the NX_LOAD_PATH
49  -----------------------------------------------------------------------*/
50 #ifdef _WIN32
51 #define LIBSEP ";"
52 #define PATHSEP "\\"
53 #define THREAD_LOCAL __declspec(thread)
54 #else
55 #define LIBSEP ":"
56 #define PATHSEP "/"
57 #define THREAD_LOCAL __thread
58 #endif
59 
60 #ifdef _MSC_VER
61 #define snprintf _snprintf
62 #endif /* _MSC_VER */
63 
64 #include "nx_stptok.h"
65 
66 #if defined(_WIN32)
67 /*
68  * HDF5 on windows does not do locking for multiple threads conveniently so we will implement it ourselves.
69  * Freddie Akeroyd, 16/06/2011
70  */
71 #include <windows.h>
72 
73 static CRITICAL_SECTION nx_critical;
74 
75 static int nxilock()
76 {
77  static int first_call = 1;
78  if (first_call) {
79  first_call = 0;
80  InitializeCriticalSection(&nx_critical);
81  }
82  EnterCriticalSection(&nx_critical);
83  return NX_OK;
84 }
85 
86 static int nxiunlock(int ret)
87 {
88  LeaveCriticalSection(&nx_critical);
89  return ret;
90 }
91 
92 #define LOCKED_CALL(__call) \
93  ( nxilock() , nxiunlock(__call) )
94 
95 #elif HAVE_LIBPTHREAD
96 
97 #include <pthread.h>
98 
99 static pthread_mutex_t nx_mutex;
100 
101 #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(__FreeBSD__)
102 #define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE
103 #else
104 #define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE_NP
105 #endif /* PTHREAD_MUTEX_RECURSIVE */
106 
107 static void nx_pthread_init()
108 {
109  pthread_mutexattr_t attr;
110  pthread_mutexattr_init(&attr);
111  pthread_mutexattr_settype(&attr, RECURSIVE_LOCK);
112  pthread_mutex_init(&nx_mutex, &attr);
113 }
114 
115 static int nxilock()
116 {
117  static pthread_once_t once_control = PTHREAD_ONCE_INIT;
118  if (pthread_once(&once_control, nx_pthread_init) != 0) {
119  NXReportError("pthread_once failed");
120  return NX_ERROR;
121  }
122  if (pthread_mutex_lock(&nx_mutex) != 0) {
123  NXReportError("pthread_mutex_lock failed");
124  return NX_ERROR;
125  }
126  return NX_OK;
127 }
128 
129 static int nxiunlock(int ret)
130 {
131  if (pthread_mutex_unlock(&nx_mutex) != 0) {
132  NXReportError("pthread_mutex_unlock failed");
133  return NX_ERROR;
134  }
135  return ret;
136 }
137 
138 #define LOCKED_CALL(__call) \
139  ( nxilock() , nxiunlock(__call) )
140 
141 #else
142 
143 #define LOCKED_CALL(__call) \
144  __call
145 
146 #endif /* _WIN32 */
147 
151 int validNXName(const char *name, int allow_colon)
152 {
153  int i;
154  if (name == NULL) {
155  return 0;
156  }
157  for (i = 0; i < (int)strlen(name); ++i) {
158  if ((name[i] >= 'a' && name[i] <= 'z') ||
159  (name[i] >= 'A' && name[i] <= 'Z') ||
160  (name[i] >= '0' && name[i] <= '9') || (name[i] == '_')) {
161  ;
162  } else if (allow_colon && name[i] == ':') {
163  ;
164  } else {
165  return 0;
166  }
167  }
168  return 1;
169 }
170 
171 static int64_t *dupDimsArray(int *dims_array, int rank)
172 {
173  int i;
174  int64_t *dims64 = (int64_t *) malloc(rank * sizeof(int64_t));
175  if (dims64 != NULL) {
176  for (i = 0; i < rank; ++i) {
177  dims64[i] = dims_array[i];
178  }
179  }
180  return dims64;
181 }
182 
183 /*---------------------------------------------------------------------
184  wrapper for getenv. This is a future proofing thing for porting to OS
185  which have different ways of accessing environment variables
186  --------------------------------------------------------------------*/
187 static char *nxgetenv(const char *name)
188 {
189  return getenv(name);
190 }
191 
192 /*----------------------------------------------------------------------*/
193 static int canOpen(char *filename)
194 {
195  FILE *fd = NULL;
196 
197  fd = fopen(filename, "r");
198  if (fd != NULL) {
199  fclose(fd);
200  return 1;
201  } else {
202  return 0;
203  }
204 }
205 
206 /*--------------------------------------------------------------------*/
207 static char *locateNexusFileInPath(char *startName)
208 {
209  char *loadPath = NULL, *testPath = NULL, *pPtr = NULL;
210  char pathPrefix[256];
211  int length;
212 
213  if (canOpen(startName)) {
214  return strdup(startName);
215  }
216 
217  loadPath = nxgetenv("NX_LOAD_PATH");
218  if (loadPath == NULL) {
219  /* file not found will be issued by upper level code */
220  return strdup(startName);
221  }
222 
223  pPtr = stptok(loadPath, pathPrefix, 255, LIBSEP);
224  while (pPtr != NULL) {
225  length =
226  (int)strlen(pathPrefix) + (int)strlen(startName) +
227  (int)strlen(PATHSEP) + 2;
228  testPath = (char *)malloc(length * sizeof(char));
229  if (testPath == NULL) {
230  return strdup(startName);
231  }
232  memset(testPath, 0, length * sizeof(char));
233  strcpy(testPath, pathPrefix);
234  strcat(testPath, PATHSEP);
235  strcat(testPath, startName);
236  if (canOpen(testPath)) {
237  return (testPath);
238  }
239  free(testPath);
240  pPtr = stptok(pPtr, pathPrefix, 255, LIBSEP);
241  }
242  return strdup(startName);
243 }
244 
245 /*------------------------------------------------------------------------
246  HDF-5 cache size special stuff
247  -------------------------------------------------------------------------*/
248 long nx_cacheSize = 1024000; /* 1MB, HDF-5 default */
249 
250 NXstatus NXsetcache(long newVal)
251 {
252  if (newVal > 0) {
253  nx_cacheSize = newVal;
254  return NX_OK;
255  }
256  return NX_ERROR;
257 }
258 
259 #ifdef WITH_MXML
260 /*-----------------------------------------------------------------------*/
261 static NXstatus NXisXML(CONSTCHAR * filename)
262 {
263  FILE *fd = NULL;
264  char line[132];
265 
266  fd = fopen(filename, "r");
267  if (fd) {
268  int fgets_ok = (fgets(line, 131, fd) != NULL);
269  fclose(fd);
270  if (fgets_ok) {
271  if (strstr(line, "?xml") != NULL) {
272  return NX_OK;
273  }
274  } else {
275  return NX_ERROR;
276  }
277  }
278  return NX_ERROR;
279 }
280 #endif
281 
282 /*-------------------------------------------------------------------------*/
283 static void NXNXNXReportError(void *pData, char *string)
284 {
285  fprintf(stderr, "%s \n", string);
286 }
287 
288  /*---------------------------------------------------------------------*/
289 
290 static void *NXEHpData = NULL;
291 static void (*NXEHIReportError) (void *pData, char *string) = NXNXNXReportError;
292 #ifdef HAVE_TLS
293 static THREAD_LOCAL void *NXEHpTData = NULL;
294 static THREAD_LOCAL void (*NXEHIReportTError) (void *pData, char *string) =
295  NULL;
296 #endif
297 
298 void NXIReportError(void *pData, char *string)
299 {
300  fprintf(stderr,
301  "Your application uses NXIReportError, but its first parameter is ignored now - you should use NXReportError.");
302  NXReportError(string);
303 }
304 
305 void NXReportError(char *string)
306 {
307 #ifdef HAVE_TLS
308  if (NXEHIReportTError) {
309  (*NXEHIReportTError) (NXEHpTData, string);
310  return;
311  }
312 #endif
313  if (NXEHIReportError) {
314  (*NXEHIReportError) (NXEHpData, string);
315  }
316 }
317 
318  /*---------------------------------------------------------------------*/
319 extern void NXMSetError(void *pData, void (*NewError) (void *pD, char *text))
320 {
321  NXEHpData = pData;
322  NXEHIReportError = NewError;
323 }
324 
325 /*----------------------------------------------------------------------*/
326 extern void NXMSetTError(void *pData, void (*NewError) (void *pD, char *text))
327 {
328 #ifdef HAVE_TLS
329  NXEHpTData = pData;
330  NXEHIReportTError = NewError;
331 #else
332  NXMSetError(pData, NewError);
333 #endif
334 }
335 
336 /*----------------------------------------------------------------------*/
337 extern ErrFunc NXMGetError()
338 {
339 #ifdef HAVE_TLS
340  if (NXEHIReportTError) {
341  return NXEHIReportTError;
342  }
343 #endif
344  return NXEHIReportError;
345 }
346 
347 /*----------------------------------------------------------------------*/
348 static void NXNXNoReport(void *pData, char *string)
349 {
350  /* do nothing */
351 }
352 
353 /*----------------------------------------------------------------------*/
354 
355 static ErrFunc last_global_errfunc = NXNXNXReportError;
356 #ifdef HAVE_TLS
357 static THREAD_LOCAL ErrFunc last_thread_errfunc = NULL;
358 #endif
359 
361 {
362 #ifdef HAVE_TLS
363  if (NXEHIReportTError) {
364  last_thread_errfunc = NXEHIReportTError;
365  NXEHIReportTError = NXNXNoReport;
366  return;
367  }
368 #endif
369  if (NXEHIReportError) {
370  last_global_errfunc = NXEHIReportError;
371  NXEHIReportError = NXNXNoReport;
372  }
373 }
374 
376 {
377 #ifdef HAVE_TLS
378  if (last_thread_errfunc) {
379  NXEHIReportTError = last_thread_errfunc;
380  last_thread_errfunc = NULL;
381  return;
382  }
383 #endif
384  if (last_global_errfunc) {
385  NXEHIReportError = last_global_errfunc;
386  last_global_errfunc = NULL;
387  }
388 }
389 
390 /*----------------------------------------------------------------------*/
391 #ifdef WITH_HDF5
392 #include "napi5.h"
393 #endif
394 #ifdef WITH_HDF4
395 #include "napi4.h"
396 #endif
397 #ifdef WITH_MXML
398 #include "nxxml.h"
399 #endif
400  /* ----------------------------------------------------------------------
401 
402  Definition of NeXus API
403 
404  --------------------------------------------------------------------- */
405 static int determineFileTypeImpl(CONSTCHAR * filename)
406 {
407  FILE *fd = NULL;
408  int iRet;
409 
410  /*
411  this is for reading, check for existence first
412  */
413  fd = fopen(filename, "r");
414  if (fd == NULL) {
415  return -1;
416  }
417  fclose(fd);
418 #ifdef WITH_HDF5
419  iRet = H5Fis_hdf5((const char *)filename);
420  if (iRet > 0) {
421  return NXACC_CREATE5;
422  }
423 #endif
424 #ifdef WITH_HDF4
425  iRet = Hishdf((const char *)filename);
426  if (iRet > 0) {
427  return NXACC_CREATE4;
428  }
429 #endif
430 #ifdef WITH_MXML
431  iRet = NXisXML(filename);
432  if (iRet == NX_OK) {
433  return NXACC_CREATEXML;
434  }
435 #endif
436  /*
437  file type not recognized
438  */
439  return 0;
440 }
441 
442 static int determineFileType(CONSTCHAR * filename)
443 {
444  return LOCKED_CALL(determineFileTypeImpl(filename));
445 }
446 
447 /*---------------------------------------------------------------------*/
448 static pNexusFunction handleToNexusFunc(NXhandle fid)
449 {
450  pFileStack fileStack = NULL;
451  fileStack = (pFileStack) fid;
452  if (fileStack != NULL) {
453  return peekFileOnStack(fileStack);
454  } else {
455  return NULL;
456  }
457 }
458 
459 /*--------------------------------------------------------------------*/
460 static NXstatus NXinternalopen(CONSTCHAR * userfilename, NXaccess am,
461  pFileStack fileStack);
462 /*----------------------------------------------------------------------*/
463 NXstatus NXopen(CONSTCHAR * userfilename, NXaccess am, NXhandle * gHandle)
464 {
465  int status;
466  pFileStack fileStack = NULL;
467 
468  *gHandle = NULL;
469  fileStack = makeFileStack();
470  if (fileStack == NULL) {
471  NXReportError("ERROR: no memory to create filestack");
472  return NX_ERROR;
473  }
474  status = NXinternalopen(userfilename, am, fileStack);
475  if (status == NX_OK) {
476  *gHandle = fileStack;
477  }
478 
479  return status;
480 }
481 
482 /*-----------------------------------------------------------------------*/
483 static NXstatus NXinternalopenImpl(CONSTCHAR * userfilename, NXaccess am,
484  pFileStack fileStack)
485 {
486  int backend_type = 0;
487  int iRet = 0;
488  pNexusFunction fHandle = NULL;
489  NXstatus retstat = NX_ERROR;
490  char error[1024];
491  char *filename = NULL;
492  int my_am = (am & NXACCMASK_REMOVEFLAGS);
493 
494  /* configure fortify
495  iFortifyScope = Fortify_EnterScope();
496  Fortify_CheckAllMemory();
497  */
498 
499  /*
500  allocate data
501  */
502  fHandle = (pNexusFunction) malloc(sizeof(NexusFunction));
503  if (fHandle == NULL) {
504  NXReportError("ERROR: no memory to create Function structure");
505  return NX_ERROR;
506  }
507  memset(fHandle, 0, sizeof(NexusFunction)); /* so any functions we miss are NULL */
508 
509  /*
510  test the strip flag. Elimnate it for the rest of the tests to work
511  */
512  fHandle->stripFlag = 1;
513  if (am & NXACC_NOSTRIP) {
514  fHandle->stripFlag = 0;
515  am = (NXaccess) (am & ~NXACC_NOSTRIP);
516  }
517  fHandle->checkNameSyntax = 0;
518  if (am & NXACC_CHECKNAMESYNTAX) {
519  fHandle->checkNameSyntax = 1;
520  am = (NXaccess) (am & ~NXACC_CHECKNAMESYNTAX);
521  }
522 
523  if (my_am == NXACC_CREATE) {
524  /* HDF4 will be used ! */
525  backend_type = NXACC_CREATE4;
526  filename = strdup(userfilename);
527  } else if (my_am == NXACC_CREATE4) {
528  /* HDF4 will be used ! */
529  backend_type = NXACC_CREATE4;
530  filename = strdup(userfilename);
531  } else if (my_am == NXACC_CREATE5) {
532  /* HDF5 will be used ! */
533  backend_type = NXACC_CREATE5;
534  filename = strdup(userfilename);
535  } else if (my_am == NXACC_CREATEXML) {
536  /* XML will be used ! */
537  backend_type = NXACC_CREATEXML;
538  filename = strdup(userfilename);
539  } else {
540  filename = locateNexusFileInPath((char *)userfilename);
541  if (filename == NULL) {
542  NXReportError("Out of memory in NeXus-API");
543  free(fHandle);
544  return NX_ERROR;
545  }
546  /* check file type hdf4/hdf5/XML for reading */
547  iRet = determineFileType(filename);
548  if (iRet < 0) {
549  snprintf(error, 1023, "failed to open %s for reading",
550  filename);
551  NXReportError(error);
552  free(filename);
553  return NX_ERROR;
554  }
555  if (iRet == 0) {
556  snprintf(error, 1023,
557  "failed to determine filetype for %s ",
558  filename);
559  NXReportError(error);
560  free(filename);
561  free(fHandle);
562  return NX_ERROR;
563  }
564  backend_type = iRet;
565  }
566  if (filename == NULL) {
567  NXReportError("Out of memory in NeXus-API");
568  return NX_ERROR;
569  }
570 
571  if (backend_type == NXACC_CREATE4) {
572  /* HDF4 type */
573 #ifdef WITH_HDF4
574  NXhandle hdf4_handle = NULL;
575  retstat = NX4open((const char *)filename, am, &hdf4_handle);
576  if (retstat != NX_OK) {
577  free(fHandle);
578  free(filename);
579  return retstat;
580  }
581  fHandle->pNexusData = hdf4_handle;
582  fHandle->access_mode = backend_type || (NXACC_READ && am);
583  NX4assignFunctions(fHandle);
584  pushFileStack(fileStack, fHandle, filename);
585 #else
587  ("ERROR: Attempt to create HDF4 file when not linked with HDF4");
588  retstat = NX_ERROR;
589 #endif /* HDF4 */
590  free(filename);
591  return retstat;
592  } else if (backend_type == NXACC_CREATE5) {
593  /* HDF5 type */
594 #ifdef WITH_HDF5
595  NXhandle hdf5_handle = NULL;
596  retstat = NX5open(filename, am, &hdf5_handle);
597  if (retstat != NX_OK) {
598  free(fHandle);
599  free(filename);
600  return retstat;
601  }
602  fHandle->pNexusData = hdf5_handle;
603  fHandle->access_mode = backend_type || (NXACC_READ && am);
604  NX5assignFunctions(fHandle);
605  pushFileStack(fileStack, fHandle, filename);
606 #else
608  ("ERROR: Attempt to create HDF5 file when not linked with HDF5");
609  retstat = NX_ERROR;
610 #endif /* HDF5 */
611  free(filename);
612  return retstat;
613  } else if (backend_type == NXACC_CREATEXML) {
614  /*
615  XML type
616  */
617 #ifdef WITH_MXML
618  NXhandle xmlHandle = NULL;
619  retstat = NXXopen(filename, am, &xmlHandle);
620  if (retstat != NX_OK) {
621  free(fHandle);
622  free(filename);
623  return retstat;
624  }
625  fHandle->pNexusData = xmlHandle;
626  fHandle->access_mode = backend_type || (NXACC_READ && am);
627  NXXassignFunctions(fHandle);
628  pushFileStack(fileStack, fHandle, filename);
629 #else
631  ("ERROR: Attempt to create XML file when not linked with XML");
632  retstat = NX_ERROR;
633 #endif
634  } else {
636  ("ERROR: Format not readable by this NeXus library");
637  retstat = NX_ERROR;
638  }
639  if (filename != NULL) {
640  free(filename);
641  }
642  return retstat;
643 }
644 
645 static NXstatus NXinternalopen(CONSTCHAR * userfilename, NXaccess am,
646  pFileStack fileStack)
647 {
648  return LOCKED_CALL(NXinternalopenImpl(userfilename, am, fileStack));
649 }
650 
651 NXstatus NXreopen(NXhandle pOrigHandle, NXhandle * pNewHandle)
652 {
653  pFileStack newFileStack;
654  pFileStack origFileStack = (pFileStack) pOrigHandle;
655  pNexusFunction fOrigHandle = NULL, fNewHandle = NULL;
656  *pNewHandle = NULL;
657  newFileStack = makeFileStack();
658  if (newFileStack == NULL) {
659  NXReportError("ERROR: no memory to create filestack");
660  return NX_ERROR;
661  }
662  // The code below will only open the last file on a stack
663  // for the moment raise an error, but this behaviour may be OK
664  if (fileStackDepth(origFileStack) > 0) {
666  ("ERROR: handle stack referes to many files - cannot reopen");
667  return NX_ERROR;
668  }
669  fOrigHandle = peekFileOnStack(origFileStack);
670  if (fOrigHandle->nxreopen == NULL) {
672  ("ERROR: NXreopen not implemented for this underlying file format");
673  return NX_ERROR;
674  }
675  fNewHandle = (NexusFunction *) malloc(sizeof(NexusFunction));
676  memcpy(fNewHandle, fOrigHandle, sizeof(NexusFunction));
677  LOCKED_CALL(fNewHandle->
678  nxreopen(fOrigHandle->pNexusData,
679  &(fNewHandle->pNexusData)));
680  pushFileStack(newFileStack, fNewHandle,
681  peekFilenameOnStack(origFileStack));
682  *pNewHandle = newFileStack;
683  return NX_OK;
684 }
685 
686 /* ------------------------------------------------------------------------- */
687 
688 NXstatus NXclose(NXhandle * fid)
689 {
690  NXhandle hfil;
691  int status;
692  pFileStack fileStack = NULL;
693  pNexusFunction pFunc = NULL;
694  if (*fid == NULL) {
695  return NX_OK;
696  }
697  fileStack = (pFileStack) * fid;
698  pFunc = peekFileOnStack(fileStack);
699  hfil = pFunc->pNexusData;
700  status = LOCKED_CALL(pFunc->nxclose(&hfil));
701  pFunc->pNexusData = hfil;
702  free(pFunc);
703  popFileStack(fileStack);
704  if (fileStackDepth(fileStack) < 0) {
705  killFileStack(fileStack);
706  *fid = NULL;
707  }
708  /* we can't set fid to NULL always as the handle points to a stack of files for external file support */
709  /*
710  Fortify_CheckAllMemory();
711  */
712 
713  return status;
714 }
715 
716  /*-----------------------------------------------------------------------*/
717 
718 NXstatus NXmakegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass)
719 {
720  char buffer[256];
721  pNexusFunction pFunc = handleToNexusFunc(fid);
722  if (pFunc->checkNameSyntax
723  && (nxclass !=
724  NULL) /* && !strncmp("NX", nxclass, 2) */ &&!validNXName(name,
725  0)) {
726  sprintf(buffer,
727  "ERROR: invalid characters in group name \"%s\"", name);
728  NXReportError(buffer);
729  return NX_ERROR;
730  }
731  return LOCKED_CALL(pFunc->
732  nxmakegroup(pFunc->pNexusData, name, nxclass));
733 }
734 
735  /*------------------------------------------------------------------------*/
736 static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen,
737  char *extPath, int extPathLen)
738 {
739  char *pPtr = NULL, *path = NULL;
740  int length;
741 
742  memset(extFile, 0, extFileLen);
743  memset(extPath, 0, extPathLen);
744  pPtr = strstr(napiMount, "nxfile://");
745  if (pPtr == NULL) {
746  return NXBADURL;
747  }
748  path = strrchr(napiMount, '#');
749  if (path == NULL) {
750  length = (int)strlen(napiMount) - 9;
751  if (length > extFileLen) {
753  ("ERROR: internal errro with external linking");
754  return NXBADURL;
755  }
756  memcpy(extFile, pPtr + 9, length);
757  strcpy(extPath, "/");
758  return NXFILE;
759  } else {
760  pPtr += 9;
761  length = (int)(path - pPtr);
762  if (length > extFileLen) {
764  ("ERROR: internal errro with external linking");
765  return NXBADURL;
766  }
767  memcpy(extFile, pPtr, length);
768  length = (int)strlen(path - 1);
769  if (length > extPathLen) {
771  ("ERROR: internal error with external linking");
772  return NXBADURL;
773  }
774  strcpy(extPath, path + 1);
775  return NXFILE;
776  }
777  return NXBADURL;
778 }
779 
780  /*------------------------------------------------------------------------*/
781 
782 NXstatus NXopengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass)
783 {
784  int status, attStatus, type = NX_CHAR, length = 1023;
785  NXaccess access = NXACC_READ;
786  NXlink breakID;
788  char nxurl[1024], exfile[512], expath[512];
789  pNexusFunction pFunc = NULL;
790 
791  fileStack = (pFileStack) fid;
792  pFunc = handleToNexusFunc(fid);
793 
794  status =
795  LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass));
796  if (status == NX_OK) {
797  pushPath(fileStack, name);
798  }
800  attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type);
802  if (attStatus == NX_OK) {
803  /*
804  this is an external linking group
805  */
806  status = analyzeNapimount(nxurl, exfile, 511, expath, 511);
807  if (status == NXBADURL) {
808  return NX_ERROR;
809  }
810  status = NXinternalopen(exfile, access, fileStack);
811  if (status == NX_ERROR) {
812  return status;
813  }
814  status = NXopenpath(fid, expath);
815  NXgetgroupID(fid, &breakID);
816  setCloseID(fileStack, breakID);
817  }
818 
819  return status;
820 }
821 
822  /* ------------------------------------------------------------------- */
823 
824 NXstatus NXclosegroup(NXhandle fid)
825 {
826  int status;
827  pFileStack fileStack = NULL;
828  NXlink closeID, currentID;
829 
830  pNexusFunction pFunc = handleToNexusFunc(fid);
831  fileStack = (pFileStack) fid;
832  if (fileStackDepth(fileStack) == 0) {
833  status = LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData));
834  if (status == NX_OK) {
835  popPath(fileStack);
836  }
837  return status;
838  } else {
839  /* we have to check for leaving an external file */
840  NXgetgroupID(fid, &currentID);
841  peekIDOnStack(fileStack, &closeID);
842  if (NXsameID(fid, &closeID, &currentID) == NX_OK) {
843  NXclose(&fid);
844  status = NXclosegroup(fid);
845  } else {
846  status =
847  LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData));
848  if (status == NX_OK) {
849  popPath(fileStack);
850  }
851  }
852  return status;
853  }
854 }
855 
856  /* --------------------------------------------------------------------- */
857 
858 NXstatus NXmakedata(NXhandle fid, CONSTCHAR * name, int datatype,
859  int rank, int dimensions[])
860 {
861  int status;
862  int64_t *dims64 = dupDimsArray(dimensions, rank);
863  status = NXmakedata64(fid, name, datatype, rank, dims64);
864  free(dims64);
865  return status;
866 }
867 
868 NXstatus NXmakedata64(NXhandle fid, CONSTCHAR * name, int datatype,
869  int rank, int64_t dimensions[])
870 {
871  char buffer[256];
872  pNexusFunction pFunc = handleToNexusFunc(fid);
873  if (pFunc->checkNameSyntax && !validNXName(name, 0)) {
874  sprintf(buffer,
875  "ERROR: invalid characters in dataset name \"%s\"",
876  name);
877  NXReportError(buffer);
878  return NX_ERROR;
879  }
880  return LOCKED_CALL(pFunc->
881  nxmakedata64(pFunc->pNexusData, name, datatype, rank,
882  dimensions));
883 }
884 
885  /* --------------------------------------------------------------------- */
886 
887 NXstatus NXcompmakedata(NXhandle fid, CONSTCHAR * name, int datatype,
888  int rank, int dimensions[], int compress_type,
889  int chunk_size[])
890 {
891  int status;
892  int64_t *dims64 = dupDimsArray(dimensions, rank);
893  int64_t *chunk64 = dupDimsArray(chunk_size, rank);
894  status =
895  NXcompmakedata64(fid, name, datatype, rank, dims64, compress_type,
896  chunk64);
897  free(dims64);
898  free(chunk64);
899  return status;
900 }
901 
902 NXstatus NXcompmakedata64(NXhandle fid, CONSTCHAR * name, int datatype,
903  int rank, int64_t dimensions[], int compress_type,
904  int64_t chunk_size[])
905 {
906  char buffer[256];
907  pNexusFunction pFunc = handleToNexusFunc(fid);
908  if (pFunc->checkNameSyntax && !validNXName(name, 0)) {
909  sprintf(buffer,
910  "ERROR: invalid characters in dataset name \"%s\"",
911  name);
912  NXReportError(buffer);
913  return NX_ERROR;
914  }
915  return LOCKED_CALL(pFunc->
916  nxcompmakedata64(pFunc->pNexusData, name, datatype,
917  rank, dimensions, compress_type,
918  chunk_size));
919 }
920 
921  /* --------------------------------------------------------------------- */
922 
923 NXstatus NXcompress(NXhandle fid, int compress_type)
924 {
925  pNexusFunction pFunc = handleToNexusFunc(fid);
926  return LOCKED_CALL(pFunc->nxcompress(pFunc->pNexusData, compress_type));
927 }
928 
929  /* --------------------------------------------------------------------- */
930 
931 NXstatus NXopendata(NXhandle fid, CONSTCHAR * name)
932 {
933  int status, attStatus, type = NX_CHAR, length = 1023;
934  NXaccess access = NXACC_READ;
935  NXlink breakID;
937  char nxurl[1024], exfile[512], expath[512];
938  pNexusFunction pFunc = NULL;
939 
940  fileStack = (pFileStack) fid;
941  pFunc = handleToNexusFunc(fid);
942  status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name));
943 
944  if (status == NX_OK) {
945  pushPath(fileStack, name);
946  }
947 
949  attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type);
951  if (attStatus == NX_OK) {
952  /*
953  this is an external linking group
954  */
955  status = analyzeNapimount(nxurl, exfile, 511, expath, 511);
956  if (status == NXBADURL) {
957  return NX_ERROR;
958  }
959  status = NXinternalopen(exfile, access, fileStack);
960  if (status == NX_ERROR) {
961  return status;
962  }
963  status = NXopenpath(fid, expath);
964  NXgetdataID(fid, &breakID);
965  setCloseID(fileStack, breakID);
966  }
967 
968  return status;
969 }
970 
971  /* ----------------------------------------------------------------- */
972 
973 NXstatus NXclosedata(NXhandle fid)
974 {
975  int status;
976  pFileStack fileStack = NULL;
977  NXlink closeID, currentID;
978 
979  pNexusFunction pFunc = handleToNexusFunc(fid);
980  fileStack = (pFileStack) fid;
981 
982  if (fileStackDepth(fileStack) == 0) {
983  status = LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData));
984  if (status == NX_OK) {
985  popPath(fileStack);
986  }
987  return status;
988  } else {
989  /* we have to check for leaving an external file */
990  NXgetdataID(fid, &currentID);
991  peekIDOnStack(fileStack, &closeID);
992  if (NXsameID(fid, &closeID, &currentID) == NX_OK) {
993  NXclose(&fid);
994  status = NXclosedata(fid);
995  } else {
996  status =
997  LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData));
998  if (status == NX_OK) {
999  popPath(fileStack);
1000  }
1001  }
1002  return status;
1003  }
1004 }
1005 
1006  /* ------------------------------------------------------------------- */
1007 
1008 NXstatus NXputdata(NXhandle fid, const void *data)
1009 {
1010  pNexusFunction pFunc = handleToNexusFunc(fid);
1011  return LOCKED_CALL(pFunc->nxputdata(pFunc->pNexusData, data));
1012 }
1013 
1014  /* ------------------------------------------------------------------- */
1015 
1016 NXstatus NXputattr(NXhandle fid, CONSTCHAR * name, const void *data,
1017  int datalen, int iType)
1018 {
1019  char buffer[256];
1020  pNexusFunction pFunc = handleToNexusFunc(fid);
1021  if (datalen > 1 && iType != NX_CHAR) {
1023  ("NXputattr: numeric arrays are not allowed as attributes - only character strings and single numbers");
1024  return NX_ERROR;
1025  }
1026  if (pFunc->checkNameSyntax && !validNXName(name, 0)) {
1027  sprintf(buffer,
1028  "ERROR: invalid characters in attribute name \"%s\"",
1029  name);
1030  NXReportError(buffer);
1031  return NX_ERROR;
1032  }
1033  return LOCKED_CALL(pFunc->
1034  nxputattr(pFunc->pNexusData, name, data, datalen,
1035  iType));
1036 }
1037 
1038  /* ------------------------------------------------------------------- */
1039 
1040 NXstatus NXputslab(NXhandle fid, const void *data, const int iStart[],
1041  const int iSize[])
1042 {
1043  int i, iType, rank;
1044  int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK];
1045  if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) {
1046  return NX_ERROR;
1047  }
1048  for (i = 0; i < rank; ++i) {
1049  iStart64[i] = iStart[i];
1050  iSize64[i] = iSize[i];
1051  }
1052  return NXputslab64(fid, data, iStart64, iSize64);
1053 }
1054 
1055 NXstatus NXputslab64(NXhandle fid, const void *data, const int64_t iStart[],
1056  const int64_t iSize[])
1057 {
1058  pNexusFunction pFunc = handleToNexusFunc(fid);
1059  return LOCKED_CALL(pFunc->
1060  nxputslab64(pFunc->pNexusData, data, iStart, iSize));
1061 }
1062 
1063  /* ------------------------------------------------------------------- */
1064 
1065 NXstatus NXgetdataID(NXhandle fid, NXlink * sRes)
1066 {
1067  pNexusFunction pFunc = handleToNexusFunc(fid);
1068  return LOCKED_CALL(pFunc->nxgetdataID(pFunc->pNexusData, sRes));
1069 }
1070 
1071  /* ------------------------------------------------------------------- */
1072 
1073 NXstatus NXmakelink(NXhandle fid, NXlink * sLink)
1074 {
1075  pNexusFunction pFunc = handleToNexusFunc(fid);
1076  return LOCKED_CALL(pFunc->nxmakelink(pFunc->pNexusData, sLink));
1077 }
1078 
1079  /* ------------------------------------------------------------------- */
1080 
1081 NXstatus NXmakenamedlink(NXhandle fid, CONSTCHAR * newname, NXlink * sLink)
1082 {
1083  char buffer[256];
1084  pNexusFunction pFunc = handleToNexusFunc(fid);
1085  if (pFunc->checkNameSyntax && !validNXName(newname, 0)) {
1086  sprintf(buffer, "ERROR: invalid characters in link name \"%s\"",
1087  newname);
1088  NXReportError(buffer);
1089  return NX_ERROR;
1090  }
1091  return LOCKED_CALL(pFunc->
1092  nxmakenamedlink(pFunc->pNexusData, newname, sLink));
1093 }
1094 
1095  /* -------------------------------------------------------------------- */
1096 NXstatus NXopensourcegroup(NXhandle fid)
1097 {
1098  char target_path[512];
1099  int status, type = NX_CHAR, length = 511;
1100 
1101  status = NXgetattr(fid, "target", target_path, &length, &type);
1102  if (status != NX_OK) {
1103  NXReportError("ERROR: item not linked");
1104  return NX_ERROR;
1105  }
1106  return NXopengrouppath(fid, target_path);
1107 }
1108 
1109  /*----------------------------------------------------------------------*/
1110 
1111 NXstatus NXflush(NXhandle * pHandle)
1112 {
1113  NXhandle hfil;
1114  pFileStack fileStack = NULL;
1115  int status;
1116 
1117  pNexusFunction pFunc = NULL;
1118  fileStack = (pFileStack) * pHandle;
1119  pFunc = peekFileOnStack(fileStack);
1120  hfil = pFunc->pNexusData;
1121  status = LOCKED_CALL(pFunc->nxflush(&hfil));
1122  pFunc->pNexusData = hfil;
1123  return status;
1124 }
1125 
1126  /*-------------------------------------------------------------------------*/
1127 
1128 NXstatus NXmalloc(void **data, int rank, const int dimensions[], int datatype)
1129 {
1130  int status;
1131  int64_t *dims64 = dupDimsArray((int *)dimensions, rank);
1132  status = NXmalloc64(data, rank, dims64, datatype);
1133  free(dims64);
1134  return status;
1135 }
1136 
1137 NXstatus NXmalloc64(void **data, int rank,
1138  const int64_t dimensions[], int datatype)
1139 {
1140  int i;
1141  size_t size = 1;
1142  *data = NULL;
1143  for (i = 0; i < rank; i++) {
1144  size *= (size_t) dimensions[i];
1145  }
1146  if ((datatype == NX_CHAR) || (datatype == NX_INT8)
1147  || (datatype == NX_UINT8)) {
1148  /* allow for terminating \0 */
1149  size += 2;
1150  } else if ((datatype == NX_INT16) || (datatype == NX_UINT16)) {
1151  size *= 2;
1152  } else if ((datatype == NX_INT32) || (datatype == NX_UINT32)
1153  || (datatype == NX_FLOAT32)) {
1154  size *= 4;
1155  } else if ((datatype == NX_INT64) || (datatype == NX_UINT64)) {
1156  size *= 8;
1157  } else if (datatype == NX_FLOAT64) {
1158  size *= 8;
1159  } else {
1160  NXReportError("ERROR: NXmalloc - unknown data type in array");
1161  return NX_ERROR;
1162  }
1163  *data = (void *)malloc(size);
1164  if(*data != NULL){
1165  memset(*data, 0, size);
1166  }
1167  return NX_OK;
1168 }
1169 
1170  /*-------------------------------------------------------------------------*/
1171 
1172 NXstatus NXfree(void **data)
1173 {
1174  if (data == NULL) {
1175  NXReportError("ERROR: passing NULL to NXfree");
1176  return NX_ERROR;
1177  }
1178  if (*data == NULL) {
1179  NXReportError("ERROR: passing already freed pointer to NXfree");
1180  return NX_ERROR;
1181  }
1182  free(*data);
1183  *data = NULL;
1184  return NX_OK;
1185 }
1186 
1187  /* --------------------------------------------------------------------- */
1188 
1189 NXstatus NXgetnextentry(NXhandle fid, NXname name, NXname nxclass,
1190  int *datatype)
1191 {
1192  pNexusFunction pFunc = handleToNexusFunc(fid);
1193  return LOCKED_CALL(pFunc->
1194  nxgetnextentry(pFunc->pNexusData, name, nxclass,
1195  datatype));
1196 }
1197 
1198 /*----------------------------------------------------------------------*/
1199 /*
1200 ** TRIM.C - Remove leading, trailing, & excess embedded spaces
1201 **
1202 ** public domain by Bob Stout
1203 */
1204 #define NUL '\0'
1205 
1206 char *nxitrim(char *str)
1207 {
1208  char *ibuf = str;
1209  int i = 0;
1210 
1211  /*
1212  ** Trap NULL
1213  */
1214 
1215  if (str) {
1216  /*
1217  ** Remove leading spaces (from RMLEAD.C)
1218  */
1219 
1220  for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf) ;
1221  str = ibuf;
1222 
1223  /*
1224  ** Remove trailing spaces (from RMTRAIL.C)
1225  */
1226  i = (int)strlen(str);
1227  while (--i >= 0) {
1228  if (!isspace(str[i]))
1229  break;
1230  }
1231  str[++i] = NUL;
1232  }
1233  return str;
1234 }
1235 
1236  /*-------------------------------------------------------------------------*/
1237 
1238 NXstatus NXgetdata(NXhandle fid, void *data)
1239 {
1240  int status, type, rank;
1241  int64_t iDim[NX_MAXRANK];
1242  char *pPtr, *pPtr2;
1243 
1244  pNexusFunction pFunc = handleToNexusFunc(fid);
1245  status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, &rank, iDim, &type)); /* unstripped size if string */
1246  /* only strip one dimensional strings */
1247  if ((type == NX_CHAR) && (pFunc->stripFlag == 1) && (rank == 1)) {
1248  pPtr = (char *)malloc((size_t) iDim[0] + 5);
1249  memset(pPtr, 0, (size_t) iDim[0] + 5);
1250  status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr));
1251  pPtr2 = nxitrim(pPtr);
1252  strncpy((char *)data, pPtr2, strlen(pPtr2)); /* not NULL terminated by default */
1253  free(pPtr);
1254  } else {
1255  status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, data));
1256  }
1257  return status;
1258 }
1259 
1260 /*---------------------------------------------------------------------------*/
1261 NXstatus NXgetrawinfo64(NXhandle fid, int *rank,
1262  int64_t dimension[], int *iType)
1263 {
1264  pNexusFunction pFunc = handleToNexusFunc(fid);
1265  return LOCKED_CALL(pFunc->
1266  nxgetinfo64(pFunc->pNexusData, rank, dimension,
1267  iType));
1268 }
1269 
1270 NXstatus NXgetrawinfo(NXhandle fid, int *rank, int dimension[], int *iType)
1271 {
1272  int i, status;
1273  int64_t dims64[NX_MAXRANK];
1274  pNexusFunction pFunc = handleToNexusFunc(fid);
1275  status =
1276  LOCKED_CALL(pFunc->
1277  nxgetinfo64(pFunc->pNexusData, rank, dims64, iType));
1278  for (i = 0; i < *rank; ++i) {
1279  dimension[i] = (int)dims64[i];
1280  }
1281  return status;
1282 }
1283 
1284  /*-------------------------------------------------------------------------*/
1285 
1286 NXstatus NXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType)
1287 {
1288  int i, status;
1289  int64_t dims64[NX_MAXRANK];
1290  status = NXgetinfo64(fid, rank, dims64, iType);
1291  for (i = 0; i < *rank; ++i) {
1292  dimension[i] = (int)dims64[i];
1293  }
1294  return status;
1295 }
1296 
1297 NXstatus NXgetinfo64(NXhandle fid, int *rank, int64_t dimension[], int *iType)
1298 {
1299  int status;
1300  char *pPtr = NULL;
1301  pNexusFunction pFunc = handleToNexusFunc(fid);
1302  *rank = 0;
1303  status =
1304  LOCKED_CALL(pFunc->
1305  nxgetinfo64(pFunc->pNexusData, rank, dimension, iType));
1306  /*
1307  the length of a string may be trimmed....
1308  */
1309  /* only strip one dimensional strings */
1310  if ((*iType == NX_CHAR) && (pFunc->stripFlag == 1) && (*rank == 1)) {
1311  pPtr =
1312  (char *)malloc((size_t) (dimension[0] + 1) * sizeof(char));
1313  if (pPtr != NULL) {
1314  memset(pPtr, 0,
1315  (size_t) (dimension[0] + 1) * sizeof(char));
1316  LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr));
1317  dimension[0] = strlen(nxitrim(pPtr));
1318  free(pPtr);
1319  }
1320  }
1321  return status;
1322 }
1323 
1324  /*-------------------------------------------------------------------------*/
1325 
1326 NXstatus NXgetslab(NXhandle fid, void *data,
1327  const int iStart[], const int iSize[])
1328 {
1329  int i, iType, rank;
1330  int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK];
1331  if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) {
1332  return NX_ERROR;
1333  }
1334  for (i = 0; i < rank; ++i) {
1335  iStart64[i] = iStart[i];
1336  iSize64[i] = iSize[i];
1337  }
1338  return NXgetslab64(fid, data, iStart64, iSize64);
1339 }
1340 
1341 NXstatus NXgetslab64(NXhandle fid, void *data,
1342  const int64_t iStart[], const int64_t iSize[])
1343 {
1344  pNexusFunction pFunc = handleToNexusFunc(fid);
1345  return LOCKED_CALL(pFunc->
1346  nxgetslab64(pFunc->pNexusData, data, iStart, iSize));
1347 }
1348 
1349  /*-------------------------------------------------------------------------*/
1350 
1351 NXstatus NXgetnextattr(NXhandle fileid, NXname pName, int *iLength, int *iType)
1352 {
1353  pNexusFunction pFunc = handleToNexusFunc(fileid);
1354  return LOCKED_CALL(pFunc->
1355  nxgetnextattr(pFunc->pNexusData, pName, iLength,
1356  iType));
1357 }
1358 
1359  /*-------------------------------------------------------------------------*/
1360 
1361 NXstatus NXgetattr(NXhandle fid, const char *name, void *data, int *datalen,
1362  int *iType)
1363 {
1364  pNexusFunction pFunc = handleToNexusFunc(fid);
1365  return LOCKED_CALL(pFunc->
1366  nxgetattr(pFunc->pNexusData, name, data, datalen,
1367  iType));
1368 }
1369 
1370  /*-------------------------------------------------------------------------*/
1371 
1372 NXstatus NXgetattrinfo(NXhandle fid, int *iN)
1373 {
1374  pNexusFunction pFunc = handleToNexusFunc(fid);
1375  return LOCKED_CALL(pFunc->nxgetattrinfo(pFunc->pNexusData, iN));
1376 }
1377 
1378  /*-------------------------------------------------------------------------*/
1379 
1380 NXstatus NXgetgroupID(NXhandle fileid, NXlink * sRes)
1381 {
1382  pNexusFunction pFunc = handleToNexusFunc(fileid);
1383  return LOCKED_CALL(pFunc->nxgetgroupID(pFunc->pNexusData, sRes));
1384 }
1385 
1386  /*-------------------------------------------------------------------------*/
1387 
1388 NXstatus NXgetgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass)
1389 {
1390  pNexusFunction pFunc = handleToNexusFunc(fid);
1391  return LOCKED_CALL(pFunc->
1392  nxgetgroupinfo(pFunc->pNexusData, iN, pName,
1393  pClass));
1394 }
1395 
1396  /*-------------------------------------------------------------------------*/
1397 
1398 NXstatus NXsameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID)
1399 {
1400  pNexusFunction pFunc = handleToNexusFunc(fileid);
1401  return LOCKED_CALL(pFunc->
1402  nxsameID(pFunc->pNexusData, pFirstID, pSecondID));
1403 }
1404 
1405  /*-------------------------------------------------------------------------*/
1406 
1407 NXstatus NXinitattrdir(NXhandle fid)
1408 {
1409  pNexusFunction pFunc = handleToNexusFunc(fid);
1410  return LOCKED_CALL(pFunc->nxinitattrdir(pFunc->pNexusData));
1411 }
1412 
1413  /*-------------------------------------------------------------------------*/
1414 
1415 NXstatus NXsetnumberformat(NXhandle fid, int type, char *format)
1416 {
1417  pNexusFunction pFunc = handleToNexusFunc(fid);
1418  if (pFunc->nxsetnumberformat != NULL) {
1419  return LOCKED_CALL(pFunc->
1420  nxsetnumberformat(pFunc->pNexusData, type,
1421  format));
1422  } else {
1423  /*
1424  silently ignore this. Most NeXus file formats do not require
1425  this
1426  */
1427  return NX_OK;
1428  }
1429 }
1430 
1431  /*-------------------------------------------------------------------------*/
1432 
1433 NXstatus NXinitgroupdir(NXhandle fid)
1434 {
1435  pNexusFunction pFunc = handleToNexusFunc(fid);
1436  return LOCKED_CALL(pFunc->nxinitgroupdir(pFunc->pNexusData));
1437 }
1438 
1439 /*----------------------------------------------------------------------*/
1440 NXstatus NXinquirefile(NXhandle handle, char *filename,
1441  int filenameBufferLength)
1442 {
1444  char *pPtr = NULL;
1445  int length, status;
1446 
1447  pNexusFunction pFunc = handleToNexusFunc(handle);
1448  if (pFunc->nxnativeinquirefile != NULL) {
1449 
1450  status =
1451  LOCKED_CALL(pFunc->
1452  nxnativeinquirefile(pFunc->pNexusData, filename,
1453  filenameBufferLength));
1454  if (status < 0) {
1455  return NX_ERROR;
1456  } else {
1457  return NX_OK;
1458  }
1459 
1460  }
1461 
1462  fileStack = (pFileStack) handle;
1463  pPtr = peekFilenameOnStack(fileStack);
1464  if (pPtr != NULL) {
1465  length = (int)strlen(pPtr);
1466  if (length > filenameBufferLength) {
1467  length = filenameBufferLength - 1;
1468  }
1469  memset(filename, 0, filenameBufferLength);
1470  memcpy(filename, pPtr, length);
1471  return NX_OK;
1472  } else {
1473  return NX_ERROR;
1474  }
1475 }
1476 
1477 /*------------------------------------------------------------------------*/
1478 NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass,
1479  char *url, int urlLen)
1480 {
1481  int status, attStatus, length = 1023, type = NX_CHAR;
1482  char nxurl[1024];
1483 
1484  pNexusFunction pFunc = handleToNexusFunc(fid);
1485 
1486  if (pFunc->nxnativeisexternallink != NULL) {
1487  status =
1488  LOCKED_CALL(pFunc->
1489  nxnativeisexternallink(pFunc->pNexusData, name,
1490  url, urlLen));
1491  if (status == NX_OK) {
1492  return NX_OK;
1493  }
1494  // need to continue, could still be old style link
1495  }
1496 
1497  status =
1498  LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass));
1499  if (status != NX_OK) {
1500  return status;
1501  }
1503  attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type);
1505  LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData));
1506  if (attStatus == NX_OK) {
1507  length = (int)strlen(nxurl);
1508  if (length >= urlLen) {
1509  length = urlLen - 1;
1510  }
1511  memset(url, 0, urlLen);
1512  memcpy(url, nxurl, length);
1513  return attStatus;
1514  } else {
1515  return NX_ERROR;
1516  }
1517 }
1518 
1519 /*------------------------------------------------------------------------*/
1520 NXstatus NXisexternaldataset(NXhandle fid, CONSTCHAR * name,
1521  char *url, int urlLen)
1522 {
1523  int status, attStatus, length = 1023, type = NX_CHAR;
1524  char nxurl[1024];
1525 
1526  pNexusFunction pFunc = handleToNexusFunc(fid);
1527 
1528  if (pFunc->nxnativeisexternallink != NULL) {
1529  status =
1530  LOCKED_CALL(pFunc->
1531  nxnativeisexternallink(pFunc->pNexusData, name,
1532  url, urlLen));
1533  if (status == NX_OK) {
1534  return NX_OK;
1535  }
1536  // need to continue, could still be old style link
1537  }
1538 
1539  status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name));
1540  if (status != NX_OK) {
1541  return status;
1542  }
1544  attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type);
1546  LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData));
1547  if (attStatus == NX_OK) {
1548  length = (int)strlen(nxurl);
1549  if (length >= urlLen) {
1550  length = urlLen - 1;
1551  }
1552  memset(url, 0, urlLen);
1553  memcpy(url, nxurl, length);
1554  return attStatus;
1555  } else {
1556  return NX_ERROR;
1557  }
1558 }
1559 
1560 /*------------------------------------------------------------------------*/
1561 NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass,
1562  CONSTCHAR * url)
1563 {
1564  int status, type = NX_CHAR, length = 1024, urllen;
1565  char nxurl[1024], exfile[512], expath[512];
1566  pNexusFunction pFunc = handleToNexusFunc(fid);
1567 
1568  // in HDF5 we support external linking natively
1569  if (pFunc->nxnativeexternallink != NULL) {
1570  urllen = (int)strlen(url);
1571  memset(nxurl, 0, length);
1572  if (urllen >= length) {
1573  urllen = length - 1;
1574  }
1575  memcpy(nxurl, url, urllen);
1576  status = analyzeNapimount(nxurl, exfile, 511, expath, 511);
1577  if (status != NX_OK) {
1578  return status;
1579  }
1580  status =
1581  LOCKED_CALL(pFunc->
1582  nxnativeexternallink(pFunc->pNexusData, name,
1583  exfile, expath));
1584  if (status != NX_OK) {
1585  return status;
1586  }
1587  return NX_OK;
1588  }
1589 
1591  LOCKED_CALL(pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass));
1593 
1594  status =
1595  LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass));
1596  if (status != NX_OK) {
1597  return status;
1598  }
1599  length = (int)strlen(url);
1600  status = NXputattr(fid, "napimount", url, length, type);
1601  if (status != NX_OK) {
1602  return status;
1603  }
1604  LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData));
1605  return NX_OK;
1606 }
1607 
1608 /*------------------------------------------------------------------------*/
1609 NXstatus NXlinkexternaldataset(NXhandle fid, CONSTCHAR * name, CONSTCHAR * url)
1610 {
1611  int status, type = NX_CHAR, length = 1024, urllen;
1612  char nxurl[1024], exfile[512], expath[512];
1613  pNexusFunction pFunc = handleToNexusFunc(fid);
1614  int rank = 1;
1615  int64_t dims[1] = { 1 };
1616 
1617  //TODO cut and paste
1618 
1619  // in HDF5 we support external linking natively
1620  if (pFunc->nxnativeexternallink != NULL) {
1621  urllen = (int)strlen(url);
1622  memset(nxurl, 0, length);
1623  if (urllen > length) {
1624  urllen = length - 1;
1625  }
1626  memcpy(nxurl, url, urllen);
1627  status = analyzeNapimount(nxurl, exfile, 511, expath, 511);
1628  if (status != NX_OK) {
1629  return status;
1630  }
1631  status =
1632  LOCKED_CALL(pFunc->
1633  nxnativeexternallink(pFunc->pNexusData, name,
1634  exfile, expath));
1635  if (status != NX_OK) {
1636  return status;
1637  }
1638  return NX_OK;
1639  }
1640 
1641  status =
1642  LOCKED_CALL(pFunc->
1643  nxmakedata64(pFunc->pNexusData, name, NX_CHAR, rank,
1644  dims));
1645  if (status != NX_OK) {
1646  return status;
1647  }
1648  status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name));
1649  if (status != NX_OK) {
1650  return status;
1651  }
1652  length = (int)strlen(url);
1653  status = NXputattr(fid, "napimount", url, length, type);
1654  if (status != NX_OK) {
1655  return status;
1656  }
1657  LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData));
1658  return NX_OK;
1659 }
1660 
1661 /*------------------------------------------------------------------------
1662  Implementation of NXopenpath
1663  --------------------------------------------------------------------------*/
1664 static int isDataSetOpen(NXhandle hfil)
1665 {
1666  NXlink id;
1667 
1668  /*
1669  This uses the (sensible) feauture that NXgetdataID returns NX_ERROR
1670  when no dataset is open
1671  */
1672  if (NXgetdataID(hfil, &id) == NX_ERROR) {
1673  return 0;
1674  } else {
1675  return 1;
1676  }
1677 }
1678 
1679 /*----------------------------------------------------------------------*/
1680 static int isRoot(NXhandle hfil)
1681 {
1682  NXlink id;
1683 
1684  /*
1685  This uses the feauture that NXgetgroupID returns NX_ERROR
1686  when we are at root level
1687  */
1688  if (NXgetgroupID(hfil, &id) == NX_ERROR) {
1689  return 1;
1690  } else {
1691  return 0;
1692  }
1693 }
1694 
1695 /*--------------------------------------------------------------------
1696  copies the next path element into element.
1697  returns a pointer into path beyond the extracted path
1698  ---------------------------------------------------------------------*/
1699 static char *extractNextPath(char *path, NXname element)
1700 {
1701  char *pPtr, *pStart;
1702  int length;
1703 
1704  pPtr = path;
1705  /*
1706  skip over leading /
1707  */
1708  if (*pPtr == '/') {
1709  pPtr++;
1710  }
1711  pStart = pPtr;
1712 
1713  /*
1714  find next /
1715  */
1716  pPtr = strchr(pStart, '/');
1717  if (pPtr == NULL) {
1718  /*
1719  this is the last path element
1720  */
1721  strcpy(element, pStart);
1722  return NULL;
1723  } else {
1724  length = (int)(pPtr - pStart);
1725  strncpy(element, pStart, length);
1726  element[length] = '\0';
1727  }
1728  return pPtr + 1;
1729 }
1730 
1731 /*-------------------------------------------------------------------*/
1732 static NXstatus gotoRoot(NXhandle hfil)
1733 {
1734  int status;
1735 
1736  if (isDataSetOpen(hfil)) {
1737  status = NXclosedata(hfil);
1738  if (status == NX_ERROR) {
1739  return status;
1740  }
1741  }
1742  while (!isRoot(hfil)) {
1743  status = NXclosegroup(hfil);
1744  if (status == NX_ERROR) {
1745  return status;
1746  }
1747  }
1748  return NX_OK;
1749 }
1750 
1751 /*--------------------------------------------------------------------*/
1752 static int isRelative(char *path)
1753 {
1754  if (path[0] == '.' && path[1] == '.')
1755  return 1;
1756  else
1757  return 0;
1758 }
1759 
1760 /*------------------------------------------------------------------*/
1761 static NXstatus moveOneDown(NXhandle hfil)
1762 {
1763  if (isDataSetOpen(hfil)) {
1764  return NXclosedata(hfil);
1765  } else {
1766  return NXclosegroup(hfil);
1767  }
1768 }
1769 
1770 /*-------------------------------------------------------------------
1771  returns a pointer to the remaining path string to move up
1772  --------------------------------------------------------------------*/
1773 static char *moveDown(NXhandle hfil, char *path, int *code)
1774 {
1775  int status;
1776  char *pPtr;
1777 
1778  *code = NX_OK;
1779 
1780  if (path[0] == '/') {
1781  *code = gotoRoot(hfil);
1782  return path;
1783  } else {
1784  pPtr = path;
1785  while (isRelative(pPtr)) {
1786  status = moveOneDown(hfil);
1787  if (status == NX_ERROR) {
1788  *code = status;
1789  return pPtr;
1790  }
1791  pPtr += 3;
1792  }
1793  return pPtr;
1794  }
1795 }
1796 
1797 /*--------------------------------------------------------------------*/
1798 static NXstatus stepOneUp(NXhandle hfil, char *name)
1799 {
1800  int datatype;
1801  NXname name2, xclass;
1802  char pBueffel[256];
1803 
1804  /*
1805  catch the case when we are there: i.e. no further stepping
1806  necessary. This can happen with paths like ../
1807  */
1808  if (strlen(name) < 1) {
1809  return NX_OK;
1810  }
1811 
1812  NXinitgroupdir(hfil);
1813 
1814  while (NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) {
1815  if (strcmp(name2, name) == 0) {
1816  if (strcmp(xclass, "SDS") == 0) {
1817  return NXopendata(hfil, name);
1818  } else {
1819  return NXopengroup(hfil, name, xclass);
1820  }
1821  }
1822  }
1823  snprintf(pBueffel, 255, "ERROR: NXopenpath cannot step into %s", name);
1824  NXReportError(pBueffel);
1825  return NX_ERROR;
1826 }
1827 
1828 /*--------------------------------------------------------------------*/
1829 static NXstatus stepOneGroupUp(NXhandle hfil, char *name)
1830 {
1831  int datatype;
1832  NXname name2, xclass;
1833  char pBueffel[256];
1834 
1835  /*
1836  catch the case when we are there: i.e. no further stepping
1837  necessary. This can happen with paths like ../
1838  */
1839  if (strlen(name) < 1) {
1840  return NX_OK;
1841  }
1842 
1843  NXinitgroupdir(hfil);
1844  while (NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) {
1845 
1846  if (strcmp(name2, name) == 0) {
1847  if (strcmp(xclass, "SDS") == 0) {
1848  return NX_EOD;
1849  } else {
1850  return NXopengroup(hfil, name, xclass);
1851  }
1852  }
1853  }
1854  snprintf(pBueffel, 255, "ERROR: NXopengrouppath cannot step into %s",
1855  name);
1856  NXReportError(pBueffel);
1857  return NX_ERROR;
1858 }
1859 
1860 /*---------------------------------------------------------------------*/
1861 NXstatus NXopenpath(NXhandle hfil, CONSTCHAR * path)
1862 {
1863  int status, run = 1;
1864  NXname pathElement;
1865  char *pPtr;
1866 
1867  if (hfil == NULL || path == NULL) {
1869  ("ERROR: NXopendata needs both a file handle and a path string");
1870  return NX_ERROR;
1871  }
1872 
1873  pPtr = moveDown(hfil, (char *)path, &status);
1874  if (status != NX_OK) {
1876  ("ERROR: NXopendata failed to move down in hierarchy");
1877  return status;
1878  }
1879 
1880  while (run == 1) {
1881  pPtr = extractNextPath(pPtr, pathElement);
1882  status = stepOneUp(hfil, pathElement);
1883  if (status != NX_OK) {
1884  return status;
1885  }
1886  if (pPtr == NULL) {
1887  run = 0;
1888  }
1889  }
1890  return NX_OK;
1891 }
1892 
1893 /*---------------------------------------------------------------------*/
1894 NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR * path)
1895 {
1896  int status;
1897  NXname pathElement;
1898  char *pPtr;
1899  char buffer[256];
1900 
1901  if (hfil == NULL || path == NULL) {
1903  ("ERROR: NXopengrouppath needs both a file handle and a path string");
1904  return NX_ERROR;
1905  }
1906 
1907  pPtr = moveDown(hfil, (char *)path, &status);
1908  if (status != NX_OK) {
1910  ("ERROR: NXopengrouppath failed to move down in hierarchy");
1911  return status;
1912  }
1913 
1914  do {
1915  pPtr = extractNextPath(pPtr, pathElement);
1916  status = stepOneGroupUp(hfil, pathElement);
1917  if (status == NX_ERROR) {
1918  sprintf(buffer,
1919  "ERROR: NXopengrouppath cannot reach path %s",
1920  path);
1921  NXReportError(buffer);
1922  return NX_ERROR;
1923  }
1924  } while (pPtr != NULL && status != NX_EOD);
1925  return NX_OK;
1926 }
1927 
1928 /*---------------------------------------------------------------------*/
1929 NXstatus NXIprintlink(NXhandle fid, NXlink * link)
1930 {
1931  pNexusFunction pFunc = handleToNexusFunc(fid);
1932  return LOCKED_CALL(pFunc->nxprintlink(pFunc->pNexusData, link));
1933 }
1934 
1935 /*----------------------------------------------------------------------*/
1936 NXstatus NXgetpath(NXhandle fid, char *path, int pathlen)
1937 {
1938  int status;
1939  pFileStack fileStack = NULL;
1940 
1941  fileStack = (pFileStack) fid;
1942  status = buildPath(fileStack, path, pathlen);
1943  if (status != 1) {
1944  return NX_ERROR;
1945  }
1946  return NX_OK;
1947 }
1948 
1949 NXstatus NXputattra(NXhandle handle, CONSTCHAR* name, const void* data, const int rank, const int dim[], const int iType)
1950 {
1951  pNexusFunction pFunc = handleToNexusFunc(handle);
1952  return LOCKED_CALL(pFunc->nxputattra(pFunc->pNexusData, name, data, rank, dim, iType));
1953 }
1954 NXstatus NXgetnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
1955 {
1956  pNexusFunction pFunc = handleToNexusFunc(handle);
1957  return LOCKED_CALL(pFunc->nxgetnextattra(pFunc->pNexusData, pName, rank, dim, iType));
1958 }
1959 NXstatus NXgetattra(NXhandle handle, const char* name, void* data)
1960 {
1961  pNexusFunction pFunc = handleToNexusFunc(handle);
1962  return LOCKED_CALL(pFunc->nxgetattra(pFunc->pNexusData, name, data));
1963 }
1964 NXstatus NXgetattrainfo(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
1965 {
1966  pNexusFunction pFunc = handleToNexusFunc(handle);
1967  return LOCKED_CALL(pFunc->nxgetattrainfo(pFunc->pNexusData, pName, rank, dim, iType));
1968 }
1969 
1970 /*--------------------------------------------------------------------
1971  format NeXus time. Code needed in every NeXus file driver
1972  ---------------------------------------------------------------------*/
1974 {
1975  time_t timer;
1976  char *time_buffer = NULL;
1977  struct tm *time_info;
1978  const char *time_format;
1979  long gmt_offset;
1980 #ifdef USE_FTIME
1981  struct timeb timeb_struct;
1982 #endif
1983 
1984  time_buffer = (char *)malloc(64 * sizeof(char));
1985  if (!time_buffer) {
1986  NXReportError("Failed to allocate buffer for time data");
1987  return NULL;
1988  }
1989 #ifdef NEED_TZSET
1990  tzset();
1991 #endif
1992  time(&timer);
1993 #ifdef USE_FTIME
1994  ftime(&timeb_struct);
1995  gmt_offset = -timeb_struct.timezone * 60;
1996  if (timeb_struct.dstflag != 0) {
1997  gmt_offset += 3600;
1998  }
1999 #else
2000  time_info = gmtime(&timer);
2001  if (time_info != NULL) {
2002  gmt_offset = (long)difftime(timer, mktime(time_info));
2003  } else {
2005  ("Your gmtime() function does not work ... timezone information will be incorrect\n");
2006  gmt_offset = 0;
2007  }
2008 #endif
2009  time_info = localtime(&timer);
2010  if (time_info != NULL) {
2011  if (gmt_offset < 0) {
2012  time_format = "%04d-%02d-%02dT%02d:%02d:%02d-%02d:%02d";
2013  } else {
2014  time_format = "%04d-%02d-%02dT%02d:%02d:%02d+%02d:%02d";
2015  }
2016  sprintf(time_buffer, time_format,
2017  1900 + time_info->tm_year,
2018  1 + time_info->tm_mon,
2019  time_info->tm_mday,
2020  time_info->tm_hour,
2021  time_info->tm_min,
2022  time_info->tm_sec,
2023  labs(gmt_offset / 3600), labs((gmt_offset % 3600) / 60)
2024  );
2025  } else {
2026  strcpy(time_buffer, "1970-01-01T00:00:00+00:00");
2027  }
2028  return time_buffer;
2029 }
2030 
2031 const char *NXgetversion()
2032 {
2033  return NEXUS_VERSION;
2034 }
NXstatus NXgetattra(NXhandle handle, const char *name, void *data)
Definition: napi.c:1959
NXstatus NXgetpath(NXhandle fid, char *path, int pathlen)
Definition: napi.c:1936
NXstatus NXgetattrinfo(NXhandle fid, int *iN)
Definition: napi.c:1372
NXstatus NXgetslab(NXhandle fid, void *data, const int iStart[], const int iSize[])
Definition: napi.c:1326
NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen)
Definition: napi.c:1478
NXstatus NXgetattr(NXhandle fid, const char *name, void *data, int *datalen, int *iType)
Definition: napi.c:1361
NXstatus(* nxgetinfo64)(NXhandle handle, int *rank, int64_t dimension[], int *datatype)
Definition: napi_internal.h:61
void NXMSetError(void *pData, void(*NewError)(void *pD, char *text))
Definition: napi.c:319
#define NXBADURL
Definition: napi.c:42
NXstatus(* nxgetdataID)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:57
struct __fileStack * pFileStack
Definition: nxstack.h:30
pFileStack makeFileStack()
Definition: nxstack.c:50
NXstatus NXgetrawinfo64(NXhandle fid, int *rank, int64_t dimension[], int *iType)
Definition: napi.c:1261
void NXMEnableErrorReporting()
Definition: napi.c:375
NXstatus NXopen(CONSTCHAR *userfilename, NXaccess am, NXhandle *gHandle)
Definition: napi.c:463
NXstatus(* nxinitgroupdir)(NXhandle handle)
Definition: napi_internal.h:73
#define LIBSEP
Definition: napi.c:55
#define NX_INT64
Definition: nxdataset.h:47
NXstatus NXputattr(NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType)
Definition: napi.c:1016
void pushFileStack(pFileStack self, pNexusFunction pDriv, char *file)
Definition: nxstack.c:73
NXstatus(* nxgetattrinfo)(NXhandle handle, int *no_items)
Definition: napi_internal.h:69
NXstatus NXmakedata64(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int64_t dimensions[])
Definition: napi.c:868
NXstatus NXputslab64(NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[])
Definition: napi.c:1055
NXstatus NXinitattrdir(NXhandle fid)
Definition: napi.c:1407
#define LOCKED_CALL(__call)
Definition: napi.c:143
NXstatus(* nxgetnextattra)(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi_internal.h:65
NXstatus NXcompmakedata64(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int64_t dimensions[], int compress_type, int64_t chunk_size[])
Definition: napi.c:902
NXaccess access_mode
Definition: napi_internal.h:82
NXstatus(* nxclose)(NXhandle *pHandle)
Definition: napi_internal.h:43
ErrFunc NXMGetError()
Definition: napi.c:337
NXstatus(* nxnativeinquirefile)(NXhandle handle, char *externalfile, const int filenamelength)
Definition: napi_internal.h:78
NXstatus NXopensourcegroup(NXhandle fid)
Definition: napi.c:1096
NXstatus NXcompmakedata(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int dimensions[], int compress_type, int chunk_size[])
Definition: napi.c:887
#define NXFILE
Definition: napi.c:43
#define NX_INT8
Definition: nxdataset.h:41
void killFileStack(pFileStack self)
Definition: nxstack.c:63
NXstatus NXmakenamedlink(NXhandle fid, CONSTCHAR *newname, NXlink *sLink)
Definition: napi.c:1081
void peekIDOnStack(pFileStack self, NXlink *id)
Definition: nxstack.c:101
char * peekFilenameOnStack(pFileStack self)
Definition: nxstack.c:97
NXstatus NXsetcache(long newVal)
Definition: napi.c:250
void NX5assignFunctions(pNexusFunction fHandle)
NXstatus NXgetgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass)
Definition: napi.c:1388
NXstatus NXopengroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass)
Definition: napi.c:782
#define NX_FLOAT64
Definition: nxdataset.h:40
NXstatus(* nxputdata)(NXhandle handle, const void *data)
Definition: napi_internal.h:53
NXstatus NXIprintlink(NXhandle fid, NXlink *link)
Definition: napi.c:1929
NXstatus(* nxgetdata)(NXhandle handle, void *data)
Definition: napi_internal.h:60
NXstatus(* nxprintlink)(NXhandle handle, NXlink *link)
Definition: napi_internal.h:76
NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR *path)
Definition: napi.c:1894
NXstatus NXgetnextentry(NXhandle fid, NXname name, NXname nxclass, int *datatype)
Definition: napi.c:1189
#define NX_UINT8
Definition: nxdataset.h:42
NXstatus NX4open(CONSTCHAR *filename, NXaccess access_method, NXhandle *pHandle)
NXstatus(* nxmakegroup)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
Definition: napi_internal.h:45
NXstatus NXflush(NXhandle *pHandle)
Definition: napi.c:1111
NXstatus NXisexternaldataset(NXhandle fid, CONSTCHAR *name, char *url, int urlLen)
Definition: napi.c:1520
int buildPath(pFileStack self, char *path, int pathlen)
Definition: nxstack.c:125
const char * NXgetversion()
Definition: napi.c:2031
NXstatus(* nxgetattra)(NXhandle handle, const char *name, void *data)
Definition: napi_internal.h:67
void NXIReportError(void *pData, char *string)
Definition: napi.c:298
#define NX_FLOAT32
Definition: nxdataset.h:39
NXstatus(* nxflush)(NXhandle *pHandle)
Definition: napi_internal.h:44
void NX4assignFunctions(pNexusFunction fHandle)
NXstatus(* nxopengroup)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *NXclass)
Definition: napi_internal.h:46
void NXMSetTError(void *pData, void(*NewError)(void *pD, char *text))
Definition: napi.c:326
NXstatus NXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType)
Definition: napi.c:1286
void popPath(pFileStack self)
Definition: nxstack.c:118
NXstatus NX5open(CONSTCHAR *filename, NXaccess access_method, NXhandle *pHandle)
NXstatus NXgetrawinfo(NXhandle fid, int *rank, int dimension[], int *iType)
Definition: napi.c:1270
NXstatus NXinitgroupdir(NXhandle fid)
Definition: napi.c:1433
NXstatus(* nxmakelink)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:58
NXstatus NXinquirefile(NXhandle handle, char *filename, int filenameBufferLength)
Definition: napi.c:1440
NXstatus(* nxcompress)(NXhandle handle, int compr_type)
Definition: napi_internal.h:50
int fileStackDepth(pFileStack self)
Definition: nxstack.c:109
long nx_cacheSize
Definition: napi.c:248
NXstatus NXreopen(NXhandle pOrigHandle, NXhandle *pNewHandle)
Definition: napi.c:651
NXstatus NXopendata(NXhandle fid, CONSTCHAR *name)
Definition: napi.c:931
NXstatus NXcompress(NXhandle fid, int compress_type)
Definition: napi.c:923
struct __fileStack fileStack
void NXXassignFunctions(pNexusFunction fHandle)
NXstatus NXmakelink(NXhandle fid, NXlink *sLink)
Definition: napi.c:1073
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 NXgetdata(NXhandle fid, void *data)
Definition: napi.c:1238
struct NexusFunction * pNexusFunction
void pushPath(pFileStack self, const char *name)
Definition: nxstack.c:113
NXstatus NXgetinfo64(NXhandle fid, int *rank, int64_t dimension[], int *iType)
Definition: napi.c:1297
NXstatus NXputslab(NXhandle fid, const void *data, const int iStart[], const int iSize[])
Definition: napi.c:1040
NXstatus NXsameID(NXhandle fileid, NXlink *pFirstID, NXlink *pSecondID)
Definition: napi.c:1398
#define THREAD_LOCAL
Definition: napi.c:57
NXstatus NXclose(NXhandle *fid)
Definition: napi.c:688
#define NX_MAXRANK
Definition: nxdataset.h:51
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
NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url)
Definition: napi.c:1561
void NXReportError(char *string)
Definition: napi.c:305
void NXMDisableErrorReporting()
Definition: napi.c:360
#define NUL
Definition: napi.c:1204
NXhandle pNexusData
Definition: napi_internal.h:41
char * nxitrim(char *str)
Definition: napi.c:1206
NXstatus NXgetgroupID(NXhandle fileid, NXlink *sRes)
Definition: napi.c:1380
#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(* nxclosegroup)(NXhandle handle)
Definition: napi_internal.h:47
NXstatus(* nxnativeexternallink)(NXhandle handle, CONSTCHAR *name, CONSTCHAR *externalfile, CONSTCHAR *remotetarget)
Definition: napi_internal.h:77
#define PATHSEP
Definition: napi.c:56
NXstatus NXmakegroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass)
Definition: napi.c:718
NXstatus NXmalloc64(void **data, int rank, const int64_t dimensions[], int datatype)
Definition: napi.c:1137
void setCloseID(pFileStack self, NXlink id)
Definition: nxstack.c:105
NXstatus NXgetnextattra(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi.c:1954
NXstatus NXgetdataID(NXhandle fid, NXlink *sRes)
Definition: napi.c:1065
NXstatus NXopenpath(NXhandle hfil, CONSTCHAR *path)
Definition: napi.c:1861
NXstatus NXXopen(CONSTCHAR *filename, NXaccess access_method, NXhandle *pHandle)
NXstatus NXmakedata(NXhandle fid, CONSTCHAR *name, int datatype, int rank, int dimensions[])
Definition: napi.c:858
NXstatus NXmalloc(void **data, int rank, const int dimensions[], int datatype)
Definition: napi.c:1128
char * NXIformatNeXusTime()
Definition: napi.c:1973
int validNXName(const char *name, int allow_colon)
valid NeXus names
Definition: napi.c:151
#define NX_CHAR
Definition: nxdataset.h:49
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 NXclosedata(NXhandle fid)
Definition: napi.c:973
NXstatus NXfree(void **data)
Definition: napi.c:1172
NXstatus NXputdata(NXhandle fid, const void *data)
Definition: napi.c:1008
NXstatus NXlinkexternaldataset(NXhandle fid, CONSTCHAR *name, CONSTCHAR *url)
Definition: napi.c:1609
NXstatus NXclosegroup(NXhandle fid)
Definition: napi.c:824
#define NX_INT16
Definition: nxdataset.h:43
NXstatus(* nxsetnumberformat)(NXhandle handle, int type, char *format)
Definition: napi_internal.h:75
NXstatus NXgetattrainfo(NXhandle handle, NXname pName, int *rank, int dim[], int *iType)
Definition: napi.c:1964
NXstatus NXsetnumberformat(NXhandle fid, int type, char *format)
Definition: napi.c:1415
NXstatus NXputattra(NXhandle handle, CONSTCHAR *name, const void *data, const int rank, const int dim[], const int iType)
Definition: napi.c:1949
NXstatus(* nxnativeisexternallink)(NXhandle handle, CONSTCHAR *name, char *url, int urllen)
Definition: napi_internal.h:79
pNexusFunction peekFileOnStack(pFileStack self)
Definition: nxstack.c:93
NXstatus NXgetslab64(NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[])
Definition: napi.c:1341
NXstatus(* nxgetgroupID)(NXhandle handle, NXlink *pLink)
Definition: napi_internal.h:70
NXstatus NXgetnextattr(NXhandle fileid, NXname pName, int *iLength, int *iType)
Definition: napi.c:1351
void popFileStack(pFileStack self)
Definition: nxstack.c:86