SUMO - Simulation of Urban MObility
|
00001 /************************************************************************ 00002 ** This file is part of the network simulator Shawn. ** 00003 ** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project ** 00004 ** Shawn is free software; you can redistribute it and/or modify it ** 00005 ** under the terms of the BSD License. Refer to the shawn-licence.txt ** 00006 ** file in the root of the Shawn source tree for further details. ** 00007 ************************************************************************ 00008 ** ** 00009 ** \author Axel Wegener <wegener@itm.uni-luebeck.de> ** 00010 ** \author Bjoern Hendriks <hendriks@ibr.cs.tu-bs.de> ** 00011 ** ** 00012 ************************************************************************/ 00013 00014 #include "storage.h" 00015 00016 #ifdef BUILD_TCPIP 00017 00018 #include <iostream> 00019 #include <iterator> 00020 #include <sstream> 00021 #include <cassert> 00022 #include <algorithm> 00023 #include <iomanip> 00024 00025 00026 using namespace std; 00027 00028 //#define NULLITER static_cast<list<unsigned char>::iterator>(0) 00029 00030 namespace tcpip 00031 { 00032 00033 // ---------------------------------------------------------------------- 00034 Storage::Storage() 00035 { 00036 init(); 00037 } 00038 00039 00040 // ---------------------------------------------------------------------- 00041 Storage::Storage(const unsigned char packet[], int length) 00042 { 00043 // Length is calculated, if -1, or given 00044 if (length == -1) length = sizeof(packet) / sizeof(unsigned char); 00045 00046 store.reserve(length); 00047 // Get the content 00048 for(int i = 0; i < length; ++i) store.push_back(packet[i]); 00049 00050 init(); 00051 } 00052 00053 00054 // ---------------------------------------------------------------------- 00055 void Storage::init() 00056 { 00057 // Initialize local variables 00058 iter_ = store.begin(); 00059 00060 short a = 0x0102; 00061 unsigned char *p_a = reinterpret_cast<unsigned char*>(&a); 00062 bigEndian_ = (p_a[0] == 0x01); // big endian? 00063 } 00064 00065 00066 // ---------------------------------------------------------------------- 00067 Storage::~Storage() 00068 {} 00069 00070 00071 // ---------------------------------------------------------------------- 00072 bool Storage::valid_pos() 00073 { 00074 return (iter_ != store.end()); // this implies !store.empty() 00075 } 00076 00077 00078 // ---------------------------------------------------------------------- 00079 unsigned int Storage::position() const 00080 { 00081 // According to C++ standard std::distance will simply compute the iterators 00082 // difference for random access iterators as std::vector provides. 00083 return static_cast<unsigned int>(std::distance(store.begin(), iter_)); 00084 } 00085 00086 00087 // ---------------------------------------------------------------------- 00088 void Storage::reset() 00089 { 00090 store.clear(); 00091 iter_ = store.begin(); 00092 } 00093 00094 00095 // ---------------------------------------------------------------------- 00100 unsigned char Storage::readChar() throw(std::invalid_argument) 00101 { 00102 if ( !valid_pos() ) 00103 { 00104 throw std::invalid_argument("Storage::readChar(): invalid position"); 00105 } 00106 return readCharUnsafe(); 00107 } 00108 00109 00110 // ---------------------------------------------------------------------- 00114 void Storage::writeChar(unsigned char value) throw() 00115 { 00116 store.push_back(value); 00117 iter_ = store.begin(); 00118 } 00119 00120 00121 // ---------------------------------------------------------------------- 00126 int Storage::readByte() throw(std::invalid_argument) 00127 { 00128 int i = static_cast<int>(readChar()); 00129 if (i < 128) return i; 00130 else return (i - 256); 00131 } 00132 00133 00134 // ---------------------------------------------------------------------- 00138 void Storage::writeByte(int value) throw(std::invalid_argument) 00139 { 00140 if (value < -128 || value > 127) 00141 { 00142 throw std::invalid_argument("Storage::writeByte(): Invalid value, not in [-128, 127]"); 00143 } 00144 writeChar( static_cast<unsigned char>( (value+256) % 256 ) ); 00145 } 00146 00147 00148 // ---------------------------------------------------------------------- 00153 int Storage::readUnsignedByte() throw(std::invalid_argument) 00154 { 00155 return static_cast<int>(readChar()); 00156 } 00157 00158 00159 // ---------------------------------------------------------------------- 00163 void Storage::writeUnsignedByte(int value) throw(std::invalid_argument) 00164 { 00165 if (value < 0 || value > 255) 00166 { 00167 throw std::invalid_argument("Storage::writeUnsignedByte(): Invalid value, not in [0, 255]"); 00168 } 00169 writeChar( static_cast<unsigned char>( value )); 00170 } 00171 00172 00173 // ----------------------------------------------------------------------- 00178 std::string Storage::readString() throw(std::invalid_argument) 00179 { 00180 int len = readInt(); 00181 checkReadSafe(len); 00182 StorageType::const_iterator end = iter_; 00183 std::advance(end, len); 00184 const string tmp(iter_, end); 00185 iter_ = end; 00186 return tmp; 00187 } 00188 00189 00190 // ---------------------------------------------------------------------- 00195 void Storage::writeString(const std::string &s) throw() 00196 { 00197 writeInt(static_cast<int>(s.length())); 00198 00199 store.insert(store.end(), s.begin(), s.end()); 00200 iter_ = store.begin(); 00201 } 00202 00203 00204 // ----------------------------------------------------------------------- 00209 std::vector<std::string> Storage::readStringList() throw(std::invalid_argument) 00210 { 00211 std::vector<std::string> tmp; 00212 const int len = readInt(); 00213 tmp.reserve(len); 00214 for (int i = 0; i < len; i++) 00215 { 00216 tmp.push_back(readString()); 00217 } 00218 return tmp; 00219 } 00220 00221 00222 // ---------------------------------------------------------------------- 00227 void Storage::writeStringList(const std::vector<std::string> &s) throw() 00228 { 00229 writeInt(static_cast<int>(s.size())); 00230 for (std::vector<std::string>::const_iterator it = s.begin(); it!=s.end() ; it++) 00231 { 00232 writeString(*it); 00233 } 00234 } 00235 00236 00237 // ---------------------------------------------------------------------- 00245 int Storage::readShort() throw(std::invalid_argument) 00246 { 00247 short value = 0; 00248 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00249 readByEndianess(p_value, 2); 00250 return value; 00251 } 00252 00253 00254 // ---------------------------------------------------------------------- 00255 void Storage::writeShort( int value ) throw(std::invalid_argument) 00256 { 00257 if (value < -32768 || value > 32767) 00258 { 00259 throw std::invalid_argument("Storage::writeShort(): Invalid value, not in [-32768, 32767]"); 00260 } 00261 00262 short svalue = static_cast<short>(value); 00263 unsigned char *p_svalue = reinterpret_cast<unsigned char*>(&svalue); 00264 writeByEndianess(p_svalue, 2); 00265 } 00266 00267 00268 // ---------------------------------------------------------------------- 00276 int Storage::readInt() throw(std::invalid_argument) 00277 { 00278 int value = 0; 00279 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00280 readByEndianess(p_value, 4); 00281 return value; 00282 } 00283 00284 00285 // ---------------------------------------------------------------------- 00286 void Storage::writeInt( int value ) throw() 00287 { 00288 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00289 writeByEndianess(p_value, 4); 00290 } 00291 00292 00293 // ---------------------------------------------------------------------- 00301 float Storage::readFloat() throw(std::invalid_argument) 00302 { 00303 float value = 0; 00304 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00305 readByEndianess(p_value, 4); 00306 return value; 00307 } 00308 00309 00310 // ---------------------------------------------------------------------- 00311 void Storage::writeFloat( float value ) throw() 00312 { 00313 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00314 writeByEndianess(p_value, 4); 00315 } 00316 00317 00318 // ---------------------------------------------------------------------- 00319 void Storage::writeDouble( double value ) throw () 00320 { 00321 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00322 writeByEndianess(p_value, 8); 00323 } 00324 00325 00326 // ---------------------------------------------------------------------- 00327 double Storage::readDouble( ) throw (std::invalid_argument) 00328 { 00329 double value = 0; 00330 unsigned char *p_value = reinterpret_cast<unsigned char*>(&value); 00331 readByEndianess(p_value, 8); 00332 return value; 00333 } 00334 00335 00336 // ---------------------------------------------------------------------- 00337 void Storage::writePacket(unsigned char* packet, int length) 00338 { 00339 store.insert(store.end(), &(packet[0]), &(packet[length])); 00340 iter_ = store.begin(); // reserve() invalidates iterators 00341 } 00342 00343 00344 // ---------------------------------------------------------------------- 00345 void Storage::writePacket(const std::vector<unsigned char> &packet) 00346 { 00347 std::copy(packet.begin(), packet.end(), std::back_inserter(store)); 00348 iter_ = store.begin(); 00349 } 00350 00351 00352 // ---------------------------------------------------------------------- 00353 void Storage::writeStorage(tcpip::Storage& other) 00354 { 00355 // the compiler cannot deduce to use a const_iterator as source 00356 store.insert<StorageType::const_iterator>(store.end(), other.iter_, other.store.end()); 00357 iter_ = store.begin(); 00358 } 00359 00360 00361 // ---------------------------------------------------------------------- 00362 void Storage::checkReadSafe(unsigned int num) const throw(std::invalid_argument) 00363 { 00364 if (std::distance(iter_, store.end()) < static_cast<int>(num)) 00365 { 00366 std::ostringstream msg; 00367 msg << "tcpip::Storage::readIsSafe: want to read " << num << " bytes from Storage, " 00368 << "but only " << std::distance(iter_, store.end()) << " remaining"; 00369 throw std::invalid_argument(msg.str()); 00370 } 00371 } 00372 00373 00374 // ---------------------------------------------------------------------- 00375 unsigned char Storage::readCharUnsafe() 00376 { 00377 char hb = *iter_; 00378 ++iter_; 00379 return hb; 00380 } 00381 00382 00383 // ---------------------------------------------------------------------- 00384 void Storage::writeByEndianess(const unsigned char * begin, unsigned int size) 00385 { 00386 const unsigned char * end = &(begin[size]); 00387 if (bigEndian_) 00388 store.insert(store.end(), begin, end); 00389 else 00390 store.insert(store.end(), std::reverse_iterator<const unsigned char *>(end), std::reverse_iterator<const unsigned char *>(begin)); 00391 iter_ = store.begin(); 00392 } 00393 00394 00395 // ---------------------------------------------------------------------- 00396 void Storage::readByEndianess(unsigned char * array, int size) 00397 { 00398 checkReadSafe(size); 00399 if (bigEndian_) 00400 { 00401 for (int i = 0; i < size; ++i) 00402 array[i] = readCharUnsafe(); 00403 } 00404 else 00405 { 00406 for (int i = size - 1; i >= 0; --i) 00407 array[i] = readCharUnsafe(); 00408 } 00409 } 00410 00411 00412 // ---------------------------------------------------------------------- 00413 std::string Storage::hexDump() const 00414 { 00415 static const int width = 2; 00416 00417 std::ostringstream dump; 00418 // adapt stream attributes 00419 // 'showbase' inserts "0x", 'internal' makes leading '0' appear between "0x" and hex digits 00420 dump.setf(std::ostream::hex | std::ostream::showbase | std::ostream::internal); 00421 dump.fill('0'); 00422 00423 for(StorageType::const_iterator it = store.begin(); it != store.end(); ++it) 00424 { 00425 // insert spaces between values 00426 if (it != store.begin()) 00427 dump << " "; 00428 dump << std::setw(width) << static_cast<int>(*it); 00429 } 00430 00431 return dump.str(); 00432 } 00433 00434 } 00435 00436 #endif // BUILD_TCPIP 00437 00438 /*----------------------------------------------------------------------- 00439 * Source $Source: $ 00440 * Version $Revision: 620 $ 00441 * Date $Date: 2011-07-08 17:39:10 +0200 (Fr, 08. Jul 2011) $ 00442 *----------------------------------------------------------------------- 00443 * $Log: $ 00444 *-----------------------------------------------------------------------*/