CppSerdes  1.0
A serialization/deserialization library designed with embedded systems in mind
bitprint.h
Go to the documentation of this file.
1 #ifndef _BITPRINT_H_
8 #define _BITPRINT_H_
9 
10 #include <stdint.h>
11 #include <cstddef>
12 #include <stdio.h>
13 #include <type_traits>
14 #include <inttypes.h>
15 
16 #ifdef __SIZEOF_INT128__
17 #define BITCPY_INT128_CONDITIONAL_DEFINE(...) __VA_ARGS__
19 #define BITCPY_INT128_CONDITIONAL_DEFINE_C(...) __VA_ARGS__ static_assert(true, "")
21 #else
22 #define BITCPY_INT128_CONDITIONAL_DEFINE(...)
24 #define BITCPY_INT128_CONDITIONAL_DEFINE_C(...) static_assert(true, "")
26 #endif
27 
29 namespace serdes
30 {
31  namespace bitprint_detail
32  {
33  template <typename T>
34  struct make_signed
35  {
36  using type = typename std::make_signed<T>::type;
37  };
38  BITCPY_INT128_CONDITIONAL_DEFINE_C(
39  template <>
40  struct make_signed<__uint128_t> {
41  using type = __int128_t;
42  };);
43  template <typename T>
44  struct make_unsigned
45  {
46  using type = typename std::make_unsigned<T>::type;
47  };
48  BITCPY_INT128_CONDITIONAL_DEFINE_C(
49  template <>
50  struct make_unsigned<__uint128_t> {
51  using type = __uint128_t;
52  };
53  template <>
54  struct make_unsigned<__int128_t> {
55  using type = __uint128_t;
56  };);
57  template <>
58  struct make_unsigned<float>
59  {
60  using type = uint32_t;
61  };
62  template <>
63  struct make_unsigned<double>
64  {
65  using type = uint64_t;
66  };
67  template <bool use_brackets>
68  void print_bracket_newline(const bool add_newline)
69  {
70  if (use_brackets)
71  printf((add_newline ? "}\n" : "}"));
72  else if (add_newline)
73  printf("\n");
74  }
75  }
76 
80  inline void printhex(const uint8_t data, const bool add_newline = true)
81  {
82  if (add_newline)
83  printf("0x%02" PRIX8 "\n", data);
84  else
85  printf("0x%02" PRIX8, data);
86  }
87 
91  inline void printhex(const uint16_t data, const bool add_newline = true)
92  {
93  if (add_newline)
94  printf("0x%04" PRIX16 "\n", data);
95  else
96  printf("0x%04" PRIX16, data);
97  }
98 
102  inline void printhex(const uint32_t data, const bool add_newline = true)
103  {
104  if (add_newline)
105  printf("0x%08" PRIX32 "\n", data);
106  else
107  printf("0x%08" PRIX32, data);
108  }
109 
113  inline void printhex(const uint64_t data, const bool add_newline = true)
114  {
115  if (add_newline)
116  printf("0x%08" PRIX32 "%08" PRIX32 "\n",
117  static_cast<uint32_t>(data >> 32),
118  static_cast<uint32_t>(data));
119  else
120  printf("0x%08" PRIX32 "%08" PRIX32,
121  static_cast<uint32_t>(data >> 32),
122  static_cast<uint32_t>(data));
123  }
124  BITCPY_INT128_CONDITIONAL_DEFINE_C(
125 
127  inline void printhex(const __uint128_t data, const bool add_newline = true)
128  {
129  if (add_newline)
130  printf("0x%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "\n",
131  static_cast<uint32_t>(data >> 32 * 3),
132  static_cast<uint32_t>(data >> 32 * 2),
133  static_cast<uint32_t>(data >> 32 * 1),
134  static_cast<uint32_t>(data));
135  else
136  printf("0x%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "%08" PRIX32,
137  static_cast<uint32_t>(data >> 32 * 3),
138  static_cast<uint32_t>(data >> 32 * 2),
139  static_cast<uint32_t>(data >> 32 * 1),
140  static_cast<uint32_t>(data));
141  });
142 
146  inline void printhex(const bool data, const bool add_newline = true)
147  {
148  printhex(uint8_t(data), add_newline);
149  }
150 
154  template <typename T = void,
155  typename std::enable_if<
156  std::is_signed<T>::value
157  BITCPY_INT128_CONDITIONAL_DEFINE(|| std::is_same<T, __int128_t>::value),
158  T>::type * = nullptr>
159  void printhex(const T data, const bool add_newline = true)
160  {
161  typedef typename bitprint_detail::make_unsigned<T>::type data_as_unsigned_type;
162  union
163  {
164  T original_value;
165  data_as_unsigned_type unsigned_value;
166  } punned_data;
167  punned_data.original_value = data;
168  printhex(punned_data.unsigned_value, add_newline);
169  }
170 
175  template <bool use_brackets = true, typename T = void, size_t N = 0u>
176  void printhex(const T (&data)[N], const bool add_newline = true)
177  {
178  if (use_brackets)
179  printf("{");
180  for (size_t i = 0; i < N; i++)
181  {
182  printhex(data[i], false);
183  printf("%s", (i + 1u < N ? ", " : ""));
184  }
185  bitprint_detail::print_bracket_newline<use_brackets>(add_newline);
186  }
187 
192  template <bool use_brackets = true, typename T = void, size_t N = 0u>
193  void printbin(const T (&data)[N], const bool add_newline = true)
194  {
195  if (use_brackets)
196  printf("{");
197  for (size_t i = 0; i < N; i++)
198  {
199  for (size_t ii = 0; ii < sizeof(T); ii++)
200  {
201  const uint8_t data_element = static_cast<uint8_t>(
202  (data[i] >> (sizeof(T) * 8 - (ii + 1) * 8)) & 0xFFu);
203  printf("%c%c%c%c%c%c%c%c",
204  ((data_element & 0x80u) ? '1' : '0'),
205  ((data_element & 0x40u) ? '1' : '0'),
206  ((data_element & 0x20u) ? '1' : '0'),
207  ((data_element & 0x10u) ? '1' : '0'),
208  ((data_element & 0x08u) ? '1' : '0'),
209  ((data_element & 0x04u) ? '1' : '0'),
210  ((data_element & 0x02u) ? '1' : '0'),
211  ((data_element & 0x01u) ? '1' : '0'));
212  }
213  printf("%s", (i + 1u < N ? ", " : ""));
214  }
215  bitprint_detail::print_bracket_newline<use_brackets>(add_newline);
216  }
217 
221  template <typename T, typename std::enable_if<!std::is_array<T>::value && !std::is_same<T, bool>::value, T>::type * = nullptr>
222  void printbin(const T data, const bool add_newline = true)
223  {
224  typedef const T data_as_array_type[1];
225  printbin<false>(*reinterpret_cast<data_as_array_type *>(&data), add_newline);
226  }
227 
231  inline void printbin(const bool data, const bool add_newline = true)
232  {
233  printbin(uint8_t(data), add_newline);
234  }
235 }
236 
237 #endif // _BITPRINT_H_
void printbin(const T(&data)[N], const bool add_newline=true)
prints an array in binary format
Definition: bitprint.h:193
void printhex(const uint8_t data, const bool add_newline=true)
prints uint8_t value in hex format
Definition: bitprint.h:80
CppSerdes library namespace.
Definition: bitcpy_common.h:69