IBR-DTNSuite  0.12
SDNV.h
Go to the documentation of this file.
1 /*
2  * SDNV.h
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * THIS FILE BASES ON DTN_2.4.0/SERVLIB/BUNDLING/SDNV.H
21  */
22 
23 #include <ibrcommon/Exceptions.h>
24 #include <ibrdtn/data/Exceptions.h>
25 #include <ibrdtn/utils/Random.h>
26 
27 #include <sstream>
28 #include <sys/types.h>
29 #include <iostream>
30 #include <stdio.h>
31 #include <stdint.h>
32 #include <limits>
33 #include <cstdlib>
34 
35 #ifndef _SDNV_H_
36 #define _SDNV_H_
37 
56 namespace dtn
57 {
58  namespace data
59  {
61  {
62  public:
63  ValueOutOfRangeException(const std::string &what = "The value is out of range.") throw() : dtn::InvalidDataException(what)
64  {
65  };
66  };
67 
68  template<class E>
69  class SDNV
70  {
71  public:
76  static const size_t MAX_LENGTH = 10;
77 
82  SDNV(const E value) : _value(value) {
83  }
84 
85  SDNV() : _value(0) {
86  }
87 
92  ~SDNV() {
93  }
94 
99  size_t getLength() const
100  {
101  size_t val_len = 0;
102  E tmp = _value;
103 
104  do {
105  tmp = tmp >> 7;
106  val_len++;
107  } while (tmp != 0);
108 
109  return val_len;
110  }
111 
112  template<typename T>
113  T get() const {
114  return static_cast<T>(_value);
115  }
116 
117  const E& get() const {
118  return _value;
119  }
120 
121  const SDNV& operator=(const E value) {
122  _value = value;
123  return (*this);
124  }
125 
126  bool operator==(const E value) const
127  {
128  return (value == _value);
129  }
130 
131  bool operator==(const SDNV<E> &value) const
132  {
133  return (value._value == _value);
134  }
135 
136  bool operator!=(const E value) const
137  {
138  return (value != _value);
139  }
140 
141  bool operator!=(const SDNV<E> &value) const
142  {
143  return (value._value != _value);
144  }
145 
146  SDNV<E> operator+(const E value)
147  {
148  E result = _value + value;
149  return SDNV<E>(result);
150  }
151 
152  SDNV<E> operator+(const SDNV<E> &value)
153  {
154  E result = _value + value._value;
155  return SDNV<E>(result);
156  }
157 
158  friend
159  SDNV<E> operator+(const SDNV<E> &left, const SDNV<E> &right)
160  {
161  SDNV<E> ret(left);
162  ret += right;
163  return ret;
164  }
165 
166  friend
167  SDNV<E> operator+(const SDNV<E> &left, const E right)
168  {
169  SDNV<E> ret(left);
170  ret += right;
171  return ret;
172  }
173 
174  SDNV<E>& operator+=(const E value)
175  {
176  _value += value;
177  return (*this);
178  }
179 
180  SDNV<E>& operator+=(const SDNV<E> &value)
181  {
182  _value += value._value;
183  return (*this);
184  }
185 
186  SDNV<E>& operator++() // prefix
187  {
188  ++_value;
189  return (*this);
190  }
191 
192  SDNV<E> operator++(int) // postfix
193  {
194  SDNV<E> prev(*this);
195  ++_value;
196  return prev;
197  }
198 
199  SDNV<E> operator-(const E value)
200  {
201  E result = _value - value;
202  return SDNV<E>(result);
203  }
204 
205  SDNV<E> operator-(const SDNV<E> &value)
206  {
207  E result = _value - value._value;
208  return SDNV<E>(result);
209  }
210 
211  friend
212  SDNV<E> operator-(const SDNV<E> &left, const SDNV<E> &right)
213  {
214  SDNV<E> ret(left);
215  ret -= right;
216  return ret;
217  }
218 
219  friend
220  SDNV<E> operator-(const SDNV<E> &left, const E right)
221  {
222  SDNV<E> ret(left);
223  ret -= right;
224  return ret;
225  }
226 
227  SDNV<E>& operator-=(const E value)
228  {
229  _value -= value;
230  return (*this);
231  }
232 
233  SDNV<E>& operator-=(const SDNV<E> &value)
234  {
235  _value -= value._value;
236  return (*this);
237  }
238 
239  SDNV<E>& operator--() // prefix
240  {
241  --_value;
242  return (*this);
243  }
244 
245  SDNV<E> operator--(int) // postfix
246  {
247  SDNV<E> prev(*this);
248  --_value;
249  return prev;
250  }
251 
252  SDNV<E> operator/(const E value)
253  {
254  E result = _value / value;
255  return SDNV<E>(result);
256  }
257 
258  SDNV<E> operator/(const SDNV<E> &value)
259  {
260  E result = _value / value._value;
261  return SDNV<E>(result);
262  }
263 
264  friend
265  SDNV<E> operator/(const SDNV<E> &left, const SDNV<E> &right)
266  {
267  SDNV<E> ret(left);
268  ret /= right;
269  return ret;
270  }
271 
272  friend
273  SDNV<E> operator/(const SDNV<E> &left, const E right)
274  {
275  SDNV<E> ret(left);
276  ret /= right;
277  return ret;
278  }
279 
280  SDNV<E>& operator/=(const E value)
281  {
282  _value /= value;
283  return (*this);
284  }
285 
286  SDNV<E>& operator/=(const SDNV<E> &value)
287  {
288  _value /= value._value;
289  return (*this);
290  }
291 
292  SDNV<E> operator*(const E value)
293  {
294  E result = _value * value;
295  return SDNV<E>(result);
296  }
297 
298  SDNV<E> operator*(const SDNV<E> &value)
299  {
300  E result = _value * value._value;
301  return SDNV<E>(result);
302  }
303 
304  friend
305  SDNV<E> operator*(const SDNV<E> &left, const SDNV<E> &right)
306  {
307  SDNV<E> ret(left);
308  ret *= right;
309  return ret;
310  }
311 
312  friend
313  SDNV<E> operator*(const SDNV<E> &left, const E right)
314  {
315  SDNV<E> ret(left);
316  ret *= right;
317  return ret;
318  }
319 
320  SDNV<E>& operator*=(const E value)
321  {
322  _value *= value;
323  return (*this);
324  }
325 
326  SDNV<E>& operator*=(const SDNV<E> &value)
327  {
328  _value *= value._value;
329  return (*this);
330  }
331 
332  bool operator&(const SDNV<E> &value) const
333  {
334  return (value._value & _value);
335  }
336 
337  bool operator|(const SDNV<E> &value) const
338  {
339  return (value._value | _value);
340  }
341 
342  SDNV<E>& operator&=(const SDNV<E> &value)
343  {
344  _value &= value._value;
345  return (*this);
346  }
347 
348  SDNV<E>& operator|=(const SDNV<E> &value)
349  {
350  _value |= value._value;
351  return (*this);
352  }
353 
354  bool operator<(const E value) const
355  {
356  return (_value < value);
357  }
358 
359  bool operator<=(const E value) const
360  {
361  return (_value <= value);
362  }
363 
364  bool operator>(const E value) const
365  {
366  return (_value > value);
367  }
368 
369  bool operator>=(const E value) const
370  {
371  return (_value >= value);
372  }
373 
374  bool operator<(const SDNV<E> &value) const
375  {
376  return (_value < value._value);
377  }
378 
379  bool operator<=(const SDNV<E> &value) const
380  {
381  return (_value <= value._value);
382  }
383 
384  bool operator>(const SDNV<E> &value) const
385  {
386  return (_value > value._value);
387  }
388 
389  bool operator>=(const SDNV<E> &value) const
390  {
391  return (_value >= value._value);
392  }
393 
394  static SDNV<E> max()
395  {
396  return std::numeric_limits<E>::max();
397  }
398 
400  {
401  // for compatibility use 32-bit here
403  uint32_t val = (uint32_t)r.gen_number();
404  (*this) = static_cast<E>(val);
405  return (*this);
406  }
407 
408  std::string toString() const {
409  std::stringstream ss;
410  ss << _value;
411  return ss.str();
412  }
413 
414  void fromString(const std::string &data) {
415  std::stringstream ss; ss.str(data);
416  ss >> _value;
417  }
418 
419  void read(std::istream &stream) {
420  stream >> _value;
421  }
422 
423  void encode(std::ostream &stream) const
424  {
425  unsigned char buffer[10];
426  unsigned char *bp = &buffer[0];
427  uint64_t val = _value;
428 
429  const size_t val_len = getLength();
430 
431  if (!(val_len > 0)) throw ValueOutOfRangeException("ERROR(SDNV): !(val_len > 0)");
432  if (!(val_len <= SDNV::MAX_LENGTH)) throw ValueOutOfRangeException("ERROR(SDNV): !(val_len <= MAX_LENGTH)");
433 
434  // Now advance bp to the last byte and fill it in backwards with the value bytes.
435  bp += val_len;
436  unsigned char high_bit = 0; // for the last octet
437  do {
438  --bp;
439  *bp = (unsigned char)(high_bit | (val & 0x7f));
440  high_bit = (1 << 7); // for all but the last octet
441  val = val >> 7;
442  } while (val != 0);
443 
444  if (!(bp == &buffer[0])) throw ValueOutOfRangeException("ERROR(SDNV): !(bp == buffer)");
445 
446  // write encoded value to the stream
447  stream.write((const char*)&buffer[0], val_len);
448  }
449 
450  void decode(std::istream &stream)
451  {
452  size_t val_len = 0;
453  unsigned char bp = 0;
454  unsigned char start = 0;
455 
456  int carry = 0;
457 
458  _value = 0;
459  do {
460  stream.get((char&)bp);
461 
462  _value = (_value << 7) | (bp & 0x7f);
463  ++val_len;
464 
465  if ((bp & (1 << 7)) == 0)
466  break; // all done;
467 
468  // check if the value fits into sizeof(E)
469  if ((val_len % 8) == 0) ++carry;
470 
471  if ((sizeof(E) + carry) < val_len)
472  throw ValueOutOfRangeException("ERROR(SDNV): overflow value in sdnv");
473 
474  if (start == 0) start = bp;
475  } while (1);
476 
477  if ((val_len > SDNV::MAX_LENGTH) || ((val_len == SDNV::MAX_LENGTH) && (start != 0x81)))
478  throw ValueOutOfRangeException("ERROR(SDNV): overflow value in sdnv");
479  }
480 
481  private:
482  friend
483  std::ostream &operator<<(std::ostream &stream, const dtn::data::SDNV<E> &obj)
484  {
485  obj.encode(stream);
486  return stream;
487  }
488 
489  friend
490  std::istream &operator>>(std::istream &stream, dtn::data::SDNV<E> &obj)
491  {
492  obj.decode(stream);
493  return stream;
494  }
495 
496  E _value;
497  };
498  }
499 }
500 
501 #endif /* _SDNV_H_ */