/* Copyright (C) 2000 Stefan Westerfeld stefan@space.twc.de This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "buffer.h" #include #include using namespace std; using namespace Arts; Buffer::Buffer() : rpos(0), _readError(false),d(0) { contents.reserve(128); } Buffer::~Buffer() { } long Buffer::size() { return contents.size(); } long Buffer::remaining() { return size()-rpos; } bool Buffer::readError() { return _readError; } void Buffer::writeBool(bool b) { contents.push_back(b?1:0); } void Buffer::writeByte(mcopbyte b) { contents.push_back(b); } void Buffer::writeLong(long l) { contents.push_back((l >> 24) & 0xff); contents.push_back((l >> 16) & 0xff); contents.push_back((l >> 8) & 0xff); contents.push_back(l & 0xff); } void Buffer::writeBoolSeq(const vector& seq) { writeLong(seq.size()); vector::const_iterator i; for(i = seq.begin(); i != seq.end(); i++) writeBool(*i); } void Buffer::writeByteSeq(const vector& seq) { writeLong(seq.size()); // bytes are sent raw, so we can call read here write(seq); } void Buffer::writeLongSeq(const vector& seq) { writeLong(seq.size()); vector::const_iterator i; for(i = seq.begin(); i != seq.end(); i++) writeLong(*i); } void Buffer::writeFloat(float f) { // FIXME: on some machines this may fail badly (there is explicit // float marshalling and demarshalling code in mico/orb/util.cpp) union { float f; long l; } u = {f}; writeLong(u.l); } void Buffer::writeFloatSeq(const std::vector& seq) { writeLong(seq.size()); vector::const_iterator i; for(i = seq.begin(); i != seq.end(); i++) writeFloat(*i); } void Buffer::writeString(const string& s) { long len = s.size()+1; writeLong(len); contents.insert(contents.end(),reinterpret_cast(s.c_str()), reinterpret_cast(s.c_str()+len)); } void Buffer::writeStringSeq(const vector& seq) { writeLong(seq.size()); vector::const_iterator i; for(i = seq.begin(); i != seq.end(); i++) writeString(*i); } void Buffer::write(void *data, long len) { unsigned char *c = (unsigned char *)data; contents.insert(contents.end(),c,c+len); } void Buffer::write(const vector& raw) { contents.insert(contents.end(), raw.begin(), raw.end()); } void Buffer::read(vector& raw, long l) { if(l >= 0 && remaining() >= l) { raw.clear(); raw.insert(raw.end(), contents.begin()+rpos, contents.begin()+rpos+l); rpos += l; } else { _readError = true; } } void *Buffer::read(long l) { void *result = 0; if(l >= 0 && remaining() >= l) { result = &contents[rpos]; rpos += l; } else { _readError = true; } return result; } void *Buffer::peek(long l) { assert(l >= 0 && remaining() >= l); return &contents[rpos]; } void Buffer::skip(long l) { if(l >= 0 && remaining() >= l) { rpos += l; } else { _readError = true; } } void Buffer::rewind() { rpos = 0; } bool Buffer::readBool() { long result = false; if(remaining() >= 1) { if(contents[rpos] == 1) result = true; else { assert(contents[rpos] == 0); } rpos += 1; } else { _readError = true; } return result; } void Buffer::readBoolSeq(vector& result) { // might be optimizable a bit long i,seqlen = readLong(); result.clear(); if(seqlen >= 0 && remaining() >= seqlen) { for(i=0;i= 1) { return contents[rpos++]; } else { _readError = true; return 0; } } void Buffer::readByteSeq(vector& result) { long seqlen = readLong(); // bytes are sent raw, so we can call read here read(result, seqlen); } long Buffer::readLong() { long result = 0; if(remaining() >= 4) { result = (contents[rpos] << 24) + (contents[rpos+1] << 16) + (contents[rpos+2] << 8) + contents[rpos+3]; rpos += 4; } else { _readError = true; } return result; } void Buffer::readLongSeq(vector& result) { // might be optimizable a bit long i,seqlen = readLong(); result.clear(); if(seqlen * 4 >= 0 && remaining() >= seqlen * 4) { for(i=0;i& result) { // might be optimizable a bit long i,seqlen = readLong(); result.clear(); if(seqlen * 4 >= 0 && remaining() >= seqlen * 4) { for(i=0;i& result) { // might be optimizable a bit long i,seqlen = readLong(); result.clear(); //result.reserve(seqlen); for(i=0;i= 8); contents[4] = (len >> 24) & 0xff; contents[5] = (len >> 16) & 0xff; contents[6] = (len >> 8) & 0xff; contents[7] = len & 0xff; } void Buffer::patchLong(long position, long value) { long len = size(); assert(len >= position+4); contents[position] = (value >> 24) & 0xff; contents[position+1] = (value >> 16) & 0xff; contents[position+2] = (value >> 8) & 0xff; contents[position+3] = value & 0xff; } string Buffer::toString(const string& name) { string result; char hex[17] = "0123456789abcdef"; vector::iterator ci; for(ci = contents.begin(); ci != contents.end(); ci++) { result += hex[(*ci >> 4) & 0xf]; result += hex[*ci & 0xf]; } if(name.empty()) return result; return name + ":" + result; } unsigned char Buffer::fromHexNibble(char c) { int uc = (unsigned char)c; if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0'; if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a'; if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A'; return 16; // error } static int stringncmp(const string& s1, const string& s2, size_t n) { // I don't know a way to implement that compliant to all STL string // implementations (compare seems to work differently sometimes) return strncmp(s1.c_str(),s2.c_str(),n); } bool Buffer::fromString(const string& data, const string& name) { string start = name+":"; if(name.empty()) start = ""; if(stringncmp(data,start,start.size()) != 0) return false; contents.clear(); string::const_iterator di = data.begin() + start.size(); while(di != data.end()) { unsigned char h = fromHexNibble(*di++); // high nibble if(di == data.end()) return false; unsigned char l = fromHexNibble(*di++); // low nibble if(h >= 16 || l >= 16) return false; // no proper hex digit contents.push_back((h << 4) + l); } return true; }