Repository navigation
Expand file tree
/
Copy pathdocument.h
More file actions
243 lines (225 loc) · 7.2 KB
/
Copy pathdocument.h
File metadata and controls
243 lines (225 loc) · 7.2 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
Copyright (c) Nathan Eloe, 2014
This file is part of FastBSON-Cpp.
FastBSON-Cpp is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FastBSON-Cpp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with FastBSON-Cpp. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file document.h
* \author Nathan Eloe
* \brief Definition of the BSON Document class
*/
#pragma once
#include "element.h"
#include "typeinfo"
#include <initializer_list>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <ostream>
namespace bson
{
class Document
{
private:
friend class Element;
std::map<std::string, Element> m_data;
std::set<std::string> m_field_names;
public:
Document() = default;
/*!
* \brief Initialization list constructor
* \pre None
* \post Constructs the dictionary using the init list of key/value pairs
*/
Document (std::initializer_list<std::pair<std::string, Element>> list)
{
for (auto i : list)
{
m_data.emplace (i.first, i.second);
m_field_names.emplace (i.first);
}
}
/*!
* \brief JSON string construction
* \pre None
* \post This document contains information mirroring the JSON string
*/
Document (const std::string &json)
{
from_json (json);
}
/*!
* \brief accessor
* \pre None
* \post None
* \return the Element at the specified field name
* \throws std::out_of_range if index is not in the dictionary
*/
const Element &operator[] (const std::string &index) const
{
return m_data.at (index);
}
Element &operator[] (const std::string &index)
{
return m_data.at (index);
}
/*!
* \brief element addition
* \pre None
* \post creates the element in the map. If name already exists in the document the value is overwritten
*/
void add (const std::string &name, const Element &data)
{
m_data.emplace (name, data);
m_field_names.insert (name);
}
/*!
* \brief element addition
* \pre T must be template specialized for the Element class
* \pre if ti is not defaulted, it and type T must be compatible
* \post creates the element in the map. If name already exists in the document the value is overwritten
*/
template <class T>
void add (const std::string &name, const T &data, const TypeInfo ti = _UNKNOWN)
{
m_data[name] = Element (data, ti);
m_field_names.insert (name);
}
/*!
* \brief element modification
* \pre name exists as an index in the document
* \post changes the element at index name
* \throws std::out_of_range if name is not in the Document
*/
void set (const std::string &name, const Element &data)
{
m_data.at (name) = data;
}
/*!
* \brief element modification
* \pre name exists as an index in the document
* \pre T must be template specialized for the Element class
* \pre if ti is not defaulted, it and type T must be compatible
* \post changes the element at index name
* \throws std::out_of_range if name is not in the Document
*/
template <class T>
void set (const std::string &name, const T &data, const TypeInfo ti = _UNKNOWN)
{
m_data.at (name) = Element (data, ti);
}
/*!
* \brief insertion operator overloading
* \pre None
* \post inserts document d into the stream (using the string conversion for insertion)
*/
friend std::ostream &operator << (std::ostream &o, const Document &d);
/*!
* \brief iterator functions
* \pre None
* \post None
* \return iterators pointing at the beginning and end of the data in the document
*/
auto begin() -> decltype (m_data.begin())
{
return m_data.begin();
}
auto begin() const -> decltype (m_data.begin())
{
return m_data.begin();
}
auto end() -> decltype (m_data.end())
{
return m_data.end();
}
auto end() const -> decltype (m_data.end())
{
return m_data.end();
}
auto rbegin() -> decltype (m_data.rbegin())
{
return m_data.rbegin();
}
auto rend() -> decltype (m_data.rend())
{
return m_data.rend();
}
auto cbegin() -> decltype (m_data.cbegin())
{
return m_data.cbegin();
}
auto cend() -> decltype (m_data.cend())
{
return m_data.cbegin();
}
auto crbegin() -> decltype (m_data.crbegin())
{
return m_data.crbegin();
}
auto crend() -> decltype (m_data.crend())
{
return m_data.crend();
}
/*!
* \brief returns the set of field names
* \pre None
* \post None
* \return the set of field names
*/
std::set<std::string> field_names() const
{
return m_field_names;
}
/*!
* \brief combines two Documents
* \pre None
* \post The supplied Document is combined into this one
*/
void combine (const bson::Document d)
{
m_data.insert (d.begin(), d.end());
m_field_names.insert (d.m_field_names.begin(), d.m_field_names.end());
return;
}
/*!
* \brief Changes this document to mirror the JSON string
* \pre None
* \post This document contains information matching the JSON string
*/
void from_json (const std::string &json);
/*!
* \brief convenience function to get the size of the dictionary
* \pre None
* \post None
* \returns Number of elements in the document
*/
int size() const
{
return m_field_names.size();
}
};
inline std::ostream &operator << (std::ostream &oss, const Document &d)
{
oss << "{ ";
if (d.size() > 0)
{
auto it = d.begin();
oss << '"' << (*it).first << "\" : " << static_cast<std::string> ((*it).second);
++it;
for (; it != d.end(); ++it)
oss << ", \"" << (*it).first << "\" : " << static_cast<std::string> ((*it).second);
}
oss << " }";
return oss;
}
}