/************************************************************************1** This file is part of the network simulator Shawn. **2** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **3** Shawn is free software; you can redistribute it and/or modify it **4** under the terms of the BSD License. Refer to the shawn-licence.txt **5** file in the root of the Shawn source tree for further details. **6************************************************************************7** **8** \author Axel Wegener <[email protected]> **9** \author Bjoern Hendriks <[email protected]> **10** **11************************************************************************/1213#include "storage.h"1415#ifdef BUILD_TCPIP1617#include <iostream>18#include <iterator>19#include <sstream>20#include <cassert>21#include <algorithm>22#include <iomanip>232425//#define NULLITER static_cast<list<unsigned char>::iterator>(0)2627namespace tcpip28{2930// ----------------------------------------------------------------------31Storage::Storage()32{33init();34}353637// ----------------------------------------------------------------------38Storage::Storage(const unsigned char packet[], int length)39{40assert(length >= 0); // fixed MB, 2015-04-214142store.reserve(length);43// Get the content44for(int i = 0; i < length; ++i) store.push_back(packet[i]);4546init();47}484950// ----------------------------------------------------------------------51void Storage::init()52{53// Initialize local variables54iter_ = store.begin();5556short a = 0x0102;57unsigned char *p_a = reinterpret_cast<unsigned char*>(&a);58bigEndian_ = (p_a[0] == 0x01); // big endian?59}606162// ----------------------------------------------------------------------63Storage::~Storage()64{}656667// ----------------------------------------------------------------------68bool Storage::valid_pos()69{70return (iter_ != store.end()); // this implies !store.empty()71}727374// ----------------------------------------------------------------------75unsigned int Storage::position() const76{77// According to C++ standard std::distance will simply compute the iterators78// difference for random access iterators as std::vector provides.79return static_cast<unsigned int>(std::distance(store.begin(), iter_));80}818283// ----------------------------------------------------------------------84void Storage::reset() {85store.clear();86iter_ = store.begin();87}888990// ----------------------------------------------------------------------91void Storage::resetPos() {92iter_ = store.begin();93}949596// ----------------------------------------------------------------------97/**98* Reads a char form the array99* @return The read char (between 0 and 255)100*/101unsigned char Storage::readChar()102{103if ( !valid_pos() )104{105throw std::invalid_argument("Storage::readChar(): invalid position");106}107return readCharUnsafe();108}109110111// ----------------------------------------------------------------------112/**113*114*/115void Storage::writeChar(unsigned char value)116{117store.push_back(value);118iter_ = store.begin();119}120121122// ----------------------------------------------------------------------123/**124* Reads a byte form the array125* @return The read byte (between -128 and 127)126*/127int Storage::readByte()128{129int i = static_cast<int>(readChar());130if (i < 128) return i;131else return (i - 256);132}133134135// ----------------------------------------------------------------------136/**137*138*/139void Storage::writeByte(int value)140{141if (value < -128 || value > 127)142{143throw std::invalid_argument("Storage::writeByte(): Invalid value, not in [-128, 127]");144}145writeChar( static_cast<unsigned char>( (value+256) % 256 ) );146}147148149// ----------------------------------------------------------------------150/**151* Reads an unsigned byte form the array152* @return The read byte (between 0 and 255)153*/154int Storage::readUnsignedByte()155{156return static_cast<int>(readChar());157}158159160// ----------------------------------------------------------------------161/**162*163*/164void Storage::writeUnsignedByte(int value)165{166if (value < 0 || value > 255)167{168throw std::invalid_argument("Storage::writeUnsignedByte(): Invalid value, not in [0, 255]");169}170writeChar( static_cast<unsigned char>( value ));171}172173174// -----------------------------------------------------------------------175/**176* Reads a string form the array177* @return The read string178*/179std::string Storage::readString()180{181int len = readInt();182checkReadSafe(len);183StorageType::const_iterator end = iter_;184std::advance(end, len);185const std::string tmp(iter_, end);186iter_ = end;187return tmp;188}189190191// ----------------------------------------------------------------------192/**193* Writes a string into the array;194* @param s The string to be written195*/196void Storage::writeString(const std::string &s)197{198writeInt(static_cast<int>(s.length()));199200store.insert(store.end(), s.begin(), s.end());201iter_ = store.begin();202}203204205// -----------------------------------------------------------------------206/**207* Reads a string list form the array208* @return The read string209*/210std::vector<std::string> Storage::readStringList()211{212std::vector<std::string> tmp;213const int len = readInt();214tmp.reserve(len);215for (int i = 0; i < len; i++)216{217tmp.push_back(readString());218}219return tmp;220}221222223// -----------------------------------------------------------------------224/**225* Reads a double list from the array226* @return The read double list227*/228std::vector<double> Storage::readDoubleList()229{230std::vector<double> tmp;231const int len = readInt();232tmp.reserve(len);233for (int i = 0; i < len; i++)234{235tmp.push_back(readDouble());236}237return tmp;238}239240241// ----------------------------------------------------------------------242/**243* Writes a string into the array;244* @param s The string to be written245*/246void Storage::writeStringList(const std::vector<std::string> &s)247{248writeInt(static_cast<int>(s.size()));249for (std::vector<std::string>::const_iterator it = s.begin(); it!=s.end() ; it++)250{251writeString(*it);252}253}254255256// ----------------------------------------------------------------------257/**258* Writes a double list into the array;259* @param s The double list to be written260*/261void Storage::writeDoubleList(const std::vector<double> &s)262{263writeInt(static_cast<int>(s.size()));264for (std::vector<double>::const_iterator it = s.begin(); it!=s.end() ; it++)265{266writeDouble(*it);267}268}269270271// ----------------------------------------------------------------------272/**273* Restores an integer, which was split up in two bytes according to the274* specification, it must have been split by its row byte representation275* with MSBF-order276*277* @return the unspoiled integer value (between -32768 and 32767)278*/279int Storage::readShort()280{281short value = 0;282unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);283readByEndianess(p_value, 2);284return value;285}286287288// ----------------------------------------------------------------------289void Storage::writeShort( int value )290{291if (value < -32768 || value > 32767)292{293throw std::invalid_argument("Storage::writeShort(): Invalid value, not in [-32768, 32767]");294}295296short svalue = static_cast<short>(value);297unsigned char *p_svalue = reinterpret_cast<unsigned char*>(&svalue);298writeByEndianess(p_svalue, 2);299}300301302// ----------------------------------------------------------------------303/**304* restores an integer, which was split up in four bytes acording to the305* specification, it must have been split by its row byte representation306* with MSBF-order307*308* @return the unspoiled integer value (between -2.147.483.648 and 2.147.483.647)309*/310int Storage::readInt()311{312int value = 0;313unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);314readByEndianess(p_value, 4);315return value;316}317318319// ----------------------------------------------------------------------320void Storage::writeInt( int value )321{322unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);323writeByEndianess(p_value, 4);324}325326327// ----------------------------------------------------------------------328/**329* restores a float , which was split up in four bytes acording to the330* specification, it must have been split by its row byte representation331* with MSBF-order332*333* @return the unspoiled float value334*/335float Storage::readFloat()336{337float value = 0;338unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);339readByEndianess(p_value, 4);340return value;341}342343344// ----------------------------------------------------------------------345void Storage::writeFloat( float value )346{347unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);348writeByEndianess(p_value, 4);349}350351352// ----------------------------------------------------------------------353void Storage::writeDouble( double value )354{355unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);356writeByEndianess(p_value, 8);357}358359360// ----------------------------------------------------------------------361double Storage::readDouble( )362{363double value = 0;364unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);365readByEndianess(p_value, 8);366return value;367}368369370// ----------------------------------------------------------------------371void Storage::writePacket(unsigned char* packet, int length)372{373store.insert(store.end(), &(packet[0]), &(packet[length]));374iter_ = store.begin(); // reserve() invalidates iterators375}376377378// ----------------------------------------------------------------------379void Storage::writePacket(const std::vector<unsigned char> &packet)380{381std::copy(packet.begin(), packet.end(), std::back_inserter(store));382iter_ = store.begin();383}384385386// ----------------------------------------------------------------------387void Storage::writeStorage(tcpip::Storage& other)388{389// the compiler cannot deduce to use a const_iterator as source390store.insert<StorageType::const_iterator>(store.end(), other.iter_, other.store.end());391iter_ = store.begin();392}393394395// ----------------------------------------------------------------------396void Storage::checkReadSafe(unsigned int num) const397{398if (std::distance(iter_, store.end()) < static_cast<int>(num))399{400std::ostringstream msg;401msg << "tcpip::Storage::readIsSafe: want to read " << num << " bytes from Storage, "402<< "but only " << std::distance(iter_, store.end()) << " remaining";403throw std::invalid_argument(msg.str());404}405}406407408// ----------------------------------------------------------------------409unsigned char Storage::readCharUnsafe()410{411const unsigned char hb = *iter_;412++iter_;413return hb;414}415416417// ----------------------------------------------------------------------418void Storage::writeByEndianess(const unsigned char * begin, unsigned int size)419{420const unsigned char * end = &(begin[size]);421if (bigEndian_)422store.insert(store.end(), begin, end);423else424store.insert(store.end(), std::reverse_iterator<const unsigned char *>(end), std::reverse_iterator<const unsigned char *>(begin));425iter_ = store.begin();426}427428429// ----------------------------------------------------------------------430void Storage::readByEndianess(unsigned char * array, int size)431{432checkReadSafe(size);433if (bigEndian_)434{435for (int i = 0; i < size; ++i)436array[i] = readCharUnsafe();437}438else439{440for (int i = size - 1; i >= 0; --i)441array[i] = readCharUnsafe();442}443}444445446// ----------------------------------------------------------------------447std::string Storage::hexDump() const448{449std::ostringstream dump;450for(StorageType::const_iterator it = store.begin(); it != store.end(); ++it)451{452// insert spaces between values453if (it != store.begin())454dump << " ";455dump << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(*it);456}457458return dump.str();459}460461}462463#endif // BUILD_TCPIP464465/*-----------------------------------------------------------------------466* Source $Source: $467* Version $Revision: 620 $468* Date $Date: 2011-07-08 17:39:10 +0200 (Fri, 08 Jul 2011) $469*-----------------------------------------------------------------------470* $Log: $471*-----------------------------------------------------------------------*/472473474