From df5a57673b782ab36ef8d24893d607f04514600e Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Fri, 14 Aug 2020 13:12:51 +0000 Subject: Make sure the entries in the set are unique. Make both a less and equal operator so std::unique can be used to. Add and interface so that whole sets can be tested effectively if they are subsets. --- document/src/tests/fieldsettest.cpp | 7 ++++--- document/src/vespa/document/base/field.cpp | 16 +++++++++++++--- document/src/vespa/document/base/field.h | 12 ++++++++++-- document/src/vespa/document/datatype/structdatatype.cpp | 2 +- document/src/vespa/document/fieldset/fieldsetrepo.cpp | 4 ++-- document/src/vespa/document/fieldset/fieldsets.cpp | 2 +- 6 files changed, 31 insertions(+), 12 deletions(-) (limited to 'document') diff --git a/document/src/tests/fieldsettest.cpp b/document/src/tests/fieldsettest.cpp index 8a01c53c278..29581ff4549 100644 --- a/document/src/tests/fieldsettest.cpp +++ b/document/src/tests/fieldsettest.cpp @@ -275,9 +275,10 @@ TEST(FieldCollectionTest, testHash ) { const DocumentTypeRepo& repo = testDocMan.getTypeRepo(); const DocumentType & type = *repo.getDocumentType("testdoctype1"); EXPECT_EQ(0ul, FieldCollection(type, Field::Set::Builder().build()).hash()); - EXPECT_EQ(0x548599858c77ef83ul, FieldCollection(type, Field::Set::Builder().insert(&type.getField("headerval")).build()).hash()); - EXPECT_EQ(0x4a7ff2406d36a9b0ul, FieldCollection(type, Field::Set::Builder().insert(&type.getField("headerval")).insert(&type.getField("hstringval")).build()).hash()); - EXPECT_EQ(0x1e0918531b19734ul, FieldCollection(type, Field::Set::Builder().insert(&type.getField("hstringval")).build()).hash()); + EXPECT_EQ(0x548599858c77ef83ul, FieldCollection(type, Field::Set::Builder().add(&type.getField("headerval")).build()).hash()); + EXPECT_EQ(0x4a7ff2406d36a9b0ul, FieldCollection(type, Field::Set::Builder().add(&type.getField("headerval")).add( + &type.getField("hstringval")).build()).hash()); + EXPECT_EQ(0x1e0918531b19734ul, FieldCollection(type, Field::Set::Builder().add(&type.getField("hstringval")).build()).hash()); } } // document diff --git a/document/src/vespa/document/base/field.cpp b/document/src/vespa/document/base/field.cpp index 7f1a598cd76..fb814fc5f17 100644 --- a/document/src/vespa/document/base/field.cpp +++ b/document/src/vespa/document/base/field.cpp @@ -14,15 +14,25 @@ namespace document { Field::Set::Set(std::vector fields) : _fields(std::move(fields)) { - std::sort(_fields.begin(), _fields.end(), Field::FieldPtrComparator()); + std::sort(_fields.begin(), _fields.end(), Field::FieldPtrLess()); + _fields.erase(std::unique(_fields.begin(), _fields.end(), Field::FieldPtrEqual()), _fields.end()); } bool Field::Set::contains(const Field & field) const { - return std::binary_search(_fields.begin(), _fields.end(), &field, Field::FieldPtrComparator()); + return std::binary_search(_fields.begin(), _fields.end(), &field, Field::FieldPtrLess()); } -Field::Field() : Field("", 0, *DataType::INT) { } +bool +Field::Set::contains(const Set & fields) const { + return std::includes(_fields.begin(), _fields.end(), + fields._fields.begin(), fields._fields.end(), + Field::FieldPtrLess()); +} + +Field::Field() + : Field("", 0, *DataType::INT) +{ } Field::Field(vespalib::stringref name, int fieldId, const DataType& dataType) : FieldBase(name), diff --git a/document/src/vespa/document/base/field.h b/document/src/vespa/document/base/field.h index cf876903dfa..7580b2b692f 100644 --- a/document/src/vespa/document/base/field.h +++ b/document/src/vespa/document/base/field.h @@ -32,27 +32,35 @@ public: using SP = std::shared_ptr; using CPtr = const Field *; - struct FieldPtrComparator { + struct FieldPtrLess { bool operator()(CPtr f1, CPtr f2) const { return (*f1 < *f2); } }; + struct FieldPtrEqual { + bool operator()(CPtr f1, CPtr f2) const { + return (*f1 == *f2); + } + }; + class Set { public: class Builder { public: Builder & reserve(size_t sz) { _vector.reserve(sz); return *this; } - Builder & insert(CPtr field) { _vector.emplace_back(field); return *this; } + Builder & add(CPtr field) { _vector.push_back(field); return *this; } Set build() { return Set(std::move(_vector)); } private: std::vector _vector; }; bool contains(const Field & field) const; + bool contains(const Set & field) const; size_t size() const { return _fields.size(); } bool empty() const { return _fields.empty(); } const CPtr * begin() const { return &_fields[0]; } const CPtr * end() const { return begin() + _fields.size(); } + static Set emptySet() { return Builder().build(); } private: explicit Set(std::vector fields); std::vector _fields; diff --git a/document/src/vespa/document/datatype/structdatatype.cpp b/document/src/vespa/document/datatype/structdatatype.cpp index 11af020c465..c0c63ddb37f 100644 --- a/document/src/vespa/document/datatype/structdatatype.cpp +++ b/document/src/vespa/document/datatype/structdatatype.cpp @@ -167,7 +167,7 @@ StructDataType::getFieldSet() const Field::Set::Builder builder; builder.reserve(_idFieldMap.size()); for (const auto & entry : _idFieldMap) { - builder.insert(entry.second.get()); + builder.add(entry.second.get()); } return builder.build(); } diff --git a/document/src/vespa/document/fieldset/fieldsetrepo.cpp b/document/src/vespa/document/fieldset/fieldsetrepo.cpp index 5cc3e548d82..33cbf6185c4 100644 --- a/document/src/vespa/document/fieldset/fieldsetrepo.cpp +++ b/document/src/vespa/document/fieldset/fieldsetrepo.cpp @@ -49,10 +49,10 @@ parseFieldCollection(const DocumentTypeRepo& repo, const DocumentType::FieldSet * fs = type.getFieldSet(token); if (fs) { for (const auto & fieldName : fs->getFields()) { - builder.insert(&type.getField(fieldName)); + builder.add(&type.getField(fieldName)); } } else { - builder.insert(&type.getField(token)); + builder.add(&type.getField(token)); } } return std::make_unique(type, builder.build()); diff --git a/document/src/vespa/document/fieldset/fieldsets.cpp b/document/src/vespa/document/fieldset/fieldsets.cpp index 115ad37343d..317c1743bb5 100644 --- a/document/src/vespa/document/fieldset/fieldsets.cpp +++ b/document/src/vespa/document/fieldset/fieldsets.cpp @@ -42,7 +42,7 @@ FieldCollection::contains(const FieldSet& fields) const return _set.contains(static_cast(fields)); case Type::SET: { const auto & coll = static_cast(fields); - return std::includes(_set.begin(), _set.end(), coll.getFields().begin(), coll.getFields().end(), Field::FieldPtrComparator()); + return _set.contains(coll.getFields()); } case Type::NONE: case Type::DOCID: -- cgit v1.2.3