libcluon  0.0.148
FromProtoVisitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2017-2018 Christian Berger
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 #ifndef CLUON_FROMPROTOVISITOR_HPP
10 #define CLUON_FROMPROTOVISITOR_HPP
11 
12 #include "cluon/ProtoConstants.hpp"
13 #include "cluon/cluon.hpp"
14 #include "cluon/any/any.hpp"
15 
16 #include <cstdint>
17 #include <cstddef>
18 #include <array>
19 #include <sstream>
20 #include <string>
21 #include <unordered_map>
22 #include <vector>
23 
24 namespace cluon {
29  private:
30  FromProtoVisitor(const FromProtoVisitor &) = delete;
32  FromProtoVisitor &operator=(FromProtoVisitor &&) = delete;
33 
34  public:
35  FromProtoVisitor() = default;
36  ~FromProtoVisitor() = default;
37 
38  public:
39  FromProtoVisitor &operator=(const FromProtoVisitor &other) noexcept;
40 
46  void decodeFrom(std::istream &in) noexcept;
47 
48  public:
49  // The following methods are provided to allow an instance of this class to
50  // be used as visitor for an instance with the method signature void accept<T>(T&);
51 
52  void preVisit(int32_t id, const std::string &shortName, const std::string &longName) noexcept;
53  void postVisit() noexcept;
54 
55  void visit(uint32_t id, std::string &&typeName, std::string &&name, bool &v) noexcept;
56  void visit(uint32_t id, std::string &&typeName, std::string &&name, char &v) noexcept;
57  void visit(uint32_t id, std::string &&typeName, std::string &&name, int8_t &v) noexcept;
58  void visit(uint32_t id, std::string &&typeName, std::string &&name, uint8_t &v) noexcept;
59  void visit(uint32_t id, std::string &&typeName, std::string &&name, int16_t &v) noexcept;
60  void visit(uint32_t id, std::string &&typeName, std::string &&name, uint16_t &v) noexcept;
61  void visit(uint32_t id, std::string &&typeName, std::string &&name, int32_t &v) noexcept;
62  void visit(uint32_t id, std::string &&typeName, std::string &&name, uint32_t &v) noexcept;
63  void visit(uint32_t id, std::string &&typeName, std::string &&name, int64_t &v) noexcept;
64  void visit(uint32_t id, std::string &&typeName, std::string &&name, uint64_t &v) noexcept;
65  void visit(uint32_t id, std::string &&typeName, std::string &&name, float &v) noexcept;
66  void visit(uint32_t id, std::string &&typeName, std::string &&name, double &v) noexcept;
67  void visit(uint32_t id, std::string &&typeName, std::string &&name, std::string &v) noexcept;
68 
69  template <typename T>
70  void visit(uint32_t &id, std::string &&typeName, std::string &&name, T &v) noexcept {
71  (void)typeName;
72  (void)name;
73 
74  if (m_callToDecodeFromWithDirectVisit) {
75  std::stringstream sstr{std::move(std::string(m_stringValue.data(), static_cast<std::size_t>(m_value)))};
76  cluon::FromProtoVisitor nestedProtoDecoder;
77  nestedProtoDecoder.decodeFrom(sstr, v);
78  }
79  else if (0 < m_mapOfKeyValues.count(id)) {
80  try {
81  std::stringstream sstr{linb::any_cast<std::string>(m_mapOfKeyValues[id])};
82  cluon::FromProtoVisitor nestedProtoDecoder;
83  nestedProtoDecoder.decodeFrom(sstr);
84  v.accept(nestedProtoDecoder);
85  } catch (const linb::bad_any_cast &) { // LCOV_EXCL_LINE
86  }
87  }
88  }
89 
90  public:
97  template<typename T>
98  void decodeFrom(std::istream &in, T &v) noexcept {
99  m_callToDecodeFromWithDirectVisit = true;
100  while (in.good()) {
101  // First stage: Read keyFieldType (encoded as VarInt).
102  if (0 < fromVarInt(in, m_keyFieldType)) {
103  // Succeeded to read keyFieldType entry; extract information.
104  m_protoType = static_cast<ProtoConstants>(m_keyFieldType & 0x7);
105  m_fieldId = static_cast<uint32_t>(m_keyFieldType >> 3);
106  switch (m_protoType) {
108  {
109  // Directly decode VarInt value.
110  fromVarInt(in, m_value);
111  v.accept(m_fieldId, *this);
112  }
113  break;
115  {
116  readBytesFromStream(in, sizeof(double), m_doubleValue.buffer.data());
117  m_doubleValue.uint64Value = le64toh(m_doubleValue.uint64Value);
118  v.accept(m_fieldId, *this);
119  }
120  break;
122  {
123  readBytesFromStream(in, sizeof(float), m_floatValue.buffer.data());
124  m_floatValue.uint32Value = le32toh(m_floatValue.uint32Value);
125  v.accept(m_fieldId, *this);
126  }
127  break;
129  {
130  fromVarInt(in, m_value);
131  const std::size_t BYTES_TO_READ_FROM_STREAM{static_cast<std::size_t>(m_value)};
132  if (m_stringValue.capacity() < BYTES_TO_READ_FROM_STREAM) {
133  m_stringValue.reserve(BYTES_TO_READ_FROM_STREAM);
134  }
135  readBytesFromStream(in, BYTES_TO_READ_FROM_STREAM, m_stringValue.data());
136  v.accept(m_fieldId, *this);
137  }
138  break;
139  }
140  }
141  }
142  m_callToDecodeFromWithDirectVisit = false;
143  }
144 
145  private:
146  int8_t fromZigZag8(uint8_t v) noexcept;
147  int16_t fromZigZag16(uint16_t v) noexcept;
148  int32_t fromZigZag32(uint32_t v) noexcept;
149  int64_t fromZigZag64(uint64_t v) noexcept;
150 
151  std::size_t fromVarInt(std::istream &in, uint64_t &value) noexcept;
152 
153  void readBytesFromStream(std::istream &in, std::size_t bytesToReadFromStream, char *buffer) noexcept;
154 
155  private:
156  // This Boolean flag indicates whether we consecutively decode from istream
157  // and inject the decoded values directly into the receiving data structure.
158  bool m_callToDecodeFromWithDirectVisit{false};
159  std::unordered_map<uint32_t, linb::any, UseUInt32ValueAsHashKey> m_mapOfKeyValues{};
160 
161  private:
162  // Fields necessary to decode from an istream.
163  uint64_t m_value{0};
164 
165  // Union buffer for double values.
166  union DoubleValue {
167  std::array<char, sizeof(double)> buffer;
168  uint64_t uint64Value;
169  double doubleValue{0};
170  } m_doubleValue;
171 
172  // Union buffer for float values.
173  union FloatValue {
174  std::array<char, sizeof(float)> buffer;
175  uint32_t uint32Value;
176  float floatValue{0};
177  } m_floatValue;
178 
179  // Buffer for strings.
180  std::vector<char> m_stringValue;
181 
182  uint64_t m_keyFieldType{0};
184  uint32_t m_fieldId{0};
185 };
186 } // namespace cluon
187 
188 #endif
void decodeFrom(std::istream &in, T &v) noexcept
Definition: FromProtoVisitor.hpp:98
Definition: cluon.hpp:65
ProtoConstants
Definition: ProtoConstants.hpp:16
Definition: FromProtoVisitor.hpp:28
#define LIBCLUON_API
Definition: cluon.hpp:56
void decodeFrom(std::istream &in) noexcept
Definition: FromProtoVisitor.cpp:35
void visit(uint32_t &id, std::string &&typeName, std::string &&name, T &v) noexcept
Definition: FromProtoVisitor.hpp:70