Line data Source code
1 :
2 : /* Copyright (c) 2015-2016, Human Brain Project
3 : * Stefan.Eilemann@epfl.ch
4 : */
5 :
6 : #include "Zerobuf.h"
7 :
8 : #include "NonMovingAllocator.h"
9 : #include "NonMovingSubAllocator.h"
10 : #include "StaticSubAllocator.h"
11 : #include "jsoncpp/json/json.h"
12 : #include <zerobuf/version.h>
13 :
14 : #include <cstring>
15 : #include <iostream>
16 :
17 : namespace zerobuf
18 : {
19 412 : Zerobuf::Zerobuf(AllocatorPtr alloc)
20 412 : : _allocator(std::move(alloc))
21 : {
22 821 : if (_allocator &&
23 409 : ((const Allocator*)_allocator.get())->getItem<uint32_t>(0) !=
24 412 : ZEROBUF_VERSION_ABI)
25 : {
26 322 : _allocator->getItem<uint32_t>(0) = ZEROBUF_VERSION_ABI;
27 : }
28 412 : }
29 :
30 187 : Zerobuf::Zerobuf(Zerobuf&& rhs)
31 : {
32 187 : _allocator = std::move(rhs._allocator);
33 374 : rhs._allocator.reset(new NonMovingAllocator(rhs.getZerobufStaticSize(),
34 374 : rhs.getZerobufNumDynamics()));
35 187 : uint32_t& version = rhs._allocator->getItem<uint32_t>(0);
36 187 : version = ZEROBUF_VERSION_ABI;
37 187 : }
38 :
39 599 : Zerobuf::~Zerobuf()
40 : {
41 599 : }
42 :
43 51 : Zerobuf& Zerobuf::operator=(const Zerobuf& rhs)
44 : {
45 51 : if (this == &rhs || !_allocator || !rhs._allocator)
46 0 : return *this;
47 :
48 51 : if (getTypeIdentifier() != rhs.getTypeIdentifier())
49 1 : throw std::runtime_error("Can't assign Zerobuf of a different type");
50 :
51 100 : _allocator->copyBuffer(rhs._allocator->getData(),
52 100 : rhs._allocator->getSize());
53 50 : notifyChanged();
54 50 : return *this;
55 : }
56 :
57 5 : Zerobuf& Zerobuf::operator=(Zerobuf&& rhs)
58 : {
59 5 : if (this == &rhs || !rhs._allocator)
60 1 : return *this;
61 :
62 4 : if (getTypeIdentifier() != rhs.getTypeIdentifier())
63 0 : throw std::runtime_error("Can't assign Zerobuf of a different type");
64 :
65 4 : if (_allocator->isMovable() && rhs._allocator->isMovable())
66 1 : _allocator = std::move(rhs._allocator);
67 : else // Sub allocator data can't be moved - need to copy
68 6 : _allocator->copyBuffer(rhs._allocator->getData(),
69 6 : rhs._allocator->getSize());
70 :
71 8 : rhs._allocator.reset(new NonMovingAllocator(rhs.getZerobufStaticSize(),
72 8 : rhs.getZerobufNumDynamics()));
73 4 : notifyChanged();
74 4 : return *this;
75 : }
76 :
77 23 : void Zerobuf::compact(const float threshold)
78 : {
79 23 : if (_allocator && getZerobufNumDynamics() > 0)
80 22 : _allocator->compact(threshold);
81 23 : }
82 :
83 1 : bool Zerobuf::_fromBinary(const void* data, const size_t size)
84 : {
85 1 : if (!_allocator)
86 1 : throw std::runtime_error("Can't copy data into empty Zerobuf object");
87 :
88 0 : if (size < 4)
89 : {
90 0 : std::cerr << "zerobuf too small" << std::endl;
91 0 : return false;
92 : }
93 :
94 0 : const uint32_t version = *reinterpret_cast<const uint32_t*>(data);
95 0 : if (version != ZEROBUF_VERSION_ABI)
96 : {
97 0 : std::cerr << "Version mismatch, got zerobuf v" << version
98 0 : << " running v" << ZEROBUF_VERSION_ABI << std::endl;
99 0 : return false;
100 : }
101 :
102 0 : _allocator->copyBuffer(data, size);
103 0 : notifyChanged();
104 0 : return true;
105 : }
106 :
107 1104 : Data Zerobuf::_toBinary() const
108 : {
109 1104 : if (!_allocator)
110 2 : return Data();
111 :
112 2204 : Data data;
113 : data.ptr =
114 2204 : std::shared_ptr<const void>(_allocator->getData(), [](const void*) {});
115 1102 : data.size = _allocator->getSize();
116 1102 : return data;
117 : }
118 :
119 9 : bool Zerobuf::_fromJSON(const std::string& string)
120 : {
121 9 : if (!_allocator)
122 2 : return true;
123 :
124 14 : Json::Value json;
125 14 : Json::Reader reader;
126 7 : if (!reader.parse(string, json))
127 : {
128 : std::cerr << "Error parsing JSON: "
129 0 : << reader.getFormattedErrorMessages() << std::endl
130 0 : << " while parsing: " << string << std::endl;
131 0 : return false;
132 : }
133 :
134 : try
135 : {
136 7 : _parseJSON(json);
137 : }
138 0 : catch (const std::exception& e)
139 : {
140 0 : std::cerr << "Error applying JSON: " << e.what() << std::endl;
141 0 : return false;
142 : }
143 :
144 7 : compact();
145 7 : return true;
146 : }
147 :
148 52 : std::string Zerobuf::_toJSON() const
149 : {
150 52 : if (!_allocator)
151 2 : return "{}";
152 :
153 100 : Json::Value json;
154 50 : _createJSON(json);
155 50 : return json.toStyledString();
156 : }
157 :
158 0 : void Zerobuf::_parseJSON(const Json::Value&)
159 : {
160 0 : throw std::runtime_error(std::string("JSON parsing missing for ") +
161 0 : typeid(*this).name());
162 : }
163 :
164 0 : void Zerobuf::_createJSON(Json::Value&) const
165 : {
166 0 : throw std::runtime_error(std::string("JSON parsing missing for ") +
167 0 : typeid(*this).name());
168 : }
169 :
170 24 : bool Zerobuf::operator==(const Zerobuf& rhs) const
171 : {
172 96 : if (this == &rhs ||
173 52 : (!_allocator && getTypeIdentifier() == rhs.getTypeIdentifier()))
174 : {
175 2 : return true;
176 : }
177 22 : return toJSON() == rhs.toJSON();
178 : }
179 :
180 0 : bool Zerobuf::operator!=(const Zerobuf& rhs) const
181 : {
182 0 : return !(*this == rhs);
183 : }
184 :
185 12 : void Zerobuf::reset(AllocatorPtr allocator)
186 : {
187 12 : _allocator.swap(allocator);
188 12 : }
189 :
190 1420 : Allocator& Zerobuf::getAllocator()
191 : {
192 1420 : if (!_allocator)
193 0 : throw std::runtime_error("Empty Zerobuf has no allocator");
194 :
195 1420 : return *_allocator;
196 : }
197 :
198 1073 : const Allocator& Zerobuf::getAllocator() const
199 : {
200 1073 : if (!_allocator)
201 0 : throw std::runtime_error("Empty Zerobuf has no allocator");
202 :
203 1073 : return *_allocator;
204 : }
205 :
206 2147 : void Zerobuf::_copyZerobufArray(const void* data, const size_t size,
207 : const size_t arrayNum)
208 : {
209 2147 : if (!_allocator)
210 0 : throw std::runtime_error("Can't copy data into empty Zerobuf object");
211 :
212 : void* array =
213 2147 : _allocator->updateAllocation(arrayNum, false /*no copy*/, size);
214 2147 : ::memcpy(array, data, size);
215 2147 : }
216 :
217 120 : void Zerobuf::check() const
218 : {
219 120 : if (_allocator)
220 120 : getAllocator().check(getZerobufNumDynamics());
221 120 : }
222 21 : }
|