c++ - Adding a string or char array to a byte vector -
i'm working on class create , read out packets send through network, far have working 16bit , 8bit integers (well unsigned still).
now problem i've tried numerous ways of copying on somehow _buffer got mangled, segfaulted, or result wrong.
i'd appreciate if show me working example.
my current code can seen below.
thanks, xeross
main
#include <iostream> #include <stdio.h> #include "packet.h" using namespace std; int main(int argc, char** argv) { cout << "#################################" << endl; cout << "# internal use #" << endl; cout << "# codename packetstorm #" << endl; cout << "#################################" << endl; cout << endl; packet packet = packet(); packet.setopcode(0x1f4d); cout << "current opcode is: " << packet.getopcode() << endl << endl; packet.add(uint8_t(5)) .add(uint16_t(4000)) .add(uint8_t(5)); for(uint8_t i=0; i<10;i++) printf("byte %u = %x\n", i, packet._buffer[i]); printf("\nreading them out: \n1 = %u\n2 = %u\n3 = %u\n4 = %s", packet.readuint8(), packet.readuint16(), packet.readuint8()); return 0; }
packet.h
#ifndef _packet_h_ #define _packet_h_ #include <iostream> #include <vector> #include <stdio.h> #include <stdint.h> #include <string.h> using namespace std; class packet { public: packet() : m_opcode(0), _buffer(0), _wpos(0), _rpos(0) {} packet(uint16_t opcode) : m_opcode(opcode), _buffer(0), _wpos(0), _rpos(0) {} uint16_t getopcode() { return m_opcode; } void setopcode(uint16_t opcode) { m_opcode = opcode; } packet& add(uint8_t value) { if(_buffer.size() < _wpos + 1) _buffer.resize(_wpos + 1); memcpy(&_buffer[_wpos], &value, 1); _wpos += 1; return *this; } packet& add(uint16_t value) { if(_buffer.size() < _wpos + 2) _buffer.resize(_wpos + 2); memcpy(&_buffer[_wpos], &value, 2); _wpos += 2; return *this; } uint8_t readuint8() { uint8_t result = _buffer[_rpos]; _rpos += sizeof(uint8_t); return result; } uint16_t readuint16() { uint16_t result; memcpy(&result, &_buffer[_rpos], sizeof(uint16_t)); _rpos += sizeof(uint16_t); return result; } uint16_t m_opcode; std::vector<uint8_t> _buffer; protected: size_t _wpos; // write position size_t _rpos; // read position }; #endif // _packet_h_
since you're using std::vector buffer, may let keep track of write position , avoid having keep manually resizing it. can avoid writing multiple overloads of add function using function template:
template <class t> packet& add(t value) { std::copy((uint8_t*) &value, ((uint8_t*) &value) + sizeof(t), std::back_inserter(_buffer)); return *this; }
now can write pod type buffer.
implicitly:
int = 5; o.write(i);
or explictly:
o.write<int>(5);
to read buffer, need keep track of read position:
template <class t> t read() { t result; uint8_t *p = &_buffer[_rpos]; std::copy(p, p + sizeof(t), (uint8_t*) &result); _rpos += sizeof(t); return result; }
you need explicitly pass type parameter read. i.e.
int = o.read<int>();
caveat: have used pattern often, since typing off top of head, there may few errors in code.
edit: noticed want able add strings or other non-pod types buffer. can via template specialization:
template <> packet& add(std::string s) { add(string.length()); (size_t = 0; < string.length(); ++i) add(string[i]); return *this; }
this tells compiler: if add called string type, use function instead of generic add() function.
and read string:
template <> std::string read<>() { size_t len = read<size_t>(); std::string s; while (len--) s += read<char>(); return s; }
Comments
Post a Comment