SUMO - Simulation of Urban MObility
storage.cpp
Go to the documentation of this file.
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  *-----------------------------------------------------------------------*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines