cdata works
This commit is contained in:
parent
54806705c5
commit
1113b2dbe3
7 changed files with 196 additions and 126 deletions
2
Makefile
2
Makefile
|
|
@ -3,7 +3,7 @@ CFLAGS = -I include -fPIC -g
|
||||||
LDFLAGS = -shared
|
LDFLAGS = -shared
|
||||||
LIBS =
|
LIBS =
|
||||||
|
|
||||||
OBJS = src/core.o src/file.o src/unicode.o src/stb_ds.o
|
OBJS = src/core.o src/file.o src/unicode.o src/util.o src/stb_ds.o
|
||||||
|
|
||||||
SO = .so
|
SO = .so
|
||||||
|
|
||||||
|
|
|
||||||
18
example.c
18
example.c
|
|
@ -2,17 +2,17 @@
|
||||||
|
|
||||||
#define INDENT 2
|
#define INDENT 2
|
||||||
|
|
||||||
void recursive(xmllib_node_t* node, int indent) {
|
void recursive(xl_node_t* node, int indent) {
|
||||||
int i;
|
int i;
|
||||||
xmllib_node_t* n;
|
xl_node_t* n;
|
||||||
for(i = 0; i < indent; i++) printf(" ");
|
for(i = 0; i < indent; i++) printf(" ");
|
||||||
if(node->name != NULL && node->type == XMLLIB_NODE_NODE) {
|
if(node->name != NULL && node->type == XL_NODE_NODE) {
|
||||||
printf("<%s>\n", node->name);
|
printf("<%s>\n", node->name);
|
||||||
if(node->text != NULL) {
|
if(node->text != NULL) {
|
||||||
for(i = 0; i < indent + INDENT; i++) printf(" ");
|
for(i = 0; i < indent + INDENT; i++) printf(" ");
|
||||||
printf("%s\n", node->text);
|
printf("%s\n", node->text);
|
||||||
}
|
}
|
||||||
} else if(node->text != NULL && node->type == XMLLIB_NODE_COMMENT) {
|
} else if(node->text != NULL && node->type == XL_NODE_COMMENT) {
|
||||||
printf("<!--%s-->\n", node->text);
|
printf("<!--%s-->\n", node->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,7 +22,7 @@ void recursive(xmllib_node_t* node, int indent) {
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node->name != NULL && node->type == XMLLIB_NODE_NODE) {
|
if(node->name != NULL && node->type == XL_NODE_NODE) {
|
||||||
for(i = 0; i < indent; i++) printf(" ");
|
for(i = 0; i < indent; i++) printf(" ");
|
||||||
printf("</%s>\n", node->name);
|
printf("</%s>\n", node->name);
|
||||||
}
|
}
|
||||||
|
|
@ -32,17 +32,17 @@ int main(int argc, char** argv) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 1; i < argc; i++) {
|
for(i = 1; i < argc; i++) {
|
||||||
xmllib_t* h = xmllib_open_file(argv[i]);
|
xmllib_t* h = xl_open_file(argv[i]);
|
||||||
if(h != NULL) {
|
if(h != NULL) {
|
||||||
printf("%s:\n", argv[i]);
|
printf("%s:\n", argv[i]);
|
||||||
if(xmllib_parse(h)) {
|
if(xl_parse(h)) {
|
||||||
if(h->root != NULL) recursive(h->root, INDENT);
|
if(h->root != NULL) recursive(h->root, INDENT);
|
||||||
} else {
|
} else {
|
||||||
int j;
|
int j;
|
||||||
for(j = 0; j < INDENT; j++) printf(" ");
|
for(j = 0; j < INDENT; j++) printf(" ");
|
||||||
printf("Parse error\n");
|
printf("Parse error\n");
|
||||||
}
|
}
|
||||||
xmllib_close(h);
|
xl_close(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,42 +8,44 @@
|
||||||
|
|
||||||
#define XLDECL extern
|
#define XLDECL extern
|
||||||
|
|
||||||
typedef struct xmllib_driver xmllib_driver_t;
|
typedef struct xl_driver xl_driver_t;
|
||||||
typedef struct xmllib xmllib_t;
|
typedef struct xmllib xmllib_t;
|
||||||
typedef struct xmllib_node xmllib_node_t;
|
typedef struct xl_node xl_node_t;
|
||||||
|
|
||||||
struct xmllib_driver {
|
#define XL_SKIPPABLE(x) (((x) == ' ') || ((x) == '\t') || ((x) == '\n') || ((x) == '\r'))
|
||||||
|
|
||||||
|
struct xl_driver {
|
||||||
int (*open)(xmllib_t* handle);
|
int (*open)(xmllib_t* handle);
|
||||||
int (*read)(xmllib_t* handle, void* data, int size);
|
int (*read)(xmllib_t* handle, void* data, int size);
|
||||||
void (*close)(xmllib_t* handle);
|
void (*close)(xmllib_t* handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum XMLLIB_NODE_TYPE {
|
enum XL_NODE_TYPE {
|
||||||
XMLLIB_NODE_COMMENT = 0,
|
XL_NODE_COMMENT = 0,
|
||||||
XMLLIB_NODE_NODE,
|
XL_NODE_NODE,
|
||||||
XMLLIB_NODE_PROCESS,
|
XL_NODE_PROCESS,
|
||||||
XMLLIB_NODE_DOCTYPE
|
XL_NODE_DOCTYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xmllib_node {
|
struct xl_node {
|
||||||
int type;
|
int type;
|
||||||
char* name;
|
char* name;
|
||||||
char* text;
|
char* text;
|
||||||
|
|
||||||
xmllib_node_t* root;
|
xl_node_t* root;
|
||||||
xmllib_node_t* parent;
|
xl_node_t* parent;
|
||||||
|
|
||||||
xmllib_node_t* first_child;
|
xl_node_t* first_child;
|
||||||
|
|
||||||
xmllib_node_t* prev;
|
xl_node_t* prev;
|
||||||
xmllib_node_t* next;
|
xl_node_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xmllib {
|
struct xmllib {
|
||||||
xmllib_driver_t* driver;
|
xl_driver_t* driver;
|
||||||
void* drv_opaque;
|
void* drv_opaque;
|
||||||
void* drv_arg;
|
void* drv_arg;
|
||||||
xmllib_node_t* root;
|
xl_node_t* root;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -51,23 +53,26 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* core.c */
|
/* core.c */
|
||||||
XLDECL xmllib_t* xmllib_open(xmllib_driver_t* driver, void* arg);
|
XLDECL xmllib_t* xl_open(xl_driver_t* driver, void* arg);
|
||||||
|
|
||||||
XLDECL int xmllib_parse(xmllib_t* handle);
|
XLDECL int xl_parse(xmllib_t* handle);
|
||||||
|
|
||||||
XLDECL void xmllib_close(xmllib_t* handle);
|
XLDECL void xl_close(xmllib_t* handle);
|
||||||
|
|
||||||
/* file.c */
|
/* file.c */
|
||||||
XLDECL xmllib_driver_t* xmllib_driver_file;
|
XLDECL xl_driver_t* xl_driver_file;
|
||||||
|
|
||||||
XLDECL xmllib_t* xmllib_open_file(const char* filename);
|
XLDECL xmllib_t* xl_open_file(const char* filename);
|
||||||
|
|
||||||
|
/* util.c */
|
||||||
|
XLDECL char* xl_util_trim(const char* str);
|
||||||
|
|
||||||
/* unicode.c */
|
/* unicode.c */
|
||||||
XLDECL int xmllib_unicode_count(unsigned char c);
|
XLDECL int xl_unicode_count(unsigned char c);
|
||||||
|
|
||||||
XLDECL int xmllib_unicode_8_to_32(const char* input, int* output);
|
XLDECL int xl_unicode_8_to_32(const char* input, int* output);
|
||||||
|
|
||||||
XLDECL int xmllib_unicode_32_to_8(const int input, char* output);
|
XLDECL int xl_unicode_32_to_8(const int input, char* output);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
137
src/core.c
137
src/core.c
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "../external/stb_ds.h"
|
#include "../external/stb_ds.h"
|
||||||
|
|
||||||
xmllib_t* xmllib_open(xmllib_driver_t* driver, void* arg) {
|
xmllib_t* xl_open(xl_driver_t* driver, void* arg) {
|
||||||
xmllib_t* handle = malloc(sizeof(*handle));
|
xmllib_t* handle = malloc(sizeof(*handle));
|
||||||
memset(handle, 0, sizeof(*handle));
|
memset(handle, 0, sizeof(*handle));
|
||||||
|
|
||||||
|
|
@ -23,14 +23,15 @@ enum STATES {
|
||||||
STATE_STRING,
|
STATE_STRING,
|
||||||
STATE_SPECIAL,
|
STATE_SPECIAL,
|
||||||
STATE_COMMENT,
|
STATE_COMMENT,
|
||||||
STATE_DOCTYPE,
|
STATE_MISC,
|
||||||
|
STATE_IGNORE_TAG
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TAKE_AS_NODE(x) \
|
#define TAKE_AS_NODE(x) \
|
||||||
{ \
|
{ \
|
||||||
char* old = node; \
|
char* old = node; \
|
||||||
char buf[4]; \
|
char buf[4]; \
|
||||||
int new = xmllib_unicode_32_to_8((x), &buf[0]); \
|
int new = xl_unicode_32_to_8((x), &buf[0]); \
|
||||||
\
|
\
|
||||||
node = malloc(strlen(old) + new + 1); \
|
node = malloc(strlen(old) + new + 1); \
|
||||||
strcpy(node, old); \
|
strcpy(node, old); \
|
||||||
|
|
@ -54,17 +55,15 @@ enum STATES {
|
||||||
longjmp(err, 1); \
|
longjmp(err, 1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIPPABLE(x) (((x) == ' ') || ((x) == '\t') || ((x) == '\n') || ((x) == '\r'))
|
|
||||||
|
|
||||||
#define STATE state[arrlen(state) - 1]
|
#define STATE state[arrlen(state) - 1]
|
||||||
|
|
||||||
int xmllib_parse(xmllib_t* handle) {
|
int xl_parse(xmllib_t* handle) {
|
||||||
jmp_buf err;
|
jmp_buf err;
|
||||||
int* state = NULL;
|
int* state = NULL;
|
||||||
char* node = NULL;
|
char* node = NULL;
|
||||||
int node_count = 0;
|
int node_count = 0;
|
||||||
int nest_level = 0;
|
int nest_level = 0;
|
||||||
xmllib_node_t* current = NULL;
|
xl_node_t* current = NULL;
|
||||||
|
|
||||||
if(setjmp(err)) {
|
if(setjmp(err)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -79,12 +78,12 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
|
|
||||||
if(handle->driver->read(handle, &in[0], 1) < 1) ERROR;
|
if(handle->driver->read(handle, &in[0], 1) < 1) ERROR;
|
||||||
|
|
||||||
c = xmllib_unicode_count(in[0]);
|
c = xl_unicode_count(in[0]);
|
||||||
if((c > 1) && handle->driver->read(handle, &in[1], c - 1) < (c - 1)) longjmp(err, 1);
|
if((c > 1) && handle->driver->read(handle, &in[1], c - 1) < (c - 1)) longjmp(err, 1);
|
||||||
|
|
||||||
xmllib_unicode_8_to_32(in, &cp);
|
xl_unicode_8_to_32(in, &cp);
|
||||||
|
|
||||||
if(cp == '<' && STATE != STATE_COMMENT && STATE != STATE_DOCTYPE) {
|
if(cp == '<' && STATE != STATE_COMMENT) {
|
||||||
if(STATE == STATE_INITIAL) {
|
if(STATE == STATE_INITIAL) {
|
||||||
arrput(state, STATE_TAG);
|
arrput(state, STATE_TAG);
|
||||||
|
|
||||||
|
|
@ -93,34 +92,51 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
node_count = 0;
|
node_count = 0;
|
||||||
} else if(STATE == STATE_STRING) {
|
} else if(STATE == STATE_STRING) {
|
||||||
TAKE_AS_NODE(cp);
|
TAKE_AS_NODE(cp);
|
||||||
|
} else if(STATE == STATE_MISC) {
|
||||||
|
arrput(state, STATE_IGNORE_TAG);
|
||||||
} else {
|
} else {
|
||||||
ERROR;
|
ERROR;
|
||||||
}
|
}
|
||||||
} else if(cp == '>') {
|
} else if(cp == '>') {
|
||||||
if(STATE == STATE_TAG || STATE == STATE_DOCTYPE || STATE == STATE_COMMENT) {
|
if(STATE == STATE_TAG || STATE == STATE_COMMENT || STATE == STATE_MISC || STATE == STATE_IGNORE_TAG) {
|
||||||
if((STATE != STATE_COMMENT || node[strlen(node) - 1] == '-') && (STATE != STATE_DOCTYPE || node[strlen(node) - 1] == ']')) {
|
if((STATE != STATE_COMMENT || node[strlen(node) - 1] == '-')) {
|
||||||
arrpop(state);
|
arrpop(state);
|
||||||
|
|
||||||
if(STATE == STATE_INITIAL) {
|
if(STATE == STATE_INITIAL) {
|
||||||
/* parsed tag */
|
/* parsed tag */
|
||||||
xmllib_node_t* n = NULL;
|
xl_node_t* n = NULL;
|
||||||
xmllib_node_t* targ = NULL;
|
xl_node_t* targ = NULL;
|
||||||
|
|
||||||
if(node[0] == '!') {
|
if(node[0] == '!') {
|
||||||
/* special tag */
|
/* special tag */
|
||||||
if(strlen(node) > 1 && node[1] == '-') {
|
if(strlen(node) > 2 && node[1] == '-') {
|
||||||
/* comment */
|
/* comment */
|
||||||
|
|
||||||
if(strlen(node) > (3 + 2) && nest_level > 0) {
|
if(strlen(node) > (1 + 3 + 2) && nest_level > 0) {
|
||||||
n = malloc(sizeof(*n));
|
n = malloc(sizeof(*n));
|
||||||
|
|
||||||
n->type = XMLLIB_NODE_COMMENT;
|
n->type = XL_NODE_COMMENT;
|
||||||
n->name = NULL;
|
n->name = NULL;
|
||||||
n->text = malloc(strlen(node) + 1);
|
n->text = malloc(strlen(node) + 1);
|
||||||
|
|
||||||
strcpy(n->text, node + 3);
|
strcpy(n->text, node + 3);
|
||||||
n->text[strlen(n->text) - 2] = 0;
|
n->text[strlen(n->text) - 2] = 0;
|
||||||
}
|
}
|
||||||
|
} else if(strlen(node) > 8 && memcmp(&node[1], "[CDATA[", 7) == 0 && node[strlen(node) - 1] == ']' && node[strlen(node) - 2] == ']') {
|
||||||
|
char* old = current->text;
|
||||||
|
|
||||||
|
if(old == NULL) {
|
||||||
|
current->text = malloc(strlen(node));
|
||||||
|
strcpy(current->text, node + 8);
|
||||||
|
} else {
|
||||||
|
current->text = malloc(strlen(old) + strlen(node));
|
||||||
|
strcpy(current->text, old);
|
||||||
|
strcpy(current->text + strlen(old), node + 8);
|
||||||
|
free(old);
|
||||||
|
}
|
||||||
|
if(strlen(current->text) > 2) {
|
||||||
|
current->text[strlen(current->text) - 2] = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* doctype or something - we ignore this for now */
|
/* doctype or something - we ignore this for now */
|
||||||
}
|
}
|
||||||
|
|
@ -130,59 +146,30 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
/* normal tag */
|
/* normal tag */
|
||||||
if(node[0] == '/') {
|
if(node[0] == '/') {
|
||||||
/* close tag */
|
/* close tag */
|
||||||
|
char* str;
|
||||||
|
|
||||||
if(nest_level > 0) {
|
if(nest_level > 0) {
|
||||||
if(strcmp(current->name, node + 1) != 0) ERROR;
|
if(strcmp(current->name, node + 1) != 0) ERROR;
|
||||||
|
|
||||||
if(current->text != NULL) {
|
|
||||||
int i, inc;
|
|
||||||
int* l = NULL;
|
|
||||||
char* txt = current->text;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while(1) {
|
|
||||||
int icp;
|
|
||||||
int nb = xmllib_unicode_8_to_32(txt + i, &icp);
|
|
||||||
|
|
||||||
if(icp == 0) break;
|
|
||||||
|
|
||||||
arrput(l, nb);
|
|
||||||
|
|
||||||
i += nb;
|
|
||||||
}
|
|
||||||
|
|
||||||
inc = strlen(txt);
|
|
||||||
i = arrlen(l) - 1;
|
|
||||||
while(1) {
|
|
||||||
int icp;
|
|
||||||
int nb;
|
|
||||||
|
|
||||||
inc -= l[i];
|
|
||||||
|
|
||||||
nb = xmllib_unicode_8_to_32(txt + inc, &icp);
|
|
||||||
|
|
||||||
if(SKIPPABLE(icp)) {
|
|
||||||
txt[inc] = 0;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
arrfree(l);
|
|
||||||
}
|
|
||||||
|
|
||||||
targ = current->parent;
|
targ = current->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
nest_level--;
|
nest_level--;
|
||||||
|
|
||||||
|
str = xl_util_trim(current->text);
|
||||||
|
free(current->text);
|
||||||
|
current->text = str;
|
||||||
|
|
||||||
|
if(strlen(current->text) == 0) {
|
||||||
|
free(current->text);
|
||||||
|
current->text = NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
n = malloc(sizeof(*n));
|
n = malloc(sizeof(*n));
|
||||||
|
|
||||||
n->type = XMLLIB_NODE_NODE;
|
n->type = XL_NODE_NODE;
|
||||||
n->name = malloc(strlen(node) + 1);
|
n->name = malloc(strlen(node) + 1);
|
||||||
n->text = NULL;
|
n->text = NULL;
|
||||||
|
|
||||||
|
|
@ -190,11 +177,11 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
int icp;
|
int icp;
|
||||||
int nb = xmllib_unicode_8_to_32(n->name + i, &icp);
|
int nb = xl_unicode_8_to_32(n->name + i, &icp);
|
||||||
|
|
||||||
if(icp == 0) break;
|
if(icp == 0) break;
|
||||||
|
|
||||||
if(SKIPPABLE(icp)) {
|
if(XL_SKIPPABLE(icp)) {
|
||||||
n->name[i] = 0;
|
n->name[i] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +201,7 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
xmllib_node_t* last = NULL;
|
xl_node_t* last = NULL;
|
||||||
|
|
||||||
if(handle->root == NULL) handle->root = n;
|
if(handle->root == NULL) handle->root = n;
|
||||||
|
|
||||||
|
|
@ -253,14 +240,14 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
} else {
|
} else {
|
||||||
ERROR;
|
ERROR;
|
||||||
}
|
}
|
||||||
} else if(cp == '"' && STATE != STATE_COMMENT && STATE != STATE_DOCTYPE) {
|
} else if(cp == '"' && STATE != STATE_COMMENT && STATE != STATE_MISC) {
|
||||||
if(STATE == STATE_TAG) {
|
if(STATE == STATE_TAG) {
|
||||||
arrput(state, STATE_STRING);
|
arrput(state, STATE_STRING);
|
||||||
} else if(STATE == STATE_STRING) {
|
} else if(STATE == STATE_STRING) {
|
||||||
arrpop(state);
|
arrpop(state);
|
||||||
}
|
}
|
||||||
TAKE_AS_NODE(cp);
|
TAKE_AS_NODE(cp);
|
||||||
} else if(STATE == STATE_TAG || STATE == STATE_STRING || STATE == STATE_SPECIAL || STATE == STATE_COMMENT || STATE == STATE_DOCTYPE) {
|
} else if(STATE == STATE_TAG || STATE == STATE_STRING || STATE == STATE_SPECIAL || STATE == STATE_COMMENT || STATE == STATE_MISC || STATE == STATE_IGNORE_TAG) {
|
||||||
if(node_count == 0 && cp == '!') {
|
if(node_count == 0 && cp == '!') {
|
||||||
arrpop(state);
|
arrpop(state);
|
||||||
arrput(state, STATE_SPECIAL);
|
arrput(state, STATE_SPECIAL);
|
||||||
|
|
@ -269,7 +256,7 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
arrput(state, STATE_COMMENT);
|
arrput(state, STATE_COMMENT);
|
||||||
} else if(node_count == 1 && STATE == STATE_SPECIAL) {
|
} else if(node_count == 1 && STATE == STATE_SPECIAL) {
|
||||||
arrpop(state);
|
arrpop(state);
|
||||||
arrput(state, STATE_DOCTYPE);
|
arrput(state, STATE_MISC);
|
||||||
}
|
}
|
||||||
TAKE_AS_NODE(cp);
|
TAKE_AS_NODE(cp);
|
||||||
} else if(STATE == STATE_INITIAL) {
|
} else if(STATE == STATE_INITIAL) {
|
||||||
|
|
@ -277,7 +264,7 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
char* old = current->text;
|
char* old = current->text;
|
||||||
if(old != NULL) {
|
if(old != NULL) {
|
||||||
char buf[4];
|
char buf[4];
|
||||||
int new = xmllib_unicode_32_to_8(cp, &buf[0]);
|
int new = xl_unicode_32_to_8(cp, &buf[0]);
|
||||||
|
|
||||||
current->text = malloc(strlen(old) + new + 1);
|
current->text = malloc(strlen(old) + new + 1);
|
||||||
strcpy(current->text, old);
|
strcpy(current->text, old);
|
||||||
|
|
@ -285,9 +272,9 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
current->text[strlen(old) + new] = 0;
|
current->text[strlen(old) + new] = 0;
|
||||||
|
|
||||||
free(old);
|
free(old);
|
||||||
} else if(!SKIPPABLE(cp)) {
|
} else {
|
||||||
char buf[4];
|
char buf[4];
|
||||||
int new = xmllib_unicode_32_to_8(cp, &buf[0]);
|
int new = xl_unicode_32_to_8(cp, &buf[0]);
|
||||||
|
|
||||||
current->text = malloc(new + 1);
|
current->text = malloc(new + 1);
|
||||||
memcpy(current->text, &buf[0], new);
|
memcpy(current->text, &buf[0], new);
|
||||||
|
|
@ -304,8 +291,8 @@ int xmllib_parse(xmllib_t* handle) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void recursive_free(xmllib_node_t* node) {
|
void recursive_free(xl_node_t* node) {
|
||||||
xmllib_node_t* n = node->first_child;
|
xl_node_t* n = node->first_child;
|
||||||
while(n != NULL) {
|
while(n != NULL) {
|
||||||
recursive_free(n);
|
recursive_free(n);
|
||||||
|
|
||||||
|
|
@ -317,8 +304,8 @@ void recursive_free(xmllib_node_t* node) {
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xmllib_close(xmllib_t* handle) {
|
void xl_close(xmllib_t* handle) {
|
||||||
recursive_free(handle->root);
|
if(handle->root != NULL) recursive_free(handle->root);
|
||||||
|
|
||||||
handle->driver->close(handle);
|
handle->driver->close(handle);
|
||||||
free(handle);
|
free(handle);
|
||||||
|
|
|
||||||
20
src/file.c
20
src/file.c
|
|
@ -1,26 +1,26 @@
|
||||||
#include <xmllib.h>
|
#include <xmllib.h>
|
||||||
|
|
||||||
static int xmllib_driver_file_open(xmllib_t* handle) {
|
static int xl_driver_file_open(xmllib_t* handle) {
|
||||||
if((handle->drv_opaque = fopen(handle->drv_arg, "rb")) == NULL) return 0;
|
if((handle->drv_opaque = fopen(handle->drv_arg, "rb")) == NULL) return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xmllib_driver_file_read(xmllib_t* handle, void* data, int size) {
|
static int xl_driver_file_read(xmllib_t* handle, void* data, int size) {
|
||||||
return fread(data, 1, size, handle->drv_opaque);
|
return fread(data, 1, size, handle->drv_opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xmllib_driver_file_close(xmllib_t* handle) {
|
static void xl_driver_file_close(xmllib_t* handle) {
|
||||||
fclose(handle->drv_opaque);
|
fclose(handle->drv_opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
xmllib_driver_t xmllib_driver_file_rec = {
|
xl_driver_t xl_driver_file_rec = {
|
||||||
xmllib_driver_file_open,
|
xl_driver_file_open,
|
||||||
xmllib_driver_file_read,
|
xl_driver_file_read,
|
||||||
xmllib_driver_file_close,
|
xl_driver_file_close,
|
||||||
};
|
};
|
||||||
xmllib_driver_t* xmllib_driver_file = &xmllib_driver_file_rec;
|
xl_driver_t* xl_driver_file = &xl_driver_file_rec;
|
||||||
|
|
||||||
xmllib_t* xmllib_open_file(const char* filename) {
|
xmllib_t* xl_open_file(const char* filename) {
|
||||||
return xmllib_open(xmllib_driver_file, (void*)filename);
|
return xl_open(xl_driver_file, (void*)filename);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#define CAST_I32(x) ((int)(x))
|
#define CAST_I32(x) ((int)(x))
|
||||||
|
|
||||||
int xmllib_unicode_count(unsigned char c) {
|
int xl_unicode_count(unsigned char c) {
|
||||||
if(c < 0x80) {
|
if(c < 0x80) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -22,9 +22,9 @@ static int unicode_later(unsigned char c) {
|
||||||
return 0x80 <= c && c < 0xc0;
|
return 0x80 <= c && c < 0xc0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmllib_unicode_8_to_32(const char* input, int* output) {
|
int xl_unicode_8_to_32(const char* input, int* output) {
|
||||||
const unsigned char* inbuf = (const unsigned char*)input;
|
const unsigned char* inbuf = (const unsigned char*)input;
|
||||||
int b = xmllib_unicode_count(inbuf[0]);
|
int b = xl_unicode_count(inbuf[0]);
|
||||||
if(b == 0) return 0;
|
if(b == 0) return 0;
|
||||||
|
|
||||||
if(b == 1) *output = inbuf[0];
|
if(b == 1) *output = inbuf[0];
|
||||||
|
|
@ -56,7 +56,7 @@ int xmllib_unicode_8_to_32(const char* input, int* output) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmllib_unicode_32_to_8(const int input, char* output) {
|
int xl_unicode_32_to_8(const int input, char* output) {
|
||||||
if(input < 128) {
|
if(input < 128) {
|
||||||
output[0] = input;
|
output[0] = input;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
78
src/util.c
Normal file
78
src/util.c
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
#include <xmllib.h>
|
||||||
|
|
||||||
|
#include "../external/stb_ds.h"
|
||||||
|
|
||||||
|
char* xl_util_trim(const char* str) {
|
||||||
|
char* s = malloc(strlen(str) + 1);
|
||||||
|
int nl = 1;
|
||||||
|
int i;
|
||||||
|
int inc = 0;
|
||||||
|
int* l = NULL;
|
||||||
|
|
||||||
|
s[0] = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while(1) {
|
||||||
|
int cp;
|
||||||
|
int new = xl_unicode_8_to_32(str + i, &cp);
|
||||||
|
int len = 0;
|
||||||
|
char buf[4];
|
||||||
|
|
||||||
|
if(cp == 0) break;
|
||||||
|
|
||||||
|
if(!nl && cp == '\n') {
|
||||||
|
len = xl_unicode_32_to_8(cp, &buf[0]);
|
||||||
|
|
||||||
|
nl = 1;
|
||||||
|
} else if(nl && XL_SKIPPABLE(cp)) {
|
||||||
|
} else {
|
||||||
|
len = xl_unicode_32_to_8(cp, &buf[0]);
|
||||||
|
nl = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len > 0) {
|
||||||
|
memcpy(s + inc, buf, len);
|
||||||
|
inc += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += new;
|
||||||
|
}
|
||||||
|
|
||||||
|
s[inc] = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while(1) {
|
||||||
|
int cp;
|
||||||
|
int new = xl_unicode_8_to_32(s + i, &cp);
|
||||||
|
|
||||||
|
if(cp == 0) break;
|
||||||
|
|
||||||
|
arrput(l, new);
|
||||||
|
|
||||||
|
i += new;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = strlen(s);
|
||||||
|
inc = arrlen(l) - 1;
|
||||||
|
if(inc > 0) {
|
||||||
|
while(1) {
|
||||||
|
int cp, new;
|
||||||
|
|
||||||
|
i -= l[inc];
|
||||||
|
new = xl_unicode_8_to_32(s + i, &cp);
|
||||||
|
|
||||||
|
if(XL_SKIPPABLE(cp)) {
|
||||||
|
s[i] = 0;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
inc--;
|
||||||
|
if(inc < 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arrfree(l);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue