30 |
#include <ctype.h> |
#include <ctype.h> |
31 |
int isblank(int c); |
int isblank(int c); |
32 |
|
|
|
#define QND_XML_BUFFER_SIZE 1024 |
|
33 |
typedef struct { |
typedef struct { |
34 |
gpointer userdata; |
gpointer userdata; |
35 |
|
|
|
FILE *file; |
|
36 |
int total, bytes_read; |
int total, bytes_read; |
37 |
|
|
38 |
char buffer[QND_XML_BUFFER_SIZE], *cur; |
char *buffer, *cur; |
|
int fill; |
|
39 |
|
|
40 |
qnd_xml_stack_t *stack, *sp; |
qnd_xml_stack_t *stack, *sp; |
41 |
int mod; // modifier (?, !, /) in element |
int mod; // modifier (?, !, /) in element |
88 |
return cur; |
return cur; |
89 |
} |
} |
90 |
|
|
|
gboolean update_buffer(qnd_xml_context_t *context) { |
|
|
|
|
|
/* if buffer is empty just fill it */ |
|
|
if(!context->fill) { |
|
|
context->cur = context->buffer; |
|
|
context->fill = fread(context->buffer, 1l, |
|
|
QND_XML_BUFFER_SIZE, context->file); |
|
|
|
|
|
if(context->fill < 0) { |
|
|
printf("read error\n"); |
|
|
context->fill = 0; |
|
|
return FALSE; |
|
|
} |
|
|
context->bytes_read += context->fill; |
|
|
return TRUE; |
|
|
} |
|
|
|
|
|
/* shift remaining data down */ |
|
|
int offset = context->cur - context->buffer; |
|
|
g_memmove(context->buffer, context->cur, QND_XML_BUFFER_SIZE - offset); |
|
|
context->fill -= offset; |
|
|
int bytes_read = fread(context->buffer + QND_XML_BUFFER_SIZE - |
|
|
offset, 1l, offset, context->file); |
|
|
|
|
|
context->cur = context->buffer; |
|
|
if(bytes_read < 0) { |
|
|
printf("read error\n"); |
|
|
return FALSE; |
|
|
} |
|
|
|
|
|
context->bytes_read += bytes_read; |
|
|
context->fill += bytes_read; |
|
|
return TRUE; |
|
|
} |
|
|
|
|
91 |
/* |
/* |
92 |
utf8: |
utf8: |
93 |
0xxxxxxx |
0xxxxxxx |
115 |
} |
} |
116 |
|
|
117 |
gboolean skip_to_char(qnd_xml_context_t *context, char *chrs) { |
gboolean skip_to_char(qnd_xml_context_t *context, char *chrs) { |
118 |
do { |
while(context->cur < context->buffer + context->total) { |
119 |
while(context->cur < context->buffer + context->fill) { |
if(strchr(chrs, current_char(context))) { |
120 |
if(strchr(chrs, current_char(context))) { |
return skip_char(context); |
|
return skip_char(context); |
|
|
} |
|
|
if(!skip_char(context)) return FALSE; |
|
121 |
} |
} |
122 |
|
if(!skip_char(context)) return FALSE; |
123 |
/* try to get more data */ |
} |
|
if(!update_buffer(context)) |
|
|
return FALSE; |
|
|
|
|
|
} while(context->fill); |
|
124 |
|
|
125 |
/* if we get here the system was unable to fill the buffer */ |
/* if we get here the system was unable to fill the buffer */ |
126 |
return FALSE; |
return FALSE; |
127 |
} |
} |
128 |
|
|
129 |
gboolean buffer_overflow(qnd_xml_context_t *context) { |
gboolean buffer_overflow(qnd_xml_context_t *context) { |
130 |
return(!(context->cur < context->buffer + context->fill)); |
return(!(context->cur < context->buffer + context->total)); |
131 |
} |
} |
132 |
|
|
133 |
gboolean get_element_name(qnd_xml_context_t *context) { |
gboolean get_element_name(qnd_xml_context_t *context) { |
134 |
|
|
|
/* drop everything before element from buffer */ |
|
|
if(!update_buffer(context)) return FALSE; |
|
|
|
|
135 |
char *start = context->cur; |
char *start = context->cur; |
136 |
|
|
137 |
if(buffer_overflow(context) || !isalpha(current_char(context))) { |
if(buffer_overflow(context) || !isalpha(current_char(context))) { |
248 |
gboolean get_attributes(qnd_xml_context_t *context) { |
gboolean get_attributes(qnd_xml_context_t *context) { |
249 |
/* drop everything before element from buffer */ |
/* drop everything before element from buffer */ |
250 |
|
|
|
if(!update_buffer(context)) return FALSE; |
|
251 |
if(!skip_white(context)) return FALSE; |
if(!skip_white(context)) return FALSE; |
252 |
|
|
253 |
while(isalpha(current_char(context))) { |
while(isalpha(current_char(context))) { |
281 |
void qnd_xml_cleanup(qnd_xml_context_t *context) { |
void qnd_xml_cleanup(qnd_xml_context_t *context) { |
282 |
/* todo: clean stack */ |
/* todo: clean stack */ |
283 |
|
|
284 |
if(context->file) fclose(context->file); |
if(context->buffer) g_free(context->buffer); |
285 |
g_free(context); |
g_free(context); |
286 |
} |
} |
287 |
|
|
347 |
} |
} |
348 |
|
|
349 |
gpointer qnd_xml_parse(char *name, qnd_xml_entry_t *root, gpointer userdata) { |
gpointer qnd_xml_parse(char *name, qnd_xml_entry_t *root, gpointer userdata) { |
350 |
|
FILE *file = NULL; |
351 |
qnd_xml_context_t *context = g_new0(qnd_xml_context_t, 1); |
qnd_xml_context_t *context = g_new0(qnd_xml_context_t, 1); |
352 |
context->cur = context->buffer; |
context->cur = context->buffer; |
353 |
context->userdata = userdata; |
context->userdata = userdata; |
364 |
} |
} |
365 |
|
|
366 |
/* open file */ |
/* open file */ |
367 |
context->file = g_fopen(name, "r"); |
file = g_fopen(name, "r"); |
368 |
if(!context->file) { |
if(!file) { |
369 |
printf("unable to open file\n"); |
printf("unable to open file\n"); |
370 |
qnd_xml_cleanup(context); |
qnd_xml_cleanup(context); |
371 |
return FALSE; |
return FALSE; |
374 |
printf("file is open\n"); |
printf("file is open\n"); |
375 |
|
|
376 |
/* get file length */ |
/* get file length */ |
377 |
fseek(context->file, 0l, SEEK_END); |
fseek(file, 0l, SEEK_END); |
378 |
context->total = ftell(context->file); |
context->total = ftell(file); |
379 |
fseek(context->file, 0l, SEEK_SET); |
fseek(file, 0l, SEEK_SET); |
380 |
|
|
381 |
printf("file length is %d bytes\n", context->total); |
printf("file length is %d bytes\n", context->total); |
382 |
|
|
383 |
|
/* load entire file into buffer */ |
384 |
|
context->buffer = g_malloc(context->total); |
385 |
|
fread(context->buffer, 1l, context->total, file); |
386 |
|
fclose(file); |
387 |
|
context->cur = context->buffer; |
388 |
|
|
389 |
|
setlocale(LC_NUMERIC, "C"); |
390 |
|
|
391 |
gboolean error = FALSE; |
gboolean error = FALSE; |
392 |
do |
do |
393 |
error = !get_element(context); |
error = !get_element(context); |
394 |
while(!error && !context->done); |
while(!error && !context->done); |
395 |
|
|
396 |
|
setlocale(LC_NUMERIC, ""); |
397 |
|
|
398 |
if(error) printf("parser ended with error\n"); |
if(error) printf("parser ended with error\n"); |
399 |
else printf("parser ended successfully\n"); |
else printf("parser ended successfully\n"); |
400 |
|
|
426 |
if(value) return g_strdup(value); |
if(value) return g_strdup(value); |
427 |
return NULL; |
return NULL; |
428 |
} |
} |
429 |
|
|
430 |
|
/* strtof this is c99 */ |
431 |
|
float strtof(const char *nptr, char **endptr); |
432 |
|
|
433 |
|
gboolean qnd_xml_get_prop_float(qnd_xml_attribute_t *attr, char *name, |
434 |
|
float *dest) { |
435 |
|
char *value = qnd_xml_get_prop(attr, name); |
436 |
|
if(!value) return FALSE; |
437 |
|
*dest = strtof(value, NULL); |
438 |
|
return TRUE; |
439 |
|
} |
440 |
|
|
441 |
gboolean qnd_xml_get_prop_double(qnd_xml_attribute_t *attr, char *name, |
gboolean qnd_xml_get_prop_double(qnd_xml_attribute_t *attr, char *name, |
442 |
double *dest) { |
double *dest) { |