UniRec  3.0.0
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 NemeaPlusPlus {
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 NemeaPlusPlus
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 T & at(size_t pos) const
Returns a reference to the element at the specified position in the UniRec field array,...
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
Provides a view into a UniRec record.
A class for working with UniRec records and their fields.
UnirecRecord(const UnirecRecord &other)
void copyFrom(const UnirecRecord &other)
UnirecRecord(ur_template_t *unirecTemplate, size_t maxVariableFieldsSize=UR_MAX_SIZE)
Constructor with template and maximum variable fields size.
UnirecArray< T > getFieldAsUnirecArray(ur_field_id_t fieldID)
Gets a UniRecArray representing a UniRec field.
UnirecRecord & operator=(const UnirecRecord &other)
void setFieldFromUnirecArray(const UnirecArray< T > &unirecArray, ur_field_id_t fieldID)
Sets the value of a UniRec field using a UnirecArray.
T getFieldAsReference(ur_field_id_t fieldID) const
void copyFieldsFrom(const UnirecRecord &otherRecord)
T getFieldAsValue(ur_field_id_t fieldID) const
UnirecArray< T > reserveUnirecArray(size_t elementsCount, ur_field_id_t fieldID)
Reserves memory for a UniRecArray within a UniRec field.
void copyFieldsFrom(const UnirecRecordView &otherRecordView)
UnirecRecord()
Default constructor.
size_t size() const noexcept
Returns the size of the UniRec record.
T getFieldAsStringType(ur_field_id_t fieldID) const
T getFieldAsPointer(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.
T getFieldAsType(ur_field_id_t fieldID) const
Gets the value of a UniRec field and converts it to the specified type.
const void * data() const noexcept
Returns a pointer to the data of the UniRec record.
ur_template_t * m_unirecTemplate
void checkDataTypeCompatibility(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.
#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