diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8dbf26d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,17 @@ +name: Build +run-name: ${{github.actor}} build +on: + push: + pull_request: +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install -y build-essential cmake clang clang-tidy libexpat1-dev zlib1g-dev + - name: Configure + run: cmake -Bbuild -S. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + - name: Build + run: cmake --build build -- -j$(nproc) + diff --git a/.gitignore b/.gitignore index ada7844..618fe20 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ # artifacts build install +/.cache # ide .vscode -*.user \ No newline at end of file +*.user diff --git a/CMakeLists.txt b/CMakeLists.txt index 900e4de..54863b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +this is an error + # Toggle integration tests option(INPUTOSM_INTEGRATION_TESTS "Build integration tests" ON) option(WARNINGS_AS_ERRORS "Treat warnings as errors" ON) diff --git a/src/inputosmlog.cpp b/src/inputosmlog.cpp index 6378eea..ecaf337 100644 --- a/src/inputosmlog.cpp +++ b/src/inputosmlog.cpp @@ -3,6 +3,7 @@ #include #include #include +#include constexpr const char* kError = "err"; constexpr const char* kInfo = "inf"; diff --git a/src/inputosmpbf.cpp b/src/inputosmpbf.cpp index a3126dd..94a4e22 100644 --- a/src/inputosmpbf.cpp +++ b/src/inputosmpbf.cpp @@ -56,7 +56,7 @@ struct field_t struct string_table_t { - std::vector st_index; + std::vector st_index; std::vector st_buffer; void clear() diff --git a/src/inputosmxml.cpp b/src/inputosmxml.cpp index 4bcf546..241b8a0 100644 --- a/src/inputosmxml.cpp +++ b/src/inputosmxml.cpp @@ -15,6 +15,7 @@ #include "inputosmlog.h" #include "timeutil.h" +#include #include #include #include @@ -46,9 +47,13 @@ enum class current_tag_t }; current_tag_t current_tag; std::vector current_strings; -std::vector current_tags; +std::vector> current_tags; std::vector current_refs; -std::vector current_members; +struct ext_relation_member_t : relation_member_t +{ + int role_index = -1; +}; +std::vector current_members; static void xml_start_node(const char **attr) { @@ -80,7 +85,14 @@ static void xml_end_node() { // node end current_tag = current_tag_t::none; - current_node.tags = {current_tags.data(), current_tags.size()}; + // assemble tags + std::vector tags; + for (std::size_t i = 0; i < current_tags.size(); i++) + { + tags.emplace_back( + tag_t{current_strings[current_tags[i].first].c_str(), current_strings[current_tags[i].second].c_str()}); + } + current_node.tags = {tags.data(), tags.size()}; if (parser_enabled && node_handler) parser_enabled = node_handler({¤t_node, 1}); current_tags.clear(); current_strings.clear(); @@ -104,7 +116,14 @@ static void xml_end_way() { // way end current_tag = current_tag_t::none; - current_way.tags = {current_tags.data(), current_tags.size()}; + // assemble tags + std::vector tags; + for (std::size_t i = 0; i < current_tags.size(); i++) + { + tags.emplace_back( + tag_t{current_strings[current_tags[i].first].c_str(), current_strings[current_tags[i].second].c_str()}); + } + current_way.tags = {tags.data(), tags.size()}; current_way.node_refs = {current_refs.data(), current_refs.size()}; if (parser_enabled && way_handler) parser_enabled = way_handler({¤t_way, 1}); current_tags.clear(); @@ -130,8 +149,22 @@ static void xml_end_relation() { // end relation current_tag = current_tag_t::none; - current_relation.tags = {current_tags.data(), current_tags.size()}; - current_relation.members = {current_members.data(), current_members.size()}; + // assemble tags + std::vector tags; + for (std::size_t i = 0; i < current_tags.size(); i++) + { + tags.emplace_back( + tag_t{current_strings[current_tags[i].first].c_str(), current_strings[current_tags[i].second].c_str()}); + } + current_relation.tags = {tags.data(), tags.size()}; + // assemble members + std::vector members; + for (const auto &m : current_members) + { + members.emplace_back( + relation_member_t{m.type, m.id, m.role_index >= 0 ? current_strings[m.role_index].c_str() : nullptr}); + } + current_relation.members = {members.data(), members.size()}; if (parser_enabled && relation_handler) parser_enabled = relation_handler({¤t_relation, 1}); current_tags.clear(); current_strings.clear(); @@ -150,7 +183,7 @@ static void xml_start_xtag(const char **attr) if (strcmp(attr[i], "v") == 0) current_strings.emplace_back(attr[i + 1]); } for (auto i = istart; i < current_strings.size(); i += 2) - current_tags.emplace_back(tag_t{current_strings[i].c_str(), current_strings[i + 1].c_str()}); + current_tags.emplace_back(std::pair{i, i + 1}); } } @@ -171,27 +204,32 @@ static void xml_start_member(const char **attr) // member start if (current_tag == current_tag_t::relation) { - relation_member_t member; + ext_relation_member_t member; for (int i = 0; attr[i]; i += 2) { if (strcmp(attr[i], "ref") == 0) member.id = atoll(attr[i + 1]); if (strcmp(attr[i], "type") == 0) { if (strcmp(attr[i + 1], "node") == 0) member.type = 0; - if (strcmp(attr[i + 1], "way") == 0) member.type = 2; + if (strcmp(attr[i + 1], "way") == 0) member.type = 1; if (strcmp(attr[i + 1], "relation") == 0) member.type = 2; } if (strcmp(attr[i], "role") == 0) { current_strings.emplace_back(attr[i + 1]); - member.role = current_strings.back().c_str(); + member.role_index = current_strings.size() - 1; } } + if (member.role_index < 0) + { + current_strings.emplace_back(); + member.role_index = current_strings.size() - 1; + } current_members.emplace_back(member); } } -static void xml_start_tag(void */*data*/, const char *el, const char **attr) +static void xml_start_tag(void * /*data*/, const char *el, const char **attr) { // XML tag start if (strcmp(el, "node") == 0) xml_start_node(attr); @@ -207,7 +245,7 @@ static void xml_start_tag(void */*data*/, const char *el, const char **attr) if (strcmp(el, "delete") == 0) osc_mode = mode_t::destroy; } -static void xml_end_tag(void */*data*/, const char *el) +static void xml_end_tag(void * /*data*/, const char *el) { // XML tag end if (strcmp(el, "node") == 0) xml_end_node(); diff --git a/src/timeutil.cpp b/src/timeutil.cpp index af44232..716e0ac 100644 --- a/src/timeutil.cpp +++ b/src/timeutil.cpp @@ -13,7 +13,8 @@ #include "timeutil.h" #include -#include +#include +#include int64_t now_ms() { @@ -29,16 +30,24 @@ int64_t now_us() time_t str_to_timestamp(const char* str) { - struct tm timeinfo; - strptime(str, "%FT%TZ", &timeinfo); - return mktime(&timeinfo); + struct tm timeinfo{}; + if (strptime(str, "%FT%TZ", &timeinfo) == nullptr) + { + return 0; + } + return timegm(&timeinfo); } + time_t str_to_timestamp_osmstate(const char* str) { - struct tm timeinfo; - strptime(str, "%FT%H\\:%M\\:%SZ", &timeinfo); - return mktime(&timeinfo); + struct tm timeinfo{}; + if (strptime(str, "%FT%H\\:%M\\:%SZ", &timeinfo) == nullptr) + { + return 0; + } + return timegm(&timeinfo); } + std::string timestamp_to_str(const time_t rawtime) { struct tm* dt;