Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve xml #188

Merged
merged 9 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/clang-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Clang Format Diff

on:
push:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]
pull_request:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linux-clang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Ubuntu (clang)

on:
push:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]
pull_request:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/linux-gcc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Ubuntu (gcc)

on:
push:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]
pull_request:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/mac.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: macOS Monterey 12

on:
push:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]
pull_request:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Windows Server 2022

on:
push:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]
pull_request:
branches: [ master, fullsupport_xml]
branches: [ master, improve_xml]

jobs:
build:
Expand Down
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(TEST_YAML test/test_yaml.cpp test/test_yaml_bech.cpp)
set(YAMLBENCH benchmark/yaml_benchmark.cpp)
set(TEST_NOTHROW test/test_yaml_nothrow.cpp)
set(TEST_UTIL test/test_util.cpp)
set(TEST_XMLNOTHROW test/test_xml_nothrow.cpp)

add_executable(json_example ${JSON_EXAMPLE})
add_executable(xml_example ${XML_EXAMPLE})
Expand All @@ -67,6 +68,7 @@ add_executable(test_yaml ${TEST_YAML})
add_executable(yaml_benchmark ${YAMLBENCH})
add_executable(test_nothrow ${TEST_NOTHROW})
add_executable(test_util ${TEST_UTIL})
add_executable(test_xml_nothrow ${TEST_XMLNOTHROW})

# unit test
option(BUILD_UNIT_TESTS "Build unit tests" ON)
Expand All @@ -91,3 +93,4 @@ add_test(NAME test_xml COMMAND test_xml)
add_test(NAME test_yaml COMMAND test_yaml)
add_test(NAME test_nothrow COMMAND test_nothrow)
add_test(NAME test_util COMMAND test_util)
add_test(NAME test_xml_nothrow COMMAND test_xml_nothrow)
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,10 @@ person p = {"admin", 20};
iguana::string_stream ss; // here use std::string is also ok
iguana::to_xml(ss, p);
std::cout << ss.str() << std::endl;
// you can also call iguana::to_xml_pretty to get pretty string
iguana::string_stream s;
iguana::to_xml_pretty(s, p);
std::cout << s.str() << std::endl;

// deserialization the structure from the string
std::string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"> <name>buke</name> <age>30</name>";
iguana::from_xml(p, xml.data());
iguana::from_xml(p, xml);
```
#### Serialization of yaml

Expand Down Expand Up @@ -212,7 +208,7 @@ std::string str = R"(
</library>
)";
library_t lib;
iguana::from_xml(lib, str.data());
iguana::from_xml(lib, str);
```
#### yaml

Expand Down
14 changes: 7 additions & 7 deletions benchmark/xml_bench.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ REFLECTION(rss_t, channel);
// ************ struct for bench_num.xml ****************

struct goods_t {
int id;
int sales;
int inventory;
double weight;
double price;
double rating;
double discount;
std::string_view id;
std::string_view sales;
std::string_view inventory;
std::string_view weight;
std::string_view price;
std::string_view rating;
std::string_view discount;
};
REFLECTION(goods_t, id, sales, inventory, weight, price, rating, discount);
struct storeowner_t {
Expand Down
49 changes: 36 additions & 13 deletions benchmark/xml_benchmark.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "../rapidxml/rapidxml.hpp"
#include "xml_bench.hpp"
#include <cstdio>

class ScopedTimer {
public:
Expand Down Expand Up @@ -44,16 +45,18 @@ const int iterations = 1000;
void bench_de_sample_filelists() {

std::string xmlfilelist = xml_file_content("../data/rpm_filelists.xml");
rapidxml::xml_document<> doc;
{
ScopedTimer timer("rapidxml fastest parse rpm_filelists.xml");
for (int i = 0; i < iterations; ++i) {
rapidxml::xml_document<> doc;
doc.parse<rapidxml::parse_fastest>(xmlfilelist.data());
doc.clear();
}
}

filelists_t filelist;
{
ScopedTimer timer("iguana_xml deserialize rpm_filelists.xml");
filelists_t filelist;
for (int i = 0; i < iterations; ++i) {
iguana::from_xml(filelist, xmlfilelist.begin(), xmlfilelist.end());
filelist.package.clear();
Expand All @@ -63,16 +66,18 @@ void bench_de_sample_filelists() {

void bench_de_sample_rss() {
std::string xmlrss = xml_file_content("../data/sample_rss.xml");
rapidxml::xml_document<> doc;
{
ScopedTimer timer("rapidxml fastest parse sample_rss.xml");
for (int i = 0; i < iterations; ++i) {
rapidxml::xml_document<> doc;
doc.parse<rapidxml::parse_fastest>(xmlrss.data());
doc.clear();
}
}

rss_t rss;
{
ScopedTimer timer("iguana_xml deserialize sample_rss.xml");
rss_t rss;
for (int i = 0; i < iterations; ++i) {
iguana::from_xml(rss, xmlrss.begin(), xmlrss.end());
rss.channel.item.clear();
Expand All @@ -82,28 +87,46 @@ void bench_de_sample_rss() {

void bench_num() {
std::string xmlnum = xml_file_content("../data/bench_num.xml");

store_t s;
iguana::from_xml(s, xmlnum);
auto good = s.goods[1];
std::cout << iguana::get_number<int>(good.sales) << ", "
<< iguana::get_number<double>(good.weight) << "\n";
s.goods.clear();

{
ScopedTimer timer("iguana_xml deserialize bench_num.xml");
for (int i = 0; i < iterations; ++i) {
store_t s;
iguana::from_xml(s, xmlnum);
s.goods.clear();
}
}
store_t store;
iguana::from_xml(store, xmlnum);
std::string ss;
ss.reserve(xmlnum.size());

rapidxml::xml_document<> doc;
{
ScopedTimer timer("iguana_xml serialize bench_num.xml");
ScopedTimer timer("rapidxml fastest parse bench_num.xml");
for (int i = 0; i < iterations; ++i) {
iguana::to_xml(store, ss);
ss.clear();
doc.parse<rapidxml::parse_fastest>(xmlnum.data());
doc.clear();
}
}

// store_t store;
// iguana::from_xml(store, xmlnum);
// std::string ss;
// ss.reserve(xmlnum.size());
// {
// ScopedTimer timer("iguana_xml serialize bench_num.xml");
// for (int i = 0; i < iterations; ++i) {
// iguana::to_xml(store, ss);
// ss.clear();
// }
// }
}

int main() {
bench_de_sample_filelists();
bench_de_sample_rss();
// bench_num();
bench_num();
}
1 change: 1 addition & 0 deletions frozen/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "frozen/bits/hash_string.h"
#include "frozen/bits/version.h"

#include <cstring>
#include <functional>

#ifdef FROZEN_LETITGO_HAS_STRING_VIEW
Expand Down
4 changes: 2 additions & 2 deletions iguana/json_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ template <typename Stream, tuple_t T>
IGUANA_INLINE void render_json_value(Stream &s, T &&t) {
using U = typename std::decay_t<T>;
s.push_back('[');
const size_t size = std::tuple_size_v<U>;
constexpr size_t size = std::tuple_size_v<U>;
for_each(std::forward<T>(t),
[&s, size](auto &v, auto i) IGUANA__INLINE_LAMBDA {
render_json_value(s, v);

if (i != size - 1)
if (i != size - 1) [[likely]]
s.push_back(',');
});
s.push_back(']');
Expand Down
37 changes: 35 additions & 2 deletions iguana/xml_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
skip_sapces_and_newline(it, end);
auto value_begin = it;
auto value_end = skip_pass_smaller(it, end);
;
if (value_begin == value_end) {
match_close_tag(it, end, name);
return;
Expand All @@ -160,6 +159,30 @@ IGUANA_INLINE void parse_item(U &value, It &&it, It &&end,
parse_item(value.value(), it, end, name);
}

// /> or skip <?>、 <!> and <tag></tag> until the </name>
// loose inspection here
template <typename It>
IGUANA_INLINE void skip_object_value(It &&it, It &&end, std::string_view name) {
skip_till_greater(it, end);
++it;
if (*(it - 2) == '/') {
// .../>
return;
}
// </name>
size_t size = name.size();
while (it != end) {
skip_till_greater(it, end);
if (*(it - size - 2) == '<' && *(it - size - 1) == '/' &&
(std::string_view{&*(it - size), size} == name)) {
++it;
return;
}
++it;
}
throw std::runtime_error("unclosed tag: " + std::string(name));
}

template <refletable T, typename It>
IGUANA_INLINE void parse_item(T &value, It &&it, It &&end,
std::string_view name) {
Expand Down Expand Up @@ -242,12 +265,16 @@ IGUANA_INLINE void parse_item(T &value, It &&it, It &&end,
"type must be memberptr");
using V = std::remove_reference_t<decltype(value.*member_ptr)>;
if constexpr (!cdata_t<V>) {
detail::parse_item(value.*member_ptr, it, end, key);
parse_item(value.*member_ptr, it, end, key);
}
},
member_it->second);
} else [[unlikely]] {
#ifdef THROW_UNKNOWN_KEY
throw std::runtime_error("Unknown key: " + std::string(key));
#else
skip_object_value(it, end, key);
#endif
}
skip_sapces_and_newline(it, end);
}
Expand Down Expand Up @@ -299,4 +326,10 @@ IGUANA_INLINE void from_xml(U &value, const View &view) {
from_xml(value, std::begin(view), std::end(view));
}

template <num_t Num> IGUANA_INLINE Num get_number(std::string_view str) {
Num num;
detail::parse_value(num, str.begin(), str.end());
return num;
}

} // namespace iguana
Loading