naev 0.11.5
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 "attributes.h"
26#include "log.h"
27#include "opengl.h"
28
29#define XML_NODE_START 1
30#define XML_NODE_TEXT 3
31
35#define xml_onlyNodes(n) \
36 if (((n)==NULL) || ((n)->type!=XML_NODE_START)) \
37 continue;
38
39/* checks to see if node n is of name s */
40#define xml_isNode(n,s) \
41 ((n!=NULL) && ((n)->type==XML_NODE_START) && \
42 (strcmp((char*)(n)->name,s)==0))
43
44/* gets the next node */
45#define xml_nextNode(n) \
46 ((n!=NULL) && ((n = n->next) != NULL))
47
48/* get data different ways */
49#define xml_raw(n) ((char*)(n)->children->content)
50#define xml_get(n) (((n)->children == NULL) ? NULL : (char*)(n)->children->content)
51#define xml_getInt(n) ((xml_get(n) == NULL) ? 0 : strtol( xml_raw(n), NULL, 10 ))
52#define xml_getUInt(n) ((xml_get(n) == NULL) ? 0 : strtoul( xml_raw(n), NULL, 10 ))
53#define xml_getLong(n) ((xml_get(n) == NULL) ? 0 : strtoll( xml_raw(n), NULL, 10 ))
54#define xml_getULong(n) ((xml_get(n) == NULL) ? 0 : strtoull( xml_raw(n), NULL, 10 ))
55#define xml_getFloat(n) ((xml_get(n) == NULL) ? 0. : strtod( xml_raw(n), NULL ))
56#define xml_getStrd(n) ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n)))
57
58/*
59 * reader crap
60 */
61#define xmlr_int(n,s,i) \
62 {if (xml_isNode(n,s)) { \
63 i = xml_getInt(n); continue; }}
64#define xmlr_uint(n,s,i) \
65 {if (xml_isNode(n,s)) { \
66 i = xml_getUInt(n); continue; }}
67#define xmlr_long(n,s,l) \
68 {if (xml_isNode(n,s)) { \
69 l = xml_getLong(n); continue; }}
70#define xmlr_ulong(n,s,l) \
71 {if (xml_isNode(n,s)) { \
72 l = xml_getULong(n); continue; }}
73#define xmlr_float(n,s,f) \
74 {if (xml_isNode(n,s)) { \
75 f = xml_getFloat(n); continue; }}
76#define xmlr_floatR(n,s,f) \
77 {if (xml_isNode(n,s)) { \
78 f = xml_getFloat(n); return 0; }}
79#define xmlr_str(n,s,str) \
80 {if (xml_isNode(n,s)) { \
81 str = xml_get(n); continue; }}
82#define xmlr_strd(n,s,str) \
83 {if (xml_isNode(n,s)) { \
84 if (str != NULL) { \
85 WARN("Node '%s' already loaded and being replaced from '%s' to '%s'", \
86 s, str, xml_raw(n) ); } \
87 str = ((xml_get(n) == NULL) ? NULL : strdup(xml_raw(n))); continue; }}
88
89/* Hack for better leak tracing: tools like LeakSanitizer can't trace past xmlGetProp(),
90 * but there's no issue if we duplicate the string ourselves. */
91
92#if DEBUGGING
93static inline char* nxml_trace_strdup( void* ptr )
94{
95 void *pointer_from_libxml2 = ptr;
96 char *ret = (ptr == NULL) ? NULL : strdup(ptr);
97 free( pointer_from_libxml2 );
98 return ret;
99}
100#else
101#define nxml_trace_strdup(ptr) ((char*) (ptr))
102#endif /* DEBUGGING */
103
104/* Attribute reader (allocates memory). */
105#define xmlr_attr_strd(n,s,a) a = nxml_trace_strdup( xmlGetProp( n, (xmlChar*)s ) )
106
107/* Attribute readers with defaults. */
108#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)
109#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)
110#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)
111#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)
112#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)
113/* Attribute readers defaulting to zero. */
114#define xmlr_attr_int(n,s,a) xmlr_attr_int_def(n,s,a,0)
115#define xmlr_attr_uint(n,s,a) xmlr_attr_uint_def(n,s,a,0)
116#define xmlr_attr_long(n,s,a) xmlr_attr_long_def(n,s,a,0)
117#define xmlr_attr_ulong(n,s,a) xmlr_attr_ulong_def(n,s,a,0)
118#define xmlr_attr_float(n,s,a) xmlr_attr_float_def(n,s,a,0.)
119/* Attribute readers for optional values. */
120#define xmlr_attr_int_opt(n,s,a) xmlr_attr_int_def(n,s,a,a)
121#define xmlr_attr_uint_opt(n,s,a) xmlr_attr_uint_def(n,s,a,a)
122#define xmlr_attr_long_opt(n,s,a) xmlr_attr_long_def(n,s,a,a)
123#define xmlr_attr_ulong_opt(n,s,a) xmlr_attr_ulong_def(n,s,a,a)
124#define xmlr_attr_float_opt(n,s,a) xmlr_attr_float_def(n,s,a,a)
125
126/*
127 * writer crap
128 */
129/* encompassing element */
130#define xmlw_startElem(w,str) \
131do {if (xmlTextWriterStartElement(w,(xmlChar*)str) < 0) { \
132 ERR("xmlw: unable to create start element"); return -1; } } while (0)
133#define xmlw_endElem(w) \
134do {if (xmlTextWriterEndElement(w) < 0) { \
135 ERR("xmlw: unable to create end element"); return -1; } } while (0)
136/* other stuff */
137#define xmlw_elemEmpty(w,n) \
138do { xmlw_startElem(w,n); xmlw_endElem(w); } while (0)
139#define xmlw_elem(w,n,str,...) \
140do { if (xmlTextWriterWriteFormatElement(w,(xmlChar*)n, \
141 str, ## __VA_ARGS__) < 0) { \
142 ERR("xmlw: unable to write format element"); return -1; } } while (0)
143#define xmlw_raw(w,b,l) \
144do {if (xmlTextWriterWriteRawLen(w,(xmlChar*)b,l) < 0) { \
145 ERR("xmlw: unable to write raw element"); return -1; } } while (0)
146#define xmlw_attr(w,str,...) \
147do {if (xmlTextWriterWriteFormatAttribute(w,(xmlChar*)str, \
148 ## __VA_ARGS__) < 0) { \
149 ERR("xmlw: unable to write element attribute"); return -1; } } while (0)
150#define xmlw_str(w,str,...) \
151do {if (xmlTextWriterWriteFormatString(w,str, ## __VA_ARGS__) < 0) { \
152 ERR("xmlw: unable to write element data"); return -1; } } while (0)
153/* document level */
154#define xmlw_start(w) \
155do {if (xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) { \
156 ERR("xmlw: unable to start document"); return -1; } } while (0)
157#define xmlw_done(w) \
158do {if (xmlTextWriterEndDocument(w) < 0) { \
159 ERR("xmlw: unable to end document"); return -1; } } while (0)
160
161/*
162 * Functions for generic complex reading.
163 */
164xmlDocPtr xml_parsePhysFS( const char* filename );
165USE_RESULT glTexture* xml_parseTexture( xmlNodePtr node,
166 const char *path, int defsx, int defsy,
167 const unsigned int flags );
168int xml_parseTime( xmlNodePtr node, time_t *t );
169
170/*
171 * Functions for generic complex writing.
172 */
173void xmlw_setParams( xmlTextWriterPtr writer );
174int 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:36