naev 0.12.6
nxml.h
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
4#pragma once
5
7#ifdef __MINGW64_VERSION_MAJOR
8/* HACK: libxml2 assumes in its function declarations that its format
9 * strings are handled by the native (legacy Microsoft) printf-family
10 * functions. Their source even #defines vsnprintf to _vsnprintf for maximum
11 * breakage. However, testing a shows, e.g., xmlw_attr with PRIu64 formats
12 * will still work on a MinGW64 build.
13 * Therefore, we vandalize their (unfixable) diagnostics Dvaered-style.
14 * */
15#define LIBXML_ATTR_FORMAT( fmt, args )
16#endif
17
18#include "libxml/parser.h" // IWYU pragma: export
19#include "libxml/xmlwriter.h" // IWYU pragma: export
21
22#include "attributes.h"
23#include "log.h"
24#include "ntime.h"
25#include "opengl_tex.h"
26
27#define XML_NODE_START 1
28#define XML_NODE_TEXT 3
29
33#define xml_onlyNodes( n ) \
34 if ( ( ( n ) == NULL ) || ( ( n )->type != XML_NODE_START ) ) \
35 continue;
36
37/* checks to see if node n is of name s */
38#define xml_isNode( n, s ) \
39 ( ( n != NULL ) && ( ( n )->type == XML_NODE_START ) && \
40 ( strcmp( (char *)( n )->name, s ) == 0 ) )
41
42/* gets the next node */
43#define xml_nextNode( n ) ( ( n != NULL ) && ( ( n = n->next ) != NULL ) )
44
45/* get data different ways */
46#define xml_raw( n ) ( (char *)( n )->children->content )
47#define xml_get( n ) \
48 ( ( ( n )->children == NULL ) ? NULL : (char *)( n )->children->content )
49#define xml_getInt( n ) \
50 ( ( xml_get( n ) == NULL ) ? 0 : strtol( xml_raw( n ), NULL, 10 ) )
51#define xml_getUInt( n ) \
52 ( ( xml_get( n ) == NULL ) ? 0 : strtoul( xml_raw( n ), NULL, 10 ) )
53#define xml_getLong( n ) \
54 ( ( xml_get( n ) == NULL ) ? 0 : strtoll( xml_raw( n ), NULL, 10 ) )
55#define xml_getULong( n ) \
56 ( ( xml_get( n ) == NULL ) ? 0 : strtoull( xml_raw( n ), NULL, 10 ) )
57#define xml_getFloat( n ) \
58 ( ( xml_get( n ) == NULL ) ? 0. : strtod( xml_raw( n ), NULL ) )
59#define xml_getStrd( n ) \
60 ( ( xml_get( n ) == NULL ) ? NULL : strdup( xml_raw( n ) ) )
61
62/*
63 * reader crap
64 */
65#define xmlr_int( n, s, i ) \
66 { \
67 if ( xml_isNode( n, s ) ) { \
68 i = xml_getInt( n ); \
69 continue; \
70 } \
71 }
72#define xmlr_uint( n, s, i ) \
73 { \
74 if ( xml_isNode( n, s ) ) { \
75 i = xml_getUInt( n ); \
76 continue; \
77 } \
78 }
79#define xmlr_long( n, s, l ) \
80 { \
81 if ( xml_isNode( n, s ) ) { \
82 l = xml_getLong( n ); \
83 continue; \
84 } \
85 }
86#define xmlr_ulong( n, s, l ) \
87 { \
88 if ( xml_isNode( n, s ) ) { \
89 l = xml_getULong( n ); \
90 continue; \
91 } \
92 }
93#define xmlr_float( n, s, f ) \
94 { \
95 if ( xml_isNode( n, s ) ) { \
96 f = xml_getFloat( n ); \
97 continue; \
98 } \
99 }
100#define xmlr_str( n, s, str ) \
101 { \
102 if ( xml_isNode( n, s ) ) { \
103 str = xml_get( n ); \
104 continue; \
105 } \
106 }
107#define xmlr_strd( n, s, str ) \
108 { \
109 if ( xml_isNode( n, s ) ) { \
110 if ( str != NULL ) { \
111 WARN( "Node '%s' already loaded and being replaced from '%s' to " \
112 "'%s'", \
113 s, str, xml_raw( n ) ); \
114 free( str ); \
115 } \
116 str = ( ( xml_get( n ) == NULL ) ? NULL : strdup( xml_raw( n ) ) ); \
117 continue; \
118 } \
119 }
120#define xmlr_strd_free( n, s, str ) \
121 { \
122 if ( xml_isNode( n, s ) ) { \
123 if ( str != NULL ) \
124 free( str ); \
125 str = ( ( xml_get( n ) == NULL ) ? NULL : strdup( xml_raw( n ) ) ); \
126 continue; \
127 } \
128 }
129
130/* Hack for better leak tracing: tools like LeakSanitizer can't trace past
131 * xmlGetProp(), but there's no issue if we duplicate the string ourselves. */
132
133#if DEBUGGING
134static inline char *nxml_trace_strdup( void *ptr )
135{
136 void *pointer_from_libxml2 = ptr;
137 char *ret = ( ptr == NULL ) ? NULL : strdup( ptr );
138 free( pointer_from_libxml2 );
139 return ret;
140}
141#else
142#define nxml_trace_strdup( ptr ) ( (char *)( ptr ) )
143#endif /* DEBUGGING */
144
145/* Attribute reader (allocates memory). */
146#define xmlr_attr_strd( n, s, a ) \
147 a = nxml_trace_strdup( xmlGetProp( n, (xmlChar *)s ) )
148#define xmlr_attr_strd_free( n, s, a ) \
149 do { \
150 if ( a != NULL ) \
151 free( a ); \
152 a = nxml_trace_strdup( xmlGetProp( n, (xmlChar *)s ) ); \
153 } while ( 0 )
154
155/* Attribute readers with defaults. */
156#define xmlr_attr_int_def( n, s, a, def ) \
157 do { \
158 xmlr_attr_strd( n, s, char *T ); \
159 a = T == NULL ? def : strtol( T, NULL, 10 ); \
160 free( T ); \
161 } while ( 0 )
162#define xmlr_attr_uint_def( n, s, a, def ) \
163 do { \
164 xmlr_attr_strd( n, s, char *T ); \
165 a = T == NULL ? def : strtoul( T, NULL, 10 ); \
166 free( T ); \
167 } while ( 0 )
168#define xmlr_attr_long_def( n, s, a, def ) \
169 do { \
170 xmlr_attr_strd( n, s, char *T ); \
171 a = T == NULL ? def : strtoll( T, NULL, 10 ); \
172 free( T ); \
173 } while ( 0 )
174#define xmlr_attr_ulong_def( n, s, a, def ) \
175 do { \
176 xmlr_attr_strd( n, s, char *T ); \
177 a = T == NULL ? def : strtoull( T, NULL, 10 ); \
178 free( T ); \
179 } while ( 0 )
180#define xmlr_attr_float_def( n, s, a, def ) \
181 do { \
182 xmlr_attr_strd( n, s, char *T ); \
183 a = T == NULL ? def : strtod( T, NULL ); \
184 free( T ); \
185 } while ( 0 )
186/* Attribute readers defaulting to zero. */
187#define xmlr_attr_int( n, s, a ) xmlr_attr_int_def( n, s, a, 0 )
188#define xmlr_attr_uint( n, s, a ) xmlr_attr_uint_def( n, s, a, 0 )
189#define xmlr_attr_long( n, s, a ) xmlr_attr_long_def( n, s, a, 0 )
190#define xmlr_attr_ulong( n, s, a ) xmlr_attr_ulong_def( n, s, a, 0 )
191#define xmlr_attr_float( n, s, a ) xmlr_attr_float_def( n, s, a, 0. )
192/* Attribute readers for optional values. */
193#define xmlr_attr_int_opt( n, s, a ) xmlr_attr_int_def( n, s, a, a )
194#define xmlr_attr_uint_opt( n, s, a ) xmlr_attr_uint_def( n, s, a, a )
195#define xmlr_attr_long_opt( n, s, a ) xmlr_attr_long_def( n, s, a, a )
196#define xmlr_attr_ulong_opt( n, s, a ) xmlr_attr_ulong_def( n, s, a, a )
197#define xmlr_attr_float_opt( n, s, a ) xmlr_attr_float_def( n, s, a, a )
198
199/*
200 * writer crap
201 */
202/* encompassing element */
203#define xmlw_startElem( w, str ) \
204 do { \
205 if ( xmlTextWriterStartElement( w, (xmlChar *)str ) < 0 ) { \
206 WARN( "xmlw: unable to create start element" ); \
207 return -1; \
208 } \
209 } while ( 0 )
210#define xmlw_endElem( w ) \
211 do { \
212 if ( xmlTextWriterEndElement( w ) < 0 ) { \
213 WARN( "xmlw: unable to create end element" ); \
214 return -1; \
215 } \
216 } while ( 0 )
217/* other stuff */
218#define xmlw_elemEmpty( w, n ) \
219 do { \
220 xmlw_startElem( w, n ); \
221 xmlw_endElem( w ); \
222 } while ( 0 )
223#define xmlw_elem( w, n, str, ... ) \
224 do { \
225 if ( xmlTextWriterWriteFormatElement( w, (xmlChar *)n, str, \
226 ##__VA_ARGS__ ) < 0 ) { \
227 WARN( "xmlw: unable to write format element" ); \
228 return -1; \
229 } \
230 } while ( 0 )
231#define xmlw_raw( w, b, l ) \
232 do { \
233 if ( xmlTextWriterWriteRawLen( w, (xmlChar *)b, l ) < 0 ) { \
234 WARN( "xmlw: unable to write raw element" ); \
235 return -1; \
236 } \
237 } while ( 0 )
238#define xmlw_attr_raw( w, str, val ) \
239 do { \
240 if ( xmlTextWriterWriteAttribute( w, (xmlChar *)str, (xmlChar *)val ) < \
241 0 ) { \
242 WARN( "xmlw: unable to write element attribute" ); \
243 return -1; \
244 } \
245 } while ( 0 )
246#define xmlw_attr( w, str, ... ) \
247 do { \
248 if ( xmlTextWriterWriteFormatAttribute( w, (xmlChar *)str, \
249 ##__VA_ARGS__ ) < 0 ) { \
250 WARN( "xmlw: unable to write element attribute" ); \
251 return -1; \
252 } \
253 } while ( 0 )
254#define xmlw_str( w, str, ... ) \
255 do { \
256 if ( xmlTextWriterWriteFormatString( w, str, ##__VA_ARGS__ ) < 0 ) { \
257 WARN( "xmlw: unable to write element data" ); \
258 return -1; \
259 } \
260 } while ( 0 )
261/* document level */
262#define xmlw_start( w ) \
263 do { \
264 if ( xmlTextWriterStartDocument( writer, NULL, "UTF-8", NULL ) < 0 ) { \
265 WARN( "xmlw: unable to start document" ); \
266 return -1; \
267 } \
268 } while ( 0 )
269#define xmlw_done( w ) \
270 do { \
271 if ( xmlTextWriterEndDocument( w ) < 0 ) { \
272 WARN( "xmlw: unable to end document" ); \
273 return -1; \
274 } \
275 } while ( 0 )
276
277/*
278 * Functions for generic complex reading.
279 */
280xmlDocPtr xml_parsePhysFS( const char *filename );
281USE_RESULT glTexture *xml_parseTexture( xmlNodePtr node, const char *path,
282 int defsx, int defsy,
283 const unsigned int flags );
284int xml_parseTime( xmlNodePtr node, time_t *t );
285int xml_parseNTime( xmlNodePtr node, ntime_t *t );
286
287/*
288 * Functions for generic complex writing.
289 */
290void xmlw_setParams( xmlTextWriterPtr writer );
291int xmlw_saveTime( xmlTextWriterPtr writer, const char *name, time_t t );
292int xmlw_saveNTime( xmlTextWriterPtr writer, const char *name, ntime_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:25
void xmlw_setParams(xmlTextWriterPtr writer)
Sets up the standard xml write parameters.
Definition nxml.c:59
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:70
Abstraction for rendering sprite sheets.
Definition opengl_tex.h:43