SpectMorph
smbinbuffer.hh
1 // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl-2.1.html
2 
3 #ifndef SPECTMORPH_BINBUFFER_HH
4 #define SPECTMORPH_BINBUFFER_HH
5 
6 #include "smhexstring.hh"
7 
8 #include <vector>
9 #include <cstring>
10 
11 namespace SpectMorph
12 {
13 
14 class BinBuffer
15 {
16  std::vector<unsigned char> data;
17 
18  size_t rpos = 0;
19  bool m_read_error = false;
20 public:
21  void
22  write_start (const char *id)
23  {
24  data.clear();
25 
26  write_int (0); // reserved for length
27  write_string (id);
28  }
29  void
30  write_end()
31  {
32  size_t len = data.size();
33 
34  data[0] = (len >> 24);
35  data[1] = (len >> 16);
36  data[2] = (len >> 8);
37  data[3] = len;
38  }
39  void
40  write_int (int i)
41  {
42  write_byte (i >> 24);
43  write_byte (i >> 16);
44  write_byte (i >> 8);
45  write_byte (i);
46  }
47  void
48  write_float (float f)
49  {
50  union {
51  float f;
52  int i;
53  } u;
54  u.f = f;
55  write_int (u.i);
56  }
57  void
58  write_string (const char *str)
59  {
60  const unsigned char *raw_str = reinterpret_cast<const unsigned char *> (str);
61  size_t len = strlen (str) + 1;
62 
63  write_int (len);
64  data.insert (data.end(), raw_str, raw_str + len);
65  }
66  void
67  write_bool (bool b)
68  {
69  data.push_back (b ? 1 : 0);
70  }
71  void
72  write_byte (unsigned char byte)
73  {
74  data.push_back (byte);
75  }
76  void
77  write_int_seq (const int* ints, size_t length)
78  {
79  write_int (length);
80 
81  for (size_t i = 0; i < length; i++)
82  write_int (ints[i]);
83  }
84  void
85  write_float_seq (const float* floats, size_t length)
86  {
87  write_int (length);
88 
89  for (size_t i = 0; i < length; i++)
90  write_float (floats[i]);
91  }
92  std::string
93  to_string()
94  {
95  std::string result;
96  char hex[17] = "0123456789abcdef";
97 
98  for (unsigned char byte : data)
99  {
100  result += hex[(byte >> 4) & 0xf];
101  result += hex[byte & 0xf];
102  }
103  return result;
104  }
105  bool
106  from_string (const std::string& str)
107  {
108  data.clear();
109  return HexString::decode (str, data);
110  }
111  size_t
112  remaining()
113  {
114  return data.size() - rpos;
115  }
116  bool
117  read_error()
118  {
119  return m_read_error;
120  }
121  int
122  read_int()
123  {
124  if (remaining() >= 4)
125  {
126  int result = (data[rpos] << 24)
127  + (data[rpos + 1] << 16)
128  + (data[rpos + 2] << 8)
129  + data[rpos + 3];
130  rpos += 4;
131 
132  return result;
133  }
134  else
135  {
136  m_read_error = true;
137  return 0;
138  }
139  }
140  float
141  read_float()
142  {
143  union {float f; int i; } u;
144  u.i = read_int();
145 
146  if (!m_read_error)
147  return u.f;
148  else
149  return 0.0;
150  }
151  const char *
152  read_string_inplace()
153  {
154  int len = read_int();
155  char *data = (char *)read (len);
156 
157  if (data && len)
158  return data;
159  else
160  return "";
161  }
162  const char *
163  read_start_inplace()
164  {
165  read_int(); // len
166  return read_string_inplace();
167  }
168  void *
169  read (size_t l)
170  {
171  if (remaining() >= l)
172  {
173  void *result = &data[rpos];
174  rpos += l;
175  return result;
176  }
177  else
178  {
179  m_read_error = true;
180  return nullptr;
181  }
182  }
183  void
184  read_int_seq (std::vector<int>& result)
185  {
186  // might be optimizable a bit
187  size_t seqlen = read_int();
188 
189  if (remaining() >= seqlen * 4)
190  {
191  result.resize (seqlen);
192 
193  for (size_t i = 0; i < seqlen; i++)
194  result[i] = read_int();
195  }
196  else
197  {
198  m_read_error = true;
199  result.clear();
200  }
201  }
202  void
203  read_float_seq (std::vector<float>& result)
204  {
205  // might be optimizable a bit
206  size_t seqlen = read_int();
207 
208  if (remaining() >= seqlen * 4)
209  {
210  result.resize (seqlen);
211 
212  for (size_t i = 0; i < seqlen; i++)
213  result[i] = read_float();
214  }
215  else
216  {
217  m_read_error = true;
218  result.clear();
219  }
220  }
221  bool
222  read_bool()
223  {
224  if(remaining() >= 1)
225  {
226  return data[rpos++] > 0;
227  }
228  else
229  {
230  m_read_error = true;
231  return false;
232  }
233  }
234 };
235 
236 }
237 
238 #endif
239 
Definition: smbinbuffer.hh:15