blob: 183c8ba046c9a95b6cdd6a82266e2686f20fccb8 (
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
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once
/**
* An overbuild of the json writer, making the code writing the json looking
* neater. Also allows templates to use it with unknown (but supported) types,
* letting the compiler take care of calling the correct function rather than
* having to resort to template specialization.
*/
#include <vespa/vespalib/util/jsonwriter.h>
namespace vespalib {
// Inherit to refer to types without namespace prefix in header file.
struct JsonStreamTypes {
class Object {};
class Array {};
class End {};
};
// Use namespace in function to avoid prefixing namespace everywhere.
namespace jsonstream {
using Object = JsonStreamTypes::Object;
using Array = JsonStreamTypes::Array;
using End = JsonStreamTypes::End;
}
// We can disable this if it ends up being a performance issue.
// Really useful to explain what code bits have tried to write invalid json
// though.
#define TRACK_JSON_CREATION_TO_CREATE_EASY_TO_DEBUG_ERROR_MESSAGES 1
class JsonStream : public JsonStreamTypes {
JSONWriter _writer;
enum class State {
ROOT,
OBJECT_EXPECTING_KEY,
OBJECT_EXPECTING_VALUE,
ARRAY
};
static const char* getStateName(const State&);
struct StateEntry {
State state;
string object_key;
size_t array_index;
StateEntry() noexcept;
StateEntry(State s) noexcept;
StateEntry(State s, stringref key) noexcept;
StateEntry(const StateEntry &) noexcept;
StateEntry & operator =(const StateEntry &) noexcept;
~StateEntry();
};
std::vector<StateEntry> _state;
StateEntry & top() { return _state.back(); }
const StateEntry & top() const { return _state.back(); }
void pop() { _state.resize(_state.size() - 1); }
void push(const StateEntry & e) { _state.push_back(e); }
public:
JsonStream(asciistream&, bool createIndents = false);
JsonStream(const JsonStream&) = delete;
JsonStream& operator=(const JsonStream&) = delete;
JsonStream(JsonStream &&) = default;
JsonStream& operator=(JsonStream &&) = default;
~JsonStream();
JsonStream& operator<<(stringref);
JsonStream& operator<<(bool);
JsonStream& operator<<(double);
JsonStream& operator<<(float); // Less precision that double
JsonStream& operator<<(long long);
JsonStream& operator<<(unsigned long long);
JsonStream& operator<<(const Object&);
JsonStream& operator<<(const Array&);
JsonStream& operator<<(const End&);
// Additional functions provided to let compiler work out correct
// function without requiring user to cast their value
JsonStream& operator<<(unsigned long v)
{ return operator<<(static_cast<unsigned long long>(v)); }
JsonStream& operator<<(unsigned int v)
{ return operator<<(static_cast<unsigned long long>(v)); }
JsonStream& operator<<(long v)
{ return operator<<(static_cast<long long>(v)); }
JsonStream& operator<<(int v)
{ return operator<<(static_cast<long long>(v)); }
JsonStream& operator<<(const char* c)
{ return operator<<(stringref(c)); }
JsonStream& finalize();
vespalib::string getJsonStreamState() const;
private:
string getStateString() const;
void fail(stringref error) const;
};
} // vespalib
|