From f64109d79a5b12f9fcb48e74d5c1740396539956 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 15 Jun 2017 08:31:47 -0700 Subject: [PATCH] Fix basic_fields insert ordering --- CHANGELOG.md | 1 + include/beast/http/impl/fields.ipp | 28 ++++++++++++---------------- test/http/fields.cpp | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a98f23b6..e5219f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Version 58: * Reorganize examples * Specification for http read * Avoid `std::string` in websocket +* Fix basic_fields insert ordering API Changes: diff --git a/include/beast/http/impl/fields.ipp b/include/beast/http/impl/fields.ipp index 7c5467a7..bde28110 100644 --- a/include/beast/http/impl/fields.ipp +++ b/include/beast/http/impl/fields.ipp @@ -480,29 +480,25 @@ insert(field name, name, sname, value.str()); auto const before = set_.upper_bound(sname, key_compare{}); - if(before == set_.end()) - { - set_.push_back(e); - list_.push_back(e); - return; - } if(before == set_.begin()) { - set_.push_front(e); - list_.push_back(e); - return; - } - auto const last = std::prev(before); - if(! beast::detail::ci_equal( - sname, last->name_string())) - { + BOOST_ASSERT(count(sname) == 0); set_.insert_before(before, e); list_.push_back(e); return; } - // count(name_string) > 0 + auto const last = std::prev(before); + // VFALCO is it worth comparing `field name` first? + if(! beast::detail::ci_equal(sname, last->name_string())) + { + BOOST_ASSERT(count(sname) == 0); + set_.insert_before(before, e); + list_.push_back(e); + return; + } + // keep duplicate fields together in the list set_.insert_before(before, e); - list_.insert(list_.iterator_to(*before), e); + list_.insert(++list_.iterator_to(*last), e); } template diff --git a/test/http/fields.cpp b/test/http/fields.cpp index 5e009400..d7f2c0e7 100644 --- a/test/http/fields.cpp +++ b/test/http/fields.cpp @@ -375,6 +375,26 @@ public: BEAST_EXPECT(std::next(f.begin(), 0)->name_string() == "a"); BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "b"); } + { + // verify insertion orde + fields f; + f.insert( "a", 1); + f.insert("dd", 2); + f.insert("b", 3); + f.insert("dD", 4); + f.insert("c", 5); + f.insert("Dd", 6); + f.insert("DD", 7); + f.insert( "e", 8); + BEAST_EXPECT(f.count("dd") == 4); + BEAST_EXPECT(std::next(f.begin(), 1)->name_string() == "dd"); + BEAST_EXPECT(std::next(f.begin(), 2)->name_string() == "dD"); + BEAST_EXPECT(std::next(f.begin(), 3)->name_string() == "Dd"); + BEAST_EXPECT(std::next(f.begin(), 4)->name_string() == "DD"); + f.set("dd", "-"); + BEAST_EXPECT(f.count("dd") == 1); + BEAST_EXPECT(f["dd"] == "-"); + } } void run() override