helics  2.8.1
ValueConverter_impl.hpp
1 /*
2 Copyright (c) 2017-2021,
3 Battelle Memorial Institute; Lawrence Livermore National Security, LLC; Alliance for Sustainable
4 Energy, LLC. See the top-level NOTICE for additional details. All rights reserved.
5 SPDX-License-Identifier: BSD-3-Clause
6 */
7 #pragma once
8 
13 #include "../core/core-data.hpp"
14 #include "data_view.hpp"
15 #include "helicsTypes.hpp"
16 
17 #include <algorithm>
18 #include <array>
19 #include <cassert>
20 #include <complex>
21 #include <cstring>
22 #include <helics/external/cereal/archives/portable_binary.hpp>
23 #include <helics/external/cereal/cereal.hpp>
24 #include <helics/external/cereal/types/complex.hpp>
25 #include <helics/external/cereal/types/utility.hpp>
26 #include <helics/external/cereal/types/vector.hpp>
27 #include <iterator>
28 #include <stdexcept>
29 #include <string>
30 #include <type_traits>
31 #include <utility>
32 #include <vector>
33 //#include <helics/external/cereal/archives/binary.hpp>
34 #include <helics/external/cereal/types/string.hpp>
35 
36 using archiver = cereal::PortableBinaryOutputArchive;
37 
38 using retriever = cereal::PortableBinaryInputArchive;
39 
40 namespace helics {
41 template<class Archive>
42 void save(Archive& ar, const data_block& db)
43 {
44  ar(db.to_string());
45 }
46 
47 template<class Archive>
48 void load(Archive& ar, data_block& db)
49 {
50  std::string val;
51  ar(val);
52  db = std::move(val);
53 }
54 
55 template<class Archive>
56 void save(Archive& ar, const data_view& db)
57 {
58  ar(db.string());
59 }
60 
61 template<class Archive>
62 void load(Archive& ar, data_view& db)
63 {
64  std::string val;
65  ar(val);
66  db = data_view{std::move(val)};
67 }
68 
69 template<class Archive>
70 void serialize(Archive& archive, NamedPoint& m)
71 {
72  archive(m.name, m.value);
73 }
74 
75 namespace detail {
76  // templates for this derived from http://www.voidcn.com/article/p-vjnlygmc-gy.html
77  class membuf: public std::streambuf {
78  public:
79  membuf(const char* buf, size_t size): begin_(buf), end_(buf + size), current_(buf) {}
80 
81  private:
82  int_type underflow()
83  {
84  if (current_ == end_) {
85  return traits_type::eof();
86  }
87 
88  return traits_type::to_int_type(*current_);
89  }
90  int_type uflow()
91  {
92  if (current_ == end_) {
93  return traits_type::eof();
94  }
95 
96  return traits_type::to_int_type(*current_++);
97  }
98  int_type pbackfail(int_type ch)
99  {
100  if (current_ == begin_ || (ch != traits_type::eof() && ch != current_[-1])) {
101  return traits_type::eof();
102  }
103 
104  return traits_type::to_int_type(*--current_);
105  }
106  std::streamsize showmanyc() { return end_ - current_; }
107 
108  public:
109  // copy ctor and assignment not implemented;
110  // copying not allowed
111  membuf(const membuf&) = delete;
112  membuf& operator=(const membuf&) = delete;
113 
114  private:
115  const char* const begin_;
116  const char* const end_;
117  const char* current_;
118  };
119 
120  struct imemstream: virtual membuf, std::istream {
121  imemstream(const char* buf, size_t size):
122  membuf(buf, size), std::istream(static_cast<std::streambuf*>(this))
123  {
124  }
125  };
126 
128  class ostringbuf: public std::streambuf {
129  public:
130  ostringbuf()
131  {
132  char* base = abuf_.data();
133  setp(base, base + bufsize - 1); // one less than the buffer size
134  }
136  void reserve(size_t size) { sbuf_.reserve(size); }
138  std::string extractString()
139  {
140  std::string retString(std::move(sbuf_));
141  sbuf_.clear();
142  return retString;
143  }
144 
145  protected:
146  void move_to_string_and_flush()
147  {
148  sbuf_.append(pbase(), pptr());
149  std::ptrdiff_t n = pptr() - pbase();
150  pbump(static_cast<int>(-n));
151  }
152 
153  private:
154  int_type overflow(int_type ch)
155  {
156  if (ch != traits_type::eof()) {
157  *pptr() = static_cast<char>(ch);
158  pbump(1); // always safe due to buffer at 1 space reserved
159  move_to_string_and_flush();
160  return ch;
161  }
162 
163  return traits_type::eof();
164  }
165  int sync()
166  {
167  move_to_string_and_flush();
168  return 0;
169  }
170 
171  // copy ctor and assignment not implemented;
172  // copying not allowed
173  ostringbuf(const ostringbuf&) = delete;
174  ostringbuf& operator=(const ostringbuf&) = delete;
175 
176  private:
177  static constexpr size_t bufsize = 64;
178  std::array<char, bufsize> abuf_;
179  std::string sbuf_;
180  };
181 
182  struct ostringbufstream: virtual ostringbuf, std::ostream {
183  ostringbufstream(): std::ostream(static_cast<std::streambuf*>(this)) {}
184  };
185 
186  struct ostreambuf: public std::streambuf {
187  ostreambuf(char* buf, size_t size) { this->setg(buf, buf, buf + size); }
188  };
189 } // namespace detail
190 
191 template<class X>
192 void ValueConverter<X>::convert(const X& val, data_block& store)
193 {
195  archiver oa(s);
196 
197  oa(val);
198 
199  // don't forget to flush the stream to finish writing into the buffer
200  s.flush();
201  store = s.extractString();
202 }
203 
204 template<class X>
205 void ValueConverter<X>::convert(const X* vals, size_t size, data_block& store)
206 {
208  archiver oa(s);
209  oa(cereal::make_size_tag(static_cast<cereal::size_type>(size))); // number of elements
210  for (size_t ii = 0; ii < size; ++ii) {
211  oa(vals[ii]);
212  }
213  // don't forget to flush the stream to finish writing into the buffer
214  s.flush();
215  // store = std::move (data);
216  store = s.extractString();
217 }
218 
220 template<typename T, typename _ = void>
221 struct is_vector {
222  static constexpr bool value = false;
223 };
224 template<typename T>
225 struct is_vector<
226  T,
227  typename std::enable_if_t<
228  std::is_same<T, std::vector<typename T::value_type, typename T::allocator_type>>::value>> {
229  static constexpr bool value = true;
230 };
231 
233 template<typename T, typename _ = void>
234 struct is_iterable {
235  static constexpr bool value = false;
236 };
237 
238 template<typename T>
239 struct is_iterable<T,
240  typename std::enable_if_t<std::is_same<
241  decltype(std::begin(T()) != std::end(T()), // begin/end and operator != and
242  // has default constructor
243  void(),
244  void(*std::begin(T())), // dereference operator
245  std::true_type{}),
246  std::true_type>::value>> {
247  static constexpr bool value = true;
248 };
249 
251 template<class X>
252 constexpr std::enable_if_t<!is_iterable<X>::value && !std::is_convertible<X, std::string>::value,
253  size_t>
255 {
256  return sizeof(X) + 1;
257 }
258 
260 template<class X>
261 constexpr std::enable_if_t<is_iterable<X>::value && !std::is_convertible<X, std::string>::value,
262  size_t>
264 {
265  return 9;
266 }
267 
268 template<class X>
269 constexpr std::enable_if_t<std::is_convertible<X, std::string>::value, size_t> getMinSize()
270 {
271  return 0;
272 }
273 
275 template<>
276 constexpr size_t getMinSize<NamedPoint>()
277 {
278  return 10;
279 }
280 
281 template<class X>
282 data_block ValueConverter<X>::convert(const X* vals, size_t size)
283 {
284  auto dv = data_block();
285  convert(vals, size, dv);
286  return dv;
287 }
288 
290 template<class X>
292 {
293  auto dv = data_block();
294  convert(val, dv);
295  return dv;
296 }
297 
298 template<class X>
299 void ValueConverter<X>::interpret(const data_view& block, X& val)
300 {
301  if (block.size() < getMinSize<X>()) {
302  std::string arg = std::string("invalid data size: expected ") +
303  std::to_string(getMinSize<X>()) + ", received " + std::to_string(block.size());
304  throw std::invalid_argument(arg);
305  }
306  detail::imemstream s(block.data(), block.size());
307  retriever ia(s);
308  try {
309  ia(val);
310  }
311  catch (const cereal::Exception& ce) {
312  throw std::invalid_argument(ce.what());
313  }
314 }
315 
316 template<class X>
318 {
319  X val;
320  interpret(block, val);
321  return val;
322 }
323 } // namespace helics
helicsTypes.hpp
helics::detail::ostringbuf::reserve
void reserve(size_t size)
Definition: ValueConverter_impl.hpp:136
helics::data_block
Definition: core-data.hpp:31
helics::ValueConverter::interpret
static X interpret(const data_view &block)
Definition: ValueConverter_impl.hpp:317
helics::detail::ostringbuf::extractString
std::string extractString()
Definition: ValueConverter_impl.hpp:138
helics::detail::ostringbuf
Definition: ValueConverter_impl.hpp:128
helics::data_view
Definition: data_view.hpp:22
helics::ValueConverter::convert
static data_block convert(const X &val)
Definition: ValueConverter_impl.hpp:291
helics::detail::ostringbufstream
Definition: ValueConverter_impl.hpp:182
helics::detail::ostreambuf
Definition: ValueConverter_impl.hpp:186
helics::data_view::data
const char * data() const noexcept
Definition: data_view.hpp:105
helics::getMinSize
constexpr std::enable_if_t<!is_iterable< X >::value &&!std::is_convertible< X, std::string >::value, size_t > getMinSize()
Definition: ValueConverter_impl.hpp:254
helics
the main namespace for the helics co-simulation library User functions will be in the helics namespac...
Definition: AsyncFedCallInfo.hpp:14
helics::data_view::size
size_t size() const noexcept
Definition: data_view.hpp:107
helics::is_vector
Definition: ValueConverter_impl.hpp:221
helics::detail::imemstream
Definition: ValueConverter_impl.hpp:120
helics::is_iterable
Definition: ValueConverter_impl.hpp:234
helics::getMinSize< NamedPoint >
constexpr size_t getMinSize< NamedPoint >()
Definition: ValueConverter_impl.hpp:276
helics::detail::membuf
Definition: ValueConverter_impl.hpp:77