summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2017-06-06 15:11:38 +0200
committerHenning Baldersheim <balder@yahoo-inc.com>2017-06-07 09:50:23 +0200
commitece112cf6aadbf135c92f1d5ddada739b290a118 (patch)
tree3fb49a56dcfd77e27ee335f5be1f172d3a7975c9
parent8438c19df2999aed6fd89c470c52a9c04c77dcdc (diff)
Forward declare XmlOutputStream and FieldValue::IteratorHandler.
-rw-r--r--document/src/tests/documenttestcase.cpp9
-rw-r--r--document/src/tests/fieldpathupdatetestcase.cpp9
-rw-r--r--document/src/vespa/document/fieldvalue/CMakeLists.txt2
-rw-r--r--document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp4
-rw-r--r--document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp44
-rw-r--r--document/src/vespa/document/fieldvalue/arrayfieldvalue.h16
-rw-r--r--document/src/vespa/document/fieldvalue/document.cpp3
-rw-r--r--document/src/vespa/document/fieldvalue/fieldvalue.cpp101
-rw-r--r--document/src/vespa/document/fieldvalue/fieldvalue.h127
-rw-r--r--document/src/vespa/document/fieldvalue/iteratorhandler.cpp43
-rw-r--r--document/src/vespa/document/fieldvalue/iteratorhandler.h99
-rw-r--r--document/src/vespa/document/fieldvalue/literalfieldvalue.cpp5
-rw-r--r--document/src/vespa/document/fieldvalue/mapfieldvalue.cpp50
-rw-r--r--document/src/vespa/document/fieldvalue/mapfieldvalue.h8
-rw-r--r--document/src/vespa/document/fieldvalue/modificationstatus.h13
-rw-r--r--document/src/vespa/document/fieldvalue/numericfieldvalue.cpp3
-rw-r--r--document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp2
-rw-r--r--document/src/vespa/document/fieldvalue/rawfieldvalue.cpp6
-rw-r--r--document/src/vespa/document/fieldvalue/structfieldvalue.cpp2
-rw-r--r--document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp44
-rw-r--r--document/src/vespa/document/fieldvalue/structuredfieldvalue.h4
-rw-r--r--document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp2
-rw-r--r--document/src/vespa/document/fieldvalue/variablemap.cpp59
-rw-r--r--document/src/vespa/document/fieldvalue/variablemap.h47
-rw-r--r--document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp20
-rw-r--r--document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h8
-rw-r--r--document/src/vespa/document/select/parser.h4
-rw-r--r--document/src/vespa/document/select/result.h7
-rw-r--r--document/src/vespa/document/select/resultlist.cpp32
-rw-r--r--document/src/vespa/document/select/resultlist.h12
-rw-r--r--document/src/vespa/document/select/value.cpp1
-rw-r--r--document/src/vespa/document/select/value.h3
-rw-r--r--document/src/vespa/document/select/valuenode.cpp136
-rw-r--r--document/src/vespa/document/select/valuenode.h17
-rw-r--r--document/src/vespa/document/update/addfieldpathupdate.cpp58
-rw-r--r--document/src/vespa/document/update/addfieldpathupdate.h19
-rw-r--r--document/src/vespa/document/update/addvalueupdate.cpp6
-rw-r--r--document/src/vespa/document/update/arithmeticvalueupdate.cpp2
-rw-r--r--document/src/vespa/document/update/assignfieldpathupdate.cpp83
-rw-r--r--document/src/vespa/document/update/assignfieldpathupdate.h48
-rw-r--r--document/src/vespa/document/update/assignvalueupdate.cpp4
-rw-r--r--document/src/vespa/document/update/clearvalueupdate.cpp2
-rw-r--r--document/src/vespa/document/update/documentupdate.cpp2
-rw-r--r--document/src/vespa/document/update/fieldpathupdate.cpp45
-rw-r--r--document/src/vespa/document/update/fieldpathupdate.h3
-rw-r--r--document/src/vespa/document/update/mapvalueupdate.cpp5
-rw-r--r--document/src/vespa/document/update/removefieldpathupdate.cpp32
-rw-r--r--document/src/vespa/document/update/removefieldpathupdate.h14
-rw-r--r--document/src/vespa/document/update/removevalueupdate.cpp8
-rw-r--r--document/src/vespa/document/util/xmlserializable.h12
-rw-r--r--memfilepersistence/src/vespa/memfilepersistence/device/devicemanager.cpp1
-rw-r--r--memfilepersistence/src/vespa/memfilepersistence/device/partitionmonitor.cpp7
-rw-r--r--memfilepersistence/src/vespa/memfilepersistence/memfile/shared_data_location_tracker.h1
-rw-r--r--metrics/src/tests/metricmanagertest.cpp1
-rw-r--r--metrics/src/vespa/metrics/xmlwriter.cpp12
-rw-r--r--searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp1
-rw-r--r--searchcore/src/vespa/searchcore/proton/test/userdocuments.h10
-rw-r--r--searchlib/src/tests/aggregator/perdocexpr.cpp3
-rw-r--r--searchlib/src/vespa/searchlib/expression/documentfieldnode.h5
-rw-r--r--staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp2
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt1
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/polymorphicarray.h82
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/polymorphicarraybase.h18
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/polymorphicarrays.h66
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/xmlserializable.cpp459
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/xmlserializable.h203
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/xmlstream.cpp463
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/xmlstream.h210
-rw-r--r--staging_vespalib/src/vespa/vespalib/util/xmlstream.hpp (renamed from staging_vespalib/src/vespa/vespalib/util/xmlserializable.hpp)8
-rw-r--r--storage/src/vespa/storage/bucketdb/bucketmanager.h1
-rw-r--r--storage/src/vespa/storage/bucketdb/storagebucketdbinitializer.h1
-rw-r--r--storage/src/vespa/storage/common/statusmetricconsumer.cpp9
-rw-r--r--storage/src/vespa/storage/distributor/bucketdbupdater.cpp1
-rw-r--r--storage/src/vespa/storage/distributor/bucketdbupdater.h1
-rw-r--r--storage/src/vespa/storage/distributor/pendingclusterstate.cpp2
-rw-r--r--storage/src/vespa/storage/storageserver/bucketintegritychecker.h1
-rw-r--r--storageapi/src/vespa/storageapi/buckets/bucketinfo.cpp7
-rw-r--r--storageframework/src/vespa/storageframework/generic/status/xmlstatusreporter.h2
-rw-r--r--streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp6
-rw-r--r--streamingvisitors/src/vespa/searchvisitor/searchvisitor.h9
-rw-r--r--vdslib/src/vespa/vdslib/container/parameters.cpp3
-rw-r--r--vsm/src/vespa/vsm/common/document.h1
-rw-r--r--vsm/src/vespa/vsm/searcher/fieldsearcher.h4
-rw-r--r--vsm/src/vespa/vsm/vsm/docsumfilter.cpp4
-rw-r--r--vsm/src/vespa/vsm/vsm/flattendocsumwriter.h5
-rw-r--r--vsm/src/vespa/vsm/vsm/snippetmodifier.h5
86 files changed, 1537 insertions, 1363 deletions
diff --git a/document/src/tests/documenttestcase.cpp b/document/src/tests/documenttestcase.cpp
index 3bbd5178055..a9e7b1897b2 100644
--- a/document/src/tests/documenttestcase.cpp
+++ b/document/src/tests/documenttestcase.cpp
@@ -5,6 +5,7 @@
#include <vespa/vdstestlib/cppunit/macros.h>
#include <vespa/document/datatype/annotationreferencedatatype.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/document/repo/configbuilder.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
#include <vespa/document/serialization/vespadocumentserializer.h>
@@ -19,6 +20,8 @@ using namespace document::config_builder;
namespace document {
+using namespace fieldvalue;
+
struct DocumentTest : public CppUnit::TestFixture {
void testTraversing();
void testFieldPath();
@@ -105,7 +108,7 @@ void DocumentTest::testFieldPath()
}
}
-class Handler : public FieldValue::IteratorHandler {
+class Handler : public fieldvalue::IteratorHandler {
public:
Handler();
~Handler();
@@ -185,7 +188,7 @@ void DocumentTest::testTraversing()
std::string("<P<P<PP[PPP][<PP><PP>]>>>"));
}
-class VariableIteratorHandler : public FieldValue::IteratorHandler {
+class VariableIteratorHandler : public IteratorHandler {
public:
VariableIteratorHandler();
~VariableIteratorHandler();
@@ -268,7 +271,7 @@ DocumentTest::testVariables()
}
-class ModifyIteratorHandler : public FieldValue::IteratorHandler {
+class ModifyIteratorHandler : public IteratorHandler {
public:
ModificationStatus doModify(FieldValue& fv) override {
StringFieldValue* sfv = dynamic_cast<StringFieldValue*>(&fv);
diff --git a/document/src/tests/fieldpathupdatetestcase.cpp b/document/src/tests/fieldpathupdatetestcase.cpp
index 4a23f828921..4311e1059c2 100644
--- a/document/src/tests/fieldpathupdatetestcase.cpp
+++ b/document/src/tests/fieldpathupdatetestcase.cpp
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/document/base/testdocman.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/document/select/node.h>
#include <vespa/vespalib/io/fileutil.h>
#include <vespa/vdstestlib/cppunit/macros.h>
@@ -21,6 +22,8 @@ using namespace document::config_builder;
namespace document {
+using namespace fieldvalue;
+
struct FieldPathUpdateTestCase : public CppUnit::TestFixture {
DocumentTypeRepo::SP _repo;
DocumentType _foobar_type;
@@ -259,7 +262,7 @@ void testSerialize(const DocumentTypeRepo& repo, const DocumentUpdate& a) {
struct TestFieldPathUpdate : FieldPathUpdate
{
- struct TestIteratorHandler : FieldValue::IteratorHandler
+ struct TestIteratorHandler : fieldvalue::IteratorHandler
{
TestIteratorHandler(std::string& str)
: _str(str) {}
@@ -288,9 +291,9 @@ struct TestFieldPathUpdate : FieldPathUpdate
TestFieldPathUpdate(const TestFieldPathUpdate& other);
- std::unique_ptr<FieldValue::IteratorHandler> getIteratorHandler(Document&) const override
+ std::unique_ptr<IteratorHandler> getIteratorHandler(Document&) const override
{
- return std::unique_ptr<FieldValue::IteratorHandler>(
+ return std::unique_ptr<IteratorHandler>(
new TestIteratorHandler(_str));
}
diff --git a/document/src/vespa/document/fieldvalue/CMakeLists.txt b/document/src/vespa/document/fieldvalue/CMakeLists.txt
index 8c76db54d5f..18ea4fc9368 100644
--- a/document/src/vespa/document/fieldvalue/CMakeLists.txt
+++ b/document/src/vespa/document/fieldvalue/CMakeLists.txt
@@ -10,6 +10,7 @@ vespa_add_library(document_fieldvalues OBJECT
fieldvalue.cpp
floatfieldvalue.cpp
intfieldvalue.cpp
+ iteratorhandler.cpp
literalfieldvalue.cpp
longfieldvalue.cpp
mapfieldvalue.cpp
@@ -22,6 +23,7 @@ vespa_add_library(document_fieldvalues OBJECT
structfieldvalue.cpp
structuredfieldvalue.cpp
tensorfieldvalue.cpp
+ variablemap.cpp
weightedsetfieldvalue.cpp
referencefieldvalue.cpp
DEPENDS
diff --git a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp
index 9863ee1c18a..cd6d43d2f4d 100644
--- a/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/annotationreferencefieldvalue.cpp
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "annotationreferencefieldvalue.h"
+#include <vespa/vespalib/util/xmlstream.h>
#include <ostream>
using std::ostream;
@@ -23,8 +24,7 @@ int AnnotationReferenceFieldValue::compare(const FieldValue &other) const {
return (getDataType()->getId() - other.getDataType()->getId());
}
-void AnnotationReferenceFieldValue::print(ostream &out, bool,
- const string &) const {
+void AnnotationReferenceFieldValue::print(ostream &out, bool, const string &) const {
out << "AnnotationReferenceFieldValue(n)";
}
diff --git a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
index 8c05c25e651..01df81db69b 100644
--- a/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/arrayfieldvalue.cpp
@@ -3,15 +3,23 @@
#include "intfieldvalue.h"
#include "stringfieldvalue.h"
#include "predicatefieldvalue.h"
+#include "iteratorhandler.h"
#include <vespa/document/util/serializableexceptions.h>
-#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/util/polymorphicarrays.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".document.fieldvalue.array");
+using namespace vespalib::xml;
+
namespace document {
using vespalib::IllegalArgumentException;
+using fieldvalue::IndexValue;
+using fieldvalue::ModificationStatus;
+using fieldvalue::IteratorHandler;
+using fieldvalue::VariableMap;
IMPLEMENT_IDENTIFIABLE_ABSTRACT(ArrayFieldValue, CollectionFieldValue);
@@ -24,7 +32,7 @@ ArrayFieldValue::ArrayFieldValue(const DataType &type)
"Cannot generate an array value with non-array type "
+ type.toString() + ".", VESPA_STRLOC);
}
- _array = createArray(getNestedType());
+ _array.reset(static_cast<IArray *>(createArray(getNestedType()).release()));
}
ArrayFieldValue::ArrayFieldValue(const ArrayFieldValue& other)
@@ -176,14 +184,13 @@ ArrayFieldValue::hasChanged() const
return false;
}
-FieldValue::IteratorHandler::ModificationStatus
+fieldvalue::ModificationStatus
ArrayFieldValue::iterateSubset(int startPos, int endPos,
const vespalib::stringref & variable,
PathRange nested,
- IteratorHandler& handler) const
+ fieldvalue::IteratorHandler& handler) const
{
- FieldValue::IteratorHandler::ModificationStatus
- retVal = FieldValue::IteratorHandler::NOT_MODIFIED;
+ fieldvalue::ModificationStatus retVal = ModificationStatus::NOT_MODIFIED;
LOG(spam, "iterateSubset(start=%d, end=%d, variable='%s')",
startPos, endPos, variable.c_str());
@@ -192,16 +199,15 @@ ArrayFieldValue::iterateSubset(int startPos, int endPos,
for (int i = startPos; i <= endPos && i < static_cast<int>(_array->size()); ++i) {
if (!variable.empty()) {
- handler.getVariables()[variable] = IteratorHandler::IndexValue(i);
+ handler.getVariables()[variable] = IndexValue(i);
}
- FieldValue::IteratorHandler::ModificationStatus
- status = array()[i].iterateNested(nested, handler);
+ ModificationStatus status = array()[i].iterateNested(nested, handler);
- if (status == FieldValue::IteratorHandler::REMOVED) {
+ if (status == ModificationStatus::REMOVED) {
indicesToRemove.push_back(i);
- retVal = FieldValue::IteratorHandler::MODIFIED;
- } else if (status == FieldValue::IteratorHandler::MODIFIED) {
+ retVal = ModificationStatus::MODIFIED;
+ } else if (status == ModificationStatus::MODIFIED) {
retVal = status;
}
}
@@ -219,7 +225,7 @@ ArrayFieldValue::iterateSubset(int startPos, int endPos,
return retVal;
}
-FieldValue::IteratorHandler::ModificationStatus
+fieldvalue::ModificationStatus
ArrayFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
{
IteratorHandler::CollectionScope autoScope(handler, *this);
@@ -235,7 +241,7 @@ ArrayFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) co
case FieldPathEntry::VARIABLE:
{
LOG(spam, "VARIABLE");
- IteratorHandler::VariableMap::iterator iter = handler.getVariables().find(fpe.getVariableName());
+ VariableMap::iterator iter = handler.getVariables().find(fpe.getVariableName());
if (iter != handler.getVariables().end()) {
int idx = iter->second.index;
@@ -259,17 +265,17 @@ ArrayFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) co
}
return iterateSubset(0, static_cast<int>(_array->size()) - 1, "", nested, handler);
} else {
- IteratorHandler::ModificationStatus status = handler.modify(const_cast<ArrayFieldValue&>(*this));
+ fieldvalue::ModificationStatus status = handler.modify(const_cast<ArrayFieldValue&>(*this));
- if (status == FieldValue::IteratorHandler::REMOVED) {
+ if (status == fieldvalue::REMOVED) {
return status;
}
if (handler.handleComplex(*this)) {
- if (iterateSubset(0, static_cast<int>(_array->size()) - 1, "",
- nested, handler) != FieldValue::IteratorHandler::NOT_MODIFIED)
+ if (iterateSubset(0, static_cast<int>(_array->size()) - 1, "", nested, handler)
+ != ModificationStatus::NOT_MODIFIED)
{
- status = FieldValue::IteratorHandler::MODIFIED;
+ status = ModificationStatus::MODIFIED;
}
}
diff --git a/document/src/vespa/document/fieldvalue/arrayfieldvalue.h b/document/src/vespa/document/fieldvalue/arrayfieldvalue.h
index 33e07e18588..d61acb8605c 100644
--- a/document/src/vespa/document/fieldvalue/arrayfieldvalue.h
+++ b/document/src/vespa/document/fieldvalue/arrayfieldvalue.h
@@ -14,25 +14,27 @@
#include "collectionfieldvalue.h"
#include <vespa/document/datatype/arraydatatype.h>
+#include <vespa/vespalib/util/polymorphicarray.h>
namespace document {
class ArrayFieldValue : public CollectionFieldValue {
private:
- IArray::UP _array;
+ using IArray = vespalib::IArrayT<FieldValue>;
+ std::unique_ptr<IArray> _array;
bool addValue(const FieldValue&) override;
bool containsValue(const FieldValue& val) const override;
bool removeValue(const FieldValue& val) override;
- IteratorHandler::ModificationStatus iterateSubset(
+ fieldvalue::ModificationStatus iterateSubset(
int startPos, int endPos, const vespalib::stringref & variable,
PathRange nested,
- IteratorHandler& handler) const;
- IteratorHandler::ModificationStatus onIterateNested(PathRange nested, IteratorHandler & handler) const override;
+ fieldvalue::IteratorHandler& handler) const;
+ fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const override;
public:
- typedef IArray::const_iterator const_iterator;
- typedef IArray::iterator iterator;
- typedef std::unique_ptr<ArrayFieldValue> UP;
+ using const_iterator = IArray::const_iterator;
+ using iterator = IArray::iterator;
+ using UP = std::unique_ptr<ArrayFieldValue>;
/**
* @param arrayType Type of the array. Must be an ArrayDataType, but does
diff --git a/document/src/vespa/document/fieldvalue/document.cpp b/document/src/vespa/document/fieldvalue/document.cpp
index 29f487df989..a8336519e16 100644
--- a/document/src/vespa/document/fieldvalue/document.cpp
+++ b/document/src/vespa/document/fieldvalue/document.cpp
@@ -10,13 +10,14 @@
#include <vespa/document/util/serializableexceptions.h>
#include <vespa/document/base/exceptions.h>
#include <vespa/document/util/bytebuffer.h>
-
+#include <vespa/vespalib/util/xmlstream.h>
#include <sstream>
using vespalib::nbostream;
using vespalib::make_string;
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
+using namespace vespalib::xml;
namespace document {
namespace {
diff --git a/document/src/vespa/document/fieldvalue/fieldvalue.cpp b/document/src/vespa/document/fieldvalue/fieldvalue.cpp
index 3279eb77a64..c137811514c 100644
--- a/document/src/vespa/document/fieldvalue/fieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/fieldvalue.cpp
@@ -10,17 +10,22 @@
#include "doublefieldvalue.h"
#include "bytefieldvalue.h"
#include "predicatefieldvalue.h"
+#include "iteratorhandler.h"
#include <vespa/document/util/bytebuffer.h>
#include <vespa/document/base/exceptions.h>
#include <vespa/document/serialization/vespadocumentserializer.h>
#include <vespa/vespalib/objects/nbostream.h>
+#include <vespa/vespalib/util/polymorphicarrays.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <sstream>
using vespalib::FieldBase;
using vespalib::nbostream;
-
+using namespace vespalib::xml;
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE_ABSTRACT(FieldValue, vespalib::Identifiable);
void FieldValue::serialize(nbostream &stream) const {
@@ -183,13 +188,13 @@ FieldValue::onGetNestedFieldValue(PathRange nested) const
return FieldValue::UP();
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
FieldValue::iterateNested(PathRange nested, IteratorHandler & handler) const
{
return onIterateNested(nested, handler);
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
FieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
{
if (nested.atEnd()) {
@@ -200,78 +205,6 @@ FieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
}
}
-FieldValue::IteratorHandler::~IteratorHandler() { }
-
-bool
-FieldValue::IteratorHandler::IndexValue::operator==(const FieldValue::IteratorHandler::IndexValue& other) const {
- if (key.get() != NULL) {
- if (other.key.get() != NULL && *key == *other.key) {
- return true;
- }
- return false;
- }
-
- return index == other.index;
-}
-
-FieldValue::IteratorHandler::IndexValue::IndexValue(const FieldValue& key_)
- : index(-1),
- key(FieldValue::CP(key_.clone()))
-{ }
-
-FieldValue::IteratorHandler::IndexValue::~IndexValue() { }
-
-vespalib::string
-FieldValue::IteratorHandler::IndexValue::toString() const {
- if (key.get() != NULL) {
- return key->toString();
- } else {
- return vespalib::make_string("%d", index);
- }
-}
-
-void
-FieldValue::IteratorHandler::handlePrimitive(uint32_t fid, const FieldValue & fv) {
- onPrimitive(fid, Content(fv, getWeight()));
-}
-bool
-FieldValue::IteratorHandler::handleComplex(const FieldValue & fv) {
- return onComplex(Content(fv, getWeight()));
-}
-void
-FieldValue::IteratorHandler::handleCollectionStart(const FieldValue & fv) {
- onCollectionStart(Content(fv, getWeight()));
-}
-void
-FieldValue::IteratorHandler::handleCollectionEnd(const FieldValue & fv) {
- onCollectionEnd(Content(fv, getWeight()));
-}
-void
-FieldValue::IteratorHandler::handleStructStart(const FieldValue & fv) {
- onStructStart(Content(fv, getWeight()));
-}
-void
-FieldValue::IteratorHandler::handleStructEnd(const FieldValue & fv) {
- onStructEnd(Content(fv, getWeight()));
-}
-
-void
-FieldValue::IteratorHandler::onPrimitive(uint32_t fid, const Content & fv) {
- (void) fid;
- (void) fv;
-}
-
-std::string
-FieldValue::IteratorHandler::toString(const VariableMap& vars) {
- std::ostringstream out;
- out << "[ ";
- for (const auto & entry : vars) {
- out << entry.first << "=" << entry.second.toString() << " ";
- }
- out << "]";
- return out.str();
-}
-
std::string
FieldValue::toString(bool verbose, const std::string& indent) const
{
@@ -295,26 +228,26 @@ private:
};
}
-FieldValue::IArray::UP
+std::unique_ptr<vespalib::IArrayBase>
FieldValue::createArray(const DataType & baseType)
{
switch(baseType.getId()) {
case DataType::T_INT:
- return IArray::UP(new PrimitiveArrayT<IntFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<IntFieldValue, FieldValue>>();
case DataType::T_FLOAT:
- return IArray::UP(new PrimitiveArrayT<FloatFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<FloatFieldValue, FieldValue>>();
case DataType::T_STRING:
- return IArray::UP(new PrimitiveArrayT<StringFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<StringFieldValue, FieldValue>>();
case DataType::T_RAW:
- return IArray::UP(new PrimitiveArrayT<RawFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<RawFieldValue, FieldValue>>();
case DataType::T_LONG:
- return IArray::UP(new PrimitiveArrayT<LongFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<LongFieldValue, FieldValue>>();
case DataType::T_DOUBLE:
- return IArray::UP(new PrimitiveArrayT<DoubleFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<DoubleFieldValue, FieldValue>>();
case DataType::T_BYTE:
- return IArray::UP(new PrimitiveArrayT<ByteFieldValue, FieldValue>());
+ return std::make_unique<PrimitiveArrayT<ByteFieldValue, FieldValue>>();
default:
- return IArray::UP(new ComplexArrayT<FieldValue>(FieldValueFactory::UP(new FieldValueFactory(DataType::UP(baseType.clone())))));
+ return std::make_unique<ComplexArrayT<FieldValue>>(std::make_unique<FieldValueFactory>(DataType::UP(baseType.clone())));
}
}
diff --git a/document/src/vespa/document/fieldvalue/fieldvalue.h b/document/src/vespa/document/fieldvalue/fieldvalue.h
index 998673ddf8d..a96628514c3 100644
--- a/document/src/vespa/document/fieldvalue/fieldvalue.h
+++ b/document/src/vespa/document/fieldvalue/fieldvalue.h
@@ -12,12 +12,12 @@
#pragma once
#include "fieldvaluevisitor.h"
+#include "modificationstatus.h"
#include <vespa/document/util/xmlserializable.h>
-#include <vespa/vespalib/util/polymorphicarrays.h>
+#include <vespa/document/base/fieldpath.h>
#include <vespa/vespalib/objects/cloneable.h>
#include <vespa/vespalib/objects/identifiable.h>
-#include <vespa/document/base/fieldpath.h>
-#include <map>
+#include <vespa/vespalib/util/polymorphicarraybase.h>
namespace vespalib {
class nbostream;
@@ -25,6 +25,10 @@ namespace vespalib {
namespace document {
+namespace fieldvalue {
+ class IteratorHandler;
+}
+
class ByteBuffer;
class DataType;
@@ -33,8 +37,7 @@ class FieldValue : public vespalib::Identifiable
protected:
FieldValue(const FieldValue&) = default;
FieldValue& operator=(const FieldValue&) = default;
- using IArray = vespalib::IArrayT<FieldValue>;
- static IArray::UP createArray(const DataType & baseType);
+ static std::unique_ptr<vespalib::IArrayBase> createArray(const DataType & baseType);
public:
using PathRange = FieldPath::Range<FieldPath::const_iterator>;
@@ -42,110 +45,6 @@ public:
using SP = std::shared_ptr<FieldValue>;
using CP = vespalib::CloneablePtr<FieldValue>;
- class IteratorHandler {
- public:
- class CollectionScope {
- public:
- CollectionScope(IteratorHandler& handler, const FieldValue& value)
- : _handler(handler), _value(value)
- {
- _handler.handleCollectionStart(_value);
- }
-
- ~CollectionScope() {
- _handler.handleCollectionEnd(_value);
- }
- private:
- IteratorHandler& _handler;
- const FieldValue& _value;
- };
-
- class StructScope {
- public:
- StructScope(IteratorHandler& handler, const FieldValue& value)
- : _handler(handler), _value(value)
- {
- _handler.handleStructStart(_value);
- }
-
- ~StructScope() {
- _handler.handleStructEnd(_value);
- }
- private:
- IteratorHandler& _handler;
- const FieldValue& _value;
- };
-
- class IndexValue {
- public:
- IndexValue() : index(-1), key() {}
- IndexValue(int index_) : index(index_), key() {}
- IndexValue(const FieldValue& key_);
- ~IndexValue();
-
- vespalib::string toString() const;
-
- bool operator==(const IndexValue& other) const;
-
- int index; // For array
- FieldValue::CP key; // For map/wset
- };
-
- enum ModificationStatus {
- MODIFIED,
- REMOVED,
- NOT_MODIFIED
- };
-
- typedef std::map<vespalib::string, IndexValue> VariableMap;
- protected:
- class Content {
- public:
- Content(const FieldValue & fv, int weight=1) : _fieldValue(fv), _weight(weight) { }
- int getWeight() const { return _weight; }
- const FieldValue & getValue() const { return _fieldValue; }
- private:
- const FieldValue & _fieldValue;
- int _weight;
- };
- IteratorHandler() : _weight(1) { }
- public:
- virtual ~IteratorHandler();
-
- void handlePrimitive(uint32_t fid, const FieldValue & fv);
-
- /**
- Handles a complex type (struct/array/map etc) that is at the end of the
- field path.
- @return Return true if you want to recurse into the members.
- */
- bool handleComplex(const FieldValue& fv);
- void handleCollectionStart(const FieldValue & fv);
- void handleCollectionEnd(const FieldValue & fv);
- void handleStructStart(const FieldValue & fv);
- void handleStructEnd(const FieldValue & fv);
- void setWeight(int weight) { _weight = weight; }
- ModificationStatus modify(FieldValue& fv) { return doModify(fv); }
-
- VariableMap& getVariables() { return _variables; }
- void setVariables(const VariableMap& vars) { _variables = vars; }
- static std::string toString(const VariableMap& vars);
- virtual bool createMissingPath() const { return false; }
- private:
- virtual bool onComplex(const Content& fv) { (void) fv; return true; }
- virtual void onPrimitive(uint32_t fid, const Content & fv);
- virtual void onCollectionStart(const Content & fv) { (void) fv; }
- virtual void onCollectionEnd(const Content & fv) { (void) fv; }
- virtual void onStructStart(const Content & fv) { (void) fv; }
- virtual void onStructEnd(const Content & fv) { (void) fv; }
- virtual ModificationStatus doModify(FieldValue&) { return NOT_MODIFIED; };
-
- // Scratchpad to store pass on weight.
- int getWeight() const { return _weight; }
- int _weight;
- VariableMap _variables;
- };
-
DECLARE_IDENTIFIABLE_ABSTRACT(FieldValue);
FieldValue() {}
@@ -270,9 +169,9 @@ public:
* invocations of the before mentioned methods and the additional
* onPrimitive.
*/
- IteratorHandler::ModificationStatus iterateNested(PathRange nested, IteratorHandler & handler) const;
+ fieldvalue::ModificationStatus iterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const;
- IteratorHandler::ModificationStatus iterateNested(const FieldPath& fieldPath, IteratorHandler& handler) const {
+ fieldvalue::ModificationStatus iterateNested(const FieldPath& fieldPath, fieldvalue::IteratorHandler& handler) const {
return iterateNested(fieldPath.begin(), fieldPath.end(), handler);
}
@@ -286,12 +185,12 @@ public:
virtual void printXml(XmlOutputStream& out) const = 0;
private:
- IteratorHandler::ModificationStatus
- iterateNested(FieldPath::const_iterator start, FieldPath::const_iterator end, IteratorHandler & handler) const {
+ fieldvalue::ModificationStatus
+ iterateNested(FieldPath::const_iterator start, FieldPath::const_iterator end, fieldvalue::IteratorHandler & handler) const {
return iterateNested(PathRange(start, end), handler);
}
virtual FieldValue::UP onGetNestedFieldValue(PathRange nested) const;
- virtual IteratorHandler::ModificationStatus onIterateNested(PathRange nested, IteratorHandler & handler) const;
+ virtual fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const;
};
std::ostream& operator<<(std::ostream& out, const FieldValue & p);
diff --git a/document/src/vespa/document/fieldvalue/iteratorhandler.cpp b/document/src/vespa/document/fieldvalue/iteratorhandler.cpp
new file mode 100644
index 00000000000..394979f31cb
--- /dev/null
+++ b/document/src/vespa/document/fieldvalue/iteratorhandler.cpp
@@ -0,0 +1,43 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+
+#include "iteratorhandler.h"
+
+namespace document::fieldvalue {
+
+IteratorHandler::~IteratorHandler() { }
+
+
+void
+IteratorHandler::handlePrimitive(uint32_t fid, const FieldValue & fv) {
+ onPrimitive(fid, Content(fv, getWeight()));
+}
+bool
+IteratorHandler::handleComplex(const FieldValue & fv) {
+ return onComplex(Content(fv, getWeight()));
+}
+void
+IteratorHandler::handleCollectionStart(const FieldValue & fv) {
+ onCollectionStart(Content(fv, getWeight()));
+}
+void
+IteratorHandler::handleCollectionEnd(const FieldValue & fv) {
+ onCollectionEnd(Content(fv, getWeight()));
+}
+void
+IteratorHandler::handleStructStart(const FieldValue & fv) {
+ onStructStart(Content(fv, getWeight()));
+}
+void
+IteratorHandler::handleStructEnd(const FieldValue & fv) {
+ onStructEnd(Content(fv, getWeight()));
+}
+
+void
+IteratorHandler::onPrimitive(uint32_t fid, const Content & fv) {
+ (void) fid;
+ (void) fv;
+}
+
+}
+
diff --git a/document/src/vespa/document/fieldvalue/iteratorhandler.h b/document/src/vespa/document/fieldvalue/iteratorhandler.h
new file mode 100644
index 00000000000..8dc98b2107d
--- /dev/null
+++ b/document/src/vespa/document/fieldvalue/iteratorhandler.h
@@ -0,0 +1,99 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include "variablemap.h"
+#include "modificationstatus.h"
+
+namespace document::fieldvalue {
+
+class IteratorHandler {
+public:
+ class CollectionScope {
+ public:
+ CollectionScope(IteratorHandler &handler, const FieldValue &value)
+ : _handler(handler), _value(value) {
+ _handler.handleCollectionStart(_value);
+ }
+
+ ~CollectionScope() {
+ _handler.handleCollectionEnd(_value);
+ }
+
+ private:
+ IteratorHandler &_handler;
+ const FieldValue &_value;
+ };
+
+ class StructScope {
+ public:
+ StructScope(IteratorHandler &handler, const FieldValue &value)
+ : _handler(handler), _value(value) {
+ _handler.handleStructStart(_value);
+ }
+
+ ~StructScope() {
+ _handler.handleStructEnd(_value);
+ }
+
+ private:
+ IteratorHandler &_handler;
+ const FieldValue &_value;
+ };
+
+protected:
+ class Content {
+ public:
+ Content(const FieldValue &fv, int weight = 1) : _fieldValue(fv), _weight(weight) {}
+
+ int getWeight() const { return _weight; }
+
+ const FieldValue &getValue() const { return _fieldValue; }
+
+ private:
+ const FieldValue &_fieldValue;
+ int _weight;
+ };
+
+ IteratorHandler() : _weight(1) {}
+
+public:
+ virtual ~IteratorHandler();
+ void handlePrimitive(uint32_t fid, const FieldValue &fv);
+
+ /**
+ Handles a complex type (struct/array/map etc) that is at the end of the
+ field path.
+ @return Return true if you want to recurse into the members.
+ */
+ bool handleComplex(const FieldValue &fv);
+ void handleCollectionStart(const FieldValue &fv);
+ void handleCollectionEnd(const FieldValue &fv);
+ void handleStructStart(const FieldValue &fv);
+ void handleStructEnd(const FieldValue &fv);
+ void setWeight(int weight) { _weight = weight; }
+ ModificationStatus modify(FieldValue &fv) { return doModify(fv); }
+ fieldvalue::VariableMap &getVariables() { return _variables; }
+ void setVariables(const fieldvalue::VariableMap &vars) { _variables = vars; }
+ virtual bool createMissingPath() const { return false; }
+private:
+ virtual bool onComplex(const Content &fv) {
+ (void) fv;
+ return true;
+ }
+
+ virtual void onPrimitive(uint32_t fid, const Content &fv);
+ virtual void onCollectionStart(const Content &fv) { (void) fv; }
+ virtual void onCollectionEnd(const Content &fv) { (void) fv; }
+ virtual void onStructStart(const Content &fv) { (void) fv; }
+ virtual void onStructEnd(const Content &fv) { (void) fv; }
+ virtual ModificationStatus doModify(FieldValue &) { return NOT_MODIFIED; };
+
+ // Scratchpad to store pass on weight.
+ int getWeight() const { return _weight; }
+
+ int _weight;
+ fieldvalue::VariableMap _variables;
+};
+
+}
diff --git a/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp b/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp
index 4d044219d4c..50c6c901808 100644
--- a/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/literalfieldvalue.cpp
@@ -1,9 +1,12 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/document/fieldvalue/literalfieldvalue.h>
+#include "literalfieldvalue.h"
#include <vespa/document/util/stringutil.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <sstream>
+using namespace vespalib::xml;
+
namespace document {
IMPLEMENT_IDENTIFIABLE_ABSTRACT(LiteralFieldValueB, FieldValue);
diff --git a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
index 2186ff28f60..a2bc5b97299 100644
--- a/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/mapfieldvalue.cpp
@@ -2,12 +2,15 @@
#include "mapfieldvalue.h"
#include "weightedsetfieldvalue.h"
+#include "iteratorhandler.h"
#include <vespa/document/base/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".document.fieldvalue.map");
using vespalib::Identifiable;
+using namespace vespalib::xml;
/// \todo TODO (was warning):
// Find a way to search through internal map without
@@ -15,6 +18,8 @@ using vespalib::Identifiable;
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE_ABSTRACT(MapFieldValue, FieldValue);
namespace {
@@ -31,8 +36,8 @@ const MapDataType *verifyMapType(const DataType& type) {
MapFieldValue::MapFieldValue(const DataType &mapType)
: FieldValue(),
_type(verifyMapType(mapType)),
- _keys(createArray(getMapType().getKeyType())),
- _values(createArray(getMapType().getValueType())),
+ _keys(static_cast<IArray *>(createArray(getMapType().getKeyType()).release())),
+ _values(static_cast<IArray *>(createArray(getMapType().getValueType()).release())),
_altered(true)
{
}
@@ -268,22 +273,22 @@ MapFieldValue::find(const FieldValue& key)
}
bool
MapFieldValue::checkAndRemove(const FieldValue& key,
- FieldValue::IteratorHandler::ModificationStatus status,
+ ModificationStatus status,
bool wasModified,
std::vector<const FieldValue*>& keysToRemove) const
{
- if (status == FieldValue::IteratorHandler::REMOVED) {
+ if (status == ModificationStatus::REMOVED) {
LOG(spam, "will remove: %s", key.toString().c_str());
keysToRemove.push_back(&key);
return true;
- } else if (status == FieldValue::IteratorHandler::MODIFIED) {
+ } else if (status == ModificationStatus::MODIFIED) {
return true;
}
return wasModified;
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
MapFieldValue::iterateNestedImpl(PathRange nested,
IteratorHandler & handler,
const FieldValue& complexFieldValue) const
@@ -307,10 +312,9 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
wasModified, keysToRemove);
} else if (handler.createMissingPath()) {
LOG(spam, "creating missing path");
- FieldValue::UP val =
- getMapType().getValueType().createFieldValue();
- IteratorHandler::ModificationStatus status = val->iterateNested(nested.next(), handler);
- if (status == IteratorHandler::MODIFIED) {
+ FieldValue::UP val = getMapType().getValueType().createFieldValue();
+ ModificationStatus status = val->iterateNested(nested.next(), handler);
+ if (status == ModificationStatus::MODIFIED) {
const_cast<MapFieldValue&>(*this).put(FieldValue::UP(fpe.getLookupKey()->clone()), std::move(val));
return status;
}
@@ -339,8 +343,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
case FieldPathEntry::VARIABLE:
{
LOG(spam, "VARIABLE");
- IteratorHandler::VariableMap::iterator
- iter = handler.getVariables().find(fpe.getVariableName());
+ VariableMap::iterator iter = handler.getVariables().find(fpe.getVariableName());
if (iter != handler.getVariables().end()) {
LOG(spam, "variable key = %s", iter->second.key->toString().c_str());
const_iterator found = find(*iter->second.key);
@@ -353,12 +356,9 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
PathRange next = nested.next();
for (const_iterator it(begin()), mt(end()); it != mt; it++) {
LOG(spam, "key is '%s'", it->first->toString().c_str());
- handler.getVariables()[fpe.getVariableName()]
- = IteratorHandler::IndexValue(*it->first);
- LOG(spam, "vars at this time = %s",
- FieldValue::IteratorHandler::toString(handler.getVariables()).c_str());
- wasModified = checkAndRemove(*it->first,
- it->second->iterateNested(next, handler),
+ handler.getVariables()[fpe.getVariableName()] = IndexValue(*it->first);
+ LOG(spam, "vars at this time = %s", handler.getVariables().toString().c_str());
+ wasModified = checkAndRemove(*it->first, it->second->iterateNested(next, handler),
wasModified, keysToRemove);
}
handler.getVariables().erase(fpe.getVariableName());
@@ -371,8 +371,7 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
if (isWSet) {
handler.setWeight(static_cast<const IntFieldValue &>(*it->second).getValue());
}
- wasModified = checkAndRemove(*it->first,
- it->first->iterateNested(nested, handler),
+ wasModified = checkAndRemove(*it->first, it->first->iterateNested(nested, handler),
wasModified, keysToRemove);
// Don't iterate over values
/*wasModified = checkAndRemove(*it->second,
@@ -383,13 +382,12 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
}
} else {
LOG(spam, "at end of field path");
- IteratorHandler::ModificationStatus
- status = handler.modify(const_cast<FieldValue&>(complexFieldValue));
+ ModificationStatus status = handler.modify(const_cast<FieldValue&>(complexFieldValue));
- if (status == IteratorHandler::REMOVED) {
+ if (status == ModificationStatus::REMOVED) {
LOG(spam, "status = REMOVED");
return status;
- } else if (status == IteratorHandler::MODIFIED) {
+ } else if (status == ModificationStatus::MODIFIED) {
LOG(spam, "status = MODIFIED");
wasModified = true;
}
@@ -419,10 +417,10 @@ MapFieldValue::iterateNestedImpl(PathRange nested,
LOG(spam, "erasing map entry with key %s", (*i)->toString().c_str());
const_cast<MapFieldValue&>(*this).erase(**i);
}
- return wasModified ? IteratorHandler::MODIFIED : IteratorHandler::NOT_MODIFIED;
+ return wasModified ? ModificationStatus::MODIFIED : ModificationStatus::NOT_MODIFIED;
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
MapFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
{
LOG(spam, "iterating over MapFieldValue");
diff --git a/document/src/vespa/document/fieldvalue/mapfieldvalue.h b/document/src/vespa/document/fieldvalue/mapfieldvalue.h
index 8b480cbb7f9..edc20fea777 100644
--- a/document/src/vespa/document/fieldvalue/mapfieldvalue.h
+++ b/document/src/vespa/document/fieldvalue/mapfieldvalue.h
@@ -26,10 +26,10 @@ private:
virtual bool containsValue(const FieldValue& fv) const { return contains(fv); }
virtual bool removeValue(const FieldValue& fv) { return erase(fv); }
bool checkAndRemove(const FieldValue& key,
- FieldValue::IteratorHandler::ModificationStatus status,
+ fieldvalue::ModificationStatus status,
bool wasModified,
std::vector<const FieldValue*>& keysToRemove) const;
- IteratorHandler::ModificationStatus onIterateNested(PathRange nested, IteratorHandler & handler) const override;
+ fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const override;
// Utility method to avoid constant explicit casting
const MapDataType& getMapType() const { return *_type; }
@@ -118,8 +118,8 @@ public:
void reserve(size_t sz) { _keys->reserve(sz); _values->reserve(sz); }
void resize(size_t sz) { _keys->resize(sz); _values->resize(sz); }
- IteratorHandler::ModificationStatus iterateNestedImpl(PathRange nested, IteratorHandler & handler,
- const FieldValue& complexFieldValue) const;
+ fieldvalue::ModificationStatus iterateNestedImpl(PathRange nested, fieldvalue::IteratorHandler & handler,
+ const FieldValue& complexFieldValue) const;
// FieldValue implementation
FieldValue& assign(const FieldValue&) override;
diff --git a/document/src/vespa/document/fieldvalue/modificationstatus.h b/document/src/vespa/document/fieldvalue/modificationstatus.h
new file mode 100644
index 00000000000..344a89338bb
--- /dev/null
+++ b/document/src/vespa/document/fieldvalue/modificationstatus.h
@@ -0,0 +1,13 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+namespace document::fieldvalue {
+
+enum ModificationStatus {
+ MODIFIED,
+ REMOVED,
+ NOT_MODIFIED
+};
+
+}
diff --git a/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp b/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp
index 3d39544b3d0..b897a8db930 100644
--- a/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/numericfieldvalue.cpp
@@ -1,6 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "numericfieldvalue.h"
+#include <vespa/vespalib/util/xmlstream.h>
namespace document {
@@ -9,7 +10,7 @@ IMPLEMENT_IDENTIFIABLE_ABSTRACT(NumericFieldValueBase, FieldValue);
void
NumericFieldValueBase::printXml(XmlOutputStream& out) const
{
- out << XmlContent(getAsString());
+ out << vespalib::xml::XmlContent(getAsString());
}
diff --git a/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp b/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp
index 8e963f75f5d..a3394d8fcf4 100644
--- a/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/predicatefieldvalue.cpp
@@ -6,9 +6,11 @@
#include <vespa/document/predicate/predicate_printer.h>
#include <vespa/vespalib/data/slime/inserter.h>
#include <vespa/vespalib/data/slime/slime.h>
+#include <vespa/vespalib/util/xmlstream.h>
using vespalib::Slime;
using vespalib::slime::SlimeInserter;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp b/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp
index 96701832b5e..c9950036435 100644
--- a/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/rawfieldvalue.cpp
@@ -3,6 +3,9 @@
#include "rawfieldvalue.h"
#include "literalfieldvalue.hpp"
#include <vespa/document/util/stringutil.h>
+#include <vespa/vespalib/util/xmlstream.h>
+
+using namespace vespalib::xml;
namespace document {
@@ -18,8 +21,7 @@ RawFieldValue::printXml(XmlOutputStream& out) const
void
RawFieldValue::print(std::ostream& out, bool, const std::string&) const
{
- StringUtil::printAsHex(out, _value.c_str(),
- _value.size());
+ StringUtil::printAsHex(out, _value.c_str(), _value.size());
}
} // document
diff --git a/document/src/vespa/document/fieldvalue/structfieldvalue.cpp b/document/src/vespa/document/fieldvalue/structfieldvalue.cpp
index 74805ce3f10..cdfba106c49 100644
--- a/document/src/vespa/document/fieldvalue/structfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/structfieldvalue.cpp
@@ -11,6 +11,7 @@
#include <vespa/document/util/serializableexceptions.h>
#include <vespa/document/base/exceptions.h>
#include <vespa/document/util/bytebuffer.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".document.structfieldvalue");
@@ -19,6 +20,7 @@ using std::vector;
using vespalib::nbostream;
using vespalib::nbostream_longlivedbuf;
using vespalib::make_string;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp b/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp
index 6d77d101ff2..beef80ed2b0 100644
--- a/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/structuredfieldvalue.cpp
@@ -1,13 +1,19 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "structuredfieldvalue.hpp"
-#include "fieldvalues.h"
+#include "iteratorhandler.h"
+#include "weightedsetfieldvalue.h"
+#include "arrayfieldvalue.h"
#include <vespa/log/log.h>
LOG_SETUP(".document.fieldvalue.structured");
+using vespalib::IllegalArgumentException;
+
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE_ABSTRACT(StructuredFieldValue, FieldValue);
StructuredFieldValue::Iterator::Iterator()
@@ -59,7 +65,7 @@ void StructuredFieldValue::setFieldValue(const Field & field, const FieldValue &
if (!field.getDataType().isValueType(value) &&
!value.getDataType()->isA(field.getDataType()))
{
- throw vespalib::IllegalArgumentException(
+ throw IllegalArgumentException(
"Cannot assign value of type " + value.getDataType()->toString()
+ "with value : '" + value.toString()
+ "' to field " + field.getName().c_str() + " of type "
@@ -81,7 +87,7 @@ StructuredFieldValue::onGetNestedFieldValue(PathRange nested) const
return fv;
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
StructuredFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
{
IteratorHandler::StructScope autoScope(handler, *this);
@@ -93,38 +99,36 @@ StructuredFieldValue::onIterateNested(PathRange nested, IteratorHandler & handle
LOG(spam, "fieldRef = %s", fpe.getFieldRef().toString().c_str());
LOG(spam, "fieldValueToSet = %s", fpe.getFieldValueToSet().toString().c_str());
if (exists) {
- IteratorHandler::ModificationStatus status = fpe.getFieldValueToSet().iterateNested(nested.next(), handler);
- if (status == IteratorHandler::REMOVED) {
+ ModificationStatus status = fpe.getFieldValueToSet().iterateNested(nested.next(), handler);
+ if (status == ModificationStatus::REMOVED) {
LOG(spam, "field exists, status = REMOVED");
const_cast<StructuredFieldValue&>(*this).remove(fpe.getFieldRef());
- return IteratorHandler::MODIFIED;
- } else if (status == IteratorHandler::MODIFIED) {
+ return ModificationStatus::MODIFIED;
+ } else if (status == ModificationStatus::MODIFIED) {
LOG(spam, "field exists, status = MODIFIED");
const_cast<StructuredFieldValue&>(*this).setFieldValue(fpe.getFieldRef(), fpe.getFieldValueToSet());
- return IteratorHandler::MODIFIED;
+ return ModificationStatus::MODIFIED;
} else {
LOG(spam, "field exists, status = %u", status);
return status;
}
} else if (handler.createMissingPath()) {
LOG(spam, "createMissingPath is true");
- IteratorHandler::ModificationStatus status
- = fpe.getFieldValueToSet().iterateNested(nested.next(), handler);
- if (status == IteratorHandler::MODIFIED) {
+ ModificationStatus status = fpe.getFieldValueToSet().iterateNested(nested.next(), handler);
+ if (status == ModificationStatus::MODIFIED) {
LOG(spam, "field did not exist, status = MODIFIED");
const_cast<StructuredFieldValue&>(*this).setFieldValue(fpe.getFieldRef(), fpe.getFieldValueToSet());
return status;
}
}
LOG(spam, "field did not exist, returning NOT_MODIFIED");
- return IteratorHandler::NOT_MODIFIED;
+ return ModificationStatus ::NOT_MODIFIED;
} else {
- throw vespalib::IllegalArgumentException("Illegal field path for struct value");
+ throw IllegalArgumentException("Illegal field path for struct value");
}
} else {
- IteratorHandler::ModificationStatus
- status = handler.modify(const_cast<StructuredFieldValue&>(*this));
- if (status == IteratorHandler::REMOVED) {
+ ModificationStatus status = handler.modify(const_cast<StructuredFieldValue&>(*this));
+ if (status == ModificationStatus::REMOVED) {
LOG(spam, "field REMOVED");
return status;
}
@@ -133,11 +137,11 @@ StructuredFieldValue::onIterateNested(PathRange nested, IteratorHandler & handle
LOG(spam, "handleComplex");
std::vector<const Field*> fieldsToRemove;
for (const_iterator it(begin()), mt(end()); it != mt; ++it) {
- IteratorHandler::ModificationStatus currStatus = getValue(it.field())->iterateNested(nested, handler);
- if (currStatus == IteratorHandler::REMOVED) {
+ ModificationStatus currStatus = getValue(it.field())->iterateNested(nested, handler);
+ if (currStatus == ModificationStatus::REMOVED) {
fieldsToRemove.push_back(&it.field());
- status = IteratorHandler::MODIFIED;
- } else if (currStatus == IteratorHandler::MODIFIED) {
+ status = ModificationStatus::MODIFIED;
+ } else if (currStatus == ModificationStatus::MODIFIED) {
status = currStatus;
}
}
diff --git a/document/src/vespa/document/fieldvalue/structuredfieldvalue.h b/document/src/vespa/document/fieldvalue/structuredfieldvalue.h
index 4cccbf05de0..eb5912734c5 100644
--- a/document/src/vespa/document/fieldvalue/structuredfieldvalue.h
+++ b/document/src/vespa/document/fieldvalue/structuredfieldvalue.h
@@ -92,8 +92,8 @@ protected:
virtual void setFieldValue(const Field&, FieldValue::UP value) = 0;
void setFieldValue(const Field & field, const FieldValue & value);
- IteratorHandler::ModificationStatus
- onIterateNested(PathRange nested, IteratorHandler & handler) const override;
+ fieldvalue::ModificationStatus
+ onIterateNested(PathRange nested, fieldvalue::IteratorHandler & handler) const override;
public:
DECLARE_IDENTIFIABLE_ABSTRACT(StructuredFieldValue);
diff --git a/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp b/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp
index 93ec934968d..d7d7721e833 100644
--- a/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/tensorfieldvalue.cpp
@@ -2,11 +2,13 @@
#include "tensorfieldvalue.h"
#include <vespa/document/datatype/datatype.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/eval/tensor/tensor.h>
#include <ostream>
#include <cassert>
using vespalib::tensor::Tensor;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/fieldvalue/variablemap.cpp b/document/src/vespa/document/fieldvalue/variablemap.cpp
new file mode 100644
index 00000000000..b38b5baeec2
--- /dev/null
+++ b/document/src/vespa/document/fieldvalue/variablemap.cpp
@@ -0,0 +1,59 @@
+#include "variablemap.h"
+#include "fieldvalue.h"
+#include <vespa/vespalib/util/stringfmt.h>
+#include <vespa/vespalib/stllike/asciistream.h>
+
+namespace document::fieldvalue {
+
+IndexValue::IndexValue() : index(-1), key() {}
+IndexValue::IndexValue(int index_) : index(index_), key() {}
+
+bool
+IndexValue::operator==(const IndexValue& other) const {
+ if (key.get() != NULL) {
+ if (other.key.get() != NULL && *key == *other.key) {
+ return true;
+ }
+ return false;
+ }
+
+ return index == other.index;
+}
+
+IndexValue::IndexValue(const FieldValue& key_)
+ : index(-1),
+ key(FieldValue::CP(key_.clone()))
+{ }
+
+IndexValue::IndexValue(const IndexValue & rhs) = default;
+IndexValue & IndexValue::operator = (const IndexValue & rhs) = default;
+
+IndexValue::~IndexValue() { }
+
+vespalib::string
+IndexValue::toString() const {
+ if (key.get() != NULL) {
+ return key->toString();
+ } else {
+ return vespalib::make_string("%d", index);
+ }
+}
+
+VariableMap::VariableMap() {}
+VariableMap::~VariableMap() {}
+VariableMap::VariableMap(const VariableMap & rhs) = default;
+VariableMap & VariableMap::operator = (const VariableMap & rhs) = default;
+
+vespalib::string
+VariableMap::toString() const {
+ vespalib::asciistream out;
+ out << "[ ";
+ for (const auto & entry : *this) {
+ out << entry.first << "=" << entry.second.toString() << " ";
+ }
+ out << "]";
+ return out.str();
+}
+
+}
+
diff --git a/document/src/vespa/document/fieldvalue/variablemap.h b/document/src/vespa/document/fieldvalue/variablemap.h
new file mode 100644
index 00000000000..06679682e0c
--- /dev/null
+++ b/document/src/vespa/document/fieldvalue/variablemap.h
@@ -0,0 +1,47 @@
+// Copyright 2017 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#pragma once
+
+#include <vespa/vespalib/util/memory.h>
+#include <vespa/vespalib/stllike/string.h>
+#include <map>
+
+namespace document {
+ class FieldValue;
+}
+
+namespace document::fieldvalue {
+
+class IndexValue {
+public:
+ IndexValue();
+ IndexValue(int index_);
+ IndexValue(const FieldValue& key_);
+ IndexValue(IndexValue && rhs) = default;
+ IndexValue & operator = (IndexValue && rhs) = default;
+ IndexValue(const IndexValue & rhs);
+ IndexValue & operator = (const IndexValue & rhs);
+
+ ~IndexValue();
+
+ vespalib::string toString() const;
+ bool operator==(const IndexValue& other) const;
+
+ int index; // For array
+ vespalib::CloneablePtr<FieldValue> key; // For map/wset
+};
+
+using VariableMapT = std::map<vespalib::string, IndexValue>;
+
+class VariableMap : public VariableMapT {
+public:
+ VariableMap();
+ VariableMap(VariableMap && rhs) = default;
+ VariableMap & operator = (VariableMap && rhs) = default;
+ VariableMap(const VariableMap & rhs);
+ VariableMap & operator = (const VariableMap & rhs);
+ ~VariableMap();
+ vespalib::string toString() const;
+};
+
+} \ No newline at end of file
diff --git a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp
index 7bf5f5350d3..67e0c8327e6 100644
--- a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.cpp
@@ -2,14 +2,20 @@
#include "weightedsetfieldvalue.h"
#include <vespa/document/base/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <ostream>
using vespalib::Identifiable;
+using vespalib::IllegalArgumentException;
+using vespalib::IllegalStateException;
+using namespace vespalib::xml;
/// \todo TODO (was warning): Find a way to search through internal map without duplicating keys to create shared pointers.
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE_ABSTRACT(WeightedSetFieldValue, CollectionFieldValue);
namespace {
@@ -17,9 +23,8 @@ const DataType &getKeyType(const DataType &type) {
const WeightedSetDataType *wtype =
Identifiable::cast<const WeightedSetDataType *>(&type);
if (!wtype) {
- throw vespalib::IllegalArgumentException(
- "Cannot generate a weighted set value with non-weighted set "
- "type " + type.toString() + ".", VESPA_STRLOC);
+ throw IllegalArgumentException("Cannot generate a weighted set value with non-weighted set "
+ "type " + type.toString() + ".", VESPA_STRLOC);
}
return wtype->getNestedType();
}
@@ -39,8 +44,7 @@ WeightedSetFieldValue::~WeightedSetFieldValue() { }
void WeightedSetFieldValue::verifyKey(const FieldValue & v)
{
if (!getNestedType().isValueType(v)) {
- throw InvalidDataTypeException(*v.getDataType(), getNestedType(),
- VESPA_STRLOC);
+ throw InvalidDataTypeException(*v.getDataType(), getNestedType(), VESPA_STRLOC);
}
}
@@ -92,9 +96,7 @@ WeightedSetFieldValue::increment(const FieldValue& key, int val)
}
} else {
if (it == _map.end()) {
- throw vespalib::IllegalStateException("Cannot modify non-existing "
- "entry in weightedset without createIfNonExistent set",
- VESPA_STRLOC);
+ throw IllegalStateException("Cannot modify non-existing entry in weightedset without createIfNonExistent set", VESPA_STRLOC);
}
IntFieldValue& fv = static_cast<IntFieldValue&>(*it->second);
fv.setValue(fv.getValue() + val);
@@ -203,7 +205,7 @@ WeightedSetFieldValue::find(const FieldValue& key)
return _map.find(key);
}
-FieldValue::IteratorHandler::ModificationStatus
+ModificationStatus
WeightedSetFieldValue::onIterateNested(PathRange nested, IteratorHandler & handler) const
{
return _map.iterateNestedImpl(nested, handler, *this);
diff --git a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h
index 4d6be1fd35a..5de0bf91614 100644
--- a/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h
+++ b/document/src/vespa/document/fieldvalue/weightedsetfieldvalue.h
@@ -7,9 +7,9 @@
*/
#pragma once
-#include <vespa/document/fieldvalue/collectionfieldvalue.h>
-#include <vespa/document/fieldvalue/mapfieldvalue.h>
-#include <vespa/document/fieldvalue/intfieldvalue.h>
+#include "collectionfieldvalue.h"
+#include "mapfieldvalue.h"
+#include "intfieldvalue.h"
#include <vespa/document/datatype/weightedsetdatatype.h>
#include <map>
@@ -33,7 +33,7 @@ private:
bool addValue(const FieldValue& fval) override { return add(fval, 1); }
bool containsValue(const FieldValue& val) const override;
bool removeValue(const FieldValue& val) override;
- IteratorHandler::ModificationStatus onIterateNested(PathRange nested, IteratorHandler& handler) const override;
+ fieldvalue::ModificationStatus onIterateNested(PathRange nested, fieldvalue::IteratorHandler& handler) const override;
public:
typedef std::unique_ptr<WeightedSetFieldValue> UP;
diff --git a/document/src/vespa/document/select/parser.h b/document/src/vespa/document/select/parser.h
index 61cc6e05876..b25ec951968 100644
--- a/document/src/vespa/document/select/parser.h
+++ b/document/src/vespa/document/select/parser.h
@@ -2,10 +2,8 @@
#pragma once
-#include <memory>
-#include <string>
-#include <vespa/document/bucket/bucketidfactory.h>
#include "node.h"
+#include <vespa/document/bucket/bucketidfactory.h>
#include <vespa/vespalib/util/exception.h>
#include <vespa/vespalib/util/sync.h>
diff --git a/document/src/vespa/document/select/result.h b/document/src/vespa/document/select/result.h
index 02d8d61700d..ace3f5f717e 100644
--- a/document/src/vespa/document/select/result.h
+++ b/document/src/vespa/document/select/result.h
@@ -21,8 +21,7 @@
#include <vespa/document/util/printable.h>
-namespace document {
-namespace select {
+namespace document::select {
class Result : public Printable {
public:
@@ -69,6 +68,4 @@ private:
Result& operator=(const Result&) = delete;
};
-} // select
-} // document
-
+}
diff --git a/document/src/vespa/document/select/resultlist.cpp b/document/src/vespa/document/select/resultlist.cpp
index f8224b7a158..2cde06fa2f2 100644
--- a/document/src/vespa/document/select/resultlist.cpp
+++ b/document/src/vespa/document/select/resultlist.cpp
@@ -15,8 +15,7 @@ ResultList::ResultList(const Result& result) {
}
void
-ResultList::add(const FieldValue::IteratorHandler::VariableMap& variables,
- const Result& result)
+ResultList::add(const fieldvalue::VariableMap& variables, const Result& result)
{
_results.push_back(ResultPair(variables, &result));
}
@@ -27,8 +26,7 @@ ResultList::print(std::ostream& out, bool, const std::string&) const
out << "ResultList(";
for (uint32_t i = 0; i < _results.size(); i++) {
if (!_results[i].first.empty()) {
- out << FieldValue::IteratorHandler::toString(_results[i].first)
- << " => ";
+ out << _results[i].first.toString() << " => ";
}
out << _results[i].second->toString() << " ";
}
@@ -66,15 +64,12 @@ ResultList::combineResults() const {
bool
ResultList::combineVariables(
- FieldValue::IteratorHandler::VariableMap& output,
- const FieldValue::IteratorHandler::VariableMap& input) const
+ fieldvalue::VariableMap& output,
+ const fieldvalue::VariableMap& input) const
{
// First, verify that all variables are overlapping
- for (FieldValue::IteratorHandler::VariableMap::const_iterator iter
- = output.begin(); iter != output.end(); iter++)
- {
- FieldValue::IteratorHandler::VariableMap::const_iterator found(
- input.find(iter->first));
+ for (fieldvalue::VariableMap::const_iterator iter = output.begin(); iter != output.end(); iter++) {
+ fieldvalue::VariableMap::const_iterator found(input.find(iter->first));
if (found != input.end()) {
if (!(found->second == iter->second)) {
@@ -83,11 +78,8 @@ ResultList::combineVariables(
}
}
- for (FieldValue::IteratorHandler::VariableMap::const_iterator iter
- = input.begin(); iter != input.end(); iter++)
- {
- FieldValue::IteratorHandler::VariableMap::const_iterator found(
- output.find(iter->first));
+ for (fieldvalue::VariableMap::const_iterator iter = input.begin(); iter != input.end(); iter++) {
+ fieldvalue::VariableMap::const_iterator found(output.find(iter->first));
if (found != output.end()) {
if (!(found->second == iter->second)) {
return false;
@@ -95,9 +87,7 @@ ResultList::combineVariables(
}
}
// Ok, variables are overlapping. Add all variables from input to output.
- for (FieldValue::IteratorHandler::VariableMap::const_iterator iter
- = input.begin(); iter != input.end(); iter++)
- {
+ for (fieldvalue::VariableMap::const_iterator iter = input.begin(); iter != input.end(); iter++) {
output[iter->first] = iter->second;
}
@@ -112,7 +102,7 @@ ResultList::operator&&(const ResultList& other) const
// TODO: optimize
for (const auto & it : _results) {
for (const auto & it2 : other._results) {
- FieldValue::IteratorHandler::VariableMap vars = it.first;
+ fieldvalue::VariableMap vars = it.first;
if (combineVariables(vars, it2.first)) {
result.add(vars, *it.second && *it2.second);
@@ -131,7 +121,7 @@ ResultList::operator||(const ResultList& other) const
// TODO: optimize
for (const auto & it : _results) {
for (const auto & it2 : other._results) {
- FieldValue::IteratorHandler::VariableMap vars = it.first;
+ fieldvalue::VariableMap vars = it.first;
if (combineVariables(vars, it2.first)) {
result.add(vars, *it.second || *it2.second);
diff --git a/document/src/vespa/document/select/resultlist.h b/document/src/vespa/document/select/resultlist.h
index 6a3cc1f78d1..a00419d9196 100644
--- a/document/src/vespa/document/select/resultlist.h
+++ b/document/src/vespa/document/select/resultlist.h
@@ -1,16 +1,15 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
-#include <vector>
-#include <vespa/document/fieldvalue/fieldvalue.h>
#include "result.h"
+#include <vector>
+#include <vespa/document/fieldvalue/variablemap.h>
-namespace document {
-namespace select {
+namespace document::select {
class ResultList : public Printable {
public:
- typedef FieldValue::IteratorHandler::VariableMap VariableMap;
+ using VariableMap = fieldvalue::VariableMap;
typedef std::pair<VariableMap, const Result*> ResultPair;
typedef std::vector<ResultPair> Results;
typedef Results::iterator iterator;
@@ -49,7 +48,7 @@ public:
private:
Results _results;
- bool combineVariables(VariableMap& output, const FieldValue::IteratorHandler::VariableMap& input) const;
+ bool combineVariables(VariableMap& output, const VariableMap& input) const;
};
inline bool operator==(const ResultList& list, const Result& other) {
@@ -61,5 +60,4 @@ inline bool operator!=(const ResultList& list, const Result& other) {
}
}
-}
diff --git a/document/src/vespa/document/select/value.cpp b/document/src/vespa/document/select/value.cpp
index 7a453fe5cf3..3540935f8c7 100644
--- a/document/src/vespa/document/select/value.cpp
+++ b/document/src/vespa/document/select/value.cpp
@@ -2,6 +2,7 @@
#include "value.h"
#include "operator.h"
+#include <vespa/document/fieldvalue/fieldvalue.h>
namespace document {
namespace select {
diff --git a/document/src/vespa/document/select/value.h b/document/src/vespa/document/select/value.h
index 15856648985..b26e959ea1d 100644
--- a/document/src/vespa/document/select/value.h
+++ b/document/src/vespa/document/select/value.h
@@ -1,4 +1,5 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
/**
* @class document::select::Value
* @ingroup select
@@ -190,7 +191,7 @@ inline ResultList FloatValue::operator==(const FloatValue& value) const
class ArrayValue : public Value
{
public:
- typedef std::pair<FieldValue::IteratorHandler::VariableMap, Value::SP> VariableValue;
+ using VariableValue = std::pair<fieldvalue::VariableMap, Value::SP>;
ArrayValue(const std::vector<VariableValue>& values);
diff --git a/document/src/vespa/document/select/valuenode.cpp b/document/src/vespa/document/select/valuenode.cpp
index 96bc46bd54e..f463c0e3288 100644
--- a/document/src/vespa/document/select/valuenode.cpp
+++ b/document/src/vespa/document/select/valuenode.cpp
@@ -4,6 +4,7 @@
#include "parser.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/document/datatype/documenttype.h>
#include <vespa/vespalib/util/md5.h>
#include <vespa/document/util/stringutil.h>
@@ -16,6 +17,7 @@
LOG_SETUP(".document.select.valuenode");
namespace document {
+
namespace select {
namespace {
@@ -157,7 +159,6 @@ VariableValueNode::getValue(const Context& context) const {
return context.getValue(_value);
}
-
void
VariableValueNode::visit(Visitor &visitor) const
{
@@ -216,82 +217,48 @@ FieldValueNode::extractFieldName(const std::string & fieldExpression) {
throw ParsingFailedException("Fatal: could not extract field name from field expression '" + fieldExpression + "'");
}
-void
-FieldValueNode::initFieldPath(const DocumentType& type) const {
- if (_fieldPath.size() == 0) {
- FieldPath::UP path(type.buildFieldPath(_fieldExpression));
- if (!path.get()) {
- throw FieldNotFoundException(
- vespalib::make_string("Could not create field path for doc type: '%s' field: '%s'",
- type.toString().c_str(), _fieldExpression.c_str()),
- VESPA_STRLOC);
- }
- _fieldPath = *path;
- }
-}
-
-std::unique_ptr<Value>
-FieldValueNode::getValue(const Context& context) const
-{
- if (context._doc == NULL) {
- return std::unique_ptr<Value>(new InvalidValue());
- }
-
- const Document& doc = *context._doc;
-
- if (!documentTypeEqualsName(doc.getType(), _doctype)) {
- return std::unique_ptr<Value>(new InvalidValue());
- }
- try{
- initFieldPath(doc.getType());
+namespace {
- IteratorHandler handler;
- doc.iterateNested(_fieldPath.getFullRange(), handler);
+class IteratorHandler : public fieldvalue::IteratorHandler {
+public:
+ IteratorHandler();
+ ~IteratorHandler();
+ bool hasSingleValue() const;
+ std::unique_ptr<Value> getSingleValue();
+ const std::vector<ArrayValue::VariableValue> &getValues();
- if (handler.hasSingleValue()) {
- return handler.getSingleValue();
- } else {
- const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
+private:
+ std::unique_ptr<Value> _firstValue;
+ std::vector<ArrayValue::VariableValue> _values;
- if (values.size() == 0) {
- return std::unique_ptr<Value>(new NullValue());
- } else {
- return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
- }
- }
- } catch (vespalib::IllegalArgumentException& e) {
- LOG(warning, "Caught exception while fetching field from document: %s", e.what());
- return std::unique_ptr<Value>(new InvalidValue());
- } catch (FieldNotFoundException& e) {
- LOG(warning, "Tried to compare to field %s, not found in document type", _fieldExpression.c_str());
- return std::unique_ptr<Value>(new InvalidValue());
- }
-}
+ void onPrimitive(uint32_t fid, const Content &fv) override;
+ std::unique_ptr<Value> getInternalValue(const FieldValue &fval) const;
+};
-FieldValueNode::IteratorHandler::IteratorHandler() { }
-FieldValueNode::IteratorHandler::~IteratorHandler() { }
+IteratorHandler::IteratorHandler() { }
+IteratorHandler::~IteratorHandler() { }
bool
-FieldValueNode::IteratorHandler::hasSingleValue() const {
+IteratorHandler::hasSingleValue() const {
return _firstValue.get() && (_values.size() == 0);
}
std::unique_ptr<Value>
-FieldValueNode::IteratorHandler::getSingleValue() {
+IteratorHandler::getSingleValue() {
return std::move(_firstValue);
}
const std::vector<ArrayValue::VariableValue>&
-FieldValueNode::IteratorHandler::getValues() {
+IteratorHandler::getValues() {
if (_firstValue.get()) {
- _values.insert(_values.begin(), ArrayValue::VariableValue(FieldValue::IteratorHandler::VariableMap(), Value::SP(_firstValue.release())));
+ _values.insert(_values.begin(), ArrayValue::VariableValue(fieldvalue::VariableMap(), Value::SP(_firstValue.release())));
}
return _values;
}
void
-FieldValueNode::IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) {
+IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) {
(void) fid;
if (!_firstValue && getVariables().empty()) {
_firstValue = getInternalValue(fv.getValue());
@@ -301,7 +268,7 @@ FieldValueNode::IteratorHandler::onPrimitive(uint32_t fid, const Content& fv) {
}
std::unique_ptr<Value>
-FieldValueNode::IteratorHandler::getInternalValue(const FieldValue& fval) const
+IteratorHandler::getInternalValue(const FieldValue& fval) const
{
switch(fval.getClass().id()) {
case document::IntFieldValue::classId:
@@ -372,10 +339,63 @@ FieldValueNode::IteratorHandler::getInternalValue(const FieldValue& fval) const
}
}
LOG(warning, "Tried to use unsupported datatype %s in field comparison",
- fval.getDataType()->toString().c_str());
+ fval.getDataType()->toString().c_str());
return std::make_unique<InvalidValue>();
}
+}
+
+void
+FieldValueNode::initFieldPath(const DocumentType& type) const {
+ if (_fieldPath.size() == 0) {
+ FieldPath::UP path(type.buildFieldPath(_fieldExpression));
+ if (!path.get()) {
+ throw FieldNotFoundException(
+ vespalib::make_string("Could not create field path for doc type: '%s' field: '%s'",
+ type.toString().c_str(), _fieldExpression.c_str()),
+ VESPA_STRLOC);
+ }
+ _fieldPath = *path;
+ }
+}
+
+std::unique_ptr<Value>
+FieldValueNode::getValue(const Context& context) const
+{
+ if (context._doc == NULL) {
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+
+ const Document& doc = *context._doc;
+
+ if (!documentTypeEqualsName(doc.getType(), _doctype)) {
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+ try{
+ initFieldPath(doc.getType());
+
+ IteratorHandler handler;
+ doc.iterateNested(_fieldPath.getFullRange(), handler);
+
+ if (handler.hasSingleValue()) {
+ return handler.getSingleValue();
+ } else {
+ const std::vector<ArrayValue::VariableValue>& values = handler.getValues();
+
+ if (values.size() == 0) {
+ return std::unique_ptr<Value>(new NullValue());
+ } else {
+ return std::unique_ptr<Value>(new ArrayValue(handler.getValues()));
+ }
+ }
+ } catch (vespalib::IllegalArgumentException& e) {
+ LOG(warning, "Caught exception while fetching field from document: %s", e.what());
+ return std::unique_ptr<Value>(new InvalidValue());
+ } catch (FieldNotFoundException& e) {
+ LOG(warning, "Tried to compare to field %s, not found in document type", _fieldExpression.c_str());
+ return std::unique_ptr<Value>(new InvalidValue());
+ }
+}
void
FieldValueNode::visit(Visitor &visitor) const
diff --git a/document/src/vespa/document/select/valuenode.h b/document/src/vespa/document/select/valuenode.h
index d56b1468508..8aae23cb1e4 100644
--- a/document/src/vespa/document/select/valuenode.h
+++ b/document/src/vespa/document/select/valuenode.h
@@ -228,23 +228,6 @@ public:
static vespalib::string extractFieldName(const std::string & fieldExpression);
private:
- class IteratorHandler : public FieldValue::IteratorHandler
- {
- public:
- IteratorHandler();
- ~IteratorHandler();
- bool hasSingleValue() const;
-
- std::unique_ptr<Value> getSingleValue();
- const std::vector<ArrayValue::VariableValue>& getValues();
-
- private:
- std::unique_ptr<Value> _firstValue;
- std::vector<ArrayValue::VariableValue> _values;
-
- void onPrimitive(uint32_t fid, const Content & fv) override;
- std::unique_ptr<Value> getInternalValue(const FieldValue& fval) const;
- };
void initFieldPath(const DocumentType&) const;
};
diff --git a/document/src/vespa/document/update/addfieldpathupdate.cpp b/document/src/vespa/document/update/addfieldpathupdate.cpp
index 03a31d882f3..656ee4580a0 100644
--- a/document/src/vespa/document/update/addfieldpathupdate.cpp
+++ b/document/src/vespa/document/update/addfieldpathupdate.cpp
@@ -1,8 +1,8 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "addfieldpathupdate.h"
-#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/select/parser.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
+#include <vespa/document/fieldvalue/arrayfieldvalue.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/util/exceptions.h>
@@ -14,14 +14,13 @@ LOG_SETUP(".document.update.fieldpathupdate");
namespace document {
+using namespace fieldvalue;
+using vespalib::make_string;
+
IMPLEMENT_IDENTIFIABLE(AddFieldPathUpdate, FieldPathUpdate);
-AddFieldPathUpdate::AddFieldPathUpdate(
- const DocumentTypeRepo& repo,
- const DataType& type,
- stringref fieldPath,
- stringref whereClause,
- const ArrayFieldValue& values)
+AddFieldPathUpdate::AddFieldPathUpdate(const DocumentTypeRepo& repo, const DataType& type,
+ stringref fieldPath, stringref whereClause, const ArrayFieldValue& values)
: FieldPathUpdate(repo, type, fieldPath, whereClause),
_values(vespalib::CloneablePtr<ArrayFieldValue>(values.clone()))
{
@@ -39,22 +38,34 @@ AddFieldPathUpdate::clone() const {
return new AddFieldPathUpdate(*this);
}
-FieldValue::IteratorHandler::ModificationStatus
-AddFieldPathUpdate::AddIteratorHandler::doModify(FieldValue& fv)
-{
+namespace {
+
+class AddIteratorHandler : public fieldvalue::IteratorHandler {
+public:
+ AddIteratorHandler(const ArrayFieldValue &values) : _values(values) {}
+ fieldvalue::ModificationStatus doModify(FieldValue &fv) override;
+ bool createMissingPath() const override { return true; }
+ bool onComplex(const fieldvalue::IteratorHandler::Content &) override { return false; }
+private:
+ const ArrayFieldValue &_values;
+};
+
+
+ModificationStatus
+AddIteratorHandler::doModify(FieldValue &fv) {
LOG(spam, "Adding values to %s", fv.toString().c_str());
if (fv.inherits(CollectionFieldValue::classId)) {
- CollectionFieldValue& cf = static_cast<CollectionFieldValue&>(fv);
+ CollectionFieldValue &cf = static_cast<CollectionFieldValue &>(fv);
for (std::size_t i = 0; i < _values.size(); ++i) {
cf.add(_values[i]);
}
} else {
- vespalib::string err = vespalib::make_string(
- "Unable to add a value to a \"%s\" field value.",
- fv.getClass().name());
- throw vespalib::IllegalArgumentException(err, VESPA_STRLOC);
+ vespalib::string err = make_string("Unable to add a value to a \"%s\" field value.", fv.getClass().name());
+ throw vespalib::IllegalArgumentException(err, VESPA_STRLOC);
}
- return MODIFIED;
+ return ModificationStatus::MODIFIED;
+}
+
}
bool
@@ -68,8 +79,7 @@ AddFieldPathUpdate::operator==(const FieldPathUpdate& other) const
}
void
-AddFieldPathUpdate::print(std::ostream& out, bool verbose,
- const std::string& indent) const
+AddFieldPathUpdate::print(std::ostream& out, bool verbose, const std::string& indent) const
{
out << "AddFieldPathUpdate(\n";
FieldPathUpdate::print(out, verbose, indent + " ");
@@ -79,8 +89,7 @@ AddFieldPathUpdate::print(std::ostream& out, bool verbose,
}
void
-AddFieldPathUpdate::deserialize(const DocumentTypeRepo& repo,
- const DataType& type,
+AddFieldPathUpdate::deserialize(const DocumentTypeRepo& repo, const DataType& type,
ByteBuffer& buffer, uint16_t version)
{
FieldPathUpdate::deserialize(repo, type, buffer, version);
@@ -95,4 +104,11 @@ AddFieldPathUpdate::deserialize(const DocumentTypeRepo& repo,
buffer.incPos(buffer.getRemaining() - stream.size());
}
+std::unique_ptr<IteratorHandler>
+AddFieldPathUpdate::getIteratorHandler(Document&) const {
+ return std::make_unique<AddIteratorHandler>(*_values);
+}
+
+
+
} // ns document
diff --git a/document/src/vespa/document/update/addfieldpathupdate.h b/document/src/vespa/document/update/addfieldpathupdate.h
index 6d75ebc4209..94156156257 100644
--- a/document/src/vespa/document/update/addfieldpathupdate.h
+++ b/document/src/vespa/document/update/addfieldpathupdate.h
@@ -10,7 +10,6 @@ class AddFieldPathUpdate : public FieldPathUpdate
public:
/** For deserialization */
AddFieldPathUpdate();
-
AddFieldPathUpdate(const DocumentTypeRepo& repo, const DataType& type, stringref fieldPath,
stringref whereClause, const ArrayFieldValue& values);
~AddFieldPathUpdate();
@@ -18,7 +17,6 @@ public:
FieldPathUpdate* clone() const override;
bool operator==(const FieldPathUpdate& other) const override;
void print(std::ostream& out, bool verbose, const std::string& indent) const override;
-
const ArrayFieldValue & getValues() const { return *_values; }
DECLARE_IDENTIFIABLE(AddFieldPathUpdate);
@@ -29,22 +27,7 @@ private:
void deserialize(const DocumentTypeRepo& repo, const DataType& type,
ByteBuffer& buffer, uint16_t version) override;
- class AddIteratorHandler : public FieldValue::IteratorHandler
- {
- public:
- AddIteratorHandler(const ArrayFieldValue& values) : _values(values) { }
-
- ModificationStatus doModify(FieldValue& fv) override;
- bool createMissingPath() const override { return true; }
- bool onComplex(const Content&) override { return false; }
- private:
- const ArrayFieldValue& _values;
- };
-
- std::unique_ptr<FieldValue::IteratorHandler> getIteratorHandler(Document&) const override {
- return std::unique_ptr<FieldValue::IteratorHandler>(
- new AddIteratorHandler(*_values));
- }
+ std::unique_ptr<fieldvalue::IteratorHandler> getIteratorHandler(Document&) const override;
vespalib::CloneablePtr<ArrayFieldValue> _values;
};
diff --git a/document/src/vespa/document/update/addvalueupdate.cpp b/document/src/vespa/document/update/addvalueupdate.cpp
index 910e3d7dd50..b1142836fc2 100644
--- a/document/src/vespa/document/update/addvalueupdate.cpp
+++ b/document/src/vespa/document/update/addvalueupdate.cpp
@@ -2,17 +2,17 @@
#include "addvalueupdate.h"
#include <vespa/document/base/field.h>
#include <vespa/document/datatype/arraydatatype.h>
-#include <vespa/document/datatype/weightedsetdatatype.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/repo/fixedtyperepo.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
-#include <vespa/document/util/serializable.h>
#include <vespa/document/util/serializableexceptions.h>
#include <vespa/vespalib/objects/nbostream.h>
+#include <vespa/vespalib/util/xmlstream.h>
+
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
using vespalib::nbostream;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/update/arithmeticvalueupdate.cpp b/document/src/vespa/document/update/arithmeticvalueupdate.cpp
index 29c24e7140f..a8fe541d0fe 100644
--- a/document/src/vespa/document/update/arithmeticvalueupdate.cpp
+++ b/document/src/vespa/document/update/arithmeticvalueupdate.cpp
@@ -3,9 +3,11 @@
#include <vespa/document/base/field.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
#include <vespa/vespalib/util/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
+using namespace vespalib::xml;
namespace document
{
diff --git a/document/src/vespa/document/update/assignfieldpathupdate.cpp b/document/src/vespa/document/update/assignfieldpathupdate.cpp
index 4b8ee510576..3d67a589ea5 100644
--- a/document/src/vespa/document/update/assignfieldpathupdate.cpp
+++ b/document/src/vespa/document/update/assignfieldpathupdate.cpp
@@ -2,6 +2,7 @@
#include "assignfieldpathupdate.h"
#include <vespa/document/fieldvalue/fieldvalues.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/document/select/parser.h>
#include <vespa/document/select/variablemap.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
@@ -16,6 +17,8 @@ using vespalib::nbostream;
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE(AssignFieldPathUpdate, FieldPathUpdate);
AssignFieldPathUpdate::AssignFieldPathUpdate()
@@ -69,24 +72,56 @@ FieldPathUpdate*
AssignFieldPathUpdate::clone() const {
return new AssignFieldPathUpdate(*this);
}
+namespace {
-std::unique_ptr<FieldValue::IteratorHandler>
-AssignFieldPathUpdate::getIteratorHandler(Document& doc) const
+class AssignValueIteratorHandler : public IteratorHandler
{
- if (!_expression.empty()) {
- return std::unique_ptr<FieldValue::IteratorHandler>(
- new AssignExpressionIteratorHandler(
- *_repo, doc, _expression, _removeIfZero, _createMissingPath));
- } else {
- return std::unique_ptr<FieldValue::IteratorHandler>(
- new AssignValueIteratorHandler(
- *_newValue, _removeIfZero, _createMissingPath));
- }
-}
-
-
-FieldValue::IteratorHandler::ModificationStatus
-AssignFieldPathUpdate::AssignValueIteratorHandler::doModify(FieldValue& fv) {
+public:
+ AssignValueIteratorHandler(const FieldValue& newValue,
+ bool removeIfZero,
+ bool createMissingPath_)
+ : _newValue(newValue), _removeIfZero(removeIfZero),
+ _createMissingPath(createMissingPath_)
+ {}
+
+ ModificationStatus doModify(FieldValue& fv) override;
+ bool onComplex(const Content&) override { return false; }
+ bool createMissingPath() const override { return _createMissingPath; }
+
+private:
+ const FieldValue& _newValue;
+ bool _removeIfZero;
+ bool _createMissingPath;
+};
+
+class AssignExpressionIteratorHandler : public IteratorHandler
+{
+public:
+ AssignExpressionIteratorHandler(
+ const DocumentTypeRepo& repo,
+ Document& doc,
+ const vespalib::string& expression,
+ bool removeIfZero,
+ bool createMissingPath_)
+ : _calc(repo, expression),
+ _doc(doc),
+ _removeIfZero(removeIfZero),
+ _createMissingPath(createMissingPath_)
+ {}
+
+ ModificationStatus doModify(FieldValue& fv) override;
+ bool onComplex(const Content&) override { return false; }
+ bool createMissingPath() const override { return _createMissingPath; }
+
+private:
+ DocumentCalculator _calc;
+ Document& _doc;
+ bool _removeIfZero;
+ bool _createMissingPath;
+};
+
+ModificationStatus
+AssignValueIteratorHandler::doModify(FieldValue& fv) {
LOG(spam, "fv = %s", fv.toString().c_str());
if (!(*fv.getDataType() == *_newValue.getDataType())) {
std::string err = vespalib::make_string(
@@ -105,8 +140,8 @@ AssignFieldPathUpdate::AssignValueIteratorHandler::doModify(FieldValue& fv) {
return MODIFIED;
}
-FieldValue::IteratorHandler::ModificationStatus
-AssignFieldPathUpdate::AssignExpressionIteratorHandler::doModify(FieldValue& fv) {
+ModificationStatus
+AssignExpressionIteratorHandler::doModify(FieldValue& fv) {
LOG(spam, "fv = %s", fv.toString().c_str());
if (fv.inherits(NumericFieldValueBase::classId)) {
std::unique_ptr<select::VariableMap> varHolder = std::make_unique<select::VariableMap>();
@@ -146,6 +181,18 @@ AssignFieldPathUpdate::AssignExpressionIteratorHandler::doModify(FieldValue& fv)
return MODIFIED;
}
+}
+
+std::unique_ptr<IteratorHandler>
+AssignFieldPathUpdate::getIteratorHandler(Document& doc) const
+{
+ if (!_expression.empty()) {
+ return std::make_unique<AssignExpressionIteratorHandler>(*_repo, doc, _expression, _removeIfZero, _createMissingPath);
+ } else {
+ return std::make_unique<AssignValueIteratorHandler>(*_newValue, _removeIfZero, _createMissingPath);
+ }
+}
+
bool
AssignFieldPathUpdate::operator==(const FieldPathUpdate& other) const
{
diff --git a/document/src/vespa/document/update/assignfieldpathupdate.h b/document/src/vespa/document/update/assignfieldpathupdate.h
index 81853246e54..3794cb331ce 100644
--- a/document/src/vespa/document/update/assignfieldpathupdate.h
+++ b/document/src/vespa/document/update/assignfieldpathupdate.h
@@ -58,53 +58,7 @@ private:
void deserialize(const DocumentTypeRepo& repo, const DataType& type,
ByteBuffer& buffer, uint16_t version) override;
- class AssignValueIteratorHandler : public FieldValue::IteratorHandler
- {
- public:
- AssignValueIteratorHandler(const FieldValue& newValue,
- bool removeIfZero,
- bool createMissingPath_)
- : _newValue(newValue), _removeIfZero(removeIfZero),
- _createMissingPath(createMissingPath_)
- {}
-
- ModificationStatus doModify(FieldValue& fv) override;
- bool onComplex(const Content&) override { return false; }
- bool createMissingPath() const override { return _createMissingPath; }
-
- private:
- const FieldValue& _newValue;
- bool _removeIfZero;
- bool _createMissingPath;
- };
-
- class AssignExpressionIteratorHandler : public FieldValue::IteratorHandler
- {
- public:
- AssignExpressionIteratorHandler(
- const DocumentTypeRepo& repo,
- Document& doc,
- const vespalib::string& expression,
- bool removeIfZero,
- bool createMissingPath_)
- : _calc(repo, expression),
- _doc(doc),
- _removeIfZero(removeIfZero),
- _createMissingPath(createMissingPath_)
- {}
-
- ModificationStatus doModify(FieldValue& fv) override;
- bool onComplex(const Content&) override { return false; }
- bool createMissingPath() const override { return _createMissingPath; }
-
- private:
- DocumentCalculator _calc;
- Document& _doc;
- bool _removeIfZero;
- bool _createMissingPath;
- };
-
- std::unique_ptr<FieldValue::IteratorHandler> getIteratorHandler(Document& doc) const override;
+ std::unique_ptr<fieldvalue::IteratorHandler> getIteratorHandler(Document& doc) const override;
const DocumentTypeRepo *_repo;
FieldValue::CP _newValue;
diff --git a/document/src/vespa/document/update/assignvalueupdate.cpp b/document/src/vespa/document/update/assignvalueupdate.cpp
index 0538bec10e5..63609ed18c1 100644
--- a/document/src/vespa/document/update/assignvalueupdate.cpp
+++ b/document/src/vespa/document/update/assignvalueupdate.cpp
@@ -3,14 +3,16 @@
#include "assignvalueupdate.h"
#include <vespa/document/base/field.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/repo/fixedtyperepo.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/util/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
+
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
using vespalib::nbostream;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/update/clearvalueupdate.cpp b/document/src/vespa/document/update/clearvalueupdate.cpp
index cb526852299..f34987ccfeb 100644
--- a/document/src/vespa/document/update/clearvalueupdate.cpp
+++ b/document/src/vespa/document/update/clearvalueupdate.cpp
@@ -4,10 +4,12 @@
#include <vespa/document/base/field.h>
#include <vespa/document/fieldvalue/document.h>
#include <vespa/vespalib/util/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <ostream>
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/update/documentupdate.cpp b/document/src/vespa/document/update/documentupdate.cpp
index d91b33650d4..43fe6c28dc8 100644
--- a/document/src/vespa/document/update/documentupdate.cpp
+++ b/document/src/vespa/document/update/documentupdate.cpp
@@ -9,12 +9,14 @@
#include <vespa/document/util/bufferexceptions.h>
#include <vespa/document/base/exceptions.h>
#include <vespa/document/datatype/documenttype.h>
+#include <vespa/vespalib/util/xmlstream.h>
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
using vespalib::nbostream;
using vespalib::make_string;
using vespalib::string;
+using namespace vespalib::xml;
namespace document {
diff --git a/document/src/vespa/document/update/fieldpathupdate.cpp b/document/src/vespa/document/update/fieldpathupdate.cpp
index a4145a9b58a..37672ac0b1d 100644
--- a/document/src/vespa/document/update/fieldpathupdate.cpp
+++ b/document/src/vespa/document/update/fieldpathupdate.cpp
@@ -1,14 +1,20 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/document/fieldvalue/fieldvalues.h>
+#include "fieldpathupdates.h"
+#include <vespa/document/fieldvalue/document.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/document/select/parser.h>
-#include <vespa/document/update/fieldpathupdates.h>
#include <vespa/document/util/serializableexceptions.h>
#include <vespa/log/log.h>
LOG_SETUP(".document.update.fieldpathupdate");
+using vespalib::make_string;
+using vespalib::IllegalArgumentException;
+
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE_ABSTRACT(FieldPathUpdate, Identifiable);
namespace {
@@ -43,9 +49,9 @@ FieldPathUpdate::FieldPathUpdate(const DocumentTypeRepo& repo,
: std::unique_ptr<select::Node>())
{
if (!_fieldPath.get()) {
- throw vespalib::IllegalArgumentException(
- vespalib::make_string("Could not create field path update for: path='%s', where='%s'",
- fieldPath.c_str(), whereClause.c_str()), VESPA_STRLOC);
+ throw IllegalArgumentException(
+ make_string("Could not create field path update for: path='%s', where='%s'",
+ fieldPath.c_str(), whereClause.c_str()), VESPA_STRLOC);
}
}
@@ -61,7 +67,7 @@ FieldPathUpdate::operator==(const FieldPathUpdate& other) const
void
FieldPathUpdate::applyTo(Document& doc) const
{
- std::unique_ptr<FieldValue::IteratorHandler> handler(getIteratorHandler(doc));
+ std::unique_ptr<IteratorHandler> handler(getIteratorHandler(doc));
if (!_whereClause) {
doc.iterateNested(*_fieldPath, *handler);
@@ -70,7 +76,7 @@ FieldPathUpdate::applyTo(Document& doc) const
for (select::ResultList::const_iterator i = results.begin();
i != results.end(); ++i)
{
- LOG(spam, "vars = %s", FieldValue::IteratorHandler::toString(handler->getVariables()).c_str());
+ LOG(spam, "vars = %s", handler->getVariables().toString().c_str());
if (*i->second == select::Result::True) {
handler->setVariables(i->first);
doc.iterateNested(*_fieldPath, *handler);
@@ -88,8 +94,7 @@ FieldPathUpdate::affectsDocumentBody() const
}
void
-FieldPathUpdate::print(std::ostream& out, bool,
- const std::string& indent) const
+FieldPathUpdate::print(std::ostream& out, bool, const std::string& indent) const
{
out << indent << "fieldPath='" << _originalFieldPath << "',\n"
<< indent << "whereClause='" << _originalWhereClause << "'";
@@ -99,10 +104,10 @@ void
FieldPathUpdate::checkCompatibility(const FieldValue& fv) const
{
if ( !getResultingDataType().isValueType(fv)) {
- throw vespalib::IllegalArgumentException(
- vespalib::make_string("Cannot update a '%s' field with a '%s' value",
- getResultingDataType().toString().c_str(),
- fv.getDataType()->toString().c_str()),
+ throw IllegalArgumentException(
+ make_string("Cannot update a '%s' field with a '%s' value",
+ getResultingDataType().toString().c_str(),
+ fv.getDataType()->toString().c_str()),
VESPA_STRLOC);
}
}
@@ -111,8 +116,7 @@ const DataType&
FieldPathUpdate::getResultingDataType() const
{
if (_fieldPath->empty()) {
- throw vespalib::IllegalStateException("Cannot get resulting data "
- "type from an empty field path", VESPA_STRLOC);
+ throw vespalib::IllegalStateException("Cannot get resulting data type from an empty field path", VESPA_STRLOC);
}
return _fieldPath->rbegin()->getDataType();
}
@@ -138,9 +142,7 @@ FieldPathUpdate::deserialize(const DocumentTypeRepo& repo,
try {
_fieldPath = type.buildFieldPath(_originalFieldPath).release();
if (!_fieldPath.get()) {
- throw DeserializeException(
- vespalib::make_string("Invalid field path: '%s'", _originalFieldPath.c_str()),
- VESPA_STRLOC);
+ throw DeserializeException(make_string("Invalid field path: '%s'", _originalFieldPath.c_str()), VESPA_STRLOC);
}
_whereClause = !_originalWhereClause.empty()
? parseDocumentSelection(_originalWhereClause, repo)
@@ -159,8 +161,7 @@ FieldPathUpdate::createInstance(const DocumentTypeRepo& repo,
buffer.getByte(updateType);
std::unique_ptr<FieldPathUpdate> update;
- switch (updateType)
- {
+ switch (updateType) {
case 0:
update.reset(new AssignFieldPathUpdate());
break;
@@ -171,9 +172,7 @@ FieldPathUpdate::createInstance(const DocumentTypeRepo& repo,
update.reset(new AddFieldPathUpdate());
break;
default:
- throw DeserializeException(
- vespalib::make_string("Unknown fieldpath update type: %d", updateType),
- VESPA_STRLOC);
+ throw DeserializeException(make_string("Unknown fieldpath update type: %d", updateType), VESPA_STRLOC);
}
update->deserialize(repo, type, buffer, serializationVersion);
return update;
diff --git a/document/src/vespa/document/update/fieldpathupdate.h b/document/src/vespa/document/update/fieldpathupdate.h
index 80a63d62281..0eaff9485bf 100644
--- a/document/src/vespa/document/update/fieldpathupdate.h
+++ b/document/src/vespa/document/update/fieldpathupdate.h
@@ -104,8 +104,7 @@ protected:
enum SerializedMagic {AssignMagic=0, RemoveMagic=1, AddMagic=2};
private:
// TODO: rename to createIteratorHandler?
- virtual std::unique_ptr<FieldValue::IteratorHandler> getIteratorHandler(
- Document& doc) const = 0;
+ virtual std::unique_ptr<fieldvalue::IteratorHandler> getIteratorHandler(Document& doc) const = 0;
vespalib::string _originalFieldPath;
vespalib::string _originalWhereClause;
diff --git a/document/src/vespa/document/update/mapvalueupdate.cpp b/document/src/vespa/document/update/mapvalueupdate.cpp
index 0a92fa7fb15..37d775bb204 100644
--- a/document/src/vespa/document/update/mapvalueupdate.cpp
+++ b/document/src/vespa/document/update/mapvalueupdate.cpp
@@ -5,13 +5,14 @@
#include <vespa/document/serialization/vespadocumentdeserializer.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/document/util/serializableexceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
using vespalib::nbostream;
+using namespace vespalib::xml;
-namespace document
-{
+namespace document {
IMPLEMENT_IDENTIFIABLE(MapValueUpdate, ValueUpdate);
diff --git a/document/src/vespa/document/update/removefieldpathupdate.cpp b/document/src/vespa/document/update/removefieldpathupdate.cpp
index 6c9d60abd2f..4af867995d9 100644
--- a/document/src/vespa/document/update/removefieldpathupdate.cpp
+++ b/document/src/vespa/document/update/removefieldpathupdate.cpp
@@ -1,11 +1,13 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "removefieldpathupdate.h"
-#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/select/parser.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
+#include <ostream>
namespace document {
+using namespace fieldvalue;
+
IMPLEMENT_IDENTIFIABLE(RemoveFieldPathUpdate, FieldPathUpdate);
RemoveFieldPathUpdate::RemoveFieldPathUpdate()
@@ -30,8 +32,7 @@ RemoveFieldPathUpdate::operator==(const FieldPathUpdate& other) const
}
void
-RemoveFieldPathUpdate::print(std::ostream& out, bool verbose,
- const std::string& indent) const
+RemoveFieldPathUpdate::print(std::ostream& out, bool verbose, const std::string& indent) const
{
out << "RemoveFieldPathUpdate(\n";
FieldPathUpdate::print(out, verbose, indent + " ");
@@ -39,11 +40,28 @@ RemoveFieldPathUpdate::print(std::ostream& out, bool verbose,
}
void
-RemoveFieldPathUpdate::deserialize(
- const DocumentTypeRepo& repo, const DataType& type,
- ByteBuffer& buffer, uint16_t version)
+RemoveFieldPathUpdate::deserialize(const DocumentTypeRepo& repo, const DataType& type,
+ ByteBuffer& buffer, uint16_t version)
{
FieldPathUpdate::deserialize(repo, type, buffer, version);
}
+namespace {
+
+class RemoveIteratorHandler : public IteratorHandler {
+public:
+ RemoveIteratorHandler() {}
+
+ ModificationStatus doModify(FieldValue &) override {
+ return ModificationStatus::REMOVED;
+ }
+};
+
+}
+
+std::unique_ptr<IteratorHandler>
+RemoveFieldPathUpdate::getIteratorHandler(Document&) const {
+ return std::make_unique<RemoveIteratorHandler>();
+}
+
} // ns document
diff --git a/document/src/vespa/document/update/removefieldpathupdate.h b/document/src/vespa/document/update/removefieldpathupdate.h
index 6de2a105cbf..1a3865fe761 100644
--- a/document/src/vespa/document/update/removefieldpathupdate.h
+++ b/document/src/vespa/document/update/removefieldpathupdate.h
@@ -29,19 +29,7 @@ private:
void deserialize(const DocumentTypeRepo& repo, const DataType& type,
ByteBuffer& buffer, uint16_t version) override;
- class RemoveIteratorHandler : public FieldValue::IteratorHandler
- {
- public:
- RemoveIteratorHandler() {}
-
- ModificationStatus doModify(FieldValue&) override {
- return REMOVED;
- }
- };
-
- std::unique_ptr<FieldValue::IteratorHandler> getIteratorHandler(Document&) const override {
- return std::make_unique<RemoveIteratorHandler>();
- }
+ std::unique_ptr<fieldvalue::IteratorHandler> getIteratorHandler(Document&) const override;
};
diff --git a/document/src/vespa/document/update/removevalueupdate.cpp b/document/src/vespa/document/update/removevalueupdate.cpp
index e0575f600da..34af57edbe8 100644
--- a/document/src/vespa/document/update/removevalueupdate.cpp
+++ b/document/src/vespa/document/update/removevalueupdate.cpp
@@ -1,20 +1,20 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include "removevalueupdate.h"
#include <vespa/document/base/field.h>
#include <vespa/document/datatype/arraydatatype.h>
#include <vespa/document/datatype/weightedsetdatatype.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
-#include <vespa/document/repo/fixedtyperepo.h>
#include <vespa/document/serialization/vespadocumentdeserializer.h>
-#include <vespa/document/update/removevalueupdate.h>
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/document/util/serializableexceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
using vespalib::IllegalArgumentException;
using vespalib::IllegalStateException;
using vespalib::nbostream;
+using namespace vespalib::xml;
-namespace document
-{
+namespace document {
IMPLEMENT_IDENTIFIABLE(RemoveValueUpdate, ValueUpdate);
diff --git a/document/src/vespa/document/util/xmlserializable.h b/document/src/vespa/document/util/xmlserializable.h
index 21e0b858dec..f74761a04f6 100644
--- a/document/src/vespa/document/util/xmlserializable.h
+++ b/document/src/vespa/document/util/xmlserializable.h
@@ -5,14 +5,6 @@
#include <vespa/vespalib/util/xmlserializable.h>
namespace document {
- typedef vespalib::xml::XmlOutputStream XmlOutputStream;
- typedef vespalib::xml::XmlSerializable XmlSerializable;
- typedef vespalib::xml::XmlTag XmlTag;
- typedef vespalib::xml::XmlEndTag XmlEndTag;
- typedef vespalib::xml::XmlAttribute XmlAttribute;
- typedef vespalib::xml::XmlContent XmlContent;
- typedef vespalib::xml::XmlEscapedContent XmlEscapedContent;
- typedef vespalib::xml::XmlBase64Content XmlBase64Content;
- typedef vespalib::xml::XmlContentWrapper XmlContentWrapper;
+ using XmlSerializable = vespalib::xml::XmlSerializable;
+ using XmlOutputStream = vespalib::xml::XmlOutputStream;
}
-
diff --git a/memfilepersistence/src/vespa/memfilepersistence/device/devicemanager.cpp b/memfilepersistence/src/vespa/memfilepersistence/device/devicemanager.cpp
index 2ae27f06671..ba249df2b73 100644
--- a/memfilepersistence/src/vespa/memfilepersistence/device/devicemanager.cpp
+++ b/memfilepersistence/src/vespa/memfilepersistence/device/devicemanager.cpp
@@ -2,6 +2,7 @@
#include "devicemanager.h"
#include <vespa/vespalib/util/exceptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
namespace storage::memfile {
diff --git a/memfilepersistence/src/vespa/memfilepersistence/device/partitionmonitor.cpp b/memfilepersistence/src/vespa/memfilepersistence/device/partitionmonitor.cpp
index b5b94d29336..b0cbe4fdbf7 100644
--- a/memfilepersistence/src/vespa/memfilepersistence/device/partitionmonitor.cpp
+++ b/memfilepersistence/src/vespa/memfilepersistence/device/partitionmonitor.cpp
@@ -3,13 +3,12 @@
#include "partitionmonitor.h"
#include <vespa/vespalib/util/exceptions.h>
#include <vespa/vespalib/stllike/asciistream.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".persistence.device.partition.monitor");
-namespace storage {
-
-namespace memfile {
+namespace storage::memfile {
namespace {
@@ -387,5 +386,3 @@ PartitionMonitor::overrideRealStat(uint32_t blockSize, uint32_t totalBlocks,
}
}
-
-} // storage
diff --git a/memfilepersistence/src/vespa/memfilepersistence/memfile/shared_data_location_tracker.h b/memfilepersistence/src/vespa/memfilepersistence/memfile/shared_data_location_tracker.h
index e0b1a7b9a2a..42d3fb0b238 100644
--- a/memfilepersistence/src/vespa/memfilepersistence/memfile/shared_data_location_tracker.h
+++ b/memfilepersistence/src/vespa/memfilepersistence/memfile/shared_data_location_tracker.h
@@ -2,6 +2,7 @@
#pragma once
#include <vespa/memfilepersistence/common/types.h>
+#include <map>
namespace storage {
namespace memfile {
diff --git a/metrics/src/tests/metricmanagertest.cpp b/metrics/src/tests/metricmanagertest.cpp
index 0ba6bdfbd2f..e4a2761cd73 100644
--- a/metrics/src/tests/metricmanagertest.cpp
+++ b/metrics/src/tests/metricmanagertest.cpp
@@ -9,6 +9,7 @@
#include <vespa/vdstestlib/cppunit/macros.h>
#include <vespa/vespalib/stllike/asciistream.h>
#include <vespa/vespalib/data/slime/slime.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".test.metricmanager");
diff --git a/metrics/src/vespa/metrics/xmlwriter.cpp b/metrics/src/vespa/metrics/xmlwriter.cpp
index 66f83cdd4bf..4a998b79294 100644
--- a/metrics/src/vespa/metrics/xmlwriter.cpp
+++ b/metrics/src/vespa/metrics/xmlwriter.cpp
@@ -1,11 +1,11 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/metrics/xmlwriter.h>
-
-#include <vespa/metrics/countmetric.h>
-#include <vespa/metrics/metricset.h>
-#include <vespa/metrics/metricsnapshot.h>
-#include <vespa/metrics/valuemetric.h>
+#include "xmlwriter.h"
+#include "countmetric.h"
+#include "metricset.h"
+#include "metricsnapshot.h"
+#include "valuemetric.h"
+#include <vespa/vespalib/util/xmlstream.h>
#include <sstream>
namespace metrics {
diff --git a/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp b/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp
index 95c6d39c51a..0fdfb09ecef 100644
--- a/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp
+++ b/searchcore/src/apps/vespa-transactionlog-inspect/vespa-transactionlog-inspect.cpp
@@ -8,6 +8,7 @@
#include <vespa/searchlib/transactionlog/translogclient.h>
#include <vespa/searchlib/transactionlog/translogserver.h>
#include <vespa/vespalib/util/programoptions.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/document/config/config-documenttypes.h>
#include <iostream>
#include <vespa/config/helper/configgetter.hpp>
diff --git a/searchcore/src/vespa/searchcore/proton/test/userdocuments.h b/searchcore/src/vespa/searchcore/proton/test/userdocuments.h
index d1ea6f6ab4c..6b5a911352b 100644
--- a/searchcore/src/vespa/searchcore/proton/test/userdocuments.h
+++ b/searchcore/src/vespa/searchcore/proton/test/userdocuments.h
@@ -2,10 +2,9 @@
#pragma once
#include "bucketdocuments.h"
+#include <map>
-namespace proton {
-
-namespace test {
+namespace proton::test {
/**
* Collection of documents for a set of users,
@@ -48,7 +47,4 @@ public:
void clear() { _docs.clear(); }
};
-} // namespace test
-
-} // namespace proton
-
+}
diff --git a/searchlib/src/tests/aggregator/perdocexpr.cpp b/searchlib/src/tests/aggregator/perdocexpr.cpp
index 6f374f1bea4..512252fd732 100644
--- a/searchlib/src/tests/aggregator/perdocexpr.cpp
+++ b/searchlib/src/tests/aggregator/perdocexpr.cpp
@@ -5,14 +5,13 @@
#include <vespa/searchlib/attribute/extendableattributes.h>
#include <vespa/vespalib/objects/objectdumper.h>
#include <vespa/vespalib/testkit/testapp.h>
-#include <stdexcept>
#include <vespa/document/base/testdocman.h>
#include <vespa/vespalib/util/md5.h>
-#include <vespa/vespalib/util/stringfmt.h>
#include <vespa/searchlib/expression/getdocidnamespacespecificfunctionnode.h>
#include <vespa/searchlib/expression/documentfieldnode.h>
#include <cmath>
#include <iostream>
+#include <list>
#define MU std::make_unique
diff --git a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
index a6c027beb22..2a202fe562e 100644
--- a/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
+++ b/searchlib/src/vespa/searchlib/expression/documentfieldnode.h
@@ -4,6 +4,7 @@
#include "documentaccessornode.h"
#include "resultnode.h"
#include "resultvector.h"
+#include <vespa/document/fieldvalue/iteratorhandler.h>
namespace search {
namespace expression {
@@ -38,11 +39,9 @@ public:
DocumentFieldNode & operator = (const DocumentFieldNode & rhs);
const vespalib::string & getFieldName() const override { return _fieldName; }
private:
- class Handler : public document::FieldValue::IteratorHandler {
+ class Handler : public document::fieldvalue::IteratorHandler {
public:
virtual void reset() = 0;
- protected:
- typedef document::FieldValue::IteratorHandler::Content Content;
private:
void onCollectionStart(const Content & c) override;
void onStructStart(const Content & c) override;
diff --git a/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp b/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp
index 90fcdb8f94f..4af70f7e6fe 100644
--- a/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp
+++ b/staging_vespalib/src/tests/xmlserializable/xmlserializabletest.cpp
@@ -1,7 +1,7 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/testapp.h>
-#include <vespa/vespalib/util/xmlserializable.h>
+#include <vespa/vespalib/util/xmlstream.h>
namespace vespalib {
diff --git a/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt b/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
index ca440428e0a..3b36b863707 100644
--- a/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
+++ b/staging_vespalib/src/vespa/vespalib/util/CMakeLists.txt
@@ -18,5 +18,6 @@ vespa_add_library(staging_vespalib_vespalib_util OBJECT
shutdownguard.cpp
timer.cpp
xmlserializable.cpp
+ xmlstream.cpp
DEPENDS
)
diff --git a/staging_vespalib/src/vespa/vespalib/util/polymorphicarray.h b/staging_vespalib/src/vespa/vespalib/util/polymorphicarray.h
new file mode 100644
index 00000000000..6c4d8e37311
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/polymorphicarray.h
@@ -0,0 +1,82 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+//
+#pragma once
+
+#include "polymorphicarraybase.h"
+
+namespace vespalib {
+
+/**
+ * Describes an interface an array of polymorphic types.
+ * The intention is to allow efficient implementations when that is possible
+ * while still enjoying the flexibility of the polymorph interface.
+ * It is not a full feldged Array implementation as std::vector. It contains just
+ * the minimum required to allow for efficient implementations for document::ArrayFieldValue.
+ *
+ * You specify the base type the interface shall provide. This base type must define
+ * virtual void assign(const B & rhs);
+ * For use with ComplexArrayT your type also need
+ * virtual T * clone() const;
+ */
+template<typename B>
+class IArrayT : public IArrayBase {
+public:
+ class iterator {
+ public:
+ iterator(IArrayT &a, size_t i) : _a(&a), _i(i) {}
+ iterator operator+(size_t diff) const { return iterator(*_a, _i + diff); }
+ iterator &operator++() {
+ ++_i;
+ return *this;
+ }
+ iterator operator++(int) {
+ iterator other(*this);
+ ++_i;
+ return other;
+ }
+ bool operator==(const iterator &other) const { return (_a == other._a) && (_i == other._i); }
+ bool operator!=(const iterator &other) const { return (_i != other._i) || (_a != other._a); }
+ B &operator*() { return (*_a)[_i]; }
+ B *operator->() { return &(*_a)[_i]; }
+ friend ssize_t operator-(const iterator &a, const iterator &b) { return a._i - b._i; }
+ private:
+ IArrayT *_a;
+ size_t _i;
+ };
+
+ class const_iterator {
+ public:
+ const_iterator(const IArrayT &a, size_t i) : _a(&a), _i(i) {}
+ const_iterator operator+(size_t diff) const { return const_iterator(*_a, _i + diff); }
+ const_iterator &operator++() {
+ ++_i;
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator other(*this);
+ ++_i;
+ return other;
+ }
+ bool operator==(const const_iterator &other) const { return (_a == other._a) && (_i == other._i); }
+ bool operator!=(const const_iterator &other) const { return (_i != other._i) || (_a != other._a); }
+ const B &operator*() const { return (*_a)[_i]; }
+ const B *operator->() const { return &(*_a)[_i]; }
+ size_t operator-(const const_iterator &b) const { return _i - b._i; }
+ private:
+ const IArrayT *_a;
+ size_t _i;
+ };
+
+ typedef std::unique_ptr<IArrayT> UP;
+ virtual const B &operator[](size_t i) const = 0;
+ virtual B &operator[](size_t i) = 0;
+ virtual IArrayT *clone() const override = 0;
+ virtual iterator erase(iterator it) = 0;
+ virtual const_iterator begin() const { return const_iterator(*this, 0); }
+ virtual const_iterator end() const { return const_iterator(*this, size()); }
+ virtual iterator begin() { return iterator(*this, 0); }
+ virtual iterator end() { return iterator(*this, size()); }
+ virtual void push_back(const B &v) = 0;
+};
+
+}
diff --git a/staging_vespalib/src/vespa/vespalib/util/polymorphicarraybase.h b/staging_vespalib/src/vespa/vespalib/util/polymorphicarraybase.h
new file mode 100644
index 00000000000..0fccd6cabb7
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/polymorphicarraybase.h
@@ -0,0 +1,18 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+//
+#pragma once
+
+namespace vespalib {
+
+class IArrayBase {
+public:
+ virtual ~IArrayBase() {}
+ virtual void resize(size_t sz) = 0;
+ virtual void reserve(size_t sz) = 0;
+ virtual void clear() = 0;
+ virtual IArrayBase *clone() const = 0;
+ virtual size_t size() const = 0;
+ bool empty() const { return size() == 0; }
+};
+
+}
diff --git a/staging_vespalib/src/vespa/vespalib/util/polymorphicarrays.h b/staging_vespalib/src/vespa/vespalib/util/polymorphicarrays.h
index 98c9d271ea2..646ca522ba3 100644
--- a/staging_vespalib/src/vespa/vespalib/util/polymorphicarrays.h
+++ b/staging_vespalib/src/vespa/vespalib/util/polymorphicarrays.h
@@ -2,76 +2,12 @@
//
#pragma once
+#include "polymorphicarray.h"
#include <vespa/vespalib/util/memory.h>
#include <vector>
namespace vespalib {
-/**
- * Describes an interface an array of polymorphic types.
- * The intention is to allow efficient implementations when that is possible
- * while still enjoying the flexibility of the polymorph interface.
- * It is not a full feldged Array implementation as std::vector. It contains just
- * the minimum required to allow for efficient implementations for document::ArrayFieldValue.
- *
- * You specify the base type the interface shall provide. This base type must define
- * virtual void assign(const B & rhs);
- * For use with ComplexArrayT your type also need
- * virtual T * clone() const;
- */
-template<typename B>
-class IArrayT
-{
-public:
- class iterator {
- public:
- iterator(IArrayT & a, size_t i) : _a(&a), _i(i) { }
- iterator operator+(size_t diff) const { return iterator(*_a, _i + diff); }
- iterator& operator++() { ++_i; return *this; }
- iterator operator++(int) { iterator other(*this); ++_i; return other; }
- bool operator==(const iterator & other) const { return (_a == other._a) && (_i == other._i); }
- bool operator!=(const iterator & other) const { return (_i != other._i) || (_a != other._a); }
- B & operator*() { return (*_a)[_i]; }
- B * operator->() { return &(*_a)[_i]; }
- friend ssize_t operator - (const iterator & a, const iterator & b) { return a._i - b._i; }
- private:
- IArrayT * _a;
- size_t _i;
- };
- class const_iterator {
- public:
- const_iterator(const IArrayT & a, size_t i) : _a(&a), _i(i) { }
- const_iterator operator+(size_t diff) const { return const_iterator(*_a, _i + diff); }
- const_iterator& operator++() { ++_i; return *this; }
- const_iterator operator++(int) { const_iterator other(*this); ++_i; return other; }
- bool operator==(const const_iterator & other) const { return (_a == other._a) && (_i == other._i); }
- bool operator!=(const const_iterator & other) const { return (_i != other._i) || (_a != other._a); }
- const B & operator*() const { return (*_a)[_i]; }
- const B * operator->() const { return &(*_a)[_i]; }
- size_t operator - (const const_iterator & b) const { return _i - b._i; }
- private:
- const IArrayT * _a;
- size_t _i;
- };
- typedef std::unique_ptr<IArrayT> UP;
-
- virtual ~IArrayT() { }
- virtual const B & operator [] (size_t i) const = 0;
- virtual B & operator [] (size_t i) = 0;
- virtual void resize(size_t sz) = 0;
- virtual void reserve(size_t sz) = 0;
- virtual void clear() = 0;
- virtual IArrayT * clone() const = 0;
- virtual size_t size() const = 0;
- virtual iterator erase(iterator it) = 0;
- virtual const_iterator begin() const { return const_iterator(*this, 0); }
- virtual const_iterator end() const { return const_iterator(*this, size()); }
- virtual iterator begin() { return iterator(*this, 0); }
- virtual iterator end() { return iterator(*this, size()); }
- bool empty() const { return size() == 0; }
- virtual void push_back(const B & v) = 0;
-};
-
template <typename T, typename B>
class PrimitiveArrayT : public IArrayT<B>
{
diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.cpp b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.cpp
index 043cddc3259..357b3d94992 100644
--- a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.cpp
+++ b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.cpp
@@ -1,449 +1,12 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include "xmlserializable.hpp"
-#include <vespa/vespalib/encoding/base64.h>
-#include <vespa/vespalib/stllike/asciistream.h>
-#include <vespa/vespalib/util/stringfmt.h>
-#include <cassert>
+#include "xmlserializable.h"
+#include "xmlstream.h"
+#include <sstream>
namespace vespalib {
namespace xml {
-namespace {
-
- std::vector<bool> getLegalIdentifierFirstCharacters() {
- std::vector<bool> vec(256, false);
- for (uint32_t i='a'; i<='z'; ++i) vec[i] = true;
- for (uint32_t i='A'; i<='Z'; ++i) vec[i] = true;
- vec[':'] = true;
- vec['_'] = true;
- return vec;
- }
-
- std::vector<bool> getLegalIdentifierCharacters() {
- std::vector<bool> vec(getLegalIdentifierFirstCharacters());
- vec['-'] = true;
- vec['.'] = true;
- for (uint32_t i='0'; i<='9'; ++i) {
- vec[i] = true;
- }
- return vec;
- }
-
- std::vector<bool> getBinaryCharacters() {
- std::vector<bool> vec(256, false);
- for (uint32_t i=0; i<32; ++i) {
- vec[i] = true;
- }
- vec['\t'] = false;
- vec['\n'] = false;
- vec['\r'] = false;
- vec['\f'] = false;
- return vec;
- }
-
- std::vector<bool> getEscapedXmlCharacters() {
- std::vector<bool> vec(256, false);
- for (uint32_t i=0; i<32; ++i) {
- vec[i] = true;
- }
- vec['\n'] = false;
- vec['<'] = true;
- vec['>'] = true;
- vec['&'] = true;
- return vec;
- }
-
- std::vector<bool> legalIdentifierFirstChar(
- getLegalIdentifierFirstCharacters());
- std::vector<bool> legalIdentifierChars = getLegalIdentifierCharacters();
- std::vector<bool> binaryChars = getBinaryCharacters();
- std::vector<bool> escapedXmlChars = getEscapedXmlCharacters();
-
- bool containsBinaryCharacters(const std::string& s) {
- for (int i=0, n=s.size(); i<n; ++i) {
- if (binaryChars[static_cast<uint8_t>(s[i])]) return true;
- }
- return false;
- }
-
- const std::string xmlAttributeEscape(const std::string& s) {
- vespalib::asciistream ost;
- for (uint32_t i=0, n=s.size(); i<n; ++i) {
- if (s[i] == '"' || s[i] == '\n'
- || escapedXmlChars[static_cast<uint8_t>(s[i])])
- {
- if (s[i] == '<') ost << "&lt;";
- else if (s[i] == '>') ost << "&gt;";
- else if (s[i] == '&') ost << "&amp;";
- else if (s[i] == '"') ost << "&quot;";
- else {
- ost << "&#" << (int) s[i] << ";";
- }
- } else {
- ost << s[i];
- }
- }
- return ost.str();
- }
-
- void writeEscaped(std::ostream& out, const std::string& s) {
- for (uint32_t i=0, n=s.size(); i<n; ++i) {
- if (escapedXmlChars[static_cast<uint8_t>(s[i])]) {
- if (s[i] == '<') out << "&lt;";
- else if (s[i] == '>') out << "&gt;";
- else if (s[i] == '&') out << "&amp;";
- else {
- out << "&#" << (int) s[i] << ";";
- }
- } else {
- out << s[i];
- }
- }
- }
-
- void writeBase64Encoded(std::ostream& out, const std::string& s) {
- out << vespalib::Base64::encode(&s[0], s.size());
- }
-}
-
-bool isLegalName(const std::string& name) {
- if (name.size() == 0) return false;
- if (!legalIdentifierFirstChar[static_cast<uint8_t>(name[0])]) return false;
- for (int i=1, n=name.size(); i<n; ++i) {
- if (!legalIdentifierChars[static_cast<uint8_t>(name[i])]) return false;
- }
- return true;
-}
-
-void convertToLegalName(std::string& name) {
- if (name.size() == 0) {
- name == "__no_name__";
- } else {
- if (!legalIdentifierFirstChar[static_cast<uint8_t>(name[0])]) {
- name[0] = '_';
- }
- for (int i=1, n=name.size(); i<n; ++i) {
- if (!legalIdentifierChars[static_cast<uint8_t>(name[i])]) {
- name[i] = '_';
- }
- }
- }
-}
-
-XmlOutputStream::XmlOutputStream(std::ostream& ostream,
- const std::string& indent)
- : _indent(indent),
- _wrappedStream(ostream),
- _tagStack(),
- _cachedTag(),
- _cachedAttributes(),
- _cachedContent()
-{
-}
-
-XmlAttribute::~XmlAttribute()
-{
-}
-
-XmlContent::~XmlContent()
-{
-}
-
-XmlOutputStream::~XmlOutputStream()
-{
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const XmlTag& tag)
-{
- //std::cerr << "Trying to add tag " << tag.getName() << ". cached tag is "
- // << (void*) _cachedTag.get() << "\n";
- if (_cachedTag.get() != 0) flush(false);
- _cachedTag.reset(new XmlTag(tag));
- _cachedContentType = XmlContent::AUTO;
- //std::cerr << "Added tag " << _cachedTag->getName() << "\n";
- return *this;
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const XmlAttribute& attribute)
-{
- //std::cerr << "Adding attribute\n";
- if (_cachedTag.get() == 0) {
- throw vespalib::IllegalStateException("Cannot add attribute "
- + attribute.getName() + ", as no tag is open");
- }
- _cachedAttributes.push_back(attribute);
- return *this;
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const XmlEndTag&)
-{
- //std::cerr << "Adding endtag\n";
- if (_cachedTag.get()) {
- flush(true);
- _cachedContentType = XmlContent::ESCAPED;
- } else if (_tagStack.empty()) {
- throw vespalib::IllegalStateException("No open tags left to end");
- } else {
- for (uint32_t i=1; i<_tagStack.size(); ++i) {
- _wrappedStream << _indent;
- }
- _wrappedStream << "</" << _tagStack.back() << ">";
- _tagStack.pop_back();
- if (!_tagStack.empty()) _wrappedStream << '\n';
- _cachedContentType = XmlContent::ESCAPED;
- }
- return *this;
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const XmlContent& content)
-{
- //std::cerr << "Adding content\n";
- if (_cachedTag.get() == 0 && _tagStack.empty()) {
- throw vespalib::IllegalStateException(
- "No open tag to write content in");
- }
- if (_cachedTag.get() != 0) {
- //std::cerr << "Content is '" << content.getContent() << "'\n";
- if (content.getType() == XmlContent::AUTO) { // Do nothing.. Always ok
- } else if (_cachedContentType == XmlContent::AUTO) {
- _cachedContentType = content.getType();
- } else if (_cachedContentType != content.getType()) {
- throw vespalib::IllegalStateException(
- "Have already added content of different type");
- }
- _cachedContent.push_back(content);
- } else {
- if (content.getType() == XmlContent::BASE64) {
- throw vespalib::IllegalStateException(
- "Cannot add Base64 encoded content after tag content");
- }
- for (uint32_t i=0; i<_tagStack.size(); ++i) {
- _wrappedStream << _indent;
- }
- _wrappedStream << content.getContent() << '\n';
- }
- return *this;
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const XmlSerializable& serializable)
-{
- //std::cerr << "Adding serializable\n";
- serializable.printXml(*this);
- return *this;
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(const std::string& content)
-{
- //std::cerr << "Adding content string\n";
- return *this << XmlContent(content);
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(char c)
-{
- return *this << XmlContent(std::string(&c, 1));
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(int32_t i)
-{
- return *this << XmlContent(vespalib::make_string("%d", i));
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(int64_t i)
-{
- return *this << XmlContent(vespalib::make_string("%" PRId64, i));
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(float f)
-{
- return *this << XmlContent(vespalib::make_string("%g", f));
-}
-
-XmlOutputStream&
-XmlOutputStream::operator<<(double d)
-{
- return *this << XmlContent(vespalib::make_string("%g", d));
-}
-
-void
-XmlOutputStream::flush(bool endTag)
-{
- //std::cerr << "Flushing\n";
- if (_cachedTag.get() == 0) {
- throw vespalib::IllegalStateException("Cannot write non-existing tag");
- }
- for (uint32_t i=0; i<_tagStack.size(); ++i) {
- _wrappedStream << _indent;
- }
- _wrappedStream << '<' << _cachedTag->getName();
- for (std::list<XmlAttribute>::const_iterator it = _cachedAttributes.begin();
- it != _cachedAttributes.end(); ++it)
- {
- _wrappedStream << ' ' << it->getName() << "=\""
- << xmlAttributeEscape(it->getValue()) << '"';
- }
- _cachedAttributes.clear();
- if (_cachedContent.empty() && endTag) {
- _wrappedStream << "/>\n";
- } else if (_cachedContent.empty()) {
- _wrappedStream << ">\n";
- _tagStack.push_back(_cachedTag->getName());
- } else {
- if (_cachedContentType == XmlContent::AUTO) {
- _cachedContentType = XmlContent::ESCAPED;
- for (std::list<XmlContent>::const_iterator it
- = _cachedContent.begin(); it != _cachedContent.end(); ++it)
- {
- if (containsBinaryCharacters(it->getContent())) {
- _cachedContentType = XmlContent::BASE64;
- break;
- }
- }
- }
- if (_cachedContentType == XmlContent::BASE64) {
- _wrappedStream << " binaryencoding=\"base64\"";
- }
- _wrappedStream << '>';
- for (std::list<XmlContent>::const_iterator it = _cachedContent.begin();
- it != _cachedContent.end(); ++it)
- {
- if (!endTag) {
- _wrappedStream << '\n';
- for (uint32_t i=0; i<=_tagStack.size(); ++i) {
- _wrappedStream << _indent;
- }
- }
- switch (_cachedContentType) {
- case XmlContent::ESCAPED: {
- writeEscaped(_wrappedStream, it->getContent());
- break;
- }
- case XmlContent::BASE64: {
- writeBase64Encoded(_wrappedStream, it->getContent());
- break;
- }
- default: assert(false);
- }
- }
- _cachedContent.clear();
- if (endTag) {
- _wrappedStream << "</" << _cachedTag->getName() << ">\n";
- } else {
- _wrappedStream << '\n';
- _tagStack.push_back(_cachedTag->getName());
- }
- }
- _cachedTag.reset(0);
-}
-
-XmlTag::XmlTag(const XmlTag& tag)
- : _name(tag._name),
- _attributes(),
- _content(),
- _flags(tag._flags)
-{
-}
-
-XmlTag::~XmlTag() {}
-
-XmlTag::XmlTag(const std::string& name, XmlTagFlags flags)
- : _name(name),
- _attributes(),
- _content(),
- _flags(flags)
-{
- if (_flags == CONVERT_ILLEGAL_CHARACTERS) {
- convertToLegalName(_name);
- }
- if (!isLegalName(_name)) {
- throw vespalib::IllegalArgumentException("Name '" + _name + "' contains "
- "illegal XML characters and cannot be used as tag name");
- }
-}
-
-XmlAttribute::XmlAttribute(const XmlAttribute& attribute)
- : _name(attribute._name),
- _value(attribute._value),
- _next()
-{
-}
-
-XmlAttribute::XmlAttribute(const std::string& name, const char * value, uint32_t flags)
- : _name(name),
- _value(),
- _next()
-{
- vespalib::asciistream ost;
- if (flags & HEX) ost << vespalib::hex << "0x";
- ost << value;
- _value = ost.str();
- if (!isLegalName(name)) {
- throw vespalib::IllegalArgumentException("Name '" + name + "' contains "
- "illegal XML characters and cannot be used as attribute name");
- }
-}
-
-XmlEndTag::XmlEndTag()
-{
-}
-
-XmlContent::XmlContent(Type type)
- : _type(type),
- _content(),
- _nextContent(),
- _nextTag()
-{
-}
-
-XmlContent::XmlContent()
- : _type(AUTO),
- _content(),
- _nextContent(),
- _nextTag()
-{
-}
-
-XmlContent::XmlContent(const XmlContent& content)
- : _type(content._type),
- _content(content._content),
- _nextContent(),
- _nextTag()
-{
-}
-
-XmlContent::XmlContent(const std::string& value)
- : _type(AUTO),
- _content(value),
- _nextContent(),
- _nextTag()
-{
-}
-
-XmlContentWrapper::XmlContentWrapper(const XmlContentWrapper& wrapper)
- : XmlContent(wrapper)
-{
-}
-
-XmlContentWrapper::XmlContentWrapper(const char* value)
- : XmlContent(std::string(value))
-{
-}
-
-XmlContentWrapper::XmlContentWrapper(const char* value, uint32_t size)
- : XmlContent(std::string(value, size))
-{
-}
-
std::string
XmlSerializable::toXml(const std::string& indent) const
{
@@ -452,22 +15,6 @@ XmlSerializable::toXml(const std::string& indent) const
printXml(xos);
return ost.str();
}
-using CharP = char *;
-using ConstCharP = const char *;
-
-template XmlAttribute::XmlAttribute(const std::string &, const std::string &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const vespalib::string &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const vespalib::stringref &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const CharP &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const ConstCharP &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const bool &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const int16_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const int32_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const int64_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const uint16_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const uint32_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const uint64_t &, unsigned int);
-template XmlAttribute::XmlAttribute(const std::string &, const double &, unsigned int);
} // xml
} // vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h
index b688c699d76..a4ddb12ed8d 100644
--- a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h
+++ b/staging_vespalib/src/vespa/vespalib/util/xmlserializable.h
@@ -1,166 +1,14 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-/**
- * @file xmlserializable.h
- * @ingroup util
- *
- * @brief Interfaces to be used for XML serialization.
- *
- * This file contains XML utility classes, to make XML serialization simple.
- * Rather than users writing their own XML, these tools let you define a tree
- * structure, and this library builds the XML for you. This ensures that you
- * write legal XML and that stuff that needs to be escaped is.
- * <p>
- * It defines a superclass for XML serializable classes, called XmlSerializable.
- * This is what classes that should be XML serializable will inherit.
- * <p>
- * When implementing the printXml() function in XmlSerializable, one will
- * use the various XML helper classes defined here to build a tree structure
- * creating the XML. These are: XmlTag, XmlEndTag, XmlAttribute, and XmlContent.
- * Some subclasses exist of XmlContent to facilitate various types of content.
- * <p>
- * The XmlOutputStream wraps a regular std::ostream. You write XML objects to it
- * and it is responsible for writing all the XML code. This way, the XML
- * serialization is done without interfering with regular output operators.
- * <p>
- * For example usage, refer to the unit test:
- * vespalib/tests/xmlserializable/xmlserializabletest.cpp
- *
- */
#pragma once
-#include <iosfwd>
-#include <list>
-#include <memory>
+#include <string>
namespace vespalib {
namespace xml {
-class XmlAttribute;
-class XmlContent;
class XmlOutputStream;
-bool isLegalName(const std::string& name);
-
-enum XmlTagFlags { NONE = 0, CONVERT_ILLEGAL_CHARACTERS = 1 };
-
-/**
- * @class document::XmlTag
- *
- * @brief Start a new tag with given name.
- */
-class XmlTag {
- std::string _name;
- std::unique_ptr<XmlAttribute> _attributes;
- std::unique_ptr<XmlContent> _content;
- XmlTagFlags _flags;
-public:
- XmlTag(const XmlTag&);
- XmlTag(const std::string& name, XmlTagFlags = NONE);
- ~XmlTag();
-
- const std::string& getName() const { return _name; }
-};
-
-/**
- * @class document::XmlEndTag
- *
- * @brief Indicates that current tag is closed.
- */
-class XmlEndTag {
-public:
- XmlEndTag();
-};
-
-/**
- * @class document::XmlAttribute
- *
- * @brief Defined a single attribute within an XML tag.
- *
- * When adding an XML to an XML stream, the attribute will be added to the last
- * tag added. This can not be called after the last tag opened in the stream is
- * closed, so add all attributes before starting to add new XML child tags.
- */
-class XmlAttribute {
- std::string _name;
- std::string _value;
- std::unique_ptr<XmlAttribute> _next;
-public:
- enum Flag { NONE = 0x0, HEX = 0x1 };
- XmlAttribute(const XmlAttribute&);
- /** Add any value that can be written to an ostringstream. */
- template<typename T>
- XmlAttribute(const std::string& name, const T& value, uint32_t flags = NONE);
- XmlAttribute(const std::string& name, const char * value, uint32_t flags = NONE);
- ~XmlAttribute();
-
- const std::string& getName() const { return _name; }
- const std::string& getValue() const { return _value; }
-};
-
-
-/**
- * @class document::XmlContent
- *
- * XML content to be written to stream. By default it will autodetect whether to
- * escape or base64 encode content. XmlOutputStream functions taking primitives
- * will generate XmlContent instances.
- */
-class XmlContent {
-public:
- enum Type { AUTO, ESCAPED, BASE64 };
-protected:
- XmlContent(Type type);
-private:
- Type _type;
- std::string _content;
- std::unique_ptr<XmlContent> _nextContent;
- std::unique_ptr<XmlTag> _nextTag;
-
-public:
- XmlContent();
- XmlContent(const XmlContent&);
- XmlContent(const std::string& value);
- ~XmlContent();
-
- Type getType() const { return _type; }
- const std::string& getContent() const { return _content; }
-};
-
-/**
- * @class document::XmlEscapedContent
- *
- * Token used to tell that this content field should only be XML escaped.
- */
-class XmlEscapedContent : public XmlContent {
-public:
- XmlEscapedContent() : XmlContent(ESCAPED) {}
-};
-
-/**
- * @class document::XmlBase64Content
- *
- * Token used to tell that this content field should always be base64 encoded.
- */
-class XmlBase64Content : public XmlContent {
-public:
- XmlBase64Content() : XmlContent(BASE64) {}
-};
-
-/**
- * @class document::XmlContentWrapper
- *
- * A wrapper class for content that one doesn't want to copy or release
- * ownership of. This wrapper merely takes pointer to data, and assumes it
- * will stay alive as long as needed.
- */
-class XmlContentWrapper : public XmlContent {
-public:
- XmlContentWrapper(const XmlContentWrapper&);
- XmlContentWrapper(const char* value);
- XmlContentWrapper(const char* value, uint32_t size);
-};
-
/**
* @class document::XmlSerializable
*
@@ -178,51 +26,6 @@ public:
virtual std::string toXml(const std::string& indent = "") const;
};
-/**
- * @class document::XmlOutputStream
- *
- * @brief std::ostream wrapper, only accepting data that will become XML.
- *
- * After XmlEndTag() has been sent to the stream, the tag is guarantueed to have
- * been written. Call isFinalized() to ensure that you have closed all the tags
- * that have been opened. Within a tag, the stream will cache some information,
- * as more information might be required before knowing what to print.
- */
-class XmlOutputStream {
- const std::string _indent;
- std::ostream& _wrappedStream;
- std::list<std::string> _tagStack;
- std::unique_ptr<XmlTag> _cachedTag;
- std::list<XmlAttribute> _cachedAttributes;
- std::list<XmlContent> _cachedContent;
- XmlContent::Type _cachedContentType;
-
- void flush(bool endTag);
-
-public:
-
- XmlOutputStream(std::ostream& ostream, const std::string& indent = "");
- ~XmlOutputStream();
-
- bool isFinalized() const
- { return (_tagStack.empty() && _cachedTag.get() == 0); }
-
- std::ostream& getWrappedStream() { return _wrappedStream; }
-
- XmlOutputStream& operator<<(const XmlTag& tag);
- XmlOutputStream& operator<<(const XmlAttribute& attribute);
- XmlOutputStream& operator<<(const XmlEndTag& endtag);
- XmlOutputStream& operator<<(const XmlContent& content);
- XmlOutputStream& operator<<(const XmlSerializable& serializable);
-
- XmlOutputStream& operator<<(const std::string& content);
- XmlOutputStream& operator<<(char c);
- XmlOutputStream& operator<<(int32_t i);
- XmlOutputStream& operator<<(int64_t i);
- XmlOutputStream& operator<<(float f);
- XmlOutputStream& operator<<(double d);
-};
-
} // xml
// The XmlSerializable and XmlOutputStream is often used in header files
@@ -230,8 +33,8 @@ public:
// vespalib namespace with all the other classes, use
// "using namespace vespalib::xml" within your printXml functions
-typedef vespalib::xml::XmlOutputStream XmlOutputStream;
-typedef vespalib::xml::XmlSerializable XmlSerializable;
+using XmlSerializable = vespalib::xml::XmlSerializable;
+using XmlOutputStream = vespalib::xml::XmlOutputStream;
} // vespalib
diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlstream.cpp b/staging_vespalib/src/vespa/vespalib/util/xmlstream.cpp
new file mode 100644
index 00000000000..16fce61ddd1
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/xmlstream.cpp
@@ -0,0 +1,463 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+
+#include "xmlstream.hpp"
+#include <vespa/vespalib/encoding/base64.h>
+#include <vespa/vespalib/stllike/asciistream.h>
+#include <vespa/vespalib/util/stringfmt.h>
+#include <cassert>
+
+namespace vespalib::xml {
+
+namespace {
+
+ std::vector<bool> getLegalIdentifierFirstCharacters() {
+ std::vector<bool> vec(256, false);
+ for (uint32_t i='a'; i<='z'; ++i) vec[i] = true;
+ for (uint32_t i='A'; i<='Z'; ++i) vec[i] = true;
+ vec[':'] = true;
+ vec['_'] = true;
+ return vec;
+ }
+
+ std::vector<bool> getLegalIdentifierCharacters() {
+ std::vector<bool> vec(getLegalIdentifierFirstCharacters());
+ vec['-'] = true;
+ vec['.'] = true;
+ for (uint32_t i='0'; i<='9'; ++i) {
+ vec[i] = true;
+ }
+ return vec;
+ }
+
+ std::vector<bool> getBinaryCharacters() {
+ std::vector<bool> vec(256, false);
+ for (uint32_t i=0; i<32; ++i) {
+ vec[i] = true;
+ }
+ vec['\t'] = false;
+ vec['\n'] = false;
+ vec['\r'] = false;
+ vec['\f'] = false;
+ return vec;
+ }
+
+ std::vector<bool> getEscapedXmlCharacters() {
+ std::vector<bool> vec(256, false);
+ for (uint32_t i=0; i<32; ++i) {
+ vec[i] = true;
+ }
+ vec['\n'] = false;
+ vec['<'] = true;
+ vec['>'] = true;
+ vec['&'] = true;
+ return vec;
+ }
+
+ std::vector<bool> legalIdentifierFirstChar(
+ getLegalIdentifierFirstCharacters());
+ std::vector<bool> legalIdentifierChars = getLegalIdentifierCharacters();
+ std::vector<bool> binaryChars = getBinaryCharacters();
+ std::vector<bool> escapedXmlChars = getEscapedXmlCharacters();
+
+ bool containsBinaryCharacters(const std::string& s) {
+ for (int i=0, n=s.size(); i<n; ++i) {
+ if (binaryChars[static_cast<uint8_t>(s[i])]) return true;
+ }
+ return false;
+ }
+
+ const std::string xmlAttributeEscape(const std::string& s) {
+ vespalib::asciistream ost;
+ for (uint32_t i=0, n=s.size(); i<n; ++i) {
+ if (s[i] == '"' || s[i] == '\n'
+ || escapedXmlChars[static_cast<uint8_t>(s[i])])
+ {
+ if (s[i] == '<') ost << "&lt;";
+ else if (s[i] == '>') ost << "&gt;";
+ else if (s[i] == '&') ost << "&amp;";
+ else if (s[i] == '"') ost << "&quot;";
+ else {
+ ost << "&#" << (int) s[i] << ";";
+ }
+ } else {
+ ost << s[i];
+ }
+ }
+ return ost.str();
+ }
+
+ void writeEscaped(std::ostream& out, const std::string& s) {
+ for (uint32_t i=0, n=s.size(); i<n; ++i) {
+ if (escapedXmlChars[static_cast<uint8_t>(s[i])]) {
+ if (s[i] == '<') out << "&lt;";
+ else if (s[i] == '>') out << "&gt;";
+ else if (s[i] == '&') out << "&amp;";
+ else {
+ out << "&#" << (int) s[i] << ";";
+ }
+ } else {
+ out << s[i];
+ }
+ }
+ }
+
+ void writeBase64Encoded(std::ostream& out, const std::string& s) {
+ out << vespalib::Base64::encode(&s[0], s.size());
+ }
+}
+
+bool isLegalName(const std::string& name) {
+ if (name.size() == 0) return false;
+ if (!legalIdentifierFirstChar[static_cast<uint8_t>(name[0])]) return false;
+ for (int i=1, n=name.size(); i<n; ++i) {
+ if (!legalIdentifierChars[static_cast<uint8_t>(name[i])]) return false;
+ }
+ return true;
+}
+
+void convertToLegalName(std::string& name) {
+ if (name.size() == 0) {
+ name == "__no_name__";
+ } else {
+ if (!legalIdentifierFirstChar[static_cast<uint8_t>(name[0])]) {
+ name[0] = '_';
+ }
+ for (int i=1, n=name.size(); i<n; ++i) {
+ if (!legalIdentifierChars[static_cast<uint8_t>(name[i])]) {
+ name[i] = '_';
+ }
+ }
+ }
+}
+
+XmlOutputStream::XmlOutputStream(std::ostream& ostream,
+ const std::string& indent)
+ : _indent(indent),
+ _wrappedStream(ostream),
+ _tagStack(),
+ _cachedTag(),
+ _cachedAttributes(),
+ _cachedContent()
+{
+}
+
+XmlAttribute::~XmlAttribute()
+{
+}
+
+XmlContent::~XmlContent()
+{
+}
+
+XmlOutputStream::~XmlOutputStream()
+{
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const XmlTag& tag)
+{
+ //std::cerr << "Trying to add tag " << tag.getName() << ". cached tag is "
+ // << (void*) _cachedTag.get() << "\n";
+ if (_cachedTag.get() != 0) flush(false);
+ _cachedTag.reset(new XmlTag(tag));
+ _cachedContentType = XmlContent::AUTO;
+ //std::cerr << "Added tag " << _cachedTag->getName() << "\n";
+ return *this;
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const XmlAttribute& attribute)
+{
+ //std::cerr << "Adding attribute\n";
+ if (_cachedTag.get() == 0) {
+ throw vespalib::IllegalStateException("Cannot add attribute "
+ + attribute.getName() + ", as no tag is open");
+ }
+ _cachedAttributes.push_back(attribute);
+ return *this;
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const XmlEndTag&)
+{
+ //std::cerr << "Adding endtag\n";
+ if (_cachedTag.get()) {
+ flush(true);
+ _cachedContentType = XmlContent::ESCAPED;
+ } else if (_tagStack.empty()) {
+ throw vespalib::IllegalStateException("No open tags left to end");
+ } else {
+ for (uint32_t i=1; i<_tagStack.size(); ++i) {
+ _wrappedStream << _indent;
+ }
+ _wrappedStream << "</" << _tagStack.back() << ">";
+ _tagStack.pop_back();
+ if (!_tagStack.empty()) _wrappedStream << '\n';
+ _cachedContentType = XmlContent::ESCAPED;
+ }
+ return *this;
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const XmlContent& content)
+{
+ //std::cerr << "Adding content\n";
+ if (_cachedTag.get() == 0 && _tagStack.empty()) {
+ throw vespalib::IllegalStateException(
+ "No open tag to write content in");
+ }
+ if (_cachedTag.get() != 0) {
+ //std::cerr << "Content is '" << content.getContent() << "'\n";
+ if (content.getType() == XmlContent::AUTO) { // Do nothing.. Always ok
+ } else if (_cachedContentType == XmlContent::AUTO) {
+ _cachedContentType = content.getType();
+ } else if (_cachedContentType != content.getType()) {
+ throw vespalib::IllegalStateException(
+ "Have already added content of different type");
+ }
+ _cachedContent.push_back(content);
+ } else {
+ if (content.getType() == XmlContent::BASE64) {
+ throw vespalib::IllegalStateException(
+ "Cannot add Base64 encoded content after tag content");
+ }
+ for (uint32_t i=0; i<_tagStack.size(); ++i) {
+ _wrappedStream << _indent;
+ }
+ _wrappedStream << content.getContent() << '\n';
+ }
+ return *this;
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const XmlSerializable& serializable)
+{
+ //std::cerr << "Adding serializable\n";
+ serializable.printXml(*this);
+ return *this;
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(const std::string& content)
+{
+ //std::cerr << "Adding content string\n";
+ return *this << XmlContent(content);
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(char c)
+{
+ return *this << XmlContent(std::string(&c, 1));
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(int32_t i)
+{
+ return *this << XmlContent(vespalib::make_string("%d", i));
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(int64_t i)
+{
+ return *this << XmlContent(vespalib::make_string("%" PRId64, i));
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(float f)
+{
+ return *this << XmlContent(vespalib::make_string("%g", f));
+}
+
+XmlOutputStream&
+XmlOutputStream::operator<<(double d)
+{
+ return *this << XmlContent(vespalib::make_string("%g", d));
+}
+
+void
+XmlOutputStream::flush(bool endTag)
+{
+ //std::cerr << "Flushing\n";
+ if (_cachedTag.get() == 0) {
+ throw vespalib::IllegalStateException("Cannot write non-existing tag");
+ }
+ for (uint32_t i=0; i<_tagStack.size(); ++i) {
+ _wrappedStream << _indent;
+ }
+ _wrappedStream << '<' << _cachedTag->getName();
+ for (std::list<XmlAttribute>::const_iterator it = _cachedAttributes.begin();
+ it != _cachedAttributes.end(); ++it)
+ {
+ _wrappedStream << ' ' << it->getName() << "=\""
+ << xmlAttributeEscape(it->getValue()) << '"';
+ }
+ _cachedAttributes.clear();
+ if (_cachedContent.empty() && endTag) {
+ _wrappedStream << "/>\n";
+ } else if (_cachedContent.empty()) {
+ _wrappedStream << ">\n";
+ _tagStack.push_back(_cachedTag->getName());
+ } else {
+ if (_cachedContentType == XmlContent::AUTO) {
+ _cachedContentType = XmlContent::ESCAPED;
+ for (std::list<XmlContent>::const_iterator it
+ = _cachedContent.begin(); it != _cachedContent.end(); ++it)
+ {
+ if (containsBinaryCharacters(it->getContent())) {
+ _cachedContentType = XmlContent::BASE64;
+ break;
+ }
+ }
+ }
+ if (_cachedContentType == XmlContent::BASE64) {
+ _wrappedStream << " binaryencoding=\"base64\"";
+ }
+ _wrappedStream << '>';
+ for (std::list<XmlContent>::const_iterator it = _cachedContent.begin();
+ it != _cachedContent.end(); ++it)
+ {
+ if (!endTag) {
+ _wrappedStream << '\n';
+ for (uint32_t i=0; i<=_tagStack.size(); ++i) {
+ _wrappedStream << _indent;
+ }
+ }
+ switch (_cachedContentType) {
+ case XmlContent::ESCAPED: {
+ writeEscaped(_wrappedStream, it->getContent());
+ break;
+ }
+ case XmlContent::BASE64: {
+ writeBase64Encoded(_wrappedStream, it->getContent());
+ break;
+ }
+ default: assert(false);
+ }
+ }
+ _cachedContent.clear();
+ if (endTag) {
+ _wrappedStream << "</" << _cachedTag->getName() << ">\n";
+ } else {
+ _wrappedStream << '\n';
+ _tagStack.push_back(_cachedTag->getName());
+ }
+ }
+ _cachedTag.reset(0);
+}
+
+XmlTag::XmlTag(const XmlTag& tag)
+ : _name(tag._name),
+ _attributes(),
+ _content(),
+ _flags(tag._flags)
+{
+}
+
+XmlTag::~XmlTag() {}
+
+XmlTag::XmlTag(const std::string& name, XmlTagFlags flags)
+ : _name(name),
+ _attributes(),
+ _content(),
+ _flags(flags)
+{
+ if (_flags == CONVERT_ILLEGAL_CHARACTERS) {
+ convertToLegalName(_name);
+ }
+ if (!isLegalName(_name)) {
+ throw vespalib::IllegalArgumentException("Name '" + _name + "' contains "
+ "illegal XML characters and cannot be used as tag name");
+ }
+}
+
+XmlAttribute::XmlAttribute(const XmlAttribute& attribute)
+ : _name(attribute._name),
+ _value(attribute._value),
+ _next()
+{
+}
+
+XmlAttribute::XmlAttribute(const std::string& name, const char * value, uint32_t flags)
+ : _name(name),
+ _value(),
+ _next()
+{
+ vespalib::asciistream ost;
+ if (flags & HEX) ost << vespalib::hex << "0x";
+ ost << value;
+ _value = ost.str();
+ if (!isLegalName(name)) {
+ throw vespalib::IllegalArgumentException("Name '" + name + "' contains "
+ "illegal XML characters and cannot be used as attribute name");
+ }
+}
+
+XmlEndTag::XmlEndTag()
+{
+}
+
+XmlContent::XmlContent(Type type)
+ : _type(type),
+ _content(),
+ _nextContent(),
+ _nextTag()
+{
+}
+
+XmlContent::XmlContent()
+ : _type(AUTO),
+ _content(),
+ _nextContent(),
+ _nextTag()
+{
+}
+
+XmlContent::XmlContent(const XmlContent& content)
+ : _type(content._type),
+ _content(content._content),
+ _nextContent(),
+ _nextTag()
+{
+}
+
+XmlContent::XmlContent(const std::string& value)
+ : _type(AUTO),
+ _content(value),
+ _nextContent(),
+ _nextTag()
+{
+}
+
+XmlContentWrapper::XmlContentWrapper(const XmlContentWrapper& wrapper)
+ : XmlContent(wrapper)
+{
+}
+
+XmlContentWrapper::XmlContentWrapper(const char* value)
+ : XmlContent(std::string(value))
+{
+}
+
+XmlContentWrapper::XmlContentWrapper(const char* value, uint32_t size)
+ : XmlContent(std::string(value, size))
+{
+}
+
+using CharP = char *;
+using ConstCharP = const char *;
+
+template XmlAttribute::XmlAttribute(const std::string &, const std::string &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const vespalib::string &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const vespalib::stringref &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const CharP &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const ConstCharP &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const bool &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const int16_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const int32_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const int64_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const uint16_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const uint32_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const uint64_t &, unsigned int);
+template XmlAttribute::XmlAttribute(const std::string &, const double &, unsigned int);
+
+}
diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlstream.h b/staging_vespalib/src/vespa/vespalib/util/xmlstream.h
new file mode 100644
index 00000000000..8ed781e57c3
--- /dev/null
+++ b/staging_vespalib/src/vespa/vespalib/util/xmlstream.h
@@ -0,0 +1,210 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+/**
+ * @file xmlserializable.h
+ * @ingroup util
+ *
+ * @brief Interfaces to be used for XML serialization.
+ *
+ * This file contains XML utility classes, to make XML serialization simple.
+ * Rather than users writing their own XML, these tools let you define a tree
+ * structure, and this library builds the XML for you. This ensures that you
+ * write legal XML and that stuff that needs to be escaped is.
+ * <p>
+ * It defines a superclass for XML serializable classes, called XmlSerializable.
+ * This is what classes that should be XML serializable will inherit.
+ * <p>
+ * When implementing the printXml() function in XmlSerializable, one will
+ * use the various XML helper classes defined here to build a tree structure
+ * creating the XML. These are: XmlTag, XmlEndTag, XmlAttribute, and XmlContent.
+ * Some subclasses exist of XmlContent to facilitate various types of content.
+ * <p>
+ * The XmlOutputStream wraps a regular std::ostream. You write XML objects to it
+ * and it is responsible for writing all the XML code. This way, the XML
+ * serialization is done without interfering with regular output operators.
+ * <p>
+ * For example usage, refer to the unit test:
+ * vespalib/tests/xmlserializable/xmlserializabletest.cpp
+ *
+ */
+
+#pragma once
+
+#include "xmlserializable.h"
+#include <iosfwd>
+#include <list>
+#include <memory>
+
+namespace vespalib::xml {
+
+class XmlAttribute;
+class XmlContent;
+class XmlOutputStream;
+
+bool isLegalName(const std::string& name);
+
+enum XmlTagFlags { NONE = 0, CONVERT_ILLEGAL_CHARACTERS = 1 };
+
+/**
+ * @class document::XmlTag
+ *
+ * @brief Start a new tag with given name.
+ */
+class XmlTag {
+ std::string _name;
+ std::unique_ptr<XmlAttribute> _attributes;
+ std::unique_ptr<XmlContent> _content;
+ XmlTagFlags _flags;
+public:
+ XmlTag(const XmlTag&);
+ XmlTag(const std::string& name, XmlTagFlags = NONE);
+ ~XmlTag();
+
+ const std::string& getName() const { return _name; }
+};
+
+/**
+ * @class document::XmlEndTag
+ *
+ * @brief Indicates that current tag is closed.
+ */
+class XmlEndTag {
+public:
+ XmlEndTag();
+};
+
+/**
+ * @class document::XmlAttribute
+ *
+ * @brief Defined a single attribute within an XML tag.
+ *
+ * When adding an XML to an XML stream, the attribute will be added to the last
+ * tag added. This can not be called after the last tag opened in the stream is
+ * closed, so add all attributes before starting to add new XML child tags.
+ */
+class XmlAttribute {
+ std::string _name;
+ std::string _value;
+ std::unique_ptr<XmlAttribute> _next;
+public:
+ enum Flag { NONE = 0x0, HEX = 0x1 };
+ XmlAttribute(const XmlAttribute&);
+ /** Add any value that can be written to an ostringstream. */
+ template<typename T>
+ XmlAttribute(const std::string& name, const T& value, uint32_t flags = NONE);
+ XmlAttribute(const std::string& name, const char * value, uint32_t flags = NONE);
+ ~XmlAttribute();
+
+ const std::string& getName() const { return _name; }
+ const std::string& getValue() const { return _value; }
+};
+
+
+/**
+ * @class document::XmlContent
+ *
+ * XML content to be written to stream. By default it will autodetect whether to
+ * escape or base64 encode content. XmlOutputStream functions taking primitives
+ * will generate XmlContent instances.
+ */
+class XmlContent {
+public:
+ enum Type { AUTO, ESCAPED, BASE64 };
+protected:
+ XmlContent(Type type);
+private:
+ Type _type;
+ std::string _content;
+ std::unique_ptr<XmlContent> _nextContent;
+ std::unique_ptr<XmlTag> _nextTag;
+
+public:
+ XmlContent();
+ XmlContent(const XmlContent&);
+ XmlContent(const std::string& value);
+ ~XmlContent();
+
+ Type getType() const { return _type; }
+ const std::string& getContent() const { return _content; }
+};
+
+/**
+ * @class document::XmlEscapedContent
+ *
+ * Token used to tell that this content field should only be XML escaped.
+ */
+class XmlEscapedContent : public XmlContent {
+public:
+ XmlEscapedContent() : XmlContent(ESCAPED) {}
+};
+
+/**
+ * @class document::XmlBase64Content
+ *
+ * Token used to tell that this content field should always be base64 encoded.
+ */
+class XmlBase64Content : public XmlContent {
+public:
+ XmlBase64Content() : XmlContent(BASE64) {}
+};
+
+/**
+ * @class document::XmlContentWrapper
+ *
+ * A wrapper class for content that one doesn't want to copy or release
+ * ownership of. This wrapper merely takes pointer to data, and assumes it
+ * will stay alive as long as needed.
+ */
+class XmlContentWrapper : public XmlContent {
+public:
+ XmlContentWrapper(const XmlContentWrapper&);
+ XmlContentWrapper(const char* value);
+ XmlContentWrapper(const char* value, uint32_t size);
+};
+
+/**
+ * @class document::XmlOutputStream
+ *
+ * @brief std::ostream wrapper, only accepting data that will become XML.
+ *
+ * After XmlEndTag() has been sent to the stream, the tag is guarantueed to have
+ * been written. Call isFinalized() to ensure that you have closed all the tags
+ * that have been opened. Within a tag, the stream will cache some information,
+ * as more information might be required before knowing what to print.
+ */
+class XmlOutputStream {
+ const std::string _indent;
+ std::ostream& _wrappedStream;
+ std::list<std::string> _tagStack;
+ std::unique_ptr<XmlTag> _cachedTag;
+ std::list<XmlAttribute> _cachedAttributes;
+ std::list<XmlContent> _cachedContent;
+ XmlContent::Type _cachedContentType;
+
+ void flush(bool endTag);
+
+public:
+
+ XmlOutputStream(std::ostream& ostream, const std::string& indent = "");
+ ~XmlOutputStream();
+
+ bool isFinalized() const
+ { return (_tagStack.empty() && _cachedTag.get() == 0); }
+
+ std::ostream& getWrappedStream() { return _wrappedStream; }
+
+ XmlOutputStream& operator<<(const XmlTag& tag);
+ XmlOutputStream& operator<<(const XmlAttribute& attribute);
+ XmlOutputStream& operator<<(const XmlEndTag& endtag);
+ XmlOutputStream& operator<<(const XmlContent& content);
+ XmlOutputStream& operator<<(const XmlSerializable& serializable);
+
+ XmlOutputStream& operator<<(const std::string& content);
+ XmlOutputStream& operator<<(char c);
+ XmlOutputStream& operator<<(int32_t i);
+ XmlOutputStream& operator<<(int64_t i);
+ XmlOutputStream& operator<<(float f);
+ XmlOutputStream& operator<<(double d);
+};
+
+}
+
diff --git a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.hpp b/staging_vespalib/src/vespa/vespalib/util/xmlstream.hpp
index 0da684d6b28..243efe9e94b 100644
--- a/staging_vespalib/src/vespa/vespalib/util/xmlserializable.hpp
+++ b/staging_vespalib/src/vespa/vespalib/util/xmlstream.hpp
@@ -2,12 +2,11 @@
#pragma once
-#include "xmlserializable.h"
+#include "xmlstream.h"
#include <vespa/vespalib/util/exceptions.h>
#include <sstream>
-namespace vespalib {
-namespace xml {
+namespace vespalib::xml {
template<typename T>
XmlAttribute::XmlAttribute(const std::string& name, const T& value, uint32_t flags)
@@ -20,10 +19,9 @@ XmlAttribute::XmlAttribute(const std::string& name, const T& value, uint32_t fla
ost << value;
_value = ost.str();
if (!isLegalName(name)) {
- throw vespalib::IllegalArgumentException("Name '" + name + "' contains "
+ throw IllegalArgumentException("Name '" + name + "' contains "
"illegal XML characters and cannot be used as attribute name");
}
}
}
-}
diff --git a/storage/src/vespa/storage/bucketdb/bucketmanager.h b/storage/src/vespa/storage/bucketdb/bucketmanager.h
index d3a939d90c5..09cbc60b58e 100644
--- a/storage/src/vespa/storage/bucketdb/bucketmanager.h
+++ b/storage/src/vespa/storage/bucketdb/bucketmanager.h
@@ -25,6 +25,7 @@
#include <vespa/storageapi/message/bucket.h>
#include <vespa/config/subscription/configuri.h>
#include <unordered_set>
+#include <list>
namespace storage {
diff --git a/storage/src/vespa/storage/bucketdb/storagebucketdbinitializer.h b/storage/src/vespa/storage/bucketdb/storagebucketdbinitializer.h
index f56b45c71b3..92c00c4420a 100644
--- a/storage/src/vespa/storage/bucketdb/storagebucketdbinitializer.h
+++ b/storage/src/vespa/storage/bucketdb/storagebucketdbinitializer.h
@@ -50,6 +50,7 @@
#include <vespa/vespalib/util/sync.h>
#include <vespa/vdslib/state/nodestate.h>
#include <vespa/config/subscription/configuri.h>
+#include <list>
namespace storage {
diff --git a/storage/src/vespa/storage/common/statusmetricconsumer.cpp b/storage/src/vespa/storage/common/statusmetricconsumer.cpp
index 3111508fddc..8cb5c9018f4 100644
--- a/storage/src/vespa/storage/common/statusmetricconsumer.cpp
+++ b/storage/src/vespa/storage/common/statusmetricconsumer.cpp
@@ -1,20 +1,19 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "statusmetricconsumer.h"
-
+#include <vespa/storageframework/generic/memory/memorymanagerinterface.h>
+#include <vespa/storageframework/generic/status/htmlstatusreporter.h>
#include <boost/assign.hpp>
#include <boost/lexical_cast.hpp>
-#include <vespa/log/log.h>
#include <vespa/metrics/printutils.h>
#include <vespa/metrics/jsonwriter.h>
#include <vespa/metrics/textwriter.h>
#include <vespa/metrics/xmlwriter.h>
#include <vespa/storageapi/messageapi/storagemessage.h>
#include <vespa/vespalib/stllike/asciistream.h>
-#include <vespa/storageframework/generic/memory/memorymanagerinterface.h>
-#include <vespa/storageframework/generic/status/htmlstatusreporter.h>
-
+#include <vespa/vespalib/util/xmlstream.h>
+#include <vespa/log/log.h>
LOG_SETUP(".status.metricreporter");
namespace storage {
diff --git a/storage/src/vespa/storage/distributor/bucketdbupdater.cpp b/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
index 068f42f8b31..eede73bed63 100644
--- a/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
+++ b/storage/src/vespa/storage/distributor/bucketdbupdater.cpp
@@ -7,6 +7,7 @@
#include <vespa/storageapi/message/persistence.h>
#include <vespa/storageapi/message/removelocation.h>
#include <vespa/storageapi/message/multioperation.h>
+#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/log/log.h>
LOG_SETUP(".distributor.bucketdb.updater");
diff --git a/storage/src/vespa/storage/distributor/bucketdbupdater.h b/storage/src/vespa/storage/distributor/bucketdbupdater.h
index 3f0989e9b4f..3bd86fc3db6 100644
--- a/storage/src/vespa/storage/distributor/bucketdbupdater.h
+++ b/storage/src/vespa/storage/distributor/bucketdbupdater.h
@@ -17,6 +17,7 @@
#include <vespa/storageapi/messageapi/messagehandler.h>
#include <set>
#include <deque>
+#include <list>
namespace storage::distributor {
diff --git a/storage/src/vespa/storage/distributor/pendingclusterstate.cpp b/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
index 9497bf05f17..5a2f0d35e8c 100644
--- a/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
+++ b/storage/src/vespa/storage/distributor/pendingclusterstate.cpp
@@ -4,7 +4,7 @@
#include "bucketdbupdater.h"
#include <vespa/storageframework/defaultimplementation/clock/realclock.h>
#include <vespa/storage/common/bucketoperationlogger.h>
-#include <vespa/vespalib/util/xmlserializable.hpp>
+#include <vespa/vespalib/util/xmlstream.hpp>
#include <vespa/log/log.h>
LOG_SETUP(".pendingclusterstate");
diff --git a/storage/src/vespa/storage/storageserver/bucketintegritychecker.h b/storage/src/vespa/storage/storageserver/bucketintegritychecker.h
index 3add8c56e4b..f55cb18366c 100644
--- a/storage/src/vespa/storage/storageserver/bucketintegritychecker.h
+++ b/storage/src/vespa/storage/storageserver/bucketintegritychecker.h
@@ -16,6 +16,7 @@
#include <vespa/storageapi/message/bucket.h>
#include <vespa/storageframework/generic/status/htmlstatusreporter.h>
#include <vespa/config/config.h>
+#include <list>
namespace storage {
diff --git a/storageapi/src/vespa/storageapi/buckets/bucketinfo.cpp b/storageapi/src/vespa/storageapi/buckets/bucketinfo.cpp
index 07ba2773e91..f9924c953c2 100644
--- a/storageapi/src/vespa/storageapi/buckets/bucketinfo.cpp
+++ b/storageapi/src/vespa/storageapi/buckets/bucketinfo.cpp
@@ -1,9 +1,9 @@
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "bucketinfo.h"
#include <vespa/vespalib/stllike/asciistream.h>
+#include <vespa/vespalib/util/xmlstream.h>
-namespace storage {
-namespace api {
+namespace storage::api {
BucketInfo::BucketInfo()
: _lastModified(0),
@@ -124,5 +124,4 @@ BucketInfo::printXml(vespalib::XmlOutputStream& xos) const
<< XmlAttribute("lastmodified", _lastModified);
}
-} // api
-} // storage
+}
diff --git a/storageframework/src/vespa/storageframework/generic/status/xmlstatusreporter.h b/storageframework/src/vespa/storageframework/generic/status/xmlstatusreporter.h
index 522a6480a75..2f38b89fa15 100644
--- a/storageframework/src/vespa/storageframework/generic/status/xmlstatusreporter.h
+++ b/storageframework/src/vespa/storageframework/generic/status/xmlstatusreporter.h
@@ -18,7 +18,7 @@
#pragma once
#include "statusreporter.h"
-#include <vespa/vespalib/util/xmlserializable.h>
+#include <vespa/vespalib/util/xmlstream.h>
namespace storage::framework {
diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
index 56c95e7fbc7..7b5e5f17671 100644
--- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
+++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp
@@ -368,7 +368,7 @@ SearchVisitorFactory::makeVisitor(StorageComponent& component,
}
void
-SearchVisitor::AttributeInserter::onPrimitive(uint32_t, const IteratorContent & c)
+SearchVisitor::AttributeInserter::onPrimitive(uint32_t, const Content & c)
{
const document::FieldValue & value = c.getValue();
LOG(debug, "AttributeInserter: Adding value '%s'(%d) to attribute '%s' for docid '%d'",
@@ -402,13 +402,13 @@ SearchVisitor::PositionInserter::PositionInserter(search::AttributeVector & attr
SearchVisitor::PositionInserter::~PositionInserter() {}
void
-SearchVisitor::PositionInserter::onPrimitive(uint32_t, const IteratorContent & c)
+SearchVisitor::PositionInserter::onPrimitive(uint32_t, const Content & c)
{
(void) c;
}
void
-SearchVisitor::PositionInserter::onStructStart(const IteratorContent & c)
+SearchVisitor::PositionInserter::onStructStart(const Content & c)
{
const document::StructuredFieldValue & value = static_cast<const document::StructuredFieldValue &>(c.getValue());
LOG(debug, "PositionInserter: Adding value '%s'(%d) to attribute '%s' for docid '%d'",
diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h
index 7767a601ea4..47d6157525c 100644
--- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h
+++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.h
@@ -27,6 +27,7 @@
#include <vespa/storage/visiting/visitor.h>
#include <vespa/document/fieldvalue/fieldvalues.h>
#include <vespa/documentapi/messagebus/messages/queryresultmessage.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
using namespace search::aggregation;
@@ -86,13 +87,12 @@ private:
* This class gets callbacks when iterating through a field value and
* inserts the values into a given attribute vector.
**/
- class AttributeInserter : public document::FieldValue::IteratorHandler {
+ class AttributeInserter : public document::fieldvalue::IteratorHandler {
protected:
- typedef document::FieldValue::IteratorHandler::Content IteratorContent;
search::AttributeVector & _attribute;
search::AttributeVector::DocId _docId;
- void onPrimitive(uint32_t fid, const IteratorContent & c) override;
+ void onPrimitive(uint32_t fid, const Content & c) override;
public:
AttributeInserter(search::AttributeVector & attribute, search::AttributeVector::DocId docId);
@@ -103,7 +103,7 @@ private:
PositionInserter(search::AttributeVector & attribute, search::AttributeVector::DocId docId);
~PositionInserter();
private:
- void onPrimitive(uint32_t fid, const IteratorContent & c) override;
+ void onPrimitive(uint32_t fid, const Content & c) override;
void onStructStart(const Content & fv) override;
document::Field _fieldX;
document::Field _fieldY;
@@ -466,4 +466,3 @@ public:
};
}
-
diff --git a/vdslib/src/vespa/vdslib/container/parameters.cpp b/vdslib/src/vespa/vdslib/container/parameters.cpp
index d82f89da29d..c685a9b884f 100644
--- a/vdslib/src/vespa/vdslib/container/parameters.cpp
+++ b/vdslib/src/vespa/vdslib/container/parameters.cpp
@@ -4,6 +4,7 @@
#include <vespa/vespalib/objects/nbostream.h>
#include <vespa/vespalib/objects/hexdump.h>
#include <vespa/vespalib/stllike/hash_map.hpp>
+#include <vespa/vespalib/util/xmlstream.h>
using namespace vdslib;
@@ -60,7 +61,7 @@ void Parameters::onDeserialize(const document::DocumentTypeRepo &repo, document:
void
Parameters::printXml(document::XmlOutputStream& xos) const
{
- using namespace document;
+ using namespace vespalib::xml;
xos << XmlTag("parameters");
for (const auto & entry : _parameters) {
xos << XmlTag("item")
diff --git a/vsm/src/vespa/vsm/common/document.h b/vsm/src/vespa/vsm/common/document.h
index a0341aaf7c0..ea0f9216ab9 100644
--- a/vsm/src/vespa/vsm/common/document.h
+++ b/vsm/src/vespa/vsm/common/document.h
@@ -4,6 +4,7 @@
#include <vespa/searchlib/query/base.h>
#include <vespa/document/fieldvalue/fieldvalue.h>
#include <vespa/vespalib/stllike/hash_map.h>
+#include <map>
namespace vespalib {
class asciistream;
diff --git a/vsm/src/vespa/vsm/searcher/fieldsearcher.h b/vsm/src/vespa/vsm/searcher/fieldsearcher.h
index 3b82f68072b..e28275536f3 100644
--- a/vsm/src/vespa/vsm/searcher/fieldsearcher.h
+++ b/vsm/src/vespa/vsm/searcher/fieldsearcher.h
@@ -4,6 +4,7 @@
#include <vespa/searchlib/query/query.h>
#include <vespa/vsm/common/document.h>
#include <vespa/vsm/common/storagedocument.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
namespace vsm {
@@ -79,9 +80,8 @@ public:
size_t maxFieldLength() const { return _maxFieldLength; }
private:
- class IteratorHandler : public document::FieldValue::IteratorHandler {
+ class IteratorHandler : public document::fieldvalue::IteratorHandler {
private:
- typedef document::FieldValue::IteratorHandler::Content Content;
FieldSearcher & _searcher;
void onPrimitive(uint32_t fid, const Content & c) override;
diff --git a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
index 961add6d7d6..b7ed6c0b7da 100644
--- a/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
+++ b/vsm/src/vespa/vsm/vsm/docsumfilter.cpp
@@ -4,6 +4,7 @@
#include "slimefieldwriter.h"
#include <vespa/searchsummary/docsummary/summaryfieldconverter.h>
#include <vespa/document/base/exceptions.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/log/log.h>
LOG_SETUP(".vsm.docsumfilter");
@@ -13,9 +14,8 @@ using namespace search::docsummary;
namespace {
-class Handler : public document::FieldValue::IteratorHandler {
+class Handler : public document::fieldvalue::IteratorHandler {
public:
- typedef document::FieldValue::IteratorHandler::Content Content;
};
struct IntResultHandler : public Handler {
diff --git a/vsm/src/vespa/vsm/vsm/flattendocsumwriter.h b/vsm/src/vespa/vsm/vsm/flattendocsumwriter.h
index 9c6ba8dae9c..aa58a6ae6df 100644
--- a/vsm/src/vespa/vsm/vsm/flattendocsumwriter.h
+++ b/vsm/src/vespa/vsm/vsm/flattendocsumwriter.h
@@ -2,6 +2,7 @@
#pragma once
#include <vespa/document/fieldvalue/fieldvalue.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
#include <vespa/vsm/common/charbuffer.h>
namespace vsm {
@@ -10,10 +11,8 @@ namespace vsm {
* This class is used to flatten out and write a complex field value.
* A separator string is inserted between primitive field values.
**/
-class FlattenDocsumWriter : public document::FieldValue::IteratorHandler {
+class FlattenDocsumWriter : public document::fieldvalue::IteratorHandler {
private:
- typedef document::FieldValue::IteratorHandler::Content Content;
-
CharBuffer _output;
vespalib::string _separator;
bool _useSeparator;
diff --git a/vsm/src/vespa/vsm/vsm/snippetmodifier.h b/vsm/src/vespa/vsm/vsm/snippetmodifier.h
index 17d6bb44d4c..182f09d5d55 100644
--- a/vsm/src/vespa/vsm/vsm/snippetmodifier.h
+++ b/vsm/src/vespa/vsm/vsm/snippetmodifier.h
@@ -7,6 +7,7 @@
#include <vespa/vsm/common/fieldmodifier.h>
#include <vespa/vsm/searcher/utf8substringsnippetmodifier.h>
#include <vespa/document/fieldvalue/fieldvalue.h>
+#include <vespa/document/fieldvalue/iteratorhandler.h>
namespace vsm {
@@ -19,11 +20,9 @@ namespace vsm {
* responsible for modifying the field value by inserting unit separators before and after matches.
* A group separator is inserted between primitive field values the same way as done by FlattenDocsumWriter.
**/
-class SnippetModifier : public FieldModifier, public document::FieldValue::IteratorHandler
+class SnippetModifier : public FieldModifier, public document::fieldvalue::IteratorHandler
{
private:
- typedef document::FieldValue::IteratorHandler::Content Content;
-
UTF8SubstringSnippetModifier::SP _searcher;
CharBuffer::SP _valueBuf; // buffer to store the final modified field value
char _groupSep;