PcapPlusPlus  Next
Serializers.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdint>
4 #include <iosfwd>
5 #include <string>
6 #include <type_traits>
7 #include <vector>
8 
10 
13 namespace pcpp
14 {
18  {
20  const uint16_t id;
21 
23  const std::string name;
24 
26  std::vector<FieldDescriptor> (*const getChildren)();
27 
33  FieldDescriptor(uint16_t fieldId, std::string fieldName,
34  std::vector<FieldDescriptor> (*fieldChildren)() = nullptr)
35  : id(fieldId), name(std::move(fieldName)), getChildren(fieldChildren)
36  {}
37 
40  bool hasChildren() const
41  {
42  return getChildren != nullptr;
43  }
44  };
45 
48  template <typename Derived> struct ObjectFieldDescriptor : FieldDescriptor
49  {
53  ObjectFieldDescriptor(uint16_t fieldId, std::string fieldName)
54  : FieldDescriptor(fieldId, std::move(fieldName), &Derived::all)
55  {}
56  };
57 
58  class ScopeBase;
59  class ArrayScope;
60  class ObjectScope;
61 
62  namespace internal
63  {
64  template <typename T>
65  using EnableIfSignedIntegral =
66  std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value && !std::is_same<T, bool>::value,
67  int>;
68 
69  template <typename T>
70  using EnableIfUnsignedIntegral =
71  std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value && !std::is_same<T, bool>::value,
72  int>;
73  } // namespace internal
74 
78  {
79  friend class ScopeBase;
80  friend class ArrayScope;
81  friend class ObjectScope;
82 
83  public:
85  virtual ~ISerializer() = default;
86 
91 
96 
97  protected:
98  // --- Scalar field writes (canonical virtuals) ---
99  virtual void writeField(const FieldDescriptor& field, const std::string& value) = 0;
100  virtual void writeField(const FieldDescriptor& field, int64_t value) = 0;
101  virtual void writeField(const FieldDescriptor& field, uint64_t value) = 0;
102  virtual void writeField(const FieldDescriptor& field, double value) = 0;
103  virtual void writeField(const FieldDescriptor& field, bool value) = 0;
104  virtual void writeNullField(const FieldDescriptor& field) = 0;
105 
106  virtual void writeField(const FieldDescriptor& field, const char* value)
107  {
108  writeField(field, std::string(value));
109  }
110 
111  template <typename T, internal::EnableIfSignedIntegral<T> = 0>
112  void writeField(const FieldDescriptor& field, T value)
113  {
114  writeField(field, static_cast<int64_t>(value));
115  }
116 
117  template <typename T, internal::EnableIfUnsignedIntegral<T> = 0>
118  void writeField(const FieldDescriptor& field, T value)
119  {
120  writeField(field, static_cast<uint64_t>(value));
121  }
122 
123  virtual void writeHexField(const FieldDescriptor& field, uint64_t value) = 0;
124 
125  template <typename T, std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, int> = 0>
126  void writeHexField(const FieldDescriptor& field, T value)
127  {
128  writeHexField(field, static_cast<uint64_t>(value));
129  }
130 
131  virtual void startObject(const FieldDescriptor& field) = 0;
132  virtual void endObject() = 0;
133  virtual void startArray(const FieldDescriptor& field) = 0;
134  virtual void endArray() = 0;
135 
136  void enforceOneRoot();
137 
138  bool m_ShouldEnforceOneRoot = true;
139 
140  private:
141  bool m_RootWritten = false;
142  };
143 
146  class ScopeBase : public ISerializer
147  {
148  public:
149  using ISerializer::writeField;
150 
154  void writeField(const FieldDescriptor& field, const std::string& value) override;
155 
159  void writeField(const FieldDescriptor& field, int64_t value) override;
160 
164  void writeField(const FieldDescriptor& field, uint64_t value) override;
165 
169  void writeField(const FieldDescriptor& field, double value) override;
170 
174  void writeField(const FieldDescriptor& field, bool value) override;
175 
178  void writeNullField(const FieldDescriptor& field) override;
179 
183  void writeHexField(const FieldDescriptor& field, uint64_t value) override;
184 
185  template <typename T, internal::EnableIfSignedIntegral<T> = 0>
186  void writeField(const FieldDescriptor& field, T value)
187  {
188  writeField(field, static_cast<int64_t>(value));
189  }
190 
191  template <typename T, internal::EnableIfUnsignedIntegral<T> = 0>
192  void writeField(const FieldDescriptor& field, T value)
193  {
194  writeField(field, static_cast<uint64_t>(value));
195  }
196 
197  protected:
198  void startObject(const FieldDescriptor& field) override;
199  void endObject() override;
200  void startArray(const FieldDescriptor& field) override;
201  void endArray() override;
202 
203  explicit ScopeBase(ISerializer* serializer) : m_Serializer(serializer)
204  {
205  m_ShouldEnforceOneRoot = false;
206  }
207 
208  ISerializer* m_Serializer;
209  };
210 
213  class ArrayScope : public ScopeBase
214  {
215  public:
216  using ScopeBase::writeField;
217 
221  ArrayScope(ISerializer* serializer, const FieldDescriptor& field);
222 
224  ~ArrayScope() override;
225  };
226 
229  class ObjectScope : public ScopeBase
230  {
231  public:
232  using ScopeBase::writeField;
233 
237  ObjectScope(ISerializer* serializer, const FieldDescriptor& field);
238 
240  ~ObjectScope() override;
241  };
242 
246  {
247  public:
248  using ISerializer::writeField;
249  using ISerializer::writeHexField;
250 
253  explicit JsonSerializer(std::ostream& out);
254 
255  protected:
256  void writeField(const FieldDescriptor& field, const std::string& value) override;
257  void writeField(const FieldDescriptor& field, int64_t value) override;
258  void writeField(const FieldDescriptor& field, uint64_t value) override;
259  void writeField(const FieldDescriptor& field, double value) override;
260  void writeField(const FieldDescriptor& field, bool value) override;
261  void writeNullField(const FieldDescriptor& field) override;
262  void writeHexField(const FieldDescriptor& field, uint64_t value) override;
263  void startObject(const FieldDescriptor& field) override;
264  void endObject() override;
265  void startArray(const FieldDescriptor& field) override;
266  void endArray() override;
267 
268  private:
269  enum class Context
270  {
271  Array,
272  Object
273  };
274 
275  void writeSeparatorIfNeeded();
276  void writeKey(const std::string& name);
277 
278  std::ostream& m_Out;
279  std::vector<Context> m_ContextStack;
280  std::vector<bool> m_FirstAtLevel;
281  };
282 
286  {
287  public:
288  using ISerializer::writeField;
289  using ISerializer::writeHexField;
290 
293  explicit YamlSerializer(std::ostream& out);
294 
295  protected:
296  void writeField(const FieldDescriptor& field, const std::string& value) override;
297  void writeField(const FieldDescriptor& field, int64_t value) override;
298  void writeField(const FieldDescriptor& field, uint64_t value) override;
299  void writeField(const FieldDescriptor& field, double value) override;
300  void writeField(const FieldDescriptor& field, bool value) override;
301  void writeNullField(const FieldDescriptor& field) override;
302  void writeHexField(const FieldDescriptor& field, uint64_t value) override;
303 
304  void startObject(const FieldDescriptor& field) override;
305  void endObject() override;
306  void startArray(const FieldDescriptor& field) override;
307  void endArray() override;
308 
309  private:
310  enum class Context
311  {
312  EmptyArray,
313  Array,
314  Object
315  };
316 
317  void writeIndent();
318  void writeNewlineIfNeeded();
319  // Called by startObject()/startArray(), BEFORE pushing the new
320  // context: writes the line introducing the container (a bare "-"
321  // for an array element, "name:" for an object member, or nothing
322  // at the document root) — content follows on subsequent, more
323  // deeply indented lines.
324  void writeContainerHeader(const std::string& name);
325  // Called by writeField()/writeNullField()/writeHexField(): writes
326  // everything on the current line up to (not including) the value
327  // itself — "- " inside an array, "name: " inside an object or at
328  // the root. Caller writes the actual value immediately after.
329  void writeFieldPrefix(const std::string& name);
330 
331  bool isArrayContext() const;
332 
333  std::ostream& m_Out;
334  std::vector<Context> m_ContextStack;
335  bool m_WriteNewLine = false;
336  bool m_WriteIdent = true;
337  };
338 
341  class XmlSerializer : public ISerializer
342  {
343  public:
344  using ISerializer::writeField;
345  using ISerializer::writeHexField;
346 
349  explicit XmlSerializer(std::ostream& out);
350 
351  protected:
352  void writeField(const FieldDescriptor& field, const std::string& value) override;
353  void writeField(const FieldDescriptor& field, int64_t value) override;
354  void writeField(const FieldDescriptor& field, uint64_t value) override;
355  void writeField(const FieldDescriptor& field, double value) override;
356  void writeField(const FieldDescriptor& field, bool value) override;
357  void writeNullField(const FieldDescriptor& field) override;
358  void writeHexField(const FieldDescriptor& field, uint64_t value) override;
359 
360  void startObject(const FieldDescriptor& field) override;
361  void endObject() override;
362  void startArray(const FieldDescriptor& field) override;
363  void endArray() override;
364 
365  private:
366  struct Context
367  {
368  std::string name; // Element name
369  bool isArray; // True if this is an array container
370  };
371 
372  // Core writing methods
373  void writeOpenTag(const std::string& name);
374  void writeCloseTag(const std::string& name);
375  void writeValueElement(const std::string& name, const std::string& value, bool isNull = false);
376  void writeIndent();
377 
378  // XML escaping (handles &, <, >, ", ')
379  static std::string escapeXML(const std::string& s);
380 
381  // Checks if a string is safe to use as an XML name
382  static bool isValidXMLName(const std::string& name);
383 
384  // Returns `name` if it's a valid XML element name, otherwise
385  // `fallback`. Centralizes the isValidXMLName()-check-plus-fallback
386  // pattern that every writeField()/startObject()/startArray()
387  // overload below needs.
388  static std::string resolveElementName(const std::string& name, const char* fallback);
389 
390  // State
391  std::ostream& m_Out;
392  std::vector<Context> m_ContextStack;
393 
394  // Optimization: pre-allocate indentation strings
395  mutable std::vector<std::string> m_IndentCache;
396  };
397 } // namespace pcpp
Definition: Serializers.h:214
ArrayScope(ISerializer *serializer, const FieldDescriptor &field)
~ArrayScope() override
Close the array.
Definition: Serializers.h:78
virtual ~ISerializer()=default
Destroy the serializer.
ObjectScope writeObject(const FieldDescriptor &field)
ArrayScope writeArray(const FieldDescriptor &field)
Definition: Serializers.h:246
JsonSerializer(std::ostream &out)
Definition: Serializers.h:230
~ObjectScope() override
Close the object.
ObjectScope(ISerializer *serializer, const FieldDescriptor &field)
Definition: Serializers.h:147
void writeField(const FieldDescriptor &field, uint64_t value) override
void writeNullField(const FieldDescriptor &field) override
void writeHexField(const FieldDescriptor &field, uint64_t value) override
void writeField(const FieldDescriptor &field, const std::string &value) override
void writeField(const FieldDescriptor &field, double value) override
void writeField(const FieldDescriptor &field, bool value) override
void writeField(const FieldDescriptor &field, int64_t value) override
Definition: Serializers.h:342
XmlSerializer(std::ostream &out)
Definition: Serializers.h:286
YamlSerializer(std::ostream &out)
The main namespace for the PcapPlusPlus lib.
Definition: AssertionUtils.h:19
Definition: Serializers.h:18
std::vector< FieldDescriptor >(*const getChildren)()
Function returning the descriptors of the field's children, or nullptr if the field has no children.
Definition: Serializers.h:26
const uint16_t id
Stable numeric identifier of the field.
Definition: Serializers.h:20
const std::string name
Name of the field.
Definition: Serializers.h:23
bool hasChildren() const
Definition: Serializers.h:40
FieldDescriptor(uint16_t fieldId, std::string fieldName, std::vector< FieldDescriptor >(*fieldChildren)()=nullptr)
Definition: Serializers.h:33
Definition: Serializers.h:49
ObjectFieldDescriptor(uint16_t fieldId, std::string fieldName)
Definition: Serializers.h:53