SUMO - Simulation of Urban MObility
storage.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ** This file is part of the network simulator Shawn. **
3  ** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
4  ** Shawn is free software; you can redistribute it and/or modify it **
5  ** under the terms of the BSD License. Refer to the shawn-licence.txt **
6  ** file in the root of the Shawn source tree for further details. **
7  ************************************************************************
8  ** **
9  ** \author Axel Wegener <wegener@itm.uni-luebeck.de> **
10  ** \author Bjoern Hendriks <hendriks@ibr.cs.tu-bs.de> **
11  ** **
12  ************************************************************************/
13 
14 #include "storage.h"
15 
16 #ifdef BUILD_TCPIP
17 
18 #include <iostream>
19 #include <iterator>
20 #include <sstream>
21 #include <cassert>
22 #include <algorithm>
23 #include <iomanip>
24 
25 
26 using namespace std;
27 
28 //#define NULLITER static_cast<list<unsigned char>::iterator>(0)
29 
30 namespace tcpip
31 {
32 
33  // ----------------------------------------------------------------------
34  Storage::Storage()
35  {
36  init();
37  }
38 
39 
40  // ----------------------------------------------------------------------
41  Storage::Storage(const unsigned char packet[], int length)
42  {
43  // Length is calculated, if -1, or given
44  if (length == -1) length = sizeof(packet) / sizeof(unsigned char);
45 
46  store.reserve(length);
47  // Get the content
48  for(int i = 0; i < length; ++i) store.push_back(packet[i]);
49 
50  init();
51  }
52 
53 
54  // ----------------------------------------------------------------------
55  void Storage::init()
56  {
57  // Initialize local variables
58  iter_ = store.begin();
59 
60  short a = 0x0102;
61  unsigned char *p_a = reinterpret_cast<unsigned char*>(&a);
62  bigEndian_ = (p_a[0] == 0x01); // big endian?
63  }
64 
65 
66  // ----------------------------------------------------------------------
67  Storage::~Storage()
68  {}
69 
70 
71  // ----------------------------------------------------------------------
72  bool Storage::valid_pos()
73  {
74  return (iter_ != store.end()); // this implies !store.empty()
75  }
76 
77 
78  // ----------------------------------------------------------------------
79  unsigned int Storage::position() const
80  {
81  // According to C++ standard std::distance will simply compute the iterators
82  // difference for random access iterators as std::vector provides.
83  return static_cast<unsigned int>(std::distance(store.begin(), iter_));
84  }
85 
86 
87  // ----------------------------------------------------------------------
88  void Storage::reset()
89  {
90  store.clear();
91  iter_ = store.begin();
92  }
93 
94 
95  // ----------------------------------------------------------------------
100  unsigned char Storage::readChar() throw(std::invalid_argument)
101  {
102  if ( !valid_pos() )
103  {
104  throw std::invalid_argument("Storage::readChar(): invalid position");
105  }
106  return readCharUnsafe();
107  }
108 
109 
110  // ----------------------------------------------------------------------
114  void Storage::writeChar(unsigned char value) throw()
115  {
116  store.push_back(value);
117  iter_ = store.begin();
118  }
119 
120 
121  // ----------------------------------------------------------------------
126  int Storage::readByte() throw(std::invalid_argument)
127  {
128  int i = static_cast<int>(readChar());
129  if (i < 128) return i;
130  else return (i - 256);
131  }
132 
133 
134  // ----------------------------------------------------------------------
138  void Storage::writeByte(int value) throw(std::invalid_argument)
139  {
140  if (value < -128 || value > 127)
141  {
142  throw std::invalid_argument("Storage::writeByte(): Invalid value, not in [-128, 127]");
143  }
144  writeChar( static_cast<unsigned char>( (value+256) % 256 ) );
145  }
146 
147 
148  // ----------------------------------------------------------------------
153  int Storage::readUnsignedByte() throw(std::invalid_argument)
154  {
155  return static_cast<int>(readChar());
156  }
157 
158 
159  // ----------------------------------------------------------------------
163  void Storage::writeUnsignedByte(int value) throw(std::invalid_argument)
164  {
165  if (value < 0 || value > 255)
166  {
167  throw std::invalid_argument("Storage::writeUnsignedByte(): Invalid value, not in [0, 255]");
168  }
169  writeChar( static_cast<unsigned char>( value ));
170  }
171 
172 
173  // -----------------------------------------------------------------------
178  std::string Storage::readString() throw(std::invalid_argument)
179  {
180  int len = readInt();
181  checkReadSafe(len);
182  StorageType::const_iterator end = iter_;
183  std::advance(end, len);
184  const string tmp(iter_, end);
185  iter_ = end;
186  return tmp;
187  }
188 
189 
190  // ----------------------------------------------------------------------
195  void Storage::writeString(const std::string &s) throw()
196  {
197  writeInt(static_cast<int>(s.length()));
198 
199  store.insert(store.end(), s.begin(), s.end());
200  iter_ = store.begin();
201  }
202 
203 
204  // -----------------------------------------------------------------------
209  std::vector<std::string> Storage::readStringList() throw(std::invalid_argument)
210  {
211  std::vector<std::string> tmp;
212  const int len = readInt();
213  tmp.reserve(len);
214  for (int i = 0; i < len; i++)
215  {
216  tmp.push_back(readString());
217  }
218  return tmp;
219  }
220 
221 
222  // ----------------------------------------------------------------------
227  void Storage::writeStringList(const std::vector<std::string> &s) throw()
228  {
229  writeInt(static_cast<int>(s.size()));
230  for (std::vector<std::string>::const_iterator it = s.begin(); it!=s.end() ; it++)
231  {
232  writeString(*it);
233  }
234  }
235 
236 
237  // ----------------------------------------------------------------------
245  int Storage::readShort() throw(std::invalid_argument)
246  {
247  short value = 0;
248  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
249  readByEndianess(p_value, 2);
250  return value;
251  }
252 
253 
254  // ----------------------------------------------------------------------
255  void Storage::writeShort( int value ) throw(std::invalid_argument)
256  {
257  if (value < -32768 || value > 32767)
258  {
259  throw std::invalid_argument("Storage::writeShort(): Invalid value, not in [-32768, 32767]");
260  }
261 
262  short svalue = static_cast<short>(value);
263  unsigned char *p_svalue = reinterpret_cast<unsigned char*>(&svalue);
264  writeByEndianess(p_svalue, 2);
265  }
266 
267 
268  // ----------------------------------------------------------------------
276  int Storage::readInt() throw(std::invalid_argument)
277  {
278  int value = 0;
279  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
280  readByEndianess(p_value, 4);
281  return value;
282  }
283 
284 
285  // ----------------------------------------------------------------------
286  void Storage::writeInt( int value ) throw()
287  {
288  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
289  writeByEndianess(p_value, 4);
290  }
291 
292 
293  // ----------------------------------------------------------------------
301  float Storage::readFloat() throw(std::invalid_argument)
302  {
303  float value = 0;
304  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
305  readByEndianess(p_value, 4);
306  return value;
307  }
308 
309 
310  // ----------------------------------------------------------------------
311  void Storage::writeFloat( float value ) throw()
312  {
313  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
314  writeByEndianess(p_value, 4);
315  }
316 
317 
318  // ----------------------------------------------------------------------
319  void Storage::writeDouble( double value ) throw ()
320  {
321  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
322  writeByEndianess(p_value, 8);
323  }
324 
325 
326  // ----------------------------------------------------------------------
327  double Storage::readDouble( ) throw (std::invalid_argument)
328  {
329  double value = 0;
330  unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
331  readByEndianess(p_value, 8);
332  return value;
333  }
334 
335 
336  // ----------------------------------------------------------------------
337  void Storage::writePacket(unsigned char* packet, int length)
338  {
339  store.insert(store.end(), &(packet[0]), &(packet[length]));
340  iter_ = store.begin(); // reserve() invalidates iterators
341  }
342 
343 
344  // ----------------------------------------------------------------------
345  void Storage::writePacket(const std::vector<unsigned char> &packet)
346  {
347  std::copy(packet.begin(), packet.end(), std::back_inserter(store));
348  iter_ = store.begin();
349  }
350 
351 
352  // ----------------------------------------------------------------------
353  void Storage::writeStorage(tcpip::Storage& other)
354  {
355  // the compiler cannot deduce to use a const_iterator as source
356  store.insert<StorageType::const_iterator>(store.end(), other.iter_, other.store.end());
357  iter_ = store.begin();
358  }
359 
360 
361  // ----------------------------------------------------------------------
362  void Storage::checkReadSafe(unsigned int num) const throw(std::invalid_argument)
363  {
364  if (std::distance(iter_, store.end()) < static_cast<int>(num))
365  {
366  std::ostringstream msg;
367  msg << "tcpip::Storage::readIsSafe: want to read " << num << " bytes from Storage, "
368  << "but only " << std::distance(iter_, store.end()) << " remaining";
369  throw std::invalid_argument(msg.str());
370  }
371  }
372 
373 
374  // ----------------------------------------------------------------------
375  unsigned char Storage::readCharUnsafe()
376  {
377  char hb = *iter_;
378  ++iter_;
379  return hb;
380  }
381 
382 
383  // ----------------------------------------------------------------------
384  void Storage::writeByEndianess(const unsigned char * begin, unsigned int size)
385  {
386  const unsigned char * end = &(begin[size]);
387  if (bigEndian_)
388  store.insert(store.end(), begin, end);
389  else
390  store.insert(store.end(), std::reverse_iterator<const unsigned char *>(end), std::reverse_iterator<const unsigned char *>(begin));
391  iter_ = store.begin();
392  }
393 
394 
395  // ----------------------------------------------------------------------
396  void Storage::readByEndianess(unsigned char * array, int size)
397  {
398  checkReadSafe(size);
399  if (bigEndian_)
400  {
401  for (int i = 0; i < size; ++i)
402  array[i] = readCharUnsafe();
403  }
404  else
405  {
406  for (int i = size - 1; i >= 0; --i)
407  array[i] = readCharUnsafe();
408  }
409  }
410 
411 
412  // ----------------------------------------------------------------------
413  std::string Storage::hexDump() const
414  {
415  static const int width = 2;
416 
417  std::ostringstream dump;
418  // adapt stream attributes
419  // 'showbase' inserts "0x", 'internal' makes leading '0' appear between "0x" and hex digits
420  dump.setf(std::ostream::hex | std::ostream::showbase | std::ostream::internal);
421  dump.fill('0');
422 
423  for(StorageType::const_iterator it = store.begin(); it != store.end(); ++it)
424  {
425  // insert spaces between values
426  if (it != store.begin())
427  dump << " ";
428  dump << std::setw(width) << static_cast<int>(*it);
429  }
430 
431  return dump.str();
432  }
433 
434 }
435 
436 #endif // BUILD_TCPIP
437 
438 /*-----------------------------------------------------------------------
439  * Source $Source: $
440  * Version $Revision: 620 $
441  * Date $Date: 2011-07-08 17:39:10 +0200 (Fr, 08. Jul 2011) $
442  *-----------------------------------------------------------------------
443  * $Log: $
444  *-----------------------------------------------------------------------*/
Definition: socket.cpp:62
StorageType store
Definition: storage.h:44
StorageType::const_iterator iter_
Definition: storage.h:45