diff options
author | Yorhel <git@yorhel.nl> | 2013-09-24 10:39:42 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2013-09-24 10:42:28 +0200 |
commit | d297de22845fd2fd090d7dba88412941c7b5dbb8 (patch) | |
tree | b9c8e6d2484eb60bcf3119319dfa632617fd701d | |
parent | e11e36a4229035cc75a1be837382e58d61583563 (diff) |
API: Change 'data' field from a single char to a string
Allowing multiple bytes to be returned in a single YXML_DATA token. This
is (unfortunately) necessary for a few special cases:
- &#N; for N > 127,
- <? ? ?>
- <![CDATA[ ] ]]>
I'll fix those separately in the next commits. This data string is now
also re-used as a temporary buffer for entity/char references, removing
the private 'ref' field.
-rw-r--r-- | test/test.c | 2 | ||||
-rw-r--r-- | yxml.c | 22 | ||||
-rw-r--r-- | yxml.c.in | 22 | ||||
-rw-r--r-- | yxml.h | 7 |
4 files changed, 32 insertions, 21 deletions
diff --git a/test/test.c b/test/test.c index ca272c9..c0a3c6c 100644 --- a/test/test.c +++ b/test/test.c @@ -87,7 +87,7 @@ static void y_printres(yxml_t *x, yxml_ret_t r) { y_printtoken(x, "data "); indata = 1; } - y_printchar(x->data); + y_printstring(x->data); break; case YXML_PISTART: y_printtoken(x, "pistart "); @@ -110,14 +110,20 @@ typedef enum { #define yxml_isRef(c) (yxml_isNum(c) || yxml_isAlpha(c) || c == '#') -/* Set the x->data value to ch and tell the application we have some data. - * This can't be done with simple assignment because char may be unsigned, and +/* Set the given char value to ch (0<=ch<=255). + * This can't be done with simple assignment because char may be signed, and * unsigned-to-signed overflow is implementation defined in C. This function * /looks/ inefficient, but gcc compiles it down to a single movb instruction * on x86, even with -O0. */ -static inline int yxml_setdata(yxml_t *x, unsigned ch) { +static inline void yxml_setchar(char *dest, unsigned ch) { unsigned char _ch = ch; - memcpy(&x->data, &_ch, 1); + memcpy(dest, &_ch, 1); +} + + +static inline int yxml_setdata(yxml_t *x, unsigned ch) { + yxml_setchar(x->data, ch); + x->data[1] = 0; return YXML_DATA; } @@ -209,23 +215,23 @@ static inline int yxml_pivalend (yxml_t *x, unsigned ch) { yxml_popstack(x); x-> static inline int yxml_refstart(yxml_t *x, unsigned ch) { - memset(x->ref, 0, sizeof(x->ref)); + memset(x->data, 0, sizeof(x->data)); x->reflen = 0; return YXML_OK; } static int yxml_ref(yxml_t *x, unsigned ch) { - if(x->reflen >= sizeof(x->ref)-1) + if(x->reflen >= sizeof(x->data)-1) return YXML_EREF; - x->ref[x->reflen] = ch; + yxml_setchar(x->data+x->reflen, ch); x->reflen++; return YXML_OK; } static int yxml_refend(yxml_t *x, unsigned ch) { - unsigned char *r = x->ref; + unsigned char *r = (unsigned char *)x->data; ch = 0; if(*r == '#') { if(r[1] == 'x') @@ -46,14 +46,20 @@ typedef enum { #define yxml_isRef(c) (yxml_isNum(c) || yxml_isAlpha(c) || c == '#') -/* Set the x->data value to ch and tell the application we have some data. - * This can't be done with simple assignment because char may be unsigned, and +/* Set the given char value to ch (0<=ch<=255). + * This can't be done with simple assignment because char may be signed, and * unsigned-to-signed overflow is implementation defined in C. This function * /looks/ inefficient, but gcc compiles it down to a single movb instruction * on x86, even with -O0. */ -static inline int yxml_setdata(yxml_t *x, unsigned ch) { +static inline void yxml_setchar(char *dest, unsigned ch) { unsigned char _ch = ch; - memcpy(&x->data, &_ch, 1); + memcpy(dest, &_ch, 1); +} + + +static inline int yxml_setdata(yxml_t *x, unsigned ch) { + yxml_setchar(x->data, ch); + x->data[1] = 0; return YXML_DATA; } @@ -145,23 +151,23 @@ static inline int yxml_pivalend (yxml_t *x, unsigned ch) { yxml_popstack(x); x-> static inline int yxml_refstart(yxml_t *x, unsigned ch) { - memset(x->ref, 0, sizeof(x->ref)); + memset(x->data, 0, sizeof(x->data)); x->reflen = 0; return YXML_OK; } static int yxml_ref(yxml_t *x, unsigned ch) { - if(x->reflen >= sizeof(x->ref)-1) + if(x->reflen >= sizeof(x->data)-1) return YXML_EREF; - x->ref[x->reflen] = ch; + yxml_setchar(x->data+x->reflen, ch); x->reflen++; return YXML_OK; } static int yxml_refend(yxml_t *x, unsigned ch) { - unsigned char *r = x->ref; + unsigned char *r = (unsigned char *)x->data; ch = 0; if(*r == '#') { if(r[1] == 'x') @@ -74,13 +74,13 @@ typedef struct { * including the YXML_ELEMCLOSE for the corresponding element. */ char *elem; - /* The last read character of an attribute value, element data, or + /* The last read character(s) of an attribute value, element data, or * processing instruction. Changed after YXML_DATA and only valid until the - * next yxml_parse() call. + * next yxml_parse() call. Currently, only the first byte is ever set. * Note: For processing instructions, the last '?' is considered part of * the data, unless the PI was empty (e.g. "<?SomePI?>"), in which case * no DATA token is emitted at all. */ - char data; + char data[8]; /* Name of the current attribute. Changed after YXML_ATTRSTART, valid up to * and including the next YXML_ATTREND. */ @@ -103,7 +103,6 @@ typedef struct { int state; unsigned char *stack; /* Stack of element names + attribute/PI name, separated by \0. Also starts with a \0. */ size_t stacksize, stacklen; - unsigned char ref[8]; unsigned reflen; unsigned quote; int nextstate; /* Used for '@' state remembering and for the "string" consuming state */ |