works
This commit is contained in:
parent
1113b2dbe3
commit
45b3706810
3 changed files with 175 additions and 38 deletions
18
example.c
18
example.c
|
|
@ -6,8 +6,22 @@ void recursive(xl_node_t* node, int indent) {
|
||||||
int i;
|
int i;
|
||||||
xl_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 == XL_NODE_NODE) {
|
if(node->name != NULL && (node->type == XL_NODE_NODE || node->type == XL_NODE_PROCESS)) {
|
||||||
printf("<%s>\n", node->name);
|
xl_attribute_t* a;
|
||||||
|
|
||||||
|
printf("<%s%s", node->type == XL_NODE_PROCESS ? "?" : "", node->name);
|
||||||
|
|
||||||
|
a = node->first_attribute;
|
||||||
|
while(a != NULL) {
|
||||||
|
if(a->value == NULL) {
|
||||||
|
printf(" %s", a->key);
|
||||||
|
} else {
|
||||||
|
printf(" %s=\"%s\"", a->key, a->value);
|
||||||
|
}
|
||||||
|
a = a->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s>\n", node->type == XL_NODE_PROCESS ? "?" : "");
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
typedef struct xl_driver xl_driver_t;
|
typedef struct xl_driver xl_driver_t;
|
||||||
typedef struct xmllib xmllib_t;
|
typedef struct xmllib xmllib_t;
|
||||||
typedef struct xl_node xl_node_t;
|
typedef struct xl_node xl_node_t;
|
||||||
|
typedef struct xl_attribute xl_attribute_t;
|
||||||
|
|
||||||
#define XL_SKIPPABLE(x) (((x) == ' ') || ((x) == '\t') || ((x) == '\n') || ((x) == '\r'))
|
#define XL_SKIPPABLE(x) (((x) == ' ') || ((x) == '\t') || ((x) == '\n') || ((x) == '\r'))
|
||||||
|
|
||||||
|
|
@ -23,14 +24,22 @@ struct xl_driver {
|
||||||
enum XL_NODE_TYPE {
|
enum XL_NODE_TYPE {
|
||||||
XL_NODE_COMMENT = 0,
|
XL_NODE_COMMENT = 0,
|
||||||
XL_NODE_NODE,
|
XL_NODE_NODE,
|
||||||
XL_NODE_PROCESS,
|
XL_NODE_PROCESS
|
||||||
XL_NODE_DOCTYPE
|
};
|
||||||
|
|
||||||
|
struct xl_attribute {
|
||||||
|
char* key;
|
||||||
|
char* value;
|
||||||
|
|
||||||
|
xl_attribute_t* prev;
|
||||||
|
xl_attribute_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xl_node {
|
struct xl_node {
|
||||||
int type;
|
int type;
|
||||||
char* name;
|
char* name;
|
||||||
char* text;
|
char* text;
|
||||||
|
xl_attribute_t* first_attribute;
|
||||||
|
|
||||||
xl_node_t* root;
|
xl_node_t* root;
|
||||||
xl_node_t* parent;
|
xl_node_t* parent;
|
||||||
|
|
|
||||||
130
src/core.c
130
src/core.c
|
|
@ -57,6 +57,83 @@ enum STATES {
|
||||||
|
|
||||||
#define STATE state[arrlen(state) - 1]
|
#define STATE state[arrlen(state) - 1]
|
||||||
|
|
||||||
|
static xl_attribute_t* xl_parse_attribute(const char* str) {
|
||||||
|
xl_attribute_t* first = NULL;
|
||||||
|
xl_attribute_t* current = NULL;
|
||||||
|
char* s = malloc(strlen(str) + 1);
|
||||||
|
int i;
|
||||||
|
int st = 0;
|
||||||
|
int start = -1;
|
||||||
|
int dq = 0;
|
||||||
|
|
||||||
|
strcpy(s, str);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while(1) {
|
||||||
|
int cp;
|
||||||
|
int new = xl_unicode_8_to_32(s + i, &cp);
|
||||||
|
|
||||||
|
if(st == 0 && XL_SKIPPABLE(cp)) {
|
||||||
|
} else if(st == 0) {
|
||||||
|
xl_attribute_t* old = current;
|
||||||
|
|
||||||
|
st = 1;
|
||||||
|
start = i;
|
||||||
|
|
||||||
|
current = malloc(sizeof(*current));
|
||||||
|
|
||||||
|
current->key = NULL;
|
||||||
|
current->value = NULL;
|
||||||
|
|
||||||
|
current->prev = NULL;
|
||||||
|
current->next = NULL;
|
||||||
|
|
||||||
|
if(old != NULL) {
|
||||||
|
current->prev = old;
|
||||||
|
old->next = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(first == NULL) first = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(st == 1 && (cp == '=' || cp == 0)) {
|
||||||
|
char* b = malloc(i - start + 1);
|
||||||
|
memcpy(b, s + start, i - start);
|
||||||
|
b[i - start] = 0;
|
||||||
|
|
||||||
|
current->key = b;
|
||||||
|
|
||||||
|
st = 2;
|
||||||
|
|
||||||
|
if(cp == '=') {
|
||||||
|
current->value = malloc(1);
|
||||||
|
current->value[0] = 0;
|
||||||
|
}
|
||||||
|
} else if(st == 2 && ((dq ? 0 : XL_SKIPPABLE(cp)) || cp == 0)) {
|
||||||
|
st = 0;
|
||||||
|
} else if(st == 2 && cp == '"') {
|
||||||
|
dq = dq ? 0 : 1;
|
||||||
|
} else if(st == 2) {
|
||||||
|
char* old = current->value;
|
||||||
|
|
||||||
|
current->value = malloc(strlen(old) + new + 1);
|
||||||
|
strcpy(current->value, old);
|
||||||
|
memcpy(current->value + strlen(old), s + i, new);
|
||||||
|
current->value[strlen(old) + new] = 0;
|
||||||
|
|
||||||
|
free(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
i += new;
|
||||||
|
|
||||||
|
if(cp == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
int xl_parse(xmllib_t* handle) {
|
int xl_parse(xmllib_t* handle) {
|
||||||
jmp_buf err;
|
jmp_buf err;
|
||||||
int* state = NULL;
|
int* state = NULL;
|
||||||
|
|
@ -118,6 +195,7 @@ int xl_parse(xmllib_t* handle) {
|
||||||
n->type = XL_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);
|
||||||
|
n->first_attribute = NULL;
|
||||||
|
|
||||||
strcpy(n->text, node + 3);
|
strcpy(n->text, node + 3);
|
||||||
n->text[strlen(n->text) - 2] = 0;
|
n->text[strlen(n->text) - 2] = 0;
|
||||||
|
|
@ -138,12 +216,12 @@ int xl_parse(xmllib_t* handle) {
|
||||||
current->text[strlen(current->text) - 2] = 0;
|
current->text[strlen(current->text) - 2] = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* doctype or something - we ignore this for now */
|
/* DOCTYPE or something - ignored for now */
|
||||||
}
|
}
|
||||||
} else if(node[0] == '?') {
|
|
||||||
/* process */
|
|
||||||
} else {
|
} else {
|
||||||
/* normal tag */
|
/* normal tag */
|
||||||
|
int proc = 0;
|
||||||
|
|
||||||
if(node[0] == '/') {
|
if(node[0] == '/') {
|
||||||
/* close tag */
|
/* close tag */
|
||||||
char* str;
|
char* str;
|
||||||
|
|
@ -164,16 +242,34 @@ int xl_parse(xmllib_t* handle) {
|
||||||
free(current->text);
|
free(current->text);
|
||||||
current->text = NULL;
|
current->text = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc = 1;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
|
int set = 0;
|
||||||
|
char* s = malloc(strlen(node) + 1);
|
||||||
|
|
||||||
n = malloc(sizeof(*n));
|
n = malloc(sizeof(*n));
|
||||||
|
|
||||||
n->type = XL_NODE_NODE;
|
if(node[0] == '?' && node[strlen(node) - 1] == '?') {
|
||||||
n->name = malloc(strlen(node) + 1);
|
n->type = XL_NODE_PROCESS;
|
||||||
n->text = NULL;
|
|
||||||
|
|
||||||
strcpy(n->name, node);
|
strcpy(s, node + 1);
|
||||||
|
s[strlen(s) - 1] = 0;
|
||||||
|
} else {
|
||||||
|
n->type = XL_NODE_NODE;
|
||||||
|
|
||||||
|
strcpy(s, node);
|
||||||
|
}
|
||||||
|
if(n->type == XL_NODE_PROCESS && nest_level == 0) {
|
||||||
|
free(n);
|
||||||
|
n = NULL;
|
||||||
|
} else {
|
||||||
|
n->name = malloc(strlen(s) + 1);
|
||||||
|
n->text = NULL;
|
||||||
|
n->first_attribute = NULL;
|
||||||
|
|
||||||
|
strcpy(n->name, s);
|
||||||
i = 0;
|
i = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
int icp;
|
int icp;
|
||||||
|
|
@ -183,22 +279,32 @@ int xl_parse(xmllib_t* handle) {
|
||||||
|
|
||||||
if(XL_SKIPPABLE(icp)) {
|
if(XL_SKIPPABLE(icp)) {
|
||||||
n->name[i] = 0;
|
n->name[i] = 0;
|
||||||
|
set = 1;
|
||||||
|
} else if(set) {
|
||||||
|
n->first_attribute = xl_parse_attribute(s + i);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += nb;
|
i += nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node[strlen(node) - 1] != '/') {
|
if(n->type == XL_NODE_NODE && node[strlen(node) - 1] != '/') {
|
||||||
/* non self-closing tag */
|
/* non self-closing tag */
|
||||||
targ = n;
|
targ = n;
|
||||||
nest_level++;
|
nest_level++;
|
||||||
|
|
||||||
|
proc = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(proc) {
|
||||||
if(nest_level < 0) ERROR;
|
if(nest_level < 0) ERROR;
|
||||||
if(nest_level == 0) break;
|
if(nest_level == 0) break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(n != NULL) {
|
if(n != NULL) {
|
||||||
xl_node_t* last = NULL;
|
xl_node_t* last = NULL;
|
||||||
|
|
@ -293,12 +399,20 @@ int xl_parse(xmllib_t* handle) {
|
||||||
|
|
||||||
void recursive_free(xl_node_t* node) {
|
void recursive_free(xl_node_t* node) {
|
||||||
xl_node_t* n = node->first_child;
|
xl_node_t* n = node->first_child;
|
||||||
|
xl_attribute_t* a = node->first_attribute;
|
||||||
while(n != NULL) {
|
while(n != NULL) {
|
||||||
recursive_free(n);
|
recursive_free(n);
|
||||||
|
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(a != NULL) {
|
||||||
|
free(a->key);
|
||||||
|
if(a->value != NULL) free(a->value);
|
||||||
|
|
||||||
|
a = a->next;
|
||||||
|
}
|
||||||
|
|
||||||
if(node->name != NULL) free(node->name);
|
if(node->name != NULL) free(node->name);
|
||||||
if(node->text != NULL) free(node->text);
|
if(node->text != NULL) free(node->text);
|
||||||
free(node);
|
free(node);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue