aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/data/slime/slime.h
blob: 4b7898380096c0777d0714c38093382edf3a66a8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include "array_traverser.h"
#include "basic_value_factory.h"
#include "binary_format.h"
#include "convenience.h"
#include "cursor.h"
#include "empty_value_factory.h"
#include "inject.h"
#include "inserter.h"
#include "inspector.h"
#include "json_format.h"
#include "named_symbol_inserter.h"
#include "named_symbol_lookup.h"
#include "nix_value.h"
#include "object_traverser.h"
#include "resolved_symbol.h"
#include "root_value.h"
#include "symbol.h"
#include "symbol_inserter.h"
#include "symbol_lookup.h"
#include "symbol_table.h"
#include "type.h"
#include "value.h"
#include "value_factory.h"
#include "external_data_value_factory.h"
#include <vespa/vespalib/data/input_reader.h>
#include <vespa/vespalib/data/output_writer.h>
#include <vespa/vespalib/data/output.h>

namespace vespalib {

/**
 * SLIME: 'Schema-Less Interface/Model/Exchange'. Slime is a way to
 * handle schema-less structured data to be used as part of interfaces
 * between components (RPC signatures), internal models
 * (config/parameters) and data exchange between components
 * (documents). The goal for Slime is to be flexible and lightweight
 * and at the same time limit the extra overhead in space and time
 * compared to schema-oriented approaches like protocol buffers and
 * avro. The data model is inspired by JSON and associative arrays
 * typically used in programming languages with dynamic typing.
 **/
class Slime
{
private:
    using Symbol = slime::Symbol;
    using SymbolTable = slime::SymbolTable;
    using RootValue = slime::RootValue;
    using Cursor = slime::Cursor;
    using Inspector = slime::Inspector;

    std::unique_ptr<SymbolTable> _names;
    std::unique_ptr<Stash>       _stash;
    RootValue                    _root;

public:
    using UP = std::unique_ptr<Slime>;
    class Params {
    private:
        std::unique_ptr<SymbolTable> _symbols;
        size_t                       _chunkSize;
    public:
        Params() : Params(4096) {}
        explicit Params(size_t chunkSize) : _symbols(std::make_unique<SymbolTable>()), _chunkSize(chunkSize) {}
        explicit Params(std::unique_ptr<SymbolTable> symbols) noexcept : _symbols(std::move(symbols)), _chunkSize(4096) {}
        Params(Params &&) noexcept = default;
        ~Params() = default;
        size_t getChunkSize() const noexcept { return _chunkSize; }
        std::unique_ptr<SymbolTable> detachSymbols() noexcept { return std::move(_symbols); }
    };
    /**
     * Construct an initially empty Slime object.
     **/
    explicit Slime() : Slime(Params()) {}
    explicit Slime(Params params);

    ~Slime();

    Slime(Slime &&rhs) noexcept;
    Slime &operator=(Slime &&rhs) noexcept;

    Slime(const Slime & rhs) = delete;
    Slime& operator = (const Slime & rhs) = delete;

    static std::unique_ptr<SymbolTable> reclaimSymbols(Slime &&rhs);

    size_t symbols() const noexcept { return _names->symbols(); }

    Memory inspect(Symbol symbol) const { return _names->inspect(symbol); }

    Symbol insert(Memory name) { return _names->insert(name); }

    Symbol lookup(Memory name) const { return _names->lookup(name); }

    Cursor &get() noexcept { return _root.get(); }

    Inspector &get() const noexcept { return _root.get(); }

    template <typename ID>
    Inspector &operator[](ID id) const { return get()[id]; }

    template <typename ID>
    Cursor &operator[](ID id) { return get()[id]; }

    Cursor &setNix() {
        return _root.set(slime::NixValueFactory());
    }
    Cursor &setBool(bool bit) {
        return _root.set(slime::BoolValueFactory(bit));
    }
    Cursor &setLong(int64_t l) {
        return _root.set(slime::LongValueFactory(l));
    }
    Cursor &setDouble(double d) {
        return _root.set(slime::DoubleValueFactory(d));
    }
    Cursor &setString(const Memory& str) {
        return _root.set(slime::StringValueFactory(str));
    }
    Cursor &setData(const Memory& data) {
        return _root.set(slime::DataValueFactory(data));
    }
    Cursor &setData(slime::ExternalMemory::UP data) {
        return _root.set(slime::ExternalDataValueFactory(std::move(data)));
    }
    Cursor &setArray() {
        return setArray(0);
    }
    Cursor &setArray(size_t reserve) {
        return _root.set(slime::ArrayValueFactory(*_names, reserve));
    }
    Cursor &setObject() {
        return _root.set(slime::ObjectValueFactory(*_names));
    }

    Cursor &wrap(Symbol sym) {
        slime::ResolvedSymbol symbol(sym);
        return *_root.wrap(*_names, symbol);
    }

    Cursor &wrap(Memory name) {
        slime::NamedSymbolInserter symbol(*_names, name);
        return *_root.wrap(*_names, symbol);
    }

    vespalib::string toString() const { return get().toString(); }
};

bool operator == (const Slime & a, const Slime & b) noexcept;
std::ostream & operator << (std::ostream & os, const Slime & slime);

} // namespace vespalib