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