From 5e77f3594f3abaf27c10a5b114b6dca2dc2bd3bd Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 5 Sep 2021 01:35:41 +0100 Subject: Introduce lightweight flatmap --- icespider/core/flatMap.h | 68 +++++++++++++++++++++++++++++++++++++ icespider/fcgi/cgiRequestBase.h | 10 +++--- icespider/unittests/Jamfile.jam | 5 +++ icespider/unittests/testFlatMap.cpp | 55 ++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 icespider/core/flatMap.h create mode 100644 icespider/unittests/testFlatMap.cpp diff --git a/icespider/core/flatMap.h b/icespider/core/flatMap.h new file mode 100644 index 0000000..2b5d5be --- /dev/null +++ b/icespider/core/flatMap.h @@ -0,0 +1,68 @@ +#ifndef ICESPIDER_CORE_FLATMAP_H +#define ICESPIDER_CORE_FLATMAP_H + +#include +#include + +namespace IceSpider { + template> + class flatmap : std::vector, std::decay_t>> { + public: + using V = std::pair, std::decay_t>; + using S = std::vector; + + private: + template struct KeyComp { + bool + operator()(const V & v, const N & n) const + { + return c(v.first, n); + } + Comp c; + }; + + public: + flatmap() = default; + flatmap(std::size_t n) + { + reserve(n); + } + + auto + insert(V v) + { + return S::insert(lower_bound(v.first), std::move(v)); + } + + template + auto + lower_bound(const N & n) const + { + return std::lower_bound(begin(), end(), n, KeyComp {}); + } + + template + auto + find(const N & n) const + { + const auto lb = lower_bound(n); + if (lb == end()) { + return lb; + } + if (Comp {}(n, lb->first)) { + return end(); + } + return lb; + } + + using S::begin; + using S::empty; + using S::end; + using S::reserve; + using S::size; + using iterator = typename S::iterator; + using const_iterator = typename S::const_iterator; + }; +} + +#endif diff --git a/icespider/fcgi/cgiRequestBase.h b/icespider/fcgi/cgiRequestBase.h index 6a63a88..0c2b3a1 100644 --- a/icespider/fcgi/cgiRequestBase.h +++ b/icespider/fcgi/cgiRequestBase.h @@ -3,8 +3,8 @@ #include #include +#include #include -#include #include namespace IceSpider { @@ -15,8 +15,8 @@ namespace IceSpider { void initialize(); public: - using VarMap = std::map; - using HdrMap = std::map; + using VarMap = flatmap; + using HdrMap = flatmap; [[nodiscard]] const PathElements & getRequestPath() const override; [[nodiscard]] PathElements & getRequestPath() override; @@ -35,10 +35,10 @@ namespace IceSpider { private: template static OptionalString optionalLookup(const std::string_view & key, const MapType &); - VarMap envmap; + VarMap envmap {40}; StringMap qsmap; StringMap cookiemap; - HdrMap hdrmap; + HdrMap hdrmap {15}; PathElements pathElements; }; } diff --git a/icespider/unittests/Jamfile.jam b/icespider/unittests/Jamfile.jam index 8dd497a..879d56a 100644 --- a/icespider/unittests/Jamfile.jam +++ b/icespider/unittests/Jamfile.jam @@ -149,3 +149,8 @@ lib test-api-lib : . ; +run testFlatMap.cpp : : : + boost_utf + BOOST_TEST_DYN_LINK + ../core//icespider-core + ; diff --git a/icespider/unittests/testFlatMap.cpp b/icespider/unittests/testFlatMap.cpp new file mode 100644 index 0000000..12d6900 --- /dev/null +++ b/icespider/unittests/testFlatMap.cpp @@ -0,0 +1,55 @@ +#define BOOST_TEST_MODULE FlatMap +#include + +#include + +using TM = IceSpider::flatmap; + +BOOST_TEST_DONT_PRINT_LOG_VALUE(TM::iterator) +BOOST_TEST_DONT_PRINT_LOG_VALUE(TM::const_iterator) + +BOOST_FIXTURE_TEST_SUITE(sv2int, TM) + +BOOST_AUTO_TEST_CASE(is_empty) +{ + BOOST_CHECK_EQUAL(size(), 0); + BOOST_CHECK(empty()); + + BOOST_CHECK_EQUAL(find(""), end()); +} + +BOOST_AUTO_TEST_CASE(single) +{ + insert({"a", 1}); + + BOOST_CHECK_EQUAL(size(), 1); + BOOST_CHECK(!empty()); + BOOST_CHECK_EQUAL(begin()->first, "a"); + BOOST_CHECK_EQUAL(begin()->second, 1); + BOOST_CHECK_EQUAL(find("a"), begin()); + BOOST_CHECK_EQUAL(find("b"), end()); +} + +BOOST_AUTO_TEST_CASE(several) +{ + insert({"c", 3}); + BOOST_CHECK_EQUAL(lower_bound("a"), begin()); + + insert({"a", 1}); + BOOST_CHECK_EQUAL(begin()->first, "a"); + + insert({"f", 6}); + + BOOST_CHECK_EQUAL(size(), 3); + BOOST_CHECK(!empty()); + BOOST_CHECK_EQUAL(begin()->first, "a"); + BOOST_CHECK_EQUAL(begin()->second, 1); + BOOST_CHECK_EQUAL(find("a"), begin()); + BOOST_CHECK_EQUAL(find("b"), end()); + BOOST_CHECK_NE(find("c"), end()); + BOOST_CHECK_EQUAL(find("c")->second, 3); + BOOST_CHECK_NE(find("f"), end()); + BOOST_CHECK_EQUAL(find("f")->second, 6); +} + +BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3