UniRec  3.3.2
unirecRecord.hpp
Go to the documentation of this file.
1 
10 #pragma once
11 
12 #include "unirecArray.hpp"
13 #include "unirecRecordView.hpp"
14 #include "unirecTypeTraits.hpp"
15 #include "unirecTypes.hpp"
16 
17 #include <cstddef>
18 #include <exception>
19 #include <numeric>
20 #include <string>
21 #include <type_traits>
22 #include <unirec/unirec.h>
23 #include <vector>
24 
25 namespace Nemea {
26 
33 class UnirecRecord {
34 public:
41  : m_recordSize(0)
42  , m_recordData(nullptr)
43  , m_unirecTemplate(nullptr)
44  {
45  }
46 
56  UnirecRecord(ur_template_t* unirecTemplate, size_t maxVariableFieldsSize = UR_MAX_SIZE)
57  : m_recordSize(maxVariableFieldsSize)
58  , m_unirecTemplate(unirecTemplate)
59  {
60  m_recordData = ur_create_record(unirecTemplate, maxVariableFieldsSize);
61  if (!m_recordData) {
62  throw std::runtime_error("Allocation of UniRec record failed");
63  }
64  }
65 
66  void copyFieldsFrom(const UnirecRecord& otherRecord)
67  {
68  if (!m_unirecTemplate || !m_recordData) {
69  throw std::runtime_error(
70  "UnirecRecord::copyFieldsFrom() has failed. Record has no template or allocated "
71  "memory!");
72  }
73 
74  // TODO: check sufficient record size
75 
76  if (otherRecord.m_recordData != nullptr) {
80  otherRecord.m_unirecTemplate,
81  otherRecord.m_recordData);
82  }
83  }
84 
85  void copyFieldsFrom(const UnirecRecordView& otherRecordView)
86  {
87  if (!m_unirecTemplate || !m_recordData) {
88  throw std::runtime_error(
89  "UnirecRecord::copyFieldsFrom() has failed. Record has no template or allocated "
90  "memory!");
91  }
92 
93  // TODO: check sufficient record size
94 
95  if (otherRecordView.m_recordData != nullptr) {
99  otherRecordView.m_unirecTemplate,
100  otherRecordView.m_recordData);
101  }
102  }
103 
111 
117  const void* data() const noexcept { return m_recordData; }
118 
124  size_t size() const noexcept { return ur_rec_size(m_unirecTemplate, m_recordData); }
125 
154  template<typename T>
155  T getFieldAsType(ur_field_id_t fieldID) const
156  {
157  using BaseType = typename std::remove_cv_t<
158  typename std::remove_pointer_t<typename std::remove_reference_t<T>>>;
159 
160  checkDataTypeCompatibility<T>(fieldID);
161 
162  if constexpr (is_string_v<T>) {
163  return getFieldAsStringType<T>(fieldID);
164  } else if constexpr (std::is_pointer_v<T>) {
165  return getFieldAsPointer<T>(fieldID);
166  } else if constexpr (std::is_reference_v<T>) {
167  return getFieldAsReference<BaseType>(fieldID);
168  } else {
169  return getFieldAsValue<T>(fieldID);
170  }
171  }
172 
188  template<typename T>
190  {
191  return UnirecArray<T>(
192  static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)),
194  ur_get_type(fieldID));
195  }
196 
222  template<typename T>
223  UnirecArray<T> reserveUnirecArray(size_t elementsCount, ur_field_id_t fieldID)
224  {
225  int retCode = ur_array_allocate(m_unirecTemplate, m_recordData, fieldID, elementsCount);
226  if (retCode != UR_OK) {
227  throw std::runtime_error("Unable to allocate memory for UnirecArray");
228  }
229 
230  return UnirecArray<T>(
231  static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)),
232  elementsCount,
233  fieldID);
234  }
235 
250  template<typename T>
251  void setFieldFromType(const T& fieldData, ur_field_id_t fieldID)
252  {
253  if constexpr (is_string_v<T>) {
254  ur_set_string(m_unirecTemplate, m_recordData, fieldID, fieldData.data());
255  } else {
256  *static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)) = fieldData;
257  }
258  }
259 
269  template<typename T>
270  void setFieldFromUnirecArray(const UnirecArray<T>& unirecArray, ur_field_id_t fieldID)
271  {
272  checkDataTypeCompatibility<T>(fieldID);
273 
274  if (ur_is_array(fieldID)) {
275  ur_array_allocate(m_unirecTemplate, m_recordData, fieldID, unirecArray.size());
276  std::copy(
277  unirecArray.begin(),
278  unirecArray.end(),
279  static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)));
280  } else {
281  setFieldFromType<T>(unirecArray.at(0), fieldID);
282  }
283  }
284 
285  UnirecRecord(const UnirecRecord& other) { copyFrom(other); }
286 
288  {
289  if (&other == this) {
290  return *this;
291  }
292 
293  if (m_recordData != nullptr) {
295  m_recordData = nullptr;
296  }
297 
298  copyFrom(other);
299  return *this;
300  }
301 
314  template<typename T>
315  void setFieldFromVector(const std::vector<T>& sourceVector, ur_field_id_t fieldID)
316  {
317  checkDataTypeCompatibility<T>(fieldID);
318 
319  if (!ur_is_array(fieldID)) {
320  throw std::runtime_error("Cannot set vector to non-array unirec field");
321  }
322 
323  ur_array_allocate(m_unirecTemplate, m_recordData, fieldID, sourceVector.size());
324  std::copy(
325  sourceVector.begin(),
326  sourceVector.end(),
327  static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)));
328  }
329 
330 private:
331  template<typename T>
333  {
334  using BaseType = typename std::remove_cv_t<
335  typename std::remove_pointer_t<typename std::remove_reference_t<T>>>;
336  using RequiredType = typename std::conditional_t<is_string_v<BaseType>, T, BaseType>;
337 
338  ur_field_type_t expectedType;
339  if (ur_is_array(fieldID)) {
340  expectedType = getExpectedUnirecType<RequiredType*>();
341  } else {
342  expectedType = getExpectedUnirecType<RequiredType>();
343  }
344 
345  if (expectedType != ur_get_type(fieldID)) {
346  throw std::runtime_error(
347  "UnirecRecord data type format mismatch: " + std::string(typeid(T).name()));
348  }
349  }
350 
351  template<typename T>
353  {
354  return T(
355  static_cast<const char*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID)),
357  }
358 
359  template<typename T>
361  {
362  return static_cast<T>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID));
363  }
364 
365  template<typename T>
367  {
368  return *reinterpret_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID));
369  }
370 
371  template<typename T>
373  {
374  return *static_cast<T*>(ur_get_ptr_by_id(m_unirecTemplate, m_recordData, fieldID));
375  }
376 
377  void copyFrom(const UnirecRecord& other)
378  {
380  m_recordSize = other.m_recordSize;
381  if (other.m_recordData != nullptr) {
384  if (!m_recordData) {
385  throw std::runtime_error("Allocation of UniRec record failed");
386  }
387  }
388  }
389 
390  size_t m_recordSize;
391 
394 };
395 
396 } // namespace Nemea
A wrapper class for a contiguous array of values with the same unirec fieldID.
Definition: unirecArray.hpp:30
constexpr Iterator begin() const noexcept
Returns an iterator to the first element of the UniRec field array.
Definition: unirecArray.hpp:94
constexpr Iterator end() const noexcept
Returns an iterator to the element following the last element of the UniRec field array.
constexpr size_t size() const noexcept
Returns the number of elements in the UniRec field array.
Definition: unirecArray.hpp:89
constexpr T & at(size_t pos) const
Returns a reference to the element at the specified position in the UniRec field array,...
Provides a view into a UniRec record.
ur_template_t * m_unirecTemplate
A class for working with UniRec records and their fields.
T getFieldAsType(ur_field_id_t fieldID) const
Gets the value of a UniRec field and converts it to the specified type.
T getFieldAsPointer(ur_field_id_t fieldID) const
const void * data() const noexcept
Returns a pointer to the data of the UniRec record.
~UnirecRecord()
Destructor.
void checkDataTypeCompatibility(ur_field_id_t fieldID) const
void setFieldFromUnirecArray(const UnirecArray< T > &unirecArray, ur_field_id_t fieldID)
Sets the value of a UniRec field using a UnirecArray.
void copyFieldsFrom(const UnirecRecord &otherRecord)
T getFieldAsReference(ur_field_id_t fieldID) const
void setFieldFromType(const T &fieldData, ur_field_id_t fieldID)
Sets the value of a UniRec field using data of a specified type.
ur_template_t * m_unirecTemplate
UnirecRecord(ur_template_t *unirecTemplate, size_t maxVariableFieldsSize=UR_MAX_SIZE)
Constructor with template and maximum variable fields size.
void copyFrom(const UnirecRecord &other)
UnirecRecord()
Default constructor.
T getFieldAsValue(ur_field_id_t fieldID) const
UnirecRecord(const UnirecRecord &other)
UnirecArray< T > reserveUnirecArray(size_t elementsCount, ur_field_id_t fieldID)
Reserves memory for a UniRecArray within a UniRec field.
UnirecArray< T > getFieldAsUnirecArray(ur_field_id_t fieldID)
Gets a UniRecArray representing a UniRec field.
size_t size() const noexcept
Returns the size of the UniRec record.
T getFieldAsStringType(ur_field_id_t fieldID) const
void setFieldFromVector(const std::vector< T > &sourceVector, ur_field_id_t fieldID)
Sets the value of a UniRec array field using a vector of values.
UnirecRecord & operator=(const UnirecRecord &other)
void copyFieldsFrom(const UnirecRecordView &otherRecordView)
#define ur_set_string(tmplt, rec, field_id, str)
Set variable-length field to given string. Set contents of a variable-length field in the record....
Definition: unirec.h:517
#define ur_array_allocate(tmplt, rec, field_id, elem_cnt)
Preallocates UniRec array field to have requested number of elements.
Definition: unirec.h:629
#define ur_is_array(field_id)
Definition: unirec.h:526
#define ur_rec_size(tmplt, rec)
Get size of UniRec record (static and variable length) Get total size of whole UniRec record.
Definition: unirec.h:680
void * ur_create_record(const ur_template_t *tmplt, uint16_t max_var_size)
Definition: unirec.c:1220
#define UR_MAX_SIZE
Definition: unirec.h:1013
#define ur_get_var_len(tmplt, rec, field_id)
Get size of a variable sized field in the record. Get size of a variable-length field in the record....
Definition: unirec.h:474
#define ur_array_get_elem_cnt(tmplt, rec, field_id)
Get number of elements stored in an UniRec array.
Definition: unirec.h:546
void ur_copy_fields(const ur_template_t *dst_tmplt, void *dst, const ur_template_t *src_tmplt, const void *src)
Copy data from one UniRec record to another. Copies all fields present in both templates from src to ...
Definition: unirec.c:1259
#define ur_get_type(field_id)
Get type of UniRec field Get type of any UniRec defined field.
Definition: unirec.h:388
void ur_free_record(void *record)
Definition: unirec.c:1229
#define ur_get_ptr_by_id(tmplt, data, field_id)
Get pointer to UniRec field Get pointer to fixed or varible length UniRec field. In contrast to ur_ge...
Definition: unirec.h:442
Header file containing the definition of the UnirecArray class and its Iterator subclass.
Provides a view into a UniRec record.
Provides a set of type traits and aliases for working with unirec++.
This file contains functions for determining the expected UniRec type for various C++ types.
Definition of UniRec structures and functions.
ur_field_type_t
Definition: unirec.h:95
int16_t ur_field_id_t
Type of UniRec field identifiers.
Definition: unirec.h:136
#define UR_OK
No problem.
Definition: unirec.h:90
UniRec template. It contains a table mapping a field to its position in an UniRec record.
Definition: unirec.h:191