naev 0.10.4
nxml.h
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
4#pragma once
5
7#include <errno.h>
8#include <time.h>
9
10#ifdef __MINGW64_VERSION_MAJOR
11 /* HACK: libxml2 assumes in its function declarations that its format
12 * strings are handled by the native (legacy Microsoft) printf-family
13 * functions. Their source even #defines vsnprintf to _vsnprintf for maximum
14 * breakage. However, testing a shows, e.g., xmlw_attr with PRIu64 formats
15 * will still work on a MinGW64 build.
16 * Therefore, we vandalize their (unfixable) diagnostics Dvaered-style.
17 * */
18# define LIBXML_ATTR_FORMAT( fmt, args )
19#endif
20
21#include "libxml/parser.h"
22#include "libxml/xmlwriter.h"
25#include "log.h"
26#include "opengl.h"
27
28#define XML_NODE_START 1
29#define XML_NODE_TEXT 3
30
34#define xml_onlyNodes(n) \
35 if (((n)==NULL) || ((n)->type!=XML_NODE_START)) \
36 continue;
37
38/* checks to see if node n is of name s */
39#define xml_isNode(n,s) \
40 ((n!=NULL) && ((n)->type==XML_NODE_START) && \
41 (strcmp((char*)(n)->name,s)==0))
42
43/* gets the next node */
44#define xml_nextNode(n) \
45 ((n!=NULL) && ((n = n->next) != NULL))
46
47/* get data different ways */
48#define xml_raw(n) ((char*)(n)->children->content)
49#define xml_get(n) (((n)->children == NULL) ? NULL : (char*)(n)->children->content)
50#define xml_getInt(n) ((xml_get(n) == NULL) ? 0 : strtol( xml_raw(n), NULL, 10 ))
51#define xml_getUInt(n) ((xml_get(n) == NULL) ? 0 : strtoul( xml_raw(n), NULL, 10 ))
52#define xml_getLong(n) ((xml_get(n) == NULL) ? 0 : strtoll( xml_raw(n), NULL, 10 ))
53#define xml_getULong(n) ((xml_get(n) == NULL) ? 0 : strtoull( xml_raw(n), NULL, 10 ))
54#define xml_getFloat(n) ((xml_get(n) == NULL) ? 0. : strtod( xml_raw(n), NULL ))
55#define xml_getStrd(n) ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n)))
56
57/*
58 * reader crap
59 */
60#define xmlr_int(n,s,i) \
61 {if (xml_isNode(n,s)) { \
62 i = xml_getInt(n); continue; }}
63#define xmlr_uint(n,s,i) \
64 {if (xml_isNode(n,s)) { \
65 i = xml_getUInt(n); continue; }}
66#define xmlr_long(n,s,l) \
67 {if (xml_isNode(n,s)) { \
68 l = xml_getLong(n); continue; }}
69#define xmlr_ulong(n,s,l) \
70 {if (xml_isNode(n,s)) { \
71 l = xml_getULong(n); continue; }}
72#define xmlr_float(n,s,f) \
73 {if (xml_isNode(n,s)) { \
74 f = xml_getFloat(n); continue; }}
75#define xmlr_floatR(n,s,f) \
76 {if (xml_isNode(n,s)) { \
77 f = xml_getFloat(n); return 0; }}
78#define xmlr_str(n,s,str) \
79 {if (xml_isNode(n,s)) { \
80 str = xml_get(n); continue; }}
81#define xmlr_strd(n,s,str) \
82 {if (xml_isNode(n,s)) { \
83 if (str != NULL) { \
84 WARN("Node '%s' already loaded and being replaced from '%s' to '%s'", \
85 s, str, xml_raw(n) ); } \
86 str = ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n))); continue; }}
87
88/* Hack for better leak tracing: tools like LeakSanitizer can't trace past xmlGetProp(),
89 * but there's no issue if we duplicate the string ourselves. */
90
91#if DEBUGGING
92static inline char* nxml_trace_strdup( void* ptr )
93{
94 void *pointer_from_libxml2 = ptr;
95 char *ret = (ptr == NULL) ? NULL : strdup(ptr);
96 free( pointer_from_libxml2 );
97 return ret;
98}
99#else
100#define nxml_trace_strdup(ptr) ((char*) (ptr))
101#endif /* DEBUGGING */
102
103/* Attribute reader (allocates memory). */
104#define xmlr_attr_strd(n,s,a) a = nxml_trace_strdup( xmlGetProp( n, (xmlChar*)s ) )
105
106/* Attribute readers with defaults. */
107#define xmlr_attr_int_def(n,s,a,def) do {xmlr_attr_strd(n,s,char*T); a = T==NULL?def: strtol( T, NULL, 10); free(T);} while(0)
108#define xmlr_attr_uint_def(n,s,a,def) do {xmlr_attr_strd(n,s,char*T); a = T==NULL?def: strtoul( T, NULL, 10); free(T);} while(0)
109#define xmlr_attr_long_def(n,s,a,def) do {xmlr_attr_strd(n,s,char*T); a = T==NULL?def: strtoll( T, NULL, 10); free(T);} while(0)
110#define xmlr_attr_ulong_def(n,s,a,def) do {xmlr_attr_strd(n,s,char*T); a = T==NULL?def:strtoull( T, NULL, 10); free(T);} while(0)
111#define xmlr_attr_float_def(n,s,a,def) do {xmlr_attr_strd(n,s,char*T); a = T==NULL?def: strtod( T, NULL ); free(T);} while(0)
112/* Attribute readers defaulting to zero. */
113#define xmlr_attr_int(n,s,a) xmlr_attr_int_def(n,s,a,0)
114#define xmlr_attr_uint(n,s,a) xmlr_attr_uint_def(n,s,a,0)
115#define xmlr_attr_long(n,s,a) xmlr_attr_long_def(n,s,a,0)
116#define xmlr_attr_ulong(n,s,a) xmlr_attr_ulong_def(n,s,a,0)
117#define xmlr_attr_float(n,s,a) xmlr_attr_float_def(n,s,a,0.)
118/* Attribute readers for optional values. */
119#define xmlr_attr_int_opt(n,s,a) xmlr_attr_int_def(n,s,a,a)
120#define xmlr_attr_uint_opt(n,s,a) xmlr_attr_uint_def(n,s,a,a)
121#define xmlr_attr_long_opt(n,s,a) xmlr_attr_long_def(n,s,a,a)
122#define xmlr_attr_ulong_opt(n,s,a) xmlr_attr_ulong_def(n,s,a,a)
123#define xmlr_attr_float_opt(n,s,a) xmlr_attr_float_def(n,s,a,a)
124
125/*
126 * writer crap
127 */
128/* encompassing element */
129#define xmlw_startElem(w,str) \
130do {if (xmlTextWriterStartElement(w,(xmlChar*)str) < 0) { \
131 ERR("xmlw: unable to create start element"); return -1; } } while (0)
132#define xmlw_endElem(w) \
133do {if (xmlTextWriterEndElement(w) < 0) { \
134 ERR("xmlw: unable to create end element"); return -1; } } while (0)
135/* other stuff */
136#define xmlw_elemEmpty(w,n) \
137do { xmlw_startElem(w,n); xmlw_endElem(w); } while (0)
138#define xmlw_elem(w,n,str,args...) \
139do { if (xmlTextWriterWriteFormatElement(w,(xmlChar*)n, \
140 str, ## args) < 0) { \
141 ERR("xmlw: unable to write format element"); return -1; } } while (0)
142#define xmlw_raw(w,b,l) \
143do {if (xmlTextWriterWriteRawLen(w,(xmlChar*)b,l) < 0) { \
144 ERR("xmlw: unable to write raw element"); return -1; } } while (0)
145#define xmlw_attr(w,str,val...) \
146do {if (xmlTextWriterWriteFormatAttribute(w,(xmlChar*)str, \
147 ## val) < 0) { \
148 ERR("xmlw: unable to write element attribute"); return -1; } } while (0)
149#define xmlw_str(w,str,val...) \
150do {if (xmlTextWriterWriteFormatString(w,str, ## val) < 0) { \
151 ERR("xmlw: unable to write element data"); return -1; } } while (0)
152/* document level */
153#define xmlw_start(w) \
154do {if (xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) { \
155 ERR("xmlw: unable to start document"); return -1; } } while (0)
156#define xmlw_done(w) \
157do {if (xmlTextWriterEndDocument(w) < 0) { \
158 ERR("xmlw: unable to end document"); return -1; } } while (0)
159
160/*
161 * Functions for generic complex reading.
162 */
163xmlDocPtr xml_parsePhysFS( const char* filename );
164glTexture* xml_parseTexture( xmlNodePtr node,
165 const char *path, int defsx, int defsy,
166 const unsigned int flags );
167int xml_parseTime( xmlNodePtr node, time_t *t );
168
169/*
170 * Functions for generic complex writing.
171 */
172void xmlw_setParams( xmlTextWriterPtr writer );
173int xmlw_saveTime( xmlTextWriterPtr writer, const char *name, time_t t );
glTexture * xml_parseTexture(xmlNodePtr node, const char *path, int defsx, int defsy, const unsigned int flags)
Parses a texture handling the sx and sy elements.
Definition: nxml.c:29
void xmlw_setParams(xmlTextWriterPtr writer)
Sets up the standard xml write parameters.
Definition: nxml.c:64
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition: nxml.c:75
Abstraction for rendering sprite sheets.
Definition: opengl_tex.h:34