Discard all but last duplicate key

fix #71, close #148
This commit is contained in:
Krystian Stasiowski 2020-08-11 16:42:10 -04:00 committed by Vinnie Falco
parent 9fe41c51f0
commit 360c5a47d9
2 changed files with 54 additions and 26 deletions

View File

@ -70,36 +70,30 @@ void
object_impl::
build() noexcept
{
auto end = this->end();
for(auto p = begin(); p != end;)
// must work when table pointer is null
auto const first = begin();
for(auto last = end(); last > first;)
{
--last;
auto head = &bucket(last->key());
auto i = *head;
while(i != null_index &&
get(i).key() != last->key())
i = next(get(i));
if(i != null_index)
{
auto& head = bucket(p->key());
auto i = head;
while(i != null_index &&
get(i).key() != p->key())
i = next(get(i));
if(i == null_index)
{
next(*p) = head;
head = index_of(*p);
++p;
continue;
}
}
p->~value_type();
--tab_->size;
--end;
if(p != end)
{
// handle duplicate
last->~value_type();
std::memcpy(
static_cast<void*>(p),
static_cast<void const*>(end),
sizeof(*p));
auto& head = bucket(p->key());
next(*p) = head;
head = index_of(*p);
static_cast<void*>(last),
static_cast<void const*>(
first + tab_->size - 1),
sizeof(*last));
--tab_->size;
head = &bucket(last->key());
}
next(*last) = *head;
*head = index_of(*last);
}
}

View File

@ -984,6 +984,39 @@ R"xx({
}
}
void
testDupeKeys()
{
{
value jv = parse(R"({"a":1,"b":2,"a":3})");
object& jo = jv.as_object();
BOOST_TEST(jo.size() == 2);
BOOST_TEST(jo.at("a").as_int64() == 3);
BOOST_TEST(jo.at("b").as_int64() == 2);
}
{
value jv = parse(R"({"a":1,"a":3,"b":2})");
object& jo = jv.as_object();
BOOST_TEST(jo.size() == 2);
BOOST_TEST(jo.at("a").as_int64() == 3);
BOOST_TEST(jo.at("b").as_int64() == 2);
}
{
value jv = parse(R"({"a":1,"a":3,"b":2,"a":4})");
object& jo = jv.as_object();
BOOST_TEST(jo.size() == 2);
BOOST_TEST(jo.at("a").as_int64() == 4);
BOOST_TEST(jo.at("b").as_int64() == 2);
}
{
value jv = parse(R"({"a":1,"a":3,"b":2,"a":4,"b":5})");
object& jo = jv.as_object();
BOOST_TEST(jo.size() == 2);
BOOST_TEST(jo.at("a").as_int64() == 4);
BOOST_TEST(jo.at("b").as_int64() == 5);
}
}
//------------------------------------------------------
// https://github.com/cppalliance/json/issues/15
@ -1034,6 +1067,7 @@ R"xx({
testTrailingCommas();
testComments();
testError();
testDupeKeys();
testIssue15();
testIssue45();
}