summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2023-09-17 00:40:34 +0200
committerMitya Selivanov <automainint@guattari.tech>2023-09-17 00:40:34 +0200
commit8499b75fb011d72eeb5acbd85bcf41e4ee51e9a7 (patch)
treea98f9a16b1deb05b949f44a13f9a30c97c812589 /source
parent3f7f888e81cc8f34520bc23145422eadb0affad4 (diff)
downloadkit-8499b75fb011d72eeb5acbd85bcf41e4ee51e9a7.zip
XML
Diffstat (limited to 'source')
-rw-r--r--source/kit/_static.c1
-rw-r--r--source/kit/allocator.h2
-rw-r--r--source/kit/input_buffer.c87
-rw-r--r--source/kit/input_buffer.h24
-rw-r--r--source/kit/shared_mutex.h12
-rw-r--r--source/kit/status.h41
-rw-r--r--source/kit/xml.c203
-rw-r--r--source/kit/xml.h10
-rw-r--r--source/tests/_static.c1
-rw-r--r--source/tests/input_buffer.test.c28
-rw-r--r--source/tests/xml.test.c61
11 files changed, 309 insertions, 161 deletions
diff --git a/source/kit/_static.c b/source/kit/_static.c
index eb66879..03a72e8 100644
--- a/source/kit/_static.c
+++ b/source/kit/_static.c
@@ -12,3 +12,4 @@
#include "threads.win32.c"
#include "shared_memory.posix.c"
#include "shared_memory.win32.c"
+#include "xml.c"
diff --git a/source/kit/allocator.h b/source/kit/allocator.h
index 3fcfe9b..9bd6e0c 100644
--- a/source/kit/allocator.h
+++ b/source/kit/allocator.h
@@ -37,7 +37,7 @@ typedef struct {
// See KIT_ENABLE_CUSTOM_ALLOC_DISPATCH macro.
//
void *kit_alloc_dispatch(kit_allocator_t *alloc, i32 request,
- i64 size, i64 previous_size, void *poi32er);
+ i64 size, i64 previous_size, void *pointer);
kit_allocator_t kit_alloc_default(void);
diff --git a/source/kit/input_buffer.c b/source/kit/input_buffer.c
index c1ae748..5081cc4 100644
--- a/source/kit/input_buffer.c
+++ b/source/kit/input_buffer.c
@@ -39,7 +39,8 @@ static void kit_buf_acquire_(void *p) {
}
static void kit_buf_release_(void *p) {
- assert(p != NULL);
+ if (p == NULL)
+ return;
internal_buffer_t *buf = (internal_buffer_t *) p;
@@ -74,9 +75,9 @@ static i64 kit_buf_read_(void *p, i64 offset, kit_str_t destination) {
return n;
}
-kit_ib_handle_t kit_ib_wrap(kit_is_handle_t upstream,
- kit_allocator_t *alloc) {
- kit_ib_handle_t buf;
+kit_ib_t kit_ib_wrap(kit_is_handle_t upstream,
+ kit_allocator_t *alloc) {
+ kit_ib_t buf;
memset(&buf, 0, sizeof buf);
buf.status = KIT_OK;
DA_INIT(buf.data, 0, alloc);
@@ -86,8 +87,8 @@ kit_ib_handle_t kit_ib_wrap(kit_is_handle_t upstream,
return buf;
}
-kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, i64 size) {
- kit_ib_handle_t next;
+kit_ib_t kit_ib_read(kit_ib_t buf, i64 size) {
+ kit_ib_t next;
memset(&next, 0, sizeof next);
if (buf.status != KIT_OK) {
@@ -115,9 +116,69 @@ kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, i64 size) {
return next;
}
-kit_ib_handle_t kit_ib_read_while(
- kit_ib_handle_t buf, kit_ib_read_condition_fn condition) {
- kit_ib_handle_t next;
+kit_ib_t kit_ib_exact(kit_ib_t buf, kit_str_t data) {
+ kit_ib_t res = kit_ib_read(buf, data.size);
+ if (!AR_EQUAL(res.data, data))
+ res.status = KIT_ERROR_INTERNAL;
+ return res;
+}
+
+kit_ib_t kit_ib_until(kit_ib_t buf, kit_str_t data) {
+ kit_ib_t next;
+ memset(&next, 0, sizeof next);
+
+ if (buf.status != KIT_OK) {
+ next.status = buf.status;
+ return next;
+ }
+
+ kit_buf_acquire_(buf.internal);
+
+ DA_INIT(next.data, 0, kit_buf_alloc_(buf.internal));
+
+ i64 size = 0;
+
+ for (;; ++size) {
+ kit_buf_adjust_(buf.internal, buf.offset + size + 1);
+
+ DA_RESIZE(next.data, size + 1);
+
+ assert(next.data.size == size + 1);
+ if (next.data.size != size + 1) {
+ next.status = KIT_ERROR_BAD_ALLOC;
+ return next;
+ }
+
+ kit_str_t destination = { .size = 1,
+ .values = next.data.values + size };
+ i64 n = kit_buf_read_(buf.internal, buf.offset + size,
+ destination);
+
+ if (n != 1)
+ break;
+
+ if (size + 1 >= data.size &&
+ AR_EQUAL(kit_str(data.size,
+ next.data.values + (size + 1 - data.size)),
+ data)) {
+ size -= data.size - 1;
+ break;
+ }
+ }
+
+ next.offset = buf.offset + size;
+ next.internal = buf.internal;
+
+ DA_RESIZE(next.data, size);
+ if (next.data.size != size)
+ next.status = KIT_ERROR_BAD_ALLOC;
+
+ return next;
+}
+
+kit_ib_t kit_ib_while(kit_ib_t buf,
+ kit_ib_read_condition_fn condition) {
+ kit_ib_t next;
memset(&next, 0, sizeof next);
if (buf.status != KIT_OK) {
@@ -135,8 +196,12 @@ kit_ib_handle_t kit_ib_read_while(
kit_buf_adjust_(buf.internal, buf.offset + size + 1);
DA_RESIZE(next.data, size + 1);
- if (next.data.size != size + 1)
+
+ assert(next.data.size == size + 1);
+ if (next.data.size != size + 1) {
next.status = KIT_ERROR_BAD_ALLOC;
+ return next;
+ }
kit_str_t destination = { .size = 1,
.values = next.data.values + size };
@@ -158,7 +223,7 @@ kit_ib_handle_t kit_ib_read_while(
return next;
}
-void kit_ib_destroy(kit_ib_handle_t buf) {
+void kit_ib_destroy(kit_ib_t buf) {
kit_buf_release_(buf.internal);
DA_DESTROY(buf.data);
}
diff --git a/source/kit/input_buffer.h b/source/kit/input_buffer.h
index 5de85c9..e34b512 100644
--- a/source/kit/input_buffer.h
+++ b/source/kit/input_buffer.h
@@ -14,19 +14,23 @@ typedef struct {
i64 offset;
void *internal;
kit_str_builder_t data;
-} kit_ib_handle_t;
+} kit_ib_t;
typedef i8 (*kit_ib_read_condition_fn)(kit_str_t data);
-kit_ib_handle_t kit_ib_wrap(kit_is_handle_t upstream,
- kit_allocator_t *alloc);
+kit_ib_t kit_ib_wrap(kit_is_handle_t upstream,
+ kit_allocator_t *alloc);
-kit_ib_handle_t kit_ib_read(kit_ib_handle_t buf, i64 size);
+kit_ib_t kit_ib_read(kit_ib_t buf, i64 size);
-kit_ib_handle_t kit_ib_read_while(kit_ib_handle_t buf,
- kit_ib_read_condition_fn condition);
+kit_ib_t kit_ib_exact(kit_ib_t buf, kit_str_t data);
-void kit_ib_destroy(kit_ib_handle_t buf);
+kit_ib_t kit_ib_until(kit_ib_t buf, kit_str_t data);
+
+kit_ib_t kit_ib_while(kit_ib_t buf,
+ kit_ib_read_condition_fn condition);
+
+void kit_ib_destroy(kit_ib_t buf);
#define KIT_IB_WRAP(upstream) kit_ib_wrap(upstream, NULL)
@@ -35,11 +39,13 @@ void kit_ib_destroy(kit_ib_handle_t buf);
#endif
#ifndef KIT_DISABLE_SHORT_NAMES
-# define ib_handle_t kit_ib_handle_t
+# define ib_t kit_ib_t
# define ib_read_condition_fn kit_ib_read_condition_fn
# define ib_wrap kit_ib_wrap
# define ib_read kit_ib_read
-# define ib_read_while kit_ib_read_while
+# define ib_exact kit_ib_exact
+# define ib_until kit_ib_until
+# define ib_while kit_ib_while
# define ib_destroy kit_ib_destroy
# define IB_WRAP KIT_IB_WRAP
diff --git a/source/kit/shared_mutex.h b/source/kit/shared_mutex.h
index 0896b86..de5958d 100644
--- a/source/kit/shared_mutex.h
+++ b/source/kit/shared_mutex.h
@@ -123,7 +123,7 @@ static i8 kit_unique_try_lock(kit_shared_mutex_t *m) {
return is_locked;
}
-static void kit_lock(kit_shared_mutex_t *m) {
+static void kit_unique_lock(kit_shared_mutex_t *m) {
assert(m != NULL);
while (!kit_unique_try_lock(m))
@@ -151,4 +151,14 @@ static void kit_unique_unlock(kit_shared_mutex_t *m) {
}
#endif
+#ifndef KIT_DISABLE_SHORT_NAMES
+# define shared_mutex_init kit_shared_mutex_init
+# define shared_try_lock kit_shared_try_lock
+# define shared_lock kit_shared_lock
+# define shared_unlock kit_shared_unlock
+# define unique_try_lock kit_unique_try_lock
+# define unique_lock kit_unique_lock
+# define unique_unlock kit_unique_unlock
+#endif
+
#endif
diff --git a/source/kit/status.h b/source/kit/status.h
index 35139e3..86b34b1 100644
--- a/source/kit/status.h
+++ b/source/kit/status.h
@@ -5,26 +5,27 @@
enum {
KIT_OK = 0,
- KIT_ERROR_BAD_ALLOC = 1,
- KIT_ERROR_INVALID_ARGUMENT = (1 << 1),
- KIT_ERROR_MKDIR_FAILED = (1 << 2),
- KIT_ERROR_RMDIR_FAILED = (1 << 3),
- KIT_ERROR_UNLINK_FAILED = (1 << 4),
- KIT_ERROR_FILE_ALREADY_EXISTS = (1 << 5),
- KIT_ERROR_FILE_DOES_NOT_EXIST = (1 << 6),
- KIT_ERROR_PATH_TOO_LONG = (1 << 7),
- KIT_ERROR_SOCKETS_STARTUP_FAILED = (1 << 8),
- KIT_ERROR_SOCKET_CONTROL_FAILED = (1 << 9),
- KIT_ERROR_NAME_TOO_LONG = (1 << 10),
- KIT_ERROR_INVALID_SIZE = (1 << 11),
- KIT_ERROR_INVALID_NAME = (1 << 12),
- KIT_ERROR_INVALID_PATH = (1 << 13),
- KIT_ERROR_OPEN_FAILED = (1 << 14),
- KIT_ERROR_TRUNCATE_FAILED = (1 << 15),
- KIT_ERROR_MAP_FAILED = (1 << 16),
- KIT_ERROR_UNMAP_FAILED = (1 << 17),
- KIT_ERROR_SYNC_FAILED = (1 << 18),
- KIT_ERROR_CLOSE_FAILED = (1 << 19),
+ KIT_ERROR_INTERNAL = 1,
+ KIT_ERROR_BAD_ALLOC = (1 << 1),
+ KIT_ERROR_INVALID_ARGUMENT = (1 << 2),
+ KIT_ERROR_MKDIR_FAILED = (1 << 3),
+ KIT_ERROR_RMDIR_FAILED = (1 << 4),
+ KIT_ERROR_UNLINK_FAILED = (1 << 5),
+ KIT_ERROR_FILE_ALREADY_EXISTS = (1 << 6),
+ KIT_ERROR_FILE_DOES_NOT_EXIST = (1 << 7),
+ KIT_ERROR_PATH_TOO_LONG = (1 << 8),
+ KIT_ERROR_SOCKETS_STARTUP_FAILED = (1 << 9),
+ KIT_ERROR_SOCKET_CONTROL_FAILED = (1 << 10),
+ KIT_ERROR_NAME_TOO_LONG = (1 << 11),
+ KIT_ERROR_INVALID_SIZE = (1 << 12),
+ KIT_ERROR_INVALID_NAME = (1 << 13),
+ KIT_ERROR_INVALID_PATH = (1 << 14),
+ KIT_ERROR_OPEN_FAILED = (1 << 15),
+ KIT_ERROR_TRUNCATE_FAILED = (1 << 16),
+ KIT_ERROR_MAP_FAILED = (1 << 17),
+ KIT_ERROR_UNMAP_FAILED = (1 << 18),
+ KIT_ERROR_SYNC_FAILED = (1 << 19),
+ KIT_ERROR_CLOSE_FAILED = (1 << 20),
KIT_ERROR_NOT_IMPLEMENTED = (1 << 30),
};
diff --git a/source/kit/xml.c b/source/kit/xml.c
index 22a850a..bb16192 100644
--- a/source/kit/xml.c
+++ b/source/kit/xml.c
@@ -1,112 +1,93 @@
#include "xml.h"
+#include "input_buffer.h"
#include <assert.h>
-static i8 kit_xml_is_spaces(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- if (data.size <= 0)
- return 1;
- char c = data.values[data.size - 1];
- return c == ' ' || c == '\t' || c == '\r' || c == '\n';
-}
-
-static i8 kit_xml_is_idword(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- if (data.size <= 0)
- return 1;
- if (data.values[0] >= '0' || data.values[0] <= '9')
- return 0;
- char c = data.values[data.size - 1];
- return c == '_' || (c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
-}
-
-static i8 kit_xml_not_tag_open(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size <= 0 || data.values[data.size - 1] != '<';
-}
-
-static i8 kit_xml_not_tag_close(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size <= 0 || data.values[data.size - 1] != '>';
-}
-
-static i8 kit_xml_is_tag_open(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size == 1 && data.values[0] == '<';
-}
-
-static i8 kit_xml_is_tag_close(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size == 1 && data.values[0] == '>';
-}
-
-static i8 kit_xml_is_tag_final_open(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size == 2 && data.values[0] == '<' &&
- data.values[1] == '/';
-}
-
-static i8 kit_xml_is_tag_final_close(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size == 2 && data.values[0] == '/' &&
- data.values[0] == '>';
-}
-
-static i8 kit_xml_is_quotes(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- return data.size == 1 && data.values[0] == '"';
-}
-
-static i8 kit_xml_is_inside_quotes(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- if (data.size <= 0)
- return 1;
- for (i64 i = 0; i < data.size; i++)
- if (data.values[i] == '"')
- return 0;
- else if (data.values[i] == '\\')
- i++;
- return 1;
-}
-
-static i8 kit_xml_is_number(str_t data) {
- assert(data.size >= 0);
- assert(data.values != NULL);
-
- if (data.size <= 0)
- return 1;
- char c = data.values[data.size - 1];
- return c >= '0' && c <= '9';
-}
-
kit_xml_parse_result_t kit_xml_parse(kit_is_handle_t is,
kit_allocator_t *alloc) {
- kit_xml_parse_result_t result;
- memset(&result, 0, sizeof result);
-
- result.status = KIT_ERROR_NOT_IMPLEMENTED;
- return result;
+ xml_parse_result_t res;
+ memset(&res, 0, sizeof res);
+
+ ib_t begin = ib_wrap(is, alloc);
+ ib_t tag_before = ib_until(begin, SZ("<"));
+ ib_t tag_open = ib_exact(tag_before, SZ("<"));
+ ib_t tag_name = ib_until(tag_open, SZ(">"));
+ ib_t tag_name_empty = ib_until(tag_open, SZ("/"));
+
+#define return_ \
+ ib_destroy(begin); \
+ ib_destroy(tag_before); \
+ ib_destroy(tag_open); \
+ ib_destroy(tag_name); \
+ ib_destroy(tag_name_empty); \
+ ib_destroy(tag_close); \
+ return
+
+ if (tag_name_empty.offset < tag_name.offset) {
+ ib_t tag_close = ib_exact(tag_name_empty, SZ("/>"));
+
+ if (tag_close.status != KIT_OK) {
+ res.status = KIT_ERROR_INTERNAL;
+ return_ res;
+ }
+
+ // move
+ res.xml.tag = tag_name_empty.data;
+ memset(&tag_name_empty.data, 0, sizeof tag_name_empty.data);
+
+ while (res.xml.tag.size > 0 &&
+ res.xml.tag.values[res.xml.tag.size - 1] == ' ')
+ --res.xml.tag.size;
+
+ DA_INIT(res.xml.text, 0, alloc);
+ DA_INIT(res.xml.tail, 0, alloc);
+ DA_INIT(res.xml.properties, 0, alloc);
+ DA_INIT(res.xml.children, 0, alloc);
+
+ res.status = KIT_OK;
+ return_ res;
+ }
+
+ ib_t tag_close = ib_exact(tag_name, SZ(">"));
+ ib_t tag_text = ib_until(tag_close, SZ("<"));
+ ib_t tagend_open = ib_exact(tag_text, SZ("</"));
+ ib_t tagend_name = ib_exact(tagend_open, WRAP_STR(tag_name.data));
+ ib_t tagend_close = ib_exact(tagend_name, SZ(">"));
+
+#undef return_
+#define return_ \
+ ib_destroy(begin); \
+ ib_destroy(tag_before); \
+ ib_destroy(tag_open); \
+ ib_destroy(tag_name); \
+ ib_destroy(tag_name_empty); \
+ ib_destroy(tag_close); \
+ ib_destroy(tag_text); \
+ ib_destroy(tagend_open); \
+ ib_destroy(tagend_name); \
+ ib_destroy(tagend_close); \
+ return
+
+ if (tagend_close.status != KIT_OK) {
+ res.status = KIT_ERROR_INTERNAL;
+ return_ res;
+ }
+
+ // move
+ res.xml.tag = tag_name.data;
+ memset(&tag_name.data, 0, sizeof tag_name.data);
+
+ // move
+ res.xml.text = tag_text.data;
+ memset(&tag_text.data, 0, sizeof tag_text.data);
+
+ DA_INIT(res.xml.tail, 0, alloc);
+ DA_INIT(res.xml.properties, 0, alloc);
+ DA_INIT(res.xml.children, 0, alloc);
+
+ res.status = KIT_OK;
+ return_ res;
+#undef return_
}
kit_xml_print_result_t kit_xml_print(kit_xml_t *xml,
@@ -122,7 +103,21 @@ kit_xml_print_result_t kit_xml_print(kit_xml_t *xml,
void kit_xml_destroy(kit_xml_t *xml) {
assert(xml != NULL);
-
if (xml == NULL)
return;
+
+ for (i64 i = 0; i < xml->properties.size; i++) {
+ DA_DESTROY(xml->properties.values[i].name);
+ DA_DESTROY(xml->properties.values[i].value);
+ }
+
+ for (i64 i = 0; i < xml->children.size; i++)
+ kit_xml_destroy(xml->children.values + i);
+
+ DA_DESTROY(xml->tag);
+ DA_DESTROY(xml->text);
+ DA_DESTROY(xml->tail);
+
+ DA_DESTROY(xml->properties);
+ DA_DESTROY(xml->children);
}
diff --git a/source/kit/xml.h b/source/kit/xml.h
index 409c835..c33392b 100644
--- a/source/kit/xml.h
+++ b/source/kit/xml.h
@@ -29,7 +29,7 @@ struct kit_xml_ {
typedef struct {
kit_status_t status;
- kit_xml_t *xml;
+ kit_xml_t xml;
} kit_xml_parse_result_t;
typedef struct {
@@ -47,4 +47,12 @@ void kit_xml_destroy(kit_xml_t *xml);
}
#endif
+#ifndef KIT_DISABLE_SHORT_NAMES
+# define xml_parse kit_xml_parse
+# define xml_print kit_xml_print
+# define xml_destroy kit_xml_destroy
+# define xml_t kit_xml_t
+# define xml_parse_result_t kit_xml_parse_result_t
+#endif
+
#endif
diff --git a/source/tests/_static.c b/source/tests/_static.c
index 9e4451d..b406f48 100644
--- a/source/tests/_static.c
+++ b/source/tests/_static.c
@@ -18,4 +18,5 @@
#include "string_ref.test.c"
#include "duration.test.c"
#include "thread.test.c"
+#include "xml.test.c"
#include "bench.test.c"
diff --git a/source/tests/input_buffer.test.c b/source/tests/input_buffer.test.c
index 4712da9..237d60d 100644
--- a/source/tests/input_buffer.test.c
+++ b/source/tests/input_buffer.test.c
@@ -6,9 +6,9 @@
TEST("input buffer read once") {
str_t text = { .size = 3, .values = "foo" };
is_handle_t in = IS_WRAP_STRING(text);
- ib_handle_t first = IB_WRAP(in);
+ ib_t first = IB_WRAP(in);
- ib_handle_t second = ib_read(first, 3);
+ ib_t second = ib_read(first, 3);
REQUIRE(second.status == KIT_OK);
REQUIRE(second.data.size == 3);
@@ -23,10 +23,10 @@ TEST("input buffer read again") {
str_t text = { .size = 6, .values = "foobar" };
str_t foo = { .size = 3, .values = "foo" };
is_handle_t in = IS_WRAP_STRING(text);
- ib_handle_t first = IB_WRAP(in);
+ ib_t first = IB_WRAP(in);
- ib_handle_t second = ib_read(first, 3);
- ib_handle_t third = ib_read(first, 3);
+ ib_t second = ib_read(first, 3);
+ ib_t third = ib_read(first, 3);
REQUIRE(AR_EQUAL(foo, second.data));
REQUIRE(AR_EQUAL(foo, third.data));
@@ -42,10 +42,10 @@ TEST("input buffer read twice") {
str_t foo = { .size = 3, .values = "foo" };
str_t bar = { .size = 3, .values = "bar" };
is_handle_t in = IS_WRAP_STRING(text);
- ib_handle_t first = IB_WRAP(in);
+ ib_t first = IB_WRAP(in);
- ib_handle_t second = ib_read(first, 3);
- ib_handle_t third = ib_read(second, 3);
+ ib_t second = ib_read(first, 3);
+ ib_t third = ib_read(second, 3);
REQUIRE(AR_EQUAL(foo, second.data));
REQUIRE(AR_EQUAL(bar, third.data));
@@ -67,9 +67,9 @@ TEST("input buffer read integer once") {
str_t text = { .size = 9, .values = "31415 foo" };
str_t num = { .size = 5, .values = "31415" };
is_handle_t in = IS_WRAP_STRING(text);
- ib_handle_t first = IB_WRAP(in);
+ ib_t first = IB_WRAP(in);
- ib_handle_t second = ib_read_while(first, is_integer_);
+ ib_t second = ib_while(first, is_integer_);
REQUIRE(second.status == KIT_OK);
REQUIRE(second.data.size == 5);
@@ -85,11 +85,11 @@ TEST("input buffer read integer twice") {
str_t num_0 = { .size = 3, .values = "314" };
str_t num_1 = { .size = 2, .values = "15" };
is_handle_t in = IS_WRAP_STRING(text);
- ib_handle_t first = IB_WRAP(in);
+ ib_t first = IB_WRAP(in);
- ib_handle_t second = ib_read_while(first, is_integer_);
- ib_handle_t third = ib_read(second, 1);
- ib_handle_t fourth = ib_read_while(third, is_integer_);
+ ib_t second = ib_while(first, is_integer_);
+ ib_t third = ib_read(second, 1);
+ ib_t fourth = ib_while(third, is_integer_);
REQUIRE(fourth.status == KIT_OK);
REQUIRE(second.data.size == 3);
diff --git a/source/tests/xml.test.c b/source/tests/xml.test.c
new file mode 100644
index 0000000..7d2151c
--- /dev/null
+++ b/source/tests/xml.test.c
@@ -0,0 +1,61 @@
+#include "../kit/xml.h"
+
+#define KIT_TEST_FILE xml
+#include "../kit/kit_test.h"
+
+TEST("xml parse tag") {
+ is_handle_t is = IS_WRAP_STRING(SZ("<foo> </foo>"));
+ xml_parse_result_t res = xml_parse(is, NULL);
+
+ REQUIRE_EQ(res.status, KIT_OK);
+
+ if (res.status == KIT_OK) {
+ REQUIRE(AR_EQUAL(res.xml.tag, SZ("foo")));
+ xml_destroy(&res.xml);
+ }
+
+ is_destroy(is);
+}
+
+TEST("xml parse tag not closed") {
+ is_handle_t is = IS_WRAP_STRING(SZ("<foo>"));
+ xml_parse_result_t res = xml_parse(is, NULL);
+
+ REQUIRE_EQ(res.status, KIT_ERROR_INTERNAL);
+
+ if (res.status == KIT_OK)
+ xml_destroy(&res.xml);
+
+ is_destroy(is);
+}
+
+TEST("xml parse tag text") {
+ is_handle_t is = IS_WRAP_STRING(SZ("<foo> bar </foo>"));
+ xml_parse_result_t res = xml_parse(is, NULL);
+
+ REQUIRE_EQ(res.status, KIT_OK);
+
+ if (res.status == KIT_OK) {
+ REQUIRE(AR_EQUAL(res.xml.tag, SZ("foo")));
+ REQUIRE(AR_EQUAL(res.xml.text, SZ(" bar ")));
+ xml_destroy(&res.xml);
+ }
+
+ is_destroy(is);
+}
+
+TEST("xml parse empty tag") {
+ is_handle_t is = IS_WRAP_STRING(SZ("<foo />"));
+ xml_parse_result_t res = xml_parse(is, NULL);
+
+ REQUIRE_EQ(res.status, KIT_OK);
+
+ if (res.status == KIT_OK) {
+ REQUIRE(AR_EQUAL(res.xml.tag, SZ("foo")));
+ xml_destroy(&res.xml);
+ }
+
+ is_destroy(is);
+}
+
+#undef KIT_TEST_FILE