Przeglądaj źródła

Recursive search example for issue #14

master
ooxi 6 lat temu
rodzic
commit
65e582d6d7
2 zmienionych plików z 207 dodań i 0 usunięć
  1. +26
    -0
      test/CMakeLists.txt
  2. +181
    -0
      test/test-huitre39.c

+ 26
- 0
test/CMakeLists.txt Wyświetl plik

@@ -96,3 +96,29 @@ add_test(
COMMAND valgrind --tool=memcheck --leak-check=full --track-origins=yes -v "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-test-cpp"
)



# Test huitre39
add_executable(
"${PROJECT_NAME}-test-huitre39"
"${CMAKE_CURRENT_LIST_DIR}/test-huitre39.c"
)

target_compile_options(
"${PROJECT_NAME}-test-huitre39"
PRIVATE
-std=c11
)

target_link_libraries(
"${PROJECT_NAME}-test-huitre39"
PRIVATE
xml
)


add_test(
NAME "${PROJECT_NAME}-test-huitre39"
COMMAND "${PROJECT_NAME}-test-huitre39"
)


+ 181
- 0
test/test-huitre39.c Wyświetl plik

@@ -0,0 +1,181 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "./xml.h"





/**
* Will halt the program iff assertion fails
*/
static void _assert_that(_Bool condition, char const* message, char const* func, char const* file, int line) {
if (!condition) {
fprintf(stderr, "Assertion failed: %s, in %s (%s:%i)\n", message, func, file, line);
exit(EXIT_FAILURE);
}
}

#define assert_that(condition, message) \
_assert_that(condition, message, __func__, __FILE__, __LINE__)





/**
* Behaves similar to `getElementsByTagName`, however returns just the first and
* not all elements with a given tag name
*
* @param base Node in tree which should be the start of te recursive search
* @param 0-terminated tag name, case sensitive
*
* @return First node below `base` iff found, otherwise 0
* @warning Depth-First search!
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
*/
static struct xml_node* get_node_by_name(struct xml_node* base, uint8_t* name) {


/* Check whether `base` already has the tag name we are searching for
*/
size_t const name_length = strlen(name);

uint8_t* base_name = xml_easy_name(base);
size_t const base_name_length = strlen(base_name);


/* Length of `name` and `base_name` do match, we should now do a real
* comparison
*/
if (name_length == base_name_length) {
int const rs = memcmp(name, base_name, name_length);

/* Names match! We have found an element which fullfills our
* search criteria
*/
if (!rs) {
free(base_name);
return base;
}
}


/* Unfortunately, `base` is not the element we are looking for :-(
*/
free(base_name);


/* Let's take a look at the children of `base`
*/
size_t const number_of_children = xml_node_children(base);


/* No children → No luck with base
*/
if (!number_of_children) {
return 0;
}


/* Recursivly look through all children
*/
size_t child = 0; for (; child < number_of_children; ++child) {
struct xml_node* child_node = xml_node_child(base, child);

/* Maybe this child does contain the element we are looking for?
*/
struct xml_node* search_result = get_node_by_name(
child_node, name
);

/* We are lucky!
*/
if (search_result) {
return search_result;
}
}


/* No luck :-(
*/
return 0;
}





int main(int argc, char** argv) {

/* XML source, could be read from disk
*/
uint8_t* source = ""
"<Root>"
"<Hello>World</Hello>"

"<Functions>"
"<Function>"
"<as>testas one</as>"
"<os>testos</os>"
"</Function>"

"<Function>"
"<is>testis</is>"
"<us>testus</us>"
"<ls>testls</ls>"
"</Function>"

"<Function>"
"<mn>testmn</mn>"
"<as>testas two</as>"
"</Function>"
"</Functions>"
"</Root>"
;

struct xml_document* document = xml_parse_document(source, strlen(source));

if (!document) {
printf("Could parse document\n");
exit(EXIT_FAILURE);
}
struct xml_node* root = xml_document_root(document);



/* We expect to find Root / Functions / Function#1 / us
*/
struct xml_node* us = get_node_by_name(root, "us");
assert_that(us, "Did not find element by tag name `us'");

uint8_t* us_content = xml_easy_content(us);
assert_that(us_content, "`us' should have content");
assert_that(!strcmp(us_content, "testus"), "Unexpected content for node `us'");
free(us_content);


/* We expect to find Root / Functions / Function#0 / as
*/
struct xml_node* as = get_node_by_name(root, "as");
assert_that(as, "Did not find element by tag name `as'");

uint8_t* as_content = xml_easy_content(as);
assert_that(as_content, "`as' should have content");
assert_that(!strcmp(as_content, "testas one"), "Unexpected content for first `as' node");
free(as_content);


/* We do not expect do find a node with tag name `does_not_exist'
*/
struct xml_node* does_not_exist = get_node_by_name(root, "does_not_exist");
assert_that(!does_not_exist, "Found node that should not exist");


xml_document_free(document, false);
}


Ładowanie…
Anuluj
Zapisz