Added xml_open_document API call to read a XML document from filemaster
@@ -2,7 +2,7 @@ | |||||
PROJECT(xml) | PROJECT(xml) | ||||
SET(VERSION_MAJOR "0") | SET(VERSION_MAJOR "0") | ||||
SET(VERSION_MINOR "1") | SET(VERSION_MINOR "1") | ||||
SET(VERSION_PATCH "3") | |||||
SET(VERSION_PATCH "4") | |||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) | CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) | ||||
@@ -30,6 +30,10 @@ ADD_EXECUTABLE(test-xml | |||||
) | ) | ||||
TARGET_LINK_LIBRARIES(test-xml xml) | TARGET_LINK_LIBRARIES(test-xml xml) | ||||
FILE( COPY ${TEST_SOURCE_DIRECTORY}/test.xml | |||||
DESTINATION ${PROJECT_BINARY_DIR} | |||||
) | |||||
# Building example | # Building example | ||||
ADD_EXECUTABLE(example | ADD_EXECUTABLE(example | ||||
@@ -629,8 +629,6 @@ exit_failure: | |||||
/** | /** | ||||
* [PUBLIC API] | * [PUBLIC API] | ||||
* | |||||
* | |||||
*/ | */ | ||||
struct xml_document* xml_parse_document(uint8_t* buffer, size_t length) { | struct xml_document* xml_parse_document(uint8_t* buffer, size_t length) { | ||||
@@ -669,6 +667,53 @@ struct xml_document* xml_parse_document(uint8_t* buffer, size_t length) { | |||||
/** | |||||
* [PUBLIC API] | |||||
*/ | |||||
struct xml_document* xml_open_document(FILE* source) { | |||||
/* Prepare buffer | |||||
*/ | |||||
size_t const read_chunk = 1; // TODO 4096; | |||||
size_t document_length = 0; | |||||
size_t buffer_size = 1; // TODO 4069 | |||||
uint8_t* buffer = malloc(buffer_size * sizeof(uint8_t)); | |||||
/* Read hole file into buffer | |||||
*/ | |||||
while (!feof(source)) { | |||||
/* Reallocate buffer | |||||
*/ | |||||
if (buffer_size - document_length < read_chunk) { | |||||
buffer = realloc(buffer, buffer_size + 2 * read_chunk); | |||||
buffer_size += 2 * read_chunk; | |||||
} | |||||
size_t read = fread( | |||||
&buffer[document_length], | |||||
sizeof(uint8_t), read_chunk, | |||||
source | |||||
); | |||||
document_length += read; | |||||
} | |||||
fclose(source); | |||||
/* Try to parse buffer | |||||
*/ | |||||
struct xml_document* document = xml_parse_document(buffer, document_length); | |||||
if (!document) { | |||||
free(buffer); | |||||
return 0; | |||||
} | |||||
return document; | |||||
} | |||||
/** | /** | ||||
* [PUBLIC API] | * [PUBLIC API] | ||||
*/ | */ | ||||
@@ -53,14 +53,29 @@ struct xml_string; | |||||
* | * | ||||
* @warning `buffer` will be referenced by the document, you may not free it | * @warning `buffer` will be referenced by the document, you may not free it | ||||
* until you free the xml_document | * until you free the xml_document | ||||
* @warning You have to call xml_free after you finished using the document | |||||
* @warning You have to call xml_document_free after you finished using the | |||||
* document | |||||
* | * | ||||
* @return The parsed xml fragment iff `parsing was successful | |||||
* @return The parsed xml fragment iff parsing was successful, 0 otherwise | |||||
*/ | */ | ||||
struct xml_document* xml_parse_document(uint8_t* buffer, size_t length); | struct xml_document* xml_parse_document(uint8_t* buffer, size_t length); | ||||
/** | |||||
* Tries to read an XML document from disk | |||||
* | |||||
* @param source File that will be read into an xml document. Will be closed | |||||
* | |||||
* @warning You have to call xml_document_free with free_buffer = true after you | |||||
* finished using the document | |||||
* | |||||
* @return The parsed xml fragment iff parsing was successful, 0 otherwise | |||||
*/ | |||||
struct xml_document* xml_open_document(FILE* source); | |||||
/** | /** | ||||
* Frees all resources associated with the document. All xml_node and xml_string | * Frees all resources associated with the document. All xml_node and xml_string | ||||
* references obtained through the document will be invalidated | * references obtained through the document will be invalidated | ||||
@@ -193,6 +193,29 @@ static void test_xml_parse_document_2() { | |||||
/** | |||||
* Tests the xml_open_document functionality | |||||
*/ | |||||
static void test_xml_parse_document_3() { | |||||
#define FILE_NAME "test.xml" | |||||
FILE* handle = fopen(FILE_NAME, "rb"); | |||||
assert_that(handle, "Cannot open " FILE_NAME); | |||||
struct xml_document* document = xml_open_document(handle); | |||||
assert_that(document, "Cannot parse " FILE_NAME); | |||||
struct xml_node* element = xml_easy_child( | |||||
xml_document_root(document), "Element", "With", 0 | |||||
); | |||||
assert_that(element, "Cannot find Document/Element/With"); | |||||
assert_that(string_equals(xml_node_content(element), "Child"), "Content of Document/Element/With must be `Child'"); | |||||
xml_document_free(document, true); | |||||
#undef FILE_NAME | |||||
} | |||||
/** | /** | ||||
@@ -202,6 +225,7 @@ int main(int argc, char** argv) { | |||||
test_xml_parse_document_0(); | test_xml_parse_document_0(); | ||||
test_xml_parse_document_1(); | test_xml_parse_document_1(); | ||||
test_xml_parse_document_2(); | test_xml_parse_document_2(); | ||||
test_xml_parse_document_3(); | |||||
fprintf(stdout, "All tests passed :-)\n"); | fprintf(stdout, "All tests passed :-)\n"); | ||||
exit(EXIT_SUCCESS); | exit(EXIT_SUCCESS); | ||||
@@ -0,0 +1,7 @@ | |||||
<Document> | |||||
<Prefix></Prefix> | |||||
<Element> | |||||
<With>Child</With> | |||||
</Element> | |||||
</Document> | |||||