Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
xData.cc
Go to the documentation of this file.
1 /*
2 # <<BEGIN-copyright>>
3 # Copyright (c) 2010, Lawrence Livermore National Security, LLC.
4 # Produced at the Lawrence Livermore National Laboratory
5 # Written by Bret R. Beck, beck6@llnl.gov.
6 # CODE-461393
7 # All rights reserved.
8 #
9 # This file is part of GIDI. For details, see nuclear.llnl.gov.
10 # Please also read the "Additional BSD Notice" at nuclear.llnl.gov.
11 #
12 # Redistribution and use in source and binary forms, with or without modification,
13 # are permitted provided that the following conditions are met:
14 #
15 # 1) Redistributions of source code must retain the above copyright notice,
16 # this list of conditions and the disclaimer below.
17 # 2) Redistributions in binary form must reproduce the above copyright notice,
18 # this list of conditions and the disclaimer (as noted below) in the
19 # documentation and/or other materials provided with the distribution.
20 # 3) Neither the name of the LLNS/LLNL nor the names of its contributors may be
21 # used to endorse or promote products derived from this software without
22 # specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
25 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27 # SHALL LAWRENCE LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR
28 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33 # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 # <<END-copyright>>
35 */
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #ifndef WIN32
40  #include <unistd.h>
41 #endif
42 #ifdef WIN32
43  #include <io.h>
44  #ifndef _SSIZE_T_DEFINED
45  typedef int ssize_t;
46  #define _SSIZE_T_DEFINED
47  #endif
48 #endif
49 
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <fcntl.h>
53 #include <errno.h>
54 
55 #include "xData.h"
56 
57 #if defined __cplusplus
58 namespace GIDI {
59 using namespace GIDI;
60 #endif
61 
62 static void *xData_parseFreeElement( statusMessageReporting *smr, xData_element *element );
63 static void xData_parseFreeElementItems( statusMessageReporting *smr, xData_element *element );
64 static void XMLCALL xData_parseStartElement( void *userData, const char *name, const char **attris );
65 static void XMLCALL xData_parseEndElement( void *userData, const char *name );
66 static void XMLCALL xData_parseCharacterData( void *userData, const XML_Char *s, int len );
67 static void xData_parseInitializeRootElement( xData_document *doc, xData_rootElement *re, xData_element *parentElement,
68  int depth );
69 static int xData_parseInitializeText( xData_document *doc, xData_text *text );
70 static int xData_parseAddElementToRoot( statusMessageReporting *smr, xData_rootElement *parentRoot, const char *name, const char **attris );
71 static enum xData_errorCodes xData_parseGetCurrentPosition( xData_document *doc, xData_docInfo *docInfo );
72 static int xData_init_xDataTypeNone( xDataType *xDT, xData_element *element );
73 static char *xData_getTraceback( statusMessageReporting *smr, xData_element *element );
74 static char *xData_getTraceback2( statusMessageReporting *smr, xData_rootElement *parentRoot, int n );
75 static int xData_elementList_defaultSorter( void const *p1, void const *p2 );
76 static int xData_elementList_indexSorter( void const *p1, void const *p2 );
77 static int xData_smrUserInterfaceInitialize( xData_document *doc );
78 static int xData_smrUserInterfaceFree( xData_document *doc );
79 static int xData_smrUserInterface( void *userData, char **smr );
80 static char const *xData_shortStringForMessage( size_t size, char *Out, char const *In );
81 /*
82 ************************************************************
83 */
85 /*
86 * Returns NULL is any error occurred. If an error occurs in an expat routine, xData_parseEndOfXML will set smr appropriately.
87 */
88  int f;
89  char buffer[10 * 1000];
90  ssize_t count, n = sizeof( buffer ) - 1;
91  ssize_t s = 0;
92  xData_document *doc = NULL;
93 
94  if( ( doc = xData_parseMalloc( smr, func, userData ) ) != NULL ) {
95  if( xData_setFileName( smr, doc, fileName ) == 0 ) {
96  f = open( fileName, O_RDONLY );
97  if( f == -1 ) {
98  xData_parseEndOfXML( smr, doc );
99  smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errFileError, "could not open file %s", fileName ); }
100  else {
101  while( ( count = read( f, buffer, n ) ) > 0 ) {
102  s += count;
103  buffer[count] = 0;
104  if( xData_parse( doc, buffer ) ) break;
105  if( !smr_isOk( doc->smr ) ) break;
106  }
107  close( f );
108  xData_parseEndOfXML( smr, doc );
109  if( count < 0 ) smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errFileError,
110  "read failed with errno = %d for %s", errno, fileName );
111  }
112  }
113  if( ( doc != NULL ) && ( !smr_isOk( smr ) ) ) {
114  xData_parseFree( smr, doc );
115  doc = NULL;
116  }
117  }
118  return( doc );
119 }
120 /*
121 ************************************************************
122 */
124 /*
125 * Returns NULL is any error occurred. If an error occurs in an expat routine, xData_parseEndOfXML will set smr appropriately.
126 */
127  xData_document *doc = NULL;
128  if( ( doc = xData_parseMalloc( smr, func, userData ) ) != NULL ) {
129  xData_parse( doc, str );
130  xData_parseEndOfXML( smr, doc );
131  if( !smr_isOk( smr ) ) {
132  xData_parseFree( smr, doc );
133  doc = NULL;
134  }
135  }
136  return( doc );
137 }
138 /*
139 ************************************************************
140 */
142 /*
143 * Returns NULL is any error occurred.
144 */
145  xData_document *doc;
146 
147  //if( ( doc = xData_malloc2( smr, sizeof( xData_document ), 1, "xData_document" ) ) != NULL ) {
148  if( ( doc = (xData_document*) xData_malloc2( smr, sizeof( xData_document ), 1, "xData_document" ) ) != NULL ) {
149  //if( xData_parseInitialize( smr, doc, func, userData ) ) doc = xData_parseFree( smr, doc );
150  if( xData_parseInitialize( smr, doc, func, userData ) ) doc = (xData_document*) xData_parseFree( smr, doc );
151  }
152  return( doc );
153 }
154 /*
155 ************************************************************
156 */
158 
159  XML_Parser xmlParser;
160 
162  doc->error = xData_errNone;
163  //doc->err = 0;
164  doc->err = (XML_Error) 0;
165  doc->err_line = 0;
166  doc->err_column = 0;
167  doc->fileName = NULL;
168  doc->xDataTypeOk_userFunction = func;
170  xData_smrUserInterfaceInitialize( doc );
171  doc->smr= smr;
172  doc->xmlParser = xmlParser = XML_ParserCreate( NULL );
173  if( xmlParser == NULL ) {
174  smr_setMessageError( smr, NULL, __FILE__, __LINE__, xData_errXML_ParserCreate, "XML_ParserCreate failed" ); }
175  else {
176  XML_SetUserData( doc->xmlParser, doc );
177  xData_parseInitializeRootElement( doc, &(doc->root), NULL, 0 );
178  doc->currentRoot = &(doc->root);
179  XML_SetElementHandler( xmlParser, xData_parseStartElement, xData_parseEndElement );
180  XML_SetCharacterDataHandler( xmlParser, xData_parseCharacterData );
181  }
182  return( !smr_isOk( smr ) );
183 }
184 /*
185 ************************************************************
186 */
188 
189  if( doc->xmlParser ) {
190  doc->err = XML_GetErrorCode( doc->xmlParser );
193  if( smr_isOk( smr ) && ( XML_Parse( doc->xmlParser, NULL, 0, 1 ) == XML_STATUS_ERROR ) ) {
194  doc->status = xData_statusError;
196  "status = %d\nXML_Error code = %d\nXML_ErrorString = %s\nerror line, column = %d, %d", xData_errXMLParser,
197  doc->err, XML_ErrorString( doc->err ), doc->err_line, doc->err_column );
198  }
199  XML_ParserFree( doc->xmlParser );
200  doc->xmlParser = NULL;
202  }
203  return( 0 );
204 }
205 /*
206 ************************************************************
207 */
209 
210  xData_parseEndOfXML( smr, doc );
211  //doc->root.children = xData_parseFreeElement( smr, doc->root.children );
212  doc->root.children = (xData_element*) xData_parseFreeElement( smr, doc->root.children );
213  //doc->fileName = xData_free( smr, doc->fileName );
214  doc->fileName = (char*) xData_free( smr, doc->fileName );
215  xData_smrUserInterfaceFree( doc );
216  xData_free( smr, doc );
217  return( NULL );
218 }
219 /*
220 ************************************************************
221 */
222 static void *xData_parseFreeElement( statusMessageReporting *smr, xData_element *element ) {
223 
224  xData_element *next;
225 
226  if( element == NULL ) return( NULL );
227  for( ; element != NULL; element = next ) {
228  next = element->next;
229  xData_parseFreeElementItems( smr, element );
230  xData_free( smr, element );
231  }
232  return( NULL );
233 }
234 /*
235 ************************************************************
236 */
237 static void xData_parseFreeElementItems( statusMessageReporting *smr, xData_element *element ) {
238 
239  //element->childrenRoot.children = xData_parseFreeElement( smr, element->childrenRoot.children );
240  element->childrenRoot.children = (xData_element*) xData_parseFreeElement( smr, element->childrenRoot.children );
241  if( ( !strcmp( element->name, "xData" ) ) && ( element->xDataTypeInfo.release != NULL ) ) element->xDataTypeInfo.release( smr,
242  &(element->xDataTypeInfo) );
243  xData_free( smr, element->name );
244  xData_free( smr, element->fullName );
245  if( element->attributes.attributes ) xData_free( smr, element->attributes.attributes );
246  if( element->text.text ) xData_free( smr, element->text.text );
247 }
248 /*
249 ************************************************************
250 */
251 int xData_parse( xData_document *doc, const char *s ) {
252 
253  if( doc->status != xData_statusParsing ) return( doc->status );
254  if( XML_Parse( doc->xmlParser, s, strlen( s ), 0 ) == XML_STATUS_ERROR ) return( -1 );
255  return( 0 );
256 }
257 /*
258 ************************************************************
259 */
260 static void XMLCALL xData_parseStartElement( void *userData, const char *name, const char **attris ) {
261 
262  xData_document *doc = (xData_document *) userData;
263 
264  if( !smr_isOk( doc->smr ) ) return;
265  xData_parseAddElementToRoot( doc->smr, doc->currentRoot, name, attris );
266 }
267 /*
268 ************************************************************
269 */
270 static void XMLCALL xData_parseEndElement( void *userData, const char *name ) {
271 
272  int status = 0;
273  xData_document *doc = (xData_document *) userData;
274 
275  if( !smr_isOk( doc->smr ) ) return;
276  if( !strcmp( name, "xData" ) ) {
278  xData_text *text = &(element->text);
279  const char *value = xData_getAttributesValueInElement( element, "type" );
280  if( !strcmp( value, xData_oned_x_ID ) ) {
281  xData_init_1d_x( doc->smr, element ); }
282  else if( !strcmp( value, xData_twod_xy_ID ) ) {
283  xData_init_2d_xy( doc->smr, element ); }
284  else if( !strcmp( value, xData_twod_xindex_y_ID ) ) {
285  xData_init_2d_xindex_y( doc->smr, element ); }
286  else if( !strcmp( value, xData_twod_xShared_yHistogram_ID ) ) {
287  xData_init_2d_xShared_yHistogram( doc->smr, element ); }
288  else if( !strcmp( value, xData_matrix_ID ) ) {
289  xData_init_matrix( doc->smr, element ); }
290  else {
291  status = -1;
292  if( doc->xDataTypeOk_userFunction != NULL ) {
293  if( doc->xDataTypeOk_userFunction( value, doc, doc->xDataTypeOk_userData ) ) status = 1;
294  }
295  if( status < 0 ) smr_setMessageError( doc->smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, -1,
296  "Unsupported xData type = %s", value );
297  }
298  if( ( status == 0 ) && ( smr_isOk( doc->smr ) ) ) status = element->xDataTypeInfo.toData( doc->smr, &(element->xDataTypeInfo),
299  &(element->attributes), text->text );
300  }
301  doc->currentRoot->currentChild = NULL;
302  doc->currentRoot = doc->currentRoot->parentRoot;
303 }
304 /*
305 ************************************************************
306 */
307 static void XMLCALL xData_parseCharacterData( void *userData, const XML_Char *s, int len ) {
308 /*
309 * Always terminates text with a 0.
310 */
311  //xData_document *doc = userData;
312  xData_document *doc = (xData_document*) userData;
314  int needSize = text->length + len + 1, l;
315  char *p;
316 
317  if( !smr_isOk( doc->smr ) ) return;
318  if( needSize < 8 ) needSize = 8;
319  //if( needSize > text->allocated ) {
320  if( needSize > (int) text->allocated ) {
321  if( text->allocated != 0 ) {
322  l = ( 20 * text->allocated ) / 100;
323  if( l < 100 ) l = 100;
324  //if( needSize < ( text->allocated + l ) ) needSize = text->allocated + l;
325  if( needSize < ( (int) text->allocated + l ) ) needSize = text->allocated + l;
326  }
327  text->allocated = needSize;
328  //text->text = xData_realloc2( doc->smr, text->text, text->allocated, "text" );
329  text->text = (char*) xData_realloc2( doc->smr, text->text, text->allocated, "text" );
330  if( !smr_isOk( doc->smr ) ) return;
331  }
332  p = &(text->text[text->length]);
333  strncpy( p, s, len );
334  text->length += len;
335  p[len] = 0;
336 }
337 /*
338 ************************************************************
339 */
340 static void xData_parseInitializeRootElement( xData_document *doc, xData_rootElement *re,
341  xData_element *parentElement, int depth ) {
342 
343  re->xData_doc = doc;
344  re->parentElement = parentElement;
345  re->parentRoot = NULL;
346  if( parentElement != NULL ) re->parentRoot = parentElement->parentRoot;
347  re->depth = depth;
348  re->numberOfElements = 0;
349  re->children = NULL;
350  re->currentChild = NULL;
351 }
352 /*
353 ************************************************************
354 */
355 static int xData_parseInitializeText( xData_document *doc, xData_text *text ) {
356 
357  xData_parseGetCurrentPosition( doc, &(text->docInfo) );
358  text->allocated = 0;
359  text->length = 0;
360  text->text = NULL;
361  return( 0 );
362 }
363 /*
364 ************************************************************
365 */
366 static int xData_parseAddElementToRoot( statusMessageReporting *smr, xData_rootElement *parentRoot, const char *name, const char **attris ) {
367 
368  xData_document *doc = parentRoot->xData_doc;
369  xData_element *element;
370  int i, n, status = 1;
371  size_t lens;
372  char *p, *e;
373  const char **pAttris;
375  void *smrUser;
376 
377  //element = xData_malloc2( doc->smr, sizeof( xData_element ), 1, "xData_element" );
378  element = (xData_element*) xData_malloc2( doc->smr, sizeof( xData_element ), 1, "xData_element" );
379  if( element == NULL ) return( 1 );
380  xData_parseGetCurrentPosition( doc, &(element->docInfo) );
381  element->ordinal = parentRoot->numberOfElements;
382  element->index = -1;
383  element->accessed = 0;
384  element->parentRoot = parentRoot;
385  xData_parseInitializeRootElement( doc, &(element->childrenRoot), element, parentRoot->depth + 1 );
386  element->next = NULL;
387  //if( ( element->name = xData_malloc2( doc->smr, strlen( name ) + 1, 0, "name" ) ) == NULL ) {
388  if( ( element->name = (char*) xData_malloc2( doc->smr, strlen( name ) + 1, 0, "name" ) ) == NULL ) {
389  xData_free( smr, element );
390  return( 1 );
391  }
392  strcpy( element->name, name );
393  if( ( element->fullName = xData_getTraceback( smr, element ) ) == NULL ) {
394  xData_free( smr, element->name );
395  xData_free( smr, element );
396  return( 1 );
397  }
398  for( i = 0, lens = 0, pAttris = attris; *pAttris; i++, pAttris++ ) lens += strlen( *pAttris ) + 1;
399  n = i / 2;
400  element->attributes.size = n * sizeof( xData_attribute ) + lens;
401  element->attributes.number = n;
402  element->attributes.attributes = NULL;
403  smrUser = xData_get_smrUserInterfaceFromElement( element );
404  if( element->attributes.size ) {
405  //if( ( element->attributes.attributes = xData_malloc2( doc->smr, element->attributes.size, 0, "attributes") ) == NULL ) {
406  if( ( element->attributes.attributes = (xData_attribute*) xData_malloc2( doc->smr, element->attributes.size, 0, "attributes") ) == NULL ) {
407  status = 0; }
408  else {
409  a = element->attributes.attributes;
410  p = (char *) &(element->attributes.attributes[n]);
411  for( i = 0, pAttris = attris; ( i < n ) && status; i++, a++, pAttris++ ) {
412  lens = strlen( *pAttris ) + 1;
413  a->name = p;
414  strcpy( p, *pAttris );
415  p += lens;
416  pAttris++;
417  lens = strlen( *pAttris ) + 1;
418  a->value= p;
419  strcpy( p, *pAttris );
420  p += lens;
421  if( !strcmp( "index", a->name ) ) {
422 #ifndef WIN32
423  element->index = strtoll( a->value, &e, 10 );
424 #endif
425 #ifdef WIN32
426  element->index = strtol( a->value, &e, 10 );
427 #endif
428  if( *e != 0 ) {
429  status = 0;
430  smr_setMessageError( doc->smr, smrUser, __FILE__, __LINE__, -1, "could not convert index attribute = %s to integer", a->value );
431  }
432  }
433  }
434  }
435  }
436  if( !status ) {
437  xData_free( smr, element->attributes.attributes );
438  xData_free( smr, element->name );
439  xData_free( smr, element->fullName );
440  xData_free( smr, element );
441  return( 1 );
442  }
443  xData_init_xDataTypeNone( &(element->xDataTypeInfo), element );
444  element->textOffset = 0;
445  xData_parseInitializeText( doc, &(element->text) );
446  if( parentRoot->parentElement != NULL ) element->textOffset = parentRoot->parentElement->text.length;
447  if( parentRoot->currentChild == NULL ) {
448  parentRoot->children = element; }
449  else {
450  parentRoot->currentChild->next = element;
451  }
452  parentRoot->numberOfElements++;
453  parentRoot->currentChild = element;
454  doc->currentRoot = &(element->childrenRoot);
455  return( 0 );
456 }
457 /*
458 ************************************************************
459 */
460 static enum xData_errorCodes xData_parseGetCurrentPosition( xData_document *doc, xData_docInfo *docInfo ) {
461 
462  docInfo->column = XML_GetCurrentColumnNumber( doc->xmlParser );
463  docInfo->line = XML_GetCurrentLineNumber( doc->xmlParser );
464  return( xData_errNone );
465 }
466 /*
467 ************************************************************
468 */
470 
471  return( doc->status == xData_statusError );
472 }
473 /*
474 ************************************************************
475 */
478 xData_element *xData_getNextElement( xData_element *element ) { return( element->next ); }
479 /*
480 ************************************************************
481 */
483 
484  item->parentElement = element;
485  item->element = xData_getFirstElement( element );
486  if( item->element == NULL ) {
487  item->mode = xData_itemModeText;
488  if( element->text.length == 0 ) item->mode = xData_itemModeEnd; }
489  else {
490  item->mode = xData_itemModeElement;
491  if( 0 < item->element->textOffset ) item->mode = xData_itemModeText;
492  }
493  item->textOffset = 0;
494  item->textLength = element->text.length;
495  if( item->element != NULL ) item->textLength = item->element->textOffset;
496  item->text = element->text.text;
497  return( item->mode );
498 }
499 /*
500 ************************************************************
501 */
503 
504  if( item->mode != xData_itemModeEnd ) {
505  if( item->mode == xData_itemModeText ) {
506  item->mode = xData_itemModeElement;
507  if( item->element == NULL ) item->mode = xData_itemModeEnd;
508  item->textOffset += item->textLength;
509  item->textLength = 0;
510  item->text = &(item->parentElement->text.text[item->textOffset]); }
511  else {
512  item->element = item->element->next;
513  item->mode = xData_itemModeText;
514  if( item->element == NULL ) {
515  if( item->textOffset < item->parentElement->text.length ) {
516  item->textLength = item->parentElement->text.length - item->textOffset; }
517  else {
518  item->mode = xData_itemModeEnd;
519  } }
520  else {
521  item->textLength = item->element->textOffset - item->textOffset;
522  }
523  }
524  }
525  return( item->mode );
526 }
527 /*
528 ************************************************************
529 */
530 char *xData_getAttributesValue( xData_attributionList *attributes, const char *name ) {
531 
532  int i;
533  char *value = NULL;
534 
535  for( i = 0; i < attributes->number; i++ ) {
536  if( !strcmp( attributes->attributes[i].name, name ) ) {
537  value = attributes->attributes[i].value;
538  break;
539  }
540  }
541  return( value );
542 }
543 /*
544 ************************************************************
545 */
546 const char *xData_getAttributesValueInElement( xData_element *element, const char *name ) {
547 
548  return( (const char *) xData_getAttributesValue( &(element->attributes), name ) );
549 }
550 /*
551 ************************************************************
552 */
553 //int xData_initializeAttributionList( statusMessageReporting *smr, xData_attributionList *attributes ) {
555 
556  attributes->number = 0;
557  attributes->size = 0;
558  attributes->attributes = NULL;
559  return( 0 );
560 }
561 /*
562 ************************************************************
563 */
565 /*
566 * The dest must not be active, else a memory leak will occur, as this routine does no free-ing.
567 */
568  int i;
569  size_t lens;
570  xData_attribute *d, *s;
571  char *p;
572 
573  //if( ( dest->attributes = xData_malloc2( smr, src->size, 0, "attributes" ) ) == NULL ) return( 1 );
574  if( ( dest->attributes = (xData_attribute*) xData_malloc2( smr, src->size, 0, "attributes" ) ) == NULL ) return( 1 );
575  dest->number = src->number;
576  dest->size = src->size;
577  d = dest->attributes;
578  s = src->attributes;
579  p = (char *) &(dest->attributes[src->number]);
580  for( i = 0; i < src->number; i++, s++, d++ ) {
581  lens = strlen( s->name ) + 1;
582  d->name = p;
583  strcpy( p, s->name );
584  p += lens;
585  lens = strlen( s->value ) + 1;
586  d->value= p;
587  strcpy( p, s->value );
588  p += lens;
589  }
590 
591  return( 0 );
592 }
593 /*
594 ************************************************************
595 */
597 
598  return( attributes->number );
599 }
600 /*
601 ************************************************************
602 */
604 
605  if( index >= attributes->number ) return( NULL );
606  return( &(attributes->attributes[index]) );
607 }
608 /*
609 ************************************************************
610 */
612 
613  attributes->number = 0;
614  attributes->size = 0;
615  //attributes->attributes = xData_free( smr, attributes->attributes );
616  attributes->attributes = (xData_attribute*) xData_free( smr, attributes->attributes );
617  return( 0 );
618 }
619 /*
620 ************************************************************
621 */
623 
624  //return( xData_getOneElementByTagName( smr, element, "xData", 1 ) );
625  return( xData_getOneElementByTagName( smr, element, (char*) "xData", 1 ) );
626 }
627 /*
628 ************************************************************
629 */
630 static int xData_init_xDataTypeNone( xDataType *xDT, xData_element *element ) {
631 
632  xDT->status = xData_xDataType_Ok;
633  xDT->typeString = NULL;
634  xDT->element = element;
635  xDT->toData = NULL;
636  xDT->toString = NULL;
637  xDT->release = NULL;
638  xDT->indexPresent = 1; /* The following describes the meaning of present variables. */
639  xDT->startPresent = 1; /* If < 0, an error occured in converting value to an integer. */
640  xDT->endPresent = 1; /* If > 0, not present as an attribute. */
641  xDT->lengthPresent = 1; /* Else, if 0, present and converted without an error. */
642  xDT->index = -1;
643  xDT->start = -1;
644  xDT->end = -1;
645  xDT->length = -1;
646  xDT->data = NULL;
647  return( 0 );
648 }
649 /*
650 ************************************************************
651 */
653  xData_Int *length ) {
654 
655  if( element->xDataTypeInfo.typeString == NULL ) {
656  smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1, "element %s is not xData", element->fullName );
657  return( 1 );
658  }
659  *index = element->xDataTypeInfo.index;
660  *start = element->xDataTypeInfo.start;
661  *end = element->xDataTypeInfo.end;
662  *length = element->xDataTypeInfo.length;
663  return( 0 );
664 }
665 /*
666 ************************************************************
667 */
669 
670  xDataType *xDT = &(element->xDataTypeInfo);
671  void *smrUser = xData_get_smrUserInterfaceFromElement( element );
672 
673  xDT->index = -1;
674  xDT->start = -1;
675  xDT->end = -1;
676  xDT->length = -1;
677  if( ( xDT->indexPresent = xData_convertAttributeTo_xData_Int( smr, element, "index", &(xDT->index) ) ) < 0 ) return( 1 );
678  if( ( xDT->startPresent = xData_convertAttributeTo_xData_Int( smr, element, "start", &(xDT->start) ) ) < 0 ) return( 1 );
679  if( ( xDT->endPresent = xData_convertAttributeTo_xData_Int( smr, element, "end", &(xDT->end) ) ) < 0 ) return( 1 );
680  if( ( xDT->lengthPresent = xData_convertAttributeTo_xData_Int( smr, element, "length", &(xDT->length) ) ) < 0 ) return( 1 );
681  if( ( xDT->endPresent > 0 ) ) {
682  if( xDT->lengthPresent > 0 ) {
683  smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "missing length (or end) in xData" );
684  return( 1 );
685  }
686  xDT->end = xDT->length; }
687  else {
688  if( xDT->lengthPresent > 0 ) xDT->length = xDT->end;
689  }
690 
691  if( xDT->startPresent > 0 ) xDT->start = 0;
692  if( xDT->start < 0 ) {
693  smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "start = %d < 0", xDT->start );
694  return( 1 );
695  }
696  if( xDT->end < xDT->start ) {
697  smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "start = %d >= end = %d", xDT->start, xDT->end );
698  return( 1 );
699  }
700  if( xDT->length < 0 ) {
701  smr_setMessageError( smr, smrUser, __FILE__, __LINE__, 1, "length = %d < 0", xDT->length );
702  return( 1 );
703  }
704 
705  return( 0 );
706 }
707 /*
708 ************************************************************
709 */
711 /*
712 * Returns 1 if no such attribute, -1 if error converting to xData_Int and 0 if successful.
713 */
714  const char *value;
715  char *e;
716 
717  if( ( value = xData_getAttributesValueInElement( element, name ) ) == NULL ) return( 1 );
718  //*n = strtoll( value, &e, 10 );
719  *n = strtol( value, &e, 10 );
720  if( *e != 0 ) {
721  smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1,
722  "could not convert attribute %s's value = %s to an integer", name, value );
723  return( -1 );
724  }
725  return( 0 );
726 }
727 /*
728 ************************************************************
729 */
730 int xData_convertAttributeToDouble( statusMessageReporting *smr, xData_element *element, const char *name, double *d ) {
731 /*
732 * Returns 1 if no such attribute, -1 if error converting to double and 0 if successful.
733 */
734  const char *value;
735  char *e;
736 
737  if( ( value = xData_getAttributesValueInElement( element, name ) ) == NULL ) return( 1 );
738  *d = strtod( value, &e );
739  if( *e != 0 ) {
740  smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element) , __FILE__, __LINE__, 1,
741  "could not convert attribute %s's values = %s to a double", name, value );
742  return( -1 );
743  }
744  return( 0 );
745 }
746 /*
747 ************************************************************
748 */
749 //int xData_numberOfElementsByTagName( statusMessageReporting *smr, xData_element *element, const char *tagName ) {
751 
752  int n = 0;
753  xData_element *child;
754 
755  for( child = xData_getFirstElement( element ); child != NULL; child = xData_getNextElement( child ) ) if( !strcmp( child->name, tagName ) ) n++;
756  return( n );
757 }
758 /*
759 ************************************************************
760 */
762 
763  int n = xData_numberOfElementsByTagName( smr, element, tagName );
764  size_t size;
765  xData_element *child;
767  xData_elementList *list = NULL;
768 
769 
770  size = sizeof( xData_elementList ) + n * sizeof( xData_elementListItem );
771  //if( ( list = xData_malloc2( smr, size, 0, "list" ) ) != NULL ) {
772  if( ( list = (xData_elementList*) xData_malloc2( smr, size, 0, "list" ) ) != NULL ) {
773  list->n = n;
774  p = list->items = (xData_elementListItem *) &(list[1]);
775  for( child = xData_getFirstElement( element ); child != NULL; child = xData_getNextElement( child ) ) {
776  if( !strcmp( child->name, tagName ) ) {
777  p->element = child;
778  p->sortString = NULL;
779  p++;
780  }
781  }
782  }
783  return( list );
784 }
785 /*
786 ************************************************************
787 */
789  const char *sortAttributeName, xData_sortElementFunc sortFunction ) {
790 
791  int i;
792  xData_elementList *list = xData_getElementsByTagName( smr, element, tagName );
794 
795  if( list != NULL ) {
796  if( sortFunction == NULL ) {
797  sortFunction = (xData_sortElementFunc) xData_elementList_defaultSorter;
798  if( sortAttributeName == NULL ) sortFunction = (xData_sortElementFunc) xData_elementList_indexSorter;
799  }
800  if( sortAttributeName == NULL ) sortAttributeName = "index";
801  for( i = 0, p = list->items; i < list->n; i++, p++ ) p->sortString = xData_getAttributesValueInElement( p->element, sortAttributeName );
802  qsort( list->items, list->n, sizeof( xData_elementListItem ), sortFunction );
803  }
804 
805  return( list );
806 }
807 /*
808 ************************************************************
809 */
811 
812  xData_elementList *list;
813  xData_element *xData = NULL;
814 
815  if( ( list = xData_getElementsByTagName( smr, element, name ) ) != NULL ) {
816  if( list->n == 0 ) {
817  if( required ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__,
818  1, "element %s does not have sub-element named %s", element->fullName, name ); }
819  else if( list->n > 1 ) {
820  smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( element ), __FILE__, __LINE__, 1,
821  "element %s contains more than one sub-element named %s", element->fullName, name ); }
822  else {
823  xData = list->items[0].element;
824  }
825  xData_freeElementList( smr, list );
826  }
827  return( xData );
828 }
829 /*
830 ************************************************************
831 */
833 
834  xData_free( smr, list );
835 }
836 /*
837 ************************************************************
838 */
839 static char *xData_getTraceback( statusMessageReporting *smr, xData_element *element ) {
840 /*
841 * Returned string must be freed by calling routine.
842 */
843  int size;
844  char *s, *name;
845 
846  name = element->name;
847  size = strlen( name ) + 1;
848  if( ( s = xData_getTraceback2( smr, element->parentRoot, size ) ) != NULL ) {
849  strcat( s, "/" );
850  strcat( s, name );
851  }
852  return( s );
853 }
854 /*
855 ************************************************************
856 */
857 static char *xData_getTraceback2( statusMessageReporting *smr, xData_rootElement *parentRoot, int n ) {
858 
859  int size;
860  char *s, *name;
861 
862  if( parentRoot->parentRoot == NULL ) {
863  //s = xData_malloc2( smr, n + 1, 0, "traceback string" );
864  s = (char*) xData_malloc2( smr, n + 1, 0, "traceback string" );
865  *s = 0; }
866  else {
867  name = parentRoot->parentElement->name;
868  size = strlen( name ) + 1;
869  n += size;
870  if( ( s = xData_getTraceback2( smr, parentRoot->parentRoot, n ) ) != NULL ) {
871  strcat( s, "/" );
872  strcat( s, name );
873  }
874  }
875  return( s );
876 }
877 /*
878 ************************************************************
879 */
880 static int xData_elementList_defaultSorter( void const *p1, void const *p2 ) {
881 
882  const char *s1 = ((xData_elementListItem *) p1)->sortString, *s2 = ((xData_elementListItem *) p2)->sortString;
883 
884  if( s2 == NULL ) return( -1 );
885  if( s1 == NULL ) return( 1 );
886  return( strcmp( s1, s2 ) );
887 }
888 /*
889 ************************************************************
890 */
891 static int xData_elementList_indexSorter( void const *p1, void const *p2 ) {
892 
893  xData_element *e1 = ((xData_elementListItem *) p1)->element, *e2 = ((xData_elementListItem *) p2)->element;
894 
895  return( e1->index - e2->index );
896 }
897 /*
898 ************************************************************
899 */
900 int xData_is_xDataType( statusMessageReporting *smr, xDataType *xDT, char const * const type, int setMsg ) {
901 
902  if( xDT->typeString == NULL ) {
903  if( setMsg ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( xDT->element ), __FILE__, __LINE__, 1,
904  "element %s not xData object", xDT->element->fullName ); }
905  else if( xDT->typeString != type ) {
906  if( setMsg ) smr_setMessageError( smr, xData_get_smrUserInterfaceFromElement( xDT->element ), __FILE__, __LINE__, 1,
907  "Element %s is not xData object of type %s", type );
908  }
909  return( xDT->typeString == type );
910 }
911 /*
912 ************************************************************
913 */
914 char const *xData_getFileName( xData_document *doc ) {
915 
916  return( doc->fileName );
917 }
918 /*
919 ************************************************************
920 */
921 int xData_setFileName( statusMessageReporting *smr, xData_document *doc, char const *fileName ) {
922 
923  doc->fileName = (char*) xData_free( smr, doc->fileName );
924  if( fileName != NULL ) {
925  //if( ( doc->fileName = xData_malloc2( smr, strlen( fileName ) + 1, 0, "doc->fileName" ) ) == NULL ) return( 1 );
926  if( ( doc->fileName = (char*) xData_malloc2( smr, strlen( fileName ) + 1, 0, "doc->fileName" ) ) == NULL ) return( 1 );
927  strcpy( doc->fileName, fileName );
928  }
929  return( 0 );
930 }
931 /*
932 ************************************************************
933 */
935 
936  xData_rootElement* root = element->parentRoot;
937 
938  while( root->parentRoot != NULL ) root = root->parentRoot;
939  return( root->xData_doc );
940 }
941 /*
942 ************************************************************
943 */
945 
946  if( doc == NULL ) return( NULL );
947  return( &(doc->smrUserInterface ) );
948 }
949 /*
950 ************************************************************
951 */
953 
955 }
956 /*
957 ************************************************************
958 */
959 static int xData_smrUserInterfaceInitialize( xData_document *doc ) {
960 
961  doc->smrUserInterface.smrUserInterface = xData_smrUserInterface;
962  doc->smrUserInterface.doc = doc;
963  return( 0 );
964 }
965 /*
966 ************************************************************
967 */
968 static int xData_smrUserInterfaceFree( xData_document *doc ) {
969 
971  doc->smrUserInterface.doc = NULL;
972  return( 0 );
973 }
974 /*
975 ************************************************************
976 */
977 static int xData_smrUserInterface( void *userData, char **str ) {
978 
979  int size, fileNameSize = 0, elementSize = 0;
980  xData_smr *smrUserInterface = (xData_smr *) userData;
981  static char lcl[] = "\nat line %d and column %d", el[] = "\nin element ", fl[] = "\nof file ";
982  char str_lcl[sizeof( lcl ) + 40];
983  xData_rootElement *currentRoot = smrUserInterface->doc->currentRoot;
984 
985  if( smrUserInterface->doc->fileName != NULL ) fileNameSize = strlen( smrUserInterface->doc->fileName ) + strlen( fl );
986  if( currentRoot != NULL ) {
987  if( currentRoot->parentElement != NULL ) {
988  sprintf( str_lcl, lcl, currentRoot->parentElement->docInfo.line, currentRoot->parentElement->docInfo.column );
989  elementSize = strlen( str_lcl ) + strlen( currentRoot->parentElement->fullName ) + strlen( el );
990  }
991  }
992  size = fileNameSize + elementSize;
993  if( ( fileNameSize != 0 ) && ( elementSize != 0 ) ) size++;
994  if( ( size > 0 ) && ( str != NULL ) ) {
995  //if( ( *str = malloc( size + 1 ) ) == NULL ) return( -1 );
996  if( ( *str = (char*) malloc( size + 1 ) ) == NULL ) return( -1 );
997  if( ( size != 0 ) && ( elementSize != 0 ) ) {
998  sprintf( *str, "%s%s%s%s%s", str_lcl, el, currentRoot->parentElement->fullName, fl, smrUserInterface->doc->fileName ); }
999  else if( size != 0 ) {
1000  sprintf( *str, "%s%s", fl, smrUserInterface->doc->fileName ); }
1001  else {
1002  sprintf( *str, "%s%s%s", str_lcl, el, currentRoot->parentElement->fullName );
1003  }
1004  }
1005  return( size );
1006 }
1007 /*
1008 ************************************************************
1009 */
1010 int xData_stringTo_xData_Int( statusMessageReporting *smr, void *smrUserInterface, char const *c, xData_Int *value, char const *endings, char **e ) {
1011 
1012  char const *s;
1013  char tmp[64];
1014  int status = 1, n = sizeof( tmp );
1015 
1016  for( s = c; *s != 0; s++ ) if( !isspace( *s ) ) break;
1017  //*value = strtoll( s, e, 10 );
1018  *value = strtol( s, e, 10 );
1019  if( *e == s ) {
1020  smr_setMessageError(smr, smrUserInterface, __FILE__, __LINE__, 1, "could not convert \"%s\" to an integer", xData_shortStringForMessage( n, tmp, c ));}
1021  else {
1022  if( *endings == 0 ) while( isspace( **e ) ) (*e)++;
1023  if( **e == 0 ) {
1024  status = 0; }
1025  else {
1026  if( *endings == 0 ) {
1027  smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "integer string \"%s\" does not end with a '\\0'",
1028  xData_shortStringForMessage( n, tmp, c ) ); }
1029  else {
1030  if( strchr( endings, **e ) == NULL ) {
1031  smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "integer string \"%s\" does not end with a white space or a '\\0\'",
1032  xData_shortStringForMessage( n, tmp, c ) ); }
1033  else {
1034  status = 0;
1035  }
1036  }
1037  }
1038  }
1039  return( status );
1040 }
1041 /*
1042 ************************************************************
1043 */
1044 int xData_stringTo_double( statusMessageReporting *smr, void *smrUserInterface, char const *c, double *value, char const *endings, char **e ) {
1045 
1046  char const *s;
1047  char tmp[64];
1048  int status = 1, n = sizeof( tmp );
1049 
1050  for( s = c; *s != 0; s++ ) if( !isspace( *s ) ) break;
1051  *value = strtod( s, e );
1052  if( *e == s ) {
1053  smr_setMessageError(smr, smrUserInterface, __FILE__, __LINE__, 1, "could not convert \"%s\" to an double", xData_shortStringForMessage( n, tmp, c ));}
1054  else {
1055  if( *endings == 0 ) while( isspace( **e ) ) (*e)++;
1056  if( **e == 0 ) {
1057  status = 0; }
1058  else {
1059  if( *endings == 0 ) {
1060  smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "double string \"%s\" does not end with a '\\0'",
1061  xData_shortStringForMessage( n, tmp, c ) ); }
1062  else {
1063  if( strchr( endings, **e ) == NULL ) {
1064  smr_setMessageError( smr, smrUserInterface, __FILE__, __LINE__, 1, "double string \"%s\" does not end with a white space or a '\\0\'",
1065  xData_shortStringForMessage( n, tmp, c ) ); }
1066  else {
1067  status = 0;
1068  }
1069  }
1070  }
1071  }
1072  return( status );
1073 }
1074 /*
1075 ************************************************************
1076 */
1077 //int xData_addToAccessed( statusMessageReporting *smr, xData_element *element, int increment ) {
1078 int xData_addToAccessed( statusMessageReporting *, xData_element *element, int increment ) {
1079 
1080  element->accessed += increment;
1081  return( element->accessed );
1082 }
1083 /*
1084 ************************************************************
1085 */
1086 //int xData_getAccessed( statusMessageReporting *smr, xData_element *element ) {
1088 
1089  return( element->accessed );
1090 }
1091 /*
1092 ************************************************************
1093 */
1094 static char const *xData_shortStringForMessage( size_t size, char *Out, char const *In ) {
1095 
1096  if( strlen( In ) > size ) {
1097  strncpy( Out, In, size - 5 );
1098  Out[size-5] = 0;
1099  strcat( Out, " ..." );
1100  return( Out );
1101  }
1102  return( In );
1103 }
1104 
1105 #if defined __cplusplus
1106 }
1107 #endif