Skip to content

Commit

Permalink
Merge pull request #188 from qicosmos/improve_xml
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jul 10, 2023
2 parents 369fcd0 + a60e034 commit 678edcc
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 82 deletions.
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

0 comments on commit 678edcc

Please sign in to comment.