#ifndef ZFOO_BYTEBUFFER_H #define ZFOO_BYTEBUFFER_H #include #include #include #include #include #include #include // 网络传输默认使用大端传输 namespace zfoo { using std::string; using std::vector; using std::list; using std::set; using std::map; using std::make_pair; using std::pair; using std::unique_ptr; // Returns true if the current machine is little endian static inline bool is_little_endian() { static std::int32_t test = 1; return (*reinterpret_cast(&test) == 1); } // Default size of the buffer static const int32_t DEFAULT_BUFFER_SIZE = 2048; static const bool IS_LITTLE_ENDIAN = is_little_endian(); static const string EMPTY_STRING = ""; class ByteBuffer; class IProtocol { public: virtual int16_t protocolId() = 0; virtual ~IProtocol() { } }; class IProtocolRegistration { public: virtual int16_t protocolId() = 0; virtual void write(ByteBuffer &buffer, IProtocol *packet) = 0; virtual IProtocol *read(ByteBuffer &buffer) = 0; }; IProtocolRegistration *getProtocol(int16_t protocolId); class ByteBuffer { private: int8_t *m_buffer; int32_t m_max_capacity; int32_t m_writerIndex; int32_t m_readerIndex; public: ByteBuffer(int32_t capacity = DEFAULT_BUFFER_SIZE) : m_max_capacity(capacity) { m_buffer = (int8_t *) calloc(m_max_capacity, sizeof(int8_t)); clear(); } ~ByteBuffer() { free(m_buffer); m_buffer = nullptr; } ByteBuffer(const ByteBuffer &buffer) = delete; ByteBuffer &operator=(const ByteBuffer &buffer) = delete; void clear() { m_writerIndex = 0; m_readerIndex = 0; } int32_t writerIndex() const { return m_writerIndex; } int32_t readerIndex() const { return m_readerIndex; } void writerIndex(int32_t writeIndex) { if (writeIndex > m_max_capacity) { string errorMessage = "writeIndex[" + std::to_string(writeIndex) + "] out of bounds exception: readerIndex: " + std::to_string(m_readerIndex) + ", writerIndex: " + std::to_string(m_writerIndex) + "(expected: 0 <= readerIndex <= writerIndex <= capacity:" + std::to_string(m_max_capacity); throw errorMessage; } m_writerIndex = writeIndex; } void readerIndex(int32_t readerIndex) { if (readerIndex > m_writerIndex) { string errorMessage = "readIndex[" + std::to_string(readerIndex) + "] out of bounds exception: readerIndex: " + std::to_string(m_readerIndex) + ", writerIndex: " + std::to_string(m_writerIndex) + "(expected: 0 <= readerIndex <= writerIndex <= capacity:" + std::to_string(m_max_capacity); throw errorMessage; } m_readerIndex = readerIndex; } inline int32_t getCapacity() const { return m_max_capacity - m_writerIndex; } inline void ensureCapacity(const int32_t &capacity) { while (capacity - getCapacity() > 0) { int32_t newSize = m_max_capacity * 2; int8_t *pBuf = (int8_t *) realloc(m_buffer, newSize); if (!pBuf) { std::cout << "relloc failed!" << std::endl; exit(1); } m_buffer = pBuf; m_max_capacity = newSize; } } inline bool isReadable() { return m_writerIndex > m_readerIndex; } inline void writeBool(const bool &value) { ensureCapacity(1); int8_t v = value ? 1 : 0; m_buffer[m_writerIndex++] = v; } inline bool readBool() { int8_t value = m_buffer[m_readerIndex++]; return value == 1; } inline void writeByte(const int8_t &value) { ensureCapacity(1); m_buffer[m_writerIndex++] = value; } inline int8_t readByte() { return m_buffer[m_readerIndex++]; } inline void setByte(const int32_t &index, const int8_t &value) { m_buffer[index] = value; } inline int8_t getByte(const int32_t &index) { return m_buffer[index]; } inline void writeBytes(const int8_t *buffer, const int32_t &length) { ensureCapacity(length); memcpy(&m_buffer[m_writerIndex], buffer, length); m_writerIndex += length; } inline int8_t *readBytes(const int32_t &length) { int8_t *bytes = &m_buffer[m_readerIndex]; m_readerIndex += length; return bytes; } inline void writeShort(const int16_t &value) { write(value); } inline int16_t readShort() { return read(); } inline void writeInt(const int32_t &intValue) { writeVarInt((uint32_t) ((intValue << 1) ^ (intValue >> 31))); } inline void writeVarInt(const uint32_t &value) { uint32_t a = value >> 7; if (a == 0) { writeByte((int8_t) value); return; } int32_t writeIndex = m_writerIndex; ensureCapacity(5); setByte(writeIndex++, (int8_t) (value | 0x80)); uint32_t b = value >> 14; if (b == 0) { setByte(writeIndex++, (int8_t) a); writerIndex(writeIndex); return; } setByte(writeIndex++, (int8_t) (a | 0x80)); a = value >> 21; if (a == 0) { setByte(writeIndex++, (int8_t) b); writerIndex(writeIndex); return; } setByte(writeIndex++, (int8_t) (b | 0x80)); b = value >> 28; if (b == 0) { setByte(writeIndex++, (int8_t) a); writerIndex(writeIndex); return; } setByte(writeIndex++, (int8_t) (a | 0x80)); setByte(writeIndex++, (int8_t) b); writerIndex(writeIndex); } inline int32_t readInt() { int32_t readIndex = m_readerIndex; int32_t b = getByte(readIndex++); uint32_t value = b; if (b < 0) { b = getByte(readIndex++); value = value & 0x0000007F | b << 7; if (b < 0) { b = getByte(readIndex++); value = value & 0x00003FFF | b << 14; if (b < 0) { b = getByte(readIndex++); value = value & 0x001FFFFF | b << 21; if (b < 0) { value = value & 0x0FFFFFFF | getByte(readIndex++) << 28; } } } } readerIndex(readIndex); value = ((value >> 1) ^ -((int32_t) value & 1)); return (int32_t) value; } inline void writeLong(const int64_t &longValue) { uint64_t mask = (uint64_t) ((longValue << 1) ^ (longValue >> 63)); if (mask >> 32 == 0) { writeVarInt((uint32_t) mask); return; } int8_t bytes[9]; bytes[0] = (int8_t) (mask | 0x80); bytes[1] = (int8_t) (mask >> 7 | 0x80); bytes[2] = (int8_t) (mask >> 14 | 0x80); bytes[3] = (int8_t) (mask >> 21 | 0x80); uint32_t a = (uint32_t) (mask >> 28); uint32_t b = (uint32_t) (mask >> 35); if (b == 0) { bytes[4] = (int8_t) a; writeBytes(bytes, 5); return; } bytes[4] = (int8_t) (a | 0x80); a = (uint32_t) (mask >> 42); if (a == 0) { bytes[5] = (int8_t) b; writeBytes(bytes, 6); return; } bytes[5] = (int8_t) (b | 0x80); b = (int) (mask >> 49); if (b == 0) { bytes[6] = (int8_t) a; writeBytes(bytes, 7); return; } bytes[6] = (int8_t) (a | 0x80); a = (int) (mask >> 56); if (a == 0) { bytes[7] = (int8_t) b; writeBytes(bytes, 8); return; } bytes[7] = (int8_t) (b | 0x80); bytes[8] = (int8_t) a; writeBytes(bytes, 9); } inline int64_t readLong() { int32_t readIndex = m_readerIndex; int64_t b = getByte(readIndex++); uint64_t value = b; if (b < 0) { b = getByte(readIndex++); value = value & 0x000000000000007FLL | b << 7; if (b < 0) { b = getByte(readIndex++); value = value & 0x0000000000003FFFLL | b << 14; if (b < 0) { b = getByte(readIndex++); value = value & 0x00000000001FFFFFLL | b << 21; if (b < 0) { b = getByte(readIndex++); value = value & 0x000000000FFFFFFFLL | b << 28; if (b < 0) { b = getByte(readIndex++); value = value & 0x00000007FFFFFFFFLL | b << 35; if (b < 0) { b = getByte(readIndex++); value = value & 0x000003FFFFFFFFFFLL | b << 42; if (b < 0) { b = getByte(readIndex++); value = value & 0x0001FFFFFFFFFFFFLL | b << 49; if (b < 0) { b = getByte(readIndex++); value = value & 0x00FFFFFFFFFFFFFFLL | b << 56; } } } } } } } } readerIndex(readIndex); value = ((value >> 1) ^ -((int64_t) value & 1)); return (int64_t) value; } inline void writeFloat(const float &value) { write(value); } inline float readFloat() { return read(); } inline void writeDouble(const double &value) { write(value); } inline double readDouble() { return read(); } inline void writeString(const string &value) { if (value.empty()) { writeInt(0); return; } int32_t length = value.size() * sizeof(value.front()); writeInt(length); writeBytes(reinterpret_cast(&value[0]), length); } inline string readString() { int32_t length = readInt(); if (length <= 0) { return EMPTY_STRING; } auto bytes = readBytes(length); string str(reinterpret_cast(bytes), length); return str; } // 很多脚本语言没有char,所以这里使用string代替 inline void writeChar(const char &value) { string str; str.push_back(value); writeString(str); } inline char readChar() { return readString()[0]; } inline bool writePacketFlag(const IProtocol *packet) { bool flag = packet == nullptr; writeBool(!flag); return flag; } inline void writePacket(IProtocol *packet, const int16_t &protocolId) { IProtocolRegistration *protocolRegistration = getProtocol(protocolId); protocolRegistration->write(*this, packet); } inline unique_ptr readPacket(const int16_t &protocolId) { IProtocolRegistration *protocolRegistration = getProtocol(protocolId); auto packet = protocolRegistration->read(*this); return unique_ptr(packet); } //---------------------------------boolean-------------------------------------- inline void writeBooleanArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeBool(value); } } inline vector readBooleanArray() { int32_t length = readInt(); int8_t *bytes = readBytes(length); vector array; for (auto i = 0; i < length; i++) { array.emplace_back((bytes[i] == 1)); } return array; } inline void writeBooleanList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeBool(value); } } inline list readBooleanList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readBool()); } return list; } inline void writeBooleanSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeBool(value); } } inline set readBooleanSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readBool()); } return set; } //---------------------------------byte-------------------------------------- inline void writeByteArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeByte(value); } } inline vector readByteArray() { int32_t length = readInt(); int8_t *bytes = readBytes(length); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(bytes[i]); } return array; } inline void writeByteList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeByte(value); } } inline list readByteList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readByte()); } return list; } inline void writeByteSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeByte(value); } } inline set readByteSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readByte()); } return set; } //---------------------------------short-------------------------------------- inline void writeShortArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeShort(value); } } inline vector readShortArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readShort()); } return array; } inline void writeShortList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeShort(value); } } inline list readShortList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readShort()); } return list; } inline void writeShortSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeShort(value); } } inline set readShortSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readShort()); } return set; } //---------------------------------int-------------------------------------- inline void writeIntArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeInt(value); } } inline vector readIntArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readInt()); } return array; } inline void writeIntList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeInt(value); } } inline list readIntList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readInt()); } return list; } inline void writeIntSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeInt(value); } } inline set readIntSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readInt()); } return set; } //---------------------------------long-------------------------------------- inline void writeLongArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeLong(value); } } inline vector readLongArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readLong()); } return array; } inline void writeLongList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeLong(value); } } inline list readLongList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readLong()); } return list; } inline void writeLongSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeLong(value); } } inline set readLongSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readLong()); } return set; } //---------------------------------float-------------------------------------- inline void writeFloatArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeFloat(value); } } inline vector readFloatArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readFloat()); } return array; } inline void writeFloatList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeFloat(value); } } inline list readFloatList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readFloat()); } return list; } inline void writeFloatSet(const set &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeFloat(value); } } inline set readFloatSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readFloat()); } return set; } //---------------------------------double-------------------------------------- inline void writeDoubleArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeDouble(value); } } inline vector readDoubleArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readDouble()); } return array; } inline void writeDoubleList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeDouble(value); } } inline list readDoubleList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readDouble()); } return list; } inline void writeDoubleSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeDouble(value); } } inline set readDoubleSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readDouble()); } return set; } //---------------------------------char-------------------------------------- inline void writeCharArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeChar(value); } } inline vector readCharArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readChar()); } return array; } inline void writeCharList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeChar(value); } } inline list readCharList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readChar()); } return list; } inline void writeCharSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeChar(value); } } inline set readCharSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readChar()); } return set; } //---------------------------------string-------------------------------------- inline void writeStringArray(const vector &array) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writeString(value); } } inline vector readStringArray() { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { array.emplace_back(readString()); } return array; } inline void writeStringList(const list &list) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writeString(value); } } inline list readStringList() { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { list.emplace_back(readString()); } return list; } inline void writeStringSet(const set &set) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writeString(value); } } inline set readStringSet() { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { set.emplace(readString()); } return set; } inline void writeIntIntMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeInt(key); writeInt(value); } } inline map readIntIntMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readInt(); auto value = readInt(); map.insert(pair(key, value)); } return map; } inline void writeIntLongMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeInt(key); writeLong(value); } } inline map readIntLongMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readInt(); auto value = readLong(); map.insert(pair(key, value)); } return map; } inline void writeIntStringMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeInt(key); writeString(value); } } inline map readIntStringMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readInt(); auto value = readString(); map.insert(pair(key, value)); } return map; } template inline void writeIntPacketMap(const map &map, const int16_t &protocolId) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeInt(key); writePacket((IProtocol *) &value, protocolId); } } template inline map readIntPacketMap(const int16_t &protocolId) { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readInt(); auto value = readPacket(protocolId); auto *p = (T *) value.get(); map.insert(pair(key, *p)); } return map; } inline void writeLongIntMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeLong(key); writeInt(value); } } inline map readLongIntMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readLong(); auto value = readInt(); map.insert(pair(key, value)); } return map; } inline void writeLongLongMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeLong(key); writeLong(value); } } inline map readLongLongMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readLong(); auto value = readLong(); map.insert(pair(key, value)); } return map; } inline void writeLongStringMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeLong(key); writeString(value); } } inline map readLongStringMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readLong(); auto value = readString(); map.insert(pair(key, value)); } return map; } template inline void writeLongPacketMap(const map &map, const int16_t &protocolId) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeLong(key); writePacket((IProtocol *) &value, protocolId); } } template inline map readLongPacketMap(const int16_t &protocolId) { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readLong(); auto value = readPacket(protocolId); auto *p = (T *) value.get(); map.insert(pair(key, *p)); } return map; } inline void writeStringIntMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeString(key); writeInt(value); } } inline map readStringIntMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readString(); auto value = readInt(); map.insert(pair(key, value)); } return map; } inline void writeStringLongMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeString(key); writeLong(value); } } inline map readStringLongMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readString(); auto value = readLong(); map.insert(pair(key, value)); } return map; } inline void writeStringStringMap(const map &map) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeString(key); writeString(value); } } inline map readStringStringMap() { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readString(); auto value = readString(); map.insert(pair(key, value)); } return map; } template inline void writeStringPacketMap(const map &map, const int16_t &protocolId) { if (map.empty()) { writeByte(0); return; } writeInt(map.size()); for (const auto&[key, value] : map) { writeString(key); writePacket((IProtocol *) &value, protocolId); } } template inline map readStringPacketMap(const int16_t &protocolId) { int32_t length = readInt(); map map; for (auto i = 0; i < length; i++) { auto key = readString(); auto value = readPacket(protocolId); auto *p = (T *) value.get(); map.insert(pair(key, *p)); } return map; } //---------------------------------packet-------------------------------------- template inline void writePacketArray(const vector &array, const int16_t &protocolId) { if (array.empty()) { writeByte(0); return; } int32_t length = array.size(); writeInt(length); for (auto value : array) { writePacket((IProtocol *) &value, protocolId); } } template inline vector readPacketArray(const int16_t &protocolId) { int32_t length = readInt(); vector array; for (auto i = 0; i < length; i++) { auto value = readPacket(protocolId); auto *p = (T *) value.get(); array.emplace_back(*p); } return array; } template inline void writePacketList(const list &list, const int16_t &protocolId) { if (list.empty()) { writeByte(0); return; } int32_t length = list.size(); writeInt(length); for (auto value : list) { writePacket((IProtocol *) &value, protocolId); } } template inline list readPacketList(const int16_t &protocolId) { int32_t length = readInt(); list list; for (auto i = 0; i < length; i++) { auto value = readPacket(protocolId); auto *p = (T *) value.get(); list.emplace_back(*p); } return list; } template inline void writePacketSet(const set &set, const int16_t &protocolId) { if (set.empty()) { writeByte(0); return; } int32_t length = set.size(); writeInt(length); for (auto value : set) { writePacket((IProtocol *) &value, protocolId); } } template inline set readPacketSet(const int16_t &protocolId) { int32_t length = readInt(); set set; for (auto i = 0; i < length; i++) { auto value = readPacket(protocolId); auto *p = (T *) value.get(); set.emplace(*p); } return set; } private: template inline void write(T value) { ensureCapacity(sizeof(T)); // MSDN: The htons function converts a u_short from host to TCP/IP network byte order (which is big-endian). // ** This mean the network byte order is big-endian ** if (IS_LITTLE_ENDIAN) { swap_bytes(reinterpret_cast(&value)); } memcpy(&m_buffer[m_writerIndex], (int8_t *) &value, sizeof(T)); m_writerIndex += sizeof(T); } template inline T read() { T value = *((T *) &m_buffer[m_readerIndex]); if (IS_LITTLE_ENDIAN) { swap_bytes(reinterpret_cast(&value)); } m_readerIndex += sizeof(T); return value; } // Swaps the order of bytes for some chunk of memory template inline void swap_bytes(int8_t *data) { for (std::size_t i = 0, end = DataSize / 2; i < end; ++i) { std::swap(data[i], data[DataSize - i - 1]); } } }; } #endif