- Fixes to make SL6 work
- New NeXus libraries - Added new raw binary transfer mode for mass data - Added a check script option to configurable virtual motor SKIPPED: psi/dumprot.c psi/make_gen psi/psi.c psi/rebin.c psi/sanslirebin.c
This commit is contained in:
651
nxio.c
651
nxio.c
@@ -21,9 +21,12 @@
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* For further information, see <http://www.neutron.anl.gov/NeXus/>
|
||||
* For further information, see <http://www.nexusformat.org>
|
||||
*/
|
||||
#include <mxml.h>
|
||||
|
||||
#ifdef NXXML
|
||||
|
||||
#include <mxml.h>
|
||||
#include <assert.h>
|
||||
#include "napi.h"
|
||||
#include "nxio.h"
|
||||
@@ -35,181 +38,188 @@
|
||||
#define MXML_WRAP 79
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* #define TESTMAIN 1 */
|
||||
/*=================== type code handling ================================= */
|
||||
typedef struct {
|
||||
char name[30];
|
||||
char format[30];
|
||||
int nx_type;
|
||||
} type_code;
|
||||
int nx_type;
|
||||
}type_code;
|
||||
|
||||
#define NTYPECODE 11
|
||||
static type_code typecode[NTYPECODE];
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void initializeNumberFormats()
|
||||
{
|
||||
void initializeNumberFormats(){
|
||||
type_code myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_FLOAT32");
|
||||
strcpy(myCode.format, "%12.4f");
|
||||
strcpy(myCode.name,"NX_FLOAT32");
|
||||
strcpy(myCode.format,"%12.4f");
|
||||
myCode.nx_type = NX_FLOAT32;
|
||||
typecode[0] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_FLOAT64");
|
||||
strcpy(myCode.format, "%16.5f");
|
||||
strcpy(myCode.name,"NX_FLOAT64");
|
||||
strcpy(myCode.format,"%16.5f");
|
||||
myCode.nx_type = NX_FLOAT64;
|
||||
typecode[1] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_INT8");
|
||||
strcpy(myCode.format, "%5d");
|
||||
strcpy(myCode.name,"NX_INT8");
|
||||
strcpy(myCode.format,"%5d");
|
||||
myCode.nx_type = NX_INT8;
|
||||
typecode[2] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_UINT8");
|
||||
strcpy(myCode.format, "%5d");
|
||||
strcpy(myCode.name,"NX_UINT8");
|
||||
strcpy(myCode.format,"%5d");
|
||||
myCode.nx_type = NX_UINT8;
|
||||
typecode[3] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_INT16");
|
||||
strcpy(myCode.format, "%8d");
|
||||
strcpy(myCode.name,"NX_INT16");
|
||||
strcpy(myCode.format,"%8d");
|
||||
myCode.nx_type = NX_INT16;
|
||||
typecode[4] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_UINT16");
|
||||
strcpy(myCode.format, "%8d");
|
||||
strcpy(myCode.name,"NX_UINT16");
|
||||
strcpy(myCode.format,"%8d");
|
||||
myCode.nx_type = NX_UINT16;
|
||||
typecode[5] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_INT32");
|
||||
strcpy(myCode.format, "%12d");
|
||||
strcpy(myCode.name,"NX_INT32");
|
||||
strcpy(myCode.format,"%12d");
|
||||
myCode.nx_type = NX_INT32;
|
||||
typecode[6] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_UINT32");
|
||||
strcpy(myCode.format, "%12d");
|
||||
strcpy(myCode.name,"NX_UINT32");
|
||||
strcpy(myCode.format,"%12d");
|
||||
myCode.nx_type = NX_UINT32;
|
||||
typecode[7] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_INT64");
|
||||
strcpy(myCode.format, "%24" PRINTF_INT64);
|
||||
strcpy(myCode.name,"NX_INT64");
|
||||
strcpy(myCode.format,"%24lld");
|
||||
myCode.nx_type = NX_INT64;
|
||||
typecode[8] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_UINT64");
|
||||
strcpy(myCode.format, "%24" PRINTF_UINT64);
|
||||
strcpy(myCode.name,"NX_UINT64");
|
||||
strcpy(myCode.format,"%24llu");
|
||||
myCode.nx_type = NX_UINT64;
|
||||
typecode[9] = myCode;
|
||||
|
||||
strcpy(myCode.name, "NX_CHAR");
|
||||
strcpy(myCode.format, "%c");
|
||||
strcpy(myCode.name,"NX_CHAR");
|
||||
strcpy(myCode.format,"%c");
|
||||
myCode.nx_type = NX_CHAR;
|
||||
typecode[10] = myCode;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
void setNumberFormat(int nx_type, char *format)
|
||||
{
|
||||
void setNumberFormat(int nx_type, char *format){
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NTYPECODE; i++) {
|
||||
if (typecode[i].nx_type == nx_type) {
|
||||
strncpy(typecode[i].format, format, 29);
|
||||
for(i = 0; i < NTYPECODE; i++){
|
||||
if(typecode[i].nx_type == nx_type){
|
||||
strncpy(typecode[i].format,format,29);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
static void getNumberFormat(int nx_type, char format[30])
|
||||
{
|
||||
static void getNumberFormat(int nx_type, char format[30]){
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NTYPECODE; i++) {
|
||||
if (typecode[i].nx_type == nx_type) {
|
||||
strncpy(format, typecode[i].format, 29);
|
||||
for(i = 0; i < NTYPECODE; i++){
|
||||
if(typecode[i].nx_type == nx_type){
|
||||
strncpy(format,typecode[i].format,29);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
void getNumberText(int nx_type, char *typestring, int typeLen)
|
||||
{
|
||||
void getNumberText(int nx_type, char *typestring, int typeLen){
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NTYPECODE; i++) {
|
||||
if (typecode[i].nx_type == nx_type) {
|
||||
strncpy(typestring, typecode[i].name, typeLen);
|
||||
for(i = 0; i < NTYPECODE; i++){
|
||||
if(typecode[i].nx_type == nx_type){
|
||||
strncpy(typestring,typecode[i].name,typeLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
|
||||
* copied here from mxml-file.c to achieve compatibility with mxml-2.1
|
||||
* standard
|
||||
*/
|
||||
|
||||
static int /* O - 0 on success, -1 on error */ myxml_add_char(int ch, /* I - Character to add */
|
||||
char **bufptr, /* IO - Current position in buffer */
|
||||
char **buffer, /* IO - Current buffer */
|
||||
int
|
||||
*bufsize)
|
||||
{ /* IO - Current buffer size */
|
||||
char *newbuffer; /* New buffer value */
|
||||
static int /* O - 0 on success, -1 on error */
|
||||
myxml_add_char(int ch, /* I - Character to add */
|
||||
char **bufptr, /* IO - Current position in buffer */
|
||||
char **buffer, /* IO - Current buffer */
|
||||
size_t *bufsize) /* IO - Current buffer size */
|
||||
{
|
||||
char *newbuffer; /* New buffer value */
|
||||
|
||||
|
||||
if (*bufptr >= (*buffer + *bufsize - 4)) {
|
||||
/*
|
||||
* Increase the size of the buffer...
|
||||
*/
|
||||
if (*bufptr >= (*buffer + *bufsize - 4))
|
||||
{
|
||||
/*
|
||||
* Increase the size of the buffer...
|
||||
*/
|
||||
|
||||
if (*bufsize < 1024) {
|
||||
if (*bufsize < 1024)
|
||||
{
|
||||
(*bufsize) *= 2;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
(*bufsize) *= 3;
|
||||
(*bufsize) /= 2;
|
||||
}
|
||||
|
||||
newbuffer = (char *) malloc(*bufsize * sizeof(char));
|
||||
if (!newbuffer) {
|
||||
newbuffer = (char *)malloc(*bufsize*sizeof(char));
|
||||
if(!newbuffer){
|
||||
free(*buffer);
|
||||
|
||||
mxml_error("Unable to expand string buffer to %d bytes!", *bufsize);
|
||||
|
||||
return (-1);
|
||||
}
|
||||
memset(newbuffer, 0, *bufsize * sizeof(char));
|
||||
memcpy(newbuffer, *buffer, *bufptr - *buffer);
|
||||
memset(newbuffer,0,*bufsize*sizeof(char));
|
||||
memcpy(newbuffer,*buffer,*bufptr - *buffer);
|
||||
free(*buffer);
|
||||
|
||||
*bufptr = newbuffer + (*bufptr - *buffer);
|
||||
*buffer = newbuffer;
|
||||
}
|
||||
|
||||
if (ch < 128) {
|
||||
/*
|
||||
* Single byte ASCII...
|
||||
*/
|
||||
if (ch < 128)
|
||||
{
|
||||
/*
|
||||
* Single byte ASCII...
|
||||
*/
|
||||
|
||||
*(*bufptr)++ = ch;
|
||||
} else if (ch < 2048) {
|
||||
/*
|
||||
* Two-byte UTF-8...
|
||||
*/
|
||||
}
|
||||
else if (ch < 2048)
|
||||
{
|
||||
/*
|
||||
* Two-byte UTF-8...
|
||||
*/
|
||||
|
||||
*(*bufptr)++ = 0xc0 | (ch >> 6);
|
||||
*(*bufptr)++ = 0x80 | (ch & 0x3f);
|
||||
} else if (ch < 65536) {
|
||||
/*
|
||||
* Three-byte UTF-8...
|
||||
*/
|
||||
}
|
||||
else if (ch < 65536)
|
||||
{
|
||||
/*
|
||||
* Three-byte UTF-8...
|
||||
*/
|
||||
|
||||
*(*bufptr)++ = 0xe0 | (ch >> 12);
|
||||
*(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f);
|
||||
*(*bufptr)++ = 0x80 | (ch & 0x3f);
|
||||
} else {
|
||||
/*
|
||||
* Four-byte UTF-8...
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Four-byte UTF-8...
|
||||
*/
|
||||
|
||||
*(*bufptr)++ = 0xf0 | (ch >> 18);
|
||||
*(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f);
|
||||
@@ -219,21 +229,27 @@ static int /* O - 0 on success, -1 on error */ myxml_add_char(int ch, /* I -
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
extern char *stptok(char *s, char *tok, size_t toklen, char *brk);
|
||||
/*=====================================================================
|
||||
actual stuff for implementing the callback functions
|
||||
=====================================================================*/
|
||||
void analyzeDim(const char *typeString, int *rank, int *iDim, int *type)
|
||||
{
|
||||
|
||||
/*
|
||||
* if passed NX_CHAR, then returns dimension of -1 and the caller
|
||||
* needs to do a strlen() or equivalent
|
||||
*/
|
||||
void analyzeDim(const char *typeString, int *rank,
|
||||
int64_t *iDim, int *type){
|
||||
char dimString[132];
|
||||
char dim[20];
|
||||
char *dimStart, *dimEnd;
|
||||
const char *dimStart, *dimEnd;
|
||||
char* dimTemp;
|
||||
int myRank;
|
||||
|
||||
if (strchr(typeString, (int) '[') == NULL) {
|
||||
switch (*type) {
|
||||
if(strchr(typeString,(int)'[') == NULL){
|
||||
*rank = 1;
|
||||
switch(*type){
|
||||
case NX_INT8:
|
||||
case NX_UINT8:
|
||||
case NX_INT16:
|
||||
@@ -247,44 +263,45 @@ void analyzeDim(const char *typeString, int *rank, int *iDim, int *type)
|
||||
iDim[0] = 1;
|
||||
break;
|
||||
case NX_CHAR:
|
||||
iDim[0] = -1;
|
||||
iDim[0] = -1; /* length unknown, caller needs to determine later */
|
||||
break;
|
||||
default:
|
||||
mxml_error("ERROR: (analyzeDim) unknown type code %d for typeString %s", *type, typeString);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
we have to determine rank and the dims.
|
||||
Start by extracting the dimension string.
|
||||
*/
|
||||
dimStart = strchr(typeString, (int) '[') + 1;
|
||||
dimEnd = strchr(typeString, (int) ']');
|
||||
if (!dimStart || !dimEnd) {
|
||||
mxml_error("ERROR: malformed dimension string in %s", typeString);
|
||||
we have to determine rank and the dims.
|
||||
Start by extracting the dimension string.
|
||||
*/
|
||||
dimStart = strchr(typeString,(int)'[') + 1;
|
||||
dimEnd = strchr(typeString,(int)']');
|
||||
if(!dimStart || !dimEnd) {
|
||||
mxml_error("ERROR: malformed dimension string in %s",typeString);
|
||||
return;
|
||||
}
|
||||
if ((dimEnd - dimStart) > 131) {
|
||||
mxml_error("ERROR: run away dimension definition in %s", typeString);
|
||||
if((dimEnd - dimStart) > 131){
|
||||
mxml_error("ERROR: run away dimension definition in %s",typeString);
|
||||
return;
|
||||
}
|
||||
memset(dimString, 0, 132);
|
||||
memcpy(dimString, dimStart, (dimEnd - dimStart) * sizeof(char));
|
||||
dimStart = stptok(dimString, dim, 19, ",");
|
||||
memset(dimString,0,132);
|
||||
memcpy(dimString,dimStart,(dimEnd-dimStart)*sizeof(char));
|
||||
dimTemp = stptok(dimString,dim,19,",");
|
||||
myRank = 0;
|
||||
while (dimStart != NULL) {
|
||||
while(dimTemp != NULL){
|
||||
iDim[myRank] = atoi(dim);
|
||||
dimStart = stptok(dimStart, dim, 19, ",");
|
||||
dimTemp = stptok(dimTemp,dim,19,",");
|
||||
myRank++;
|
||||
}
|
||||
*rank = myRank;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
int translateTypeCode(char *code)
|
||||
{
|
||||
int translateTypeCode(const char *code){
|
||||
int i, result = -1;
|
||||
|
||||
for (i = 0; i < NTYPECODE; i++) {
|
||||
if (strstr(code, typecode[i].name) != NULL) {
|
||||
|
||||
for(i = 0; i < NTYPECODE; i++){
|
||||
if(strstr(code,typecode[i].name) != NULL){
|
||||
result = typecode[i].nx_type;
|
||||
break;
|
||||
}
|
||||
@@ -292,68 +309,95 @@ int translateTypeCode(char *code)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void analyzeDataType(mxml_node_t * parent, int *rank, int *type,
|
||||
int *iDim)
|
||||
/*
|
||||
* This is used to locate an Idims node from the new style table data layout
|
||||
*/
|
||||
static mxml_node_t* findDimsNode(mxml_node_t *node)
|
||||
{
|
||||
mxml_node_t *tnode = NULL;
|
||||
const char* name = node->value.element.name;
|
||||
if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DATA_NODE_NAME) )
|
||||
{
|
||||
tnode = mxmlFindElement(node->parent->parent, node->parent->parent, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST);
|
||||
if (tnode != NULL)
|
||||
{
|
||||
tnode = mxmlFindElement(tnode,tnode,name,NULL,NULL,MXML_DESCEND_FIRST);
|
||||
}
|
||||
}
|
||||
return tnode;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
/*return 1 if in table mode , 0 if not */
|
||||
static void analyzeDataType(mxml_node_t *parent, int *rank, int *type,
|
||||
int64_t *iDim){
|
||||
const char *typeString;
|
||||
mxml_type_t myType;
|
||||
int i, nx_type = -1;
|
||||
mxml_node_t* tnode;
|
||||
int nx_type = -1;
|
||||
int table_mode = 0;
|
||||
|
||||
*rank = 1;
|
||||
*type = NX_CHAR;
|
||||
iDim[0] = -1;
|
||||
|
||||
/*
|
||||
get the type attribute. No attribute means: plain text
|
||||
*/
|
||||
typeString = mxmlElementGetAttr(parent, TYPENAME);
|
||||
if (typeString == NULL) {
|
||||
get the type attribute. No attribute means: plain text
|
||||
*/
|
||||
tnode = findDimsNode(parent);
|
||||
if (tnode != NULL)
|
||||
{
|
||||
table_mode = 1;
|
||||
parent = tnode;
|
||||
}
|
||||
typeString = mxmlElementGetAttr(parent,TYPENAME);
|
||||
if(typeString == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
nx_type = translateTypeCode((char *) typeString);
|
||||
nx_type = translateTypeCode((char *)typeString);
|
||||
|
||||
/*
|
||||
assign type
|
||||
*/
|
||||
if (nx_type == -1) {
|
||||
mxml_error
|
||||
("ERROR: %s is an invalid NeXus type, I try to continue but may fail",
|
||||
typeString);
|
||||
*type = NX_CHAR;
|
||||
assign type
|
||||
*/
|
||||
if(nx_type == -1){
|
||||
mxml_error(
|
||||
"ERROR: %s is an invalid NeXus type, I try to continue but may fail",
|
||||
typeString);
|
||||
*type =NX_CHAR;
|
||||
return;
|
||||
}
|
||||
|
||||
*type = nx_type;
|
||||
|
||||
|
||||
analyzeDim(typeString, rank, iDim, type);
|
||||
if (table_mode)
|
||||
{
|
||||
*rank = 1;
|
||||
iDim[0] = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
void destroyDataset(void *data)
|
||||
{
|
||||
if (data != NULL) {
|
||||
dropNXDataset((pNXDS) data);
|
||||
void destroyDataset(void *data){
|
||||
if(data != NULL){
|
||||
dropNXDataset((pNXDS)data);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static char *getNextNumber(char *pStart, char pNumber[80])
|
||||
{
|
||||
static char *getNextNumber(char *pStart, char pNumber[80]){
|
||||
int charCount = 0;
|
||||
pNumber[0] = '\0';
|
||||
|
||||
/* advance to first digit */
|
||||
while (isspace(*pStart) && *pStart != '\0') {
|
||||
while(isspace(*pStart) && *pStart != '\0'){
|
||||
pStart++;
|
||||
}
|
||||
if (*pStart == '\0') {
|
||||
if(*pStart == '\0'){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy */
|
||||
while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) {
|
||||
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
|
||||
pNumber[charCount] = *pStart;
|
||||
pStart++;
|
||||
charCount++;
|
||||
@@ -361,108 +405,111 @@ static char *getNextNumber(char *pStart, char pNumber[80])
|
||||
pNumber[charCount] = '\0';
|
||||
return pStart;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
mxml_type_t nexusTypeCallback(mxml_node_t * parent)
|
||||
{
|
||||
mxml_type_t nexusTypeCallback(mxml_node_t *parent){
|
||||
const char *typeString;
|
||||
|
||||
if (strstr(parent->value.element.name, "?xml") != NULL ||
|
||||
strstr(parent->value.element.name, "NX") != NULL) {
|
||||
if(strstr(parent->value.element.name,"?xml") != NULL ||
|
||||
!strncmp(parent->value.element.name,"NX",2) ||
|
||||
!strcmp(parent->value.element.name,DATA_NODE_NAME) ||
|
||||
!strcmp(parent->value.element.name,DIMS_NODE_NAME)){
|
||||
return MXML_ELEMENT;
|
||||
} else {
|
||||
typeString = mxmlElementGetAttr(parent, TYPENAME);
|
||||
if (typeString == NULL) {
|
||||
/* data nodes do not habe TYPENAME in table style but are always CUSTOM */
|
||||
if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DATA_NODE_NAME))
|
||||
{
|
||||
return MXML_CUSTOM;
|
||||
}
|
||||
if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME))
|
||||
{
|
||||
return MXML_OPAQUE;
|
||||
}
|
||||
typeString = mxmlElementGetAttr(parent,TYPENAME);
|
||||
if(typeString == NULL){
|
||||
/*
|
||||
MXML_TEXT seems more appropriate here. But mxml hacks text into
|
||||
single words which is not what NeXus wants.
|
||||
*/
|
||||
MXML_TEXT seems more appropriate here. But mxml hacks text into
|
||||
single words which is not what NeXus wants.
|
||||
*/
|
||||
return MXML_OPAQUE;
|
||||
} else {
|
||||
if (strstr(typeString, "NX_CHAR") != NULL) {
|
||||
return MXML_OPAQUE;
|
||||
} else{
|
||||
if(strstr(typeString,"NX_CHAR") != NULL){
|
||||
return MXML_OPAQUE;
|
||||
} else {
|
||||
return MXML_CUSTOM;
|
||||
return MXML_CUSTOM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
int nexusLoadCallback(mxml_node_t * node, const char *buffer)
|
||||
{
|
||||
int nexusLoadCallback(mxml_node_t *node, const char *buffer){
|
||||
mxml_node_t *parent = NULL;
|
||||
int rank, type, iDim[NX_MAXRANK];
|
||||
int rank, type;
|
||||
int64_t iDim[NX_MAXRANK];
|
||||
char pNumber[80], *pStart;
|
||||
long address, maxAddress;
|
||||
pNXDS dataset = NULL;
|
||||
int i;
|
||||
|
||||
parent = node->parent;
|
||||
analyzeDataType(parent, &rank, &type, iDim);
|
||||
if (iDim[0] == -1) {
|
||||
analyzeDataType(parent,&rank,&type,iDim);
|
||||
if(iDim[0] == -1 || !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)){
|
||||
iDim[0] = strlen(buffer);
|
||||
node->value.custom.data = strdup(buffer);
|
||||
node->value.custom.destroy = free;
|
||||
return 0;
|
||||
} else {
|
||||
node->value.custom.data = createNXDataset(rank, type, iDim);
|
||||
dataset = (pNXDS) node->value.custom.data;
|
||||
if (dataset == NULL) {
|
||||
node->value.custom.data = createNXDataset(rank,type,iDim);
|
||||
dataset = (pNXDS)node->value.custom.data;
|
||||
if(dataset == NULL){
|
||||
mxml_error("Failed to allocate custom dataset");
|
||||
return 1;
|
||||
}
|
||||
node->value.custom.destroy = destroyDataset;
|
||||
node->value.custom.destroy = destroyDataset;
|
||||
}
|
||||
|
||||
/*
|
||||
load data
|
||||
*/
|
||||
pStart = (char *) buffer;
|
||||
load data
|
||||
*/
|
||||
pStart = (char *)buffer;
|
||||
maxAddress = getNXDatasetLength(dataset);
|
||||
address = 0;
|
||||
while ((pStart = getNextNumber(pStart, pNumber)) != NULL &&
|
||||
address < maxAddress) {
|
||||
putNXDatasetValueAt(dataset, address, atof(pNumber));
|
||||
while( (pStart = getNextNumber(pStart,pNumber)) != NULL &&
|
||||
address < maxAddress){
|
||||
putNXDatasetValueAt(dataset,address,atof(pNumber));
|
||||
address++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void stringIntoBuffer(char **buffer, char **bufPtr, int *bufSize,
|
||||
char *string)
|
||||
{
|
||||
int i;
|
||||
static void stringIntoBuffer(char **buffer, char **bufPtr, size_t *bufSize,
|
||||
char *string){
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < strlen(string); i++) {
|
||||
myxml_add_char(string[i], bufPtr, buffer, bufSize);
|
||||
for(i = 0; i < strlen(string); i++){
|
||||
myxml_add_char(string[i],bufPtr,buffer,bufSize);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void formatNumber(double value, char *txt, int txtLen,
|
||||
char *format, int type)
|
||||
{
|
||||
switch (type) {
|
||||
char *format, int type){
|
||||
switch(type){
|
||||
case NX_INT8:
|
||||
case NX_UINT8:
|
||||
case NX_INT16:
|
||||
case NX_UINT16:
|
||||
case NX_INT32:
|
||||
case NX_UINT32:
|
||||
snprintf(txt, txtLen, format, (int) value);
|
||||
snprintf(txt,txtLen,format,(int)value);
|
||||
break;
|
||||
case NX_INT64:
|
||||
snprintf(txt, txtLen, format, (int64_t) value);
|
||||
snprintf(txt,txtLen,format,(int64_t)value);
|
||||
break;
|
||||
case NX_UINT64:
|
||||
snprintf(txt, txtLen, format, (uint64_t) value);
|
||||
snprintf(txt,txtLen,format,(uint64_t)value);
|
||||
break;
|
||||
case NX_FLOAT32:
|
||||
case NX_FLOAT64:
|
||||
snprintf(txt, txtLen, format, value);
|
||||
snprintf(txt,txtLen,format,value);
|
||||
break;
|
||||
default:
|
||||
/*assert(0); something is very wrong here */
|
||||
@@ -470,205 +517,231 @@ static void formatNumber(double value, char *txt, int txtLen,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int countDepth(mxml_node_t * node)
|
||||
{
|
||||
static int countDepth(mxml_node_t *node){
|
||||
int count = 0;
|
||||
mxml_node_t *cur;
|
||||
|
||||
cur = node;
|
||||
while (cur != NULL) {
|
||||
while(cur != NULL){
|
||||
count++;
|
||||
cur = cur->parent;
|
||||
}
|
||||
count--;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
char *nexusWriteCallback(mxml_node_t * node)
|
||||
{
|
||||
char *nexusWriteCallback(mxml_node_t *node){
|
||||
int type, col;
|
||||
char pNumber[80], indent[80], format[30];
|
||||
char *buffer, *bufPtr;
|
||||
pNXDS dataset;
|
||||
int bufsize, i, length, currentLen;
|
||||
int currentLen, table_style = 0;
|
||||
size_t i, bufsize, length;
|
||||
int is_definition = 0;
|
||||
/* this is set by nxconvert when making a definiton */
|
||||
is_definition = (getenv("NX_IS_DEFINITION") != NULL);
|
||||
|
||||
if (!strcmp(node->parent->parent->value.element.name, DATA_NODE_NAME))
|
||||
{
|
||||
table_style = 1;
|
||||
}
|
||||
/*
|
||||
allocate output buffer
|
||||
*/
|
||||
buffer = (char *) malloc(1024 * sizeof(char));
|
||||
if (buffer == NULL) {
|
||||
allocate output buffer
|
||||
*/
|
||||
buffer = (char *)malloc(1024*sizeof(char));
|
||||
if(buffer == NULL){
|
||||
mxml_error("Unable to allocate buffer");
|
||||
return NULL;
|
||||
}
|
||||
memset(buffer, 0, 1024);
|
||||
memset(buffer,0,1024);
|
||||
bufPtr = buffer;
|
||||
bufsize = 1024;
|
||||
|
||||
dataset = (pNXDS) node->value.custom.data;
|
||||
dataset = (pNXDS)node->value.custom.data;
|
||||
|
||||
/*
|
||||
prepare indentation level
|
||||
*/
|
||||
col = countDepth(node) * 2;
|
||||
memset(indent, 0, 80);
|
||||
for (i = 0; i < col; i++) {
|
||||
prepare indentation level
|
||||
*/
|
||||
col = countDepth(node)*2;
|
||||
memset(indent,0,80);
|
||||
for(i = 0; i < col; i++){
|
||||
indent[i] = ' ';
|
||||
}
|
||||
|
||||
/*
|
||||
get dataset info
|
||||
*/
|
||||
get dataset info
|
||||
*/
|
||||
type = getNXDatasetType(dataset);
|
||||
length = getNXDatasetLength(dataset);
|
||||
if (dataset->format != NULL) {
|
||||
strcpy(format, dataset->format);
|
||||
if (is_definition) {
|
||||
length = 1;
|
||||
} else {
|
||||
getNumberFormat(type, format);
|
||||
length = getNXDatasetLength(dataset);
|
||||
}
|
||||
if(dataset->format != NULL){
|
||||
strcpy(format,dataset->format);
|
||||
} else {
|
||||
getNumberFormat(type,format);
|
||||
}
|
||||
|
||||
/*
|
||||
actually get the data out
|
||||
*/
|
||||
currentLen = col;
|
||||
myxml_add_char('\n', &bufPtr, &buffer, &bufsize);
|
||||
stringIntoBuffer(&buffer, &bufPtr, &bufsize, indent);
|
||||
for (i = 0; i < length; i++) {
|
||||
formatNumber(getNXDatasetValueAt(dataset, i), pNumber, 79, format,
|
||||
type);
|
||||
if (currentLen + strlen(pNumber) > MXML_WRAP) {
|
||||
/*
|
||||
wrap line
|
||||
*/
|
||||
myxml_add_char('\n', &bufPtr, &buffer, &bufsize);
|
||||
stringIntoBuffer(&buffer, &bufPtr, &bufsize, indent);
|
||||
actually get the data out
|
||||
*/
|
||||
if (table_style)
|
||||
{
|
||||
for(i = 0; i < length; i++){
|
||||
formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type);
|
||||
stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLen = col;
|
||||
}
|
||||
stringIntoBuffer(&buffer, &bufPtr, &bufsize, pNumber);
|
||||
myxml_add_char(' ', &bufPtr, &buffer, &bufsize);
|
||||
currentLen += strlen(pNumber) + 1;
|
||||
myxml_add_char('\n',&bufPtr,&buffer,&bufsize);
|
||||
stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent);
|
||||
for(i = 0; i < length; i++){
|
||||
formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type);
|
||||
if(currentLen + strlen(pNumber) > MXML_WRAP){
|
||||
/*
|
||||
wrap line
|
||||
*/
|
||||
myxml_add_char('\n',&bufPtr,&buffer,&bufsize);
|
||||
stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent);
|
||||
currentLen = col;
|
||||
}
|
||||
stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber);
|
||||
myxml_add_char(' ',&bufPtr,&buffer,&bufsize);
|
||||
currentLen += strlen(pNumber) + 1;
|
||||
}
|
||||
}
|
||||
myxml_add_char('\0', &bufPtr, &buffer, &bufsize);
|
||||
return (char *) buffer;
|
||||
myxml_add_char('\0',&bufPtr,&buffer,&bufsize);
|
||||
return (char *)buffer;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
int isDataNode(mxml_node_t * node)
|
||||
{
|
||||
if (mxmlElementGetAttr(node, "name") != NULL) {
|
||||
int isDataNode(mxml_node_t *node){
|
||||
if(mxmlElementGetAttr(node,"name") != NULL){
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(node->value.element.name, "NXroot") == 0) {
|
||||
if(strcmp(node->value.element.name,"NXroot") == 0){
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(node->value.element.name, "NAPIlink") == 0) {
|
||||
if(strcmp(node->value.element.name,DIMS_NODE_NAME) == 0){
|
||||
return 0;
|
||||
}
|
||||
if(strcmp(node->value.element.name,DATA_NODE_NAME) == 0){
|
||||
return 0;
|
||||
}
|
||||
if(strcmp(node->value.element.name,"NAPIlink") == 0){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int isTextData(mxml_node_t * node)
|
||||
{
|
||||
static int isTextData(mxml_node_t *node){
|
||||
const char *attr = NULL;
|
||||
int rank, type = 0, iDim[NX_MAXRANK];
|
||||
|
||||
if (!isDataNode(node)) {
|
||||
if(!isDataNode(node)){
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
test datasets
|
||||
*/
|
||||
attr = mxmlElementGetAttr(node, TYPENAME);
|
||||
if (attr == NULL) {
|
||||
test datasets
|
||||
*/
|
||||
attr = mxmlElementGetAttr(node,TYPENAME);
|
||||
if(attr == NULL){
|
||||
return 1;
|
||||
}
|
||||
analyzeDim(attr, &rank, iDim, &type);
|
||||
if (type == NX_CHAR) {
|
||||
if(strstr(attr,"NX_CHAR") != NULL){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* note: not reentrant or thead safe; returns pointer to static storage
|
||||
*/
|
||||
const char *NXwhitespaceCallback(mxml_node_t * node, int where)
|
||||
{
|
||||
const char *NXwhitespaceCallback(mxml_node_t *node, int where){
|
||||
static char *indent = NULL;
|
||||
int len;
|
||||
int len;
|
||||
|
||||
if (strstr(node->value.element.name, "?xml") != NULL) {
|
||||
if(strstr(node->value.element.name,"?xml") != NULL){
|
||||
return NULL;
|
||||
}
|
||||
if (node->parent != NULL && !strcmp(node->parent->value.element.name, DATA_NODE_NAME))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (where == MXML_WS_BEFORE_CLOSE && !strcmp(node->value.element.name, DATA_NODE_NAME))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (isTextData(node)) {
|
||||
if (where == MXML_WS_BEFORE_OPEN) {
|
||||
len = countDepth(node) * 2 + 2;
|
||||
if (indent != NULL) {
|
||||
free(indent);
|
||||
indent = NULL;
|
||||
if(isTextData(node)){
|
||||
if(where == MXML_WS_BEFORE_OPEN){
|
||||
len = countDepth(node)*2 + 2;
|
||||
if (indent != NULL)
|
||||
{
|
||||
free(indent);
|
||||
indent = NULL;
|
||||
}
|
||||
indent = (char *) malloc(len * sizeof(char));
|
||||
if (indent != NULL) {
|
||||
memset(indent, ' ', len);
|
||||
indent[0] = '\n';
|
||||
indent[len - 1] = '\0';
|
||||
return (const char *) indent;
|
||||
indent = (char *)malloc(len*sizeof(char));
|
||||
if(indent != NULL){
|
||||
memset(indent,' ',len);
|
||||
indent[0]= '\n';
|
||||
indent[len-1] = '\0';
|
||||
return (const char*)indent;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE) {
|
||||
len = countDepth(node) * 2 + 2;
|
||||
if (indent != NULL) {
|
||||
free(indent);
|
||||
indent = NULL;
|
||||
if(where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE){
|
||||
len = countDepth(node)*2 + 2;
|
||||
if (indent != NULL)
|
||||
{
|
||||
free(indent);
|
||||
indent = NULL;
|
||||
}
|
||||
indent = (char *) malloc(len * sizeof(char));
|
||||
if (indent != NULL) {
|
||||
memset(indent, ' ', len);
|
||||
indent[0] = '\n';
|
||||
indent[len - 1] = '\0';
|
||||
return (const char *) indent;
|
||||
indent = (char *)malloc(len*sizeof(char));
|
||||
if(indent != NULL){
|
||||
memset(indent,' ',len);
|
||||
indent[0]= '\n';
|
||||
indent[len-1] = '\0';
|
||||
return (const char*)indent;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#ifdef TESTMAIN
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mxml_node_t *root = NULL;
|
||||
FILE *f;
|
||||
int main(int argc, char *argv[]){
|
||||
mxml_node_t *root = NULL;
|
||||
FILE *f;
|
||||
|
||||
mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback);
|
||||
initializeNumberFormats();
|
||||
mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback);
|
||||
initializeNumberFormats();
|
||||
|
||||
/*
|
||||
/*
|
||||
read test
|
||||
*/
|
||||
f = fopen("dmc.xml", "r");
|
||||
root = mxmlLoadFile(NULL, f, nexusTypeCallback);
|
||||
fclose(f);
|
||||
f = fopen("dmc.xml","r");
|
||||
root = mxmlLoadFile(NULL,f,nexusTypeCallback);
|
||||
fclose(f);
|
||||
|
||||
/*
|
||||
/*
|
||||
write test
|
||||
*/
|
||||
setNumberFormat(NX_INT32, "%8d");
|
||||
setNumberFormat(NX_FLOAT32, "%8.2f");
|
||||
f = fopen("dmc2.xml", "w");
|
||||
mxmlSaveFile(root, f, NXwhitespaceCallback);
|
||||
fclose(f);
|
||||
setNumberFormat(NX_INT32,"%8d");
|
||||
setNumberFormat(NX_FLOAT32,"%8.2f");
|
||||
f = fopen("dmc2.xml","w");
|
||||
mxmlSaveFile(root,f,NXwhitespaceCallback);
|
||||
fclose(f);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /*NXXML*/
|
||||
|
||||
Reference in New Issue
Block a user