All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cpp.ByteBuffer.h Maven / Gradle / Ivy

Go to download

zfoo protocol is binary serialization framework for Java/C++/js/ts/C#/Go/Lua/GDScript/Python

The newest version!
#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 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 *buffer;
        int32_t max_capacity;
        int32_t writeOffset;
        int32_t readOffset;

    public:
        ByteBuffer(int32_t capacity = DEFAULT_BUFFER_SIZE) : max_capacity(capacity) {
            buffer = (int8_t *) calloc(max_capacity, sizeof(int8_t));
            clear();
        }

        ~ByteBuffer() {
            free(buffer);
            buffer = nullptr;
        }


        ByteBuffer(const ByteBuffer &buffer) = delete;

        ByteBuffer &operator=(const ByteBuffer &buffer) = delete;

        void adjustPadding(int32_t predictionLength, int32_t beforeWriteIndex) {
            int32_t currentWriteIndex = getWriteOffset();
            int32_t predictionCount = writeIntCount(predictionLength);
            int32_t length = currentWriteIndex - beforeWriteIndex - predictionCount;
            int32_t lengthCount = writeIntCount(length);
            int32_t padding = lengthCount - predictionCount;
            if (padding == 0) {
                setWriteOffset(beforeWriteIndex);
                writeInt(length);
                setWriteOffset(currentWriteIndex);
            } else {
//                int8_t *targetPtr = (int8_t *) calloc(length, sizeof(int8_t));
//                memcpy(targetPtr, &buffer[currentWriteIndex - length], length);
//                setWriteOffset(beforeWriteIndex);
//                writeInt(length);
//                writeBytes(targetPtr, length);
//                free(targetPtr);

                memmove(&buffer[beforeWriteIndex + lengthCount], &buffer[currentWriteIndex - length], length);
                setWriteOffset(beforeWriteIndex);
                writeInt(length);
                setWriteOffset(beforeWriteIndex + lengthCount + length);
            }
        }

        bool compatibleRead(int32_t beforeReadIndex, int32_t length) {
            return length != -1 && getReadOffset() < length + beforeReadIndex;
        }

        void clear() {
            writeOffset = 0;
            readOffset = 0;
        }

        int8_t *getBuffer() {
            return buffer;
        }

        int32_t getWriteOffset() const {
            return writeOffset;
        }

        int32_t getReadOffset() const {
            return readOffset;
        }

        void setWriteOffset(int32_t writeIndex) {
            if (writeIndex > max_capacity) {
                string errorMessage =
                        "writeIndex[" + std::to_string(writeIndex) + "] out of bounds exception: readOffset: " +
                        std::to_string(readOffset) +
                        ", writeOffset: " + std::to_string(writeOffset) +
                        "(expected: 0 <= readOffset <= writeOffset <= capacity:" + std::to_string(max_capacity)  + ")";
                throw errorMessage;
            }
            writeOffset = writeIndex;
        }

        void setReadOffset(int32_t readIndex) {
            if (readIndex > writeOffset) {
                string errorMessage =
                        "readIndex[" + std::to_string(readIndex) + "] out of bounds exception: readOffset: " +
                        std::to_string(readOffset) +
                        ", writeOffset: " + std::to_string(writeOffset) +
                        "(expected: 0 <= readOffset <= writeOffset <= capacity:" + std::to_string(max_capacity)  + ")";
                throw errorMessage;
            }
            readOffset = readIndex;
        }

        inline int32_t getCapacity() const {
            return max_capacity - writeOffset;
        }

        inline void ensureCapacity(const int32_t &capacity) {
            while (capacity - getCapacity() > 0) {
                int32_t newSize = max_capacity * 2;
                int8_t *pBuf = (int8_t *) realloc(buffer, newSize);
                if (!pBuf) {
                    string errorMessage = "relloc failed!";
                    throw errorMessage;
                }
                buffer = pBuf;
                max_capacity = newSize;
            }
        }

        inline bool isReadable() {
            return writeOffset > readOffset;
        }

        inline void writeBool(const bool &value) {
            ensureCapacity(1);
            int8_t v = value ? 1 : 0;
            buffer[writeOffset++] = v;
        }

        inline bool readBool() {
            int8_t value = buffer[readOffset++];
            return value == 1;
        }

        inline void writeByte(const int8_t &value) {
            ensureCapacity(1);
            buffer[writeOffset++] = value;
        }

        inline int8_t readByte() {
            return buffer[readOffset++];
        }

        inline void setByte(const int32_t &index, const int8_t &value) {
            buffer[index] = value;
        }

        inline int8_t getByte(const int32_t &index) {
            return buffer[index];
        }

        inline void writeBytes(const int8_t *buf, const int32_t &length) {
            ensureCapacity(length);
            memcpy(&buffer[writeOffset], buf, length);
            writeOffset += length;
        }

        inline int8_t *readBytes(const int32_t &length) {
            int8_t *bytes = &buffer[readOffset];
            readOffset += 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 = writeOffset;
            ensureCapacity(5);

            setByte(writeIndex++, (int8_t) (value | 0x80));
            uint32_t b = value >> 14;
            if (b == 0) {
                setByte(writeIndex++, (int8_t) a);
                setWriteOffset(writeIndex);
                return;
            }

            setByte(writeIndex++, (int8_t) (a | 0x80));
            a = value >> 21;
            if (a == 0) {
                setByte(writeIndex++, (int8_t) b);
                setWriteOffset(writeIndex);
                return;
            }

            setByte(writeIndex++, (int8_t) (b | 0x80));
            b = value >> 28;
            if (b == 0) {
                setByte(writeIndex++, (int8_t) a);
                setWriteOffset(writeIndex);
                return;
            }

            setByte(writeIndex++, (int8_t) (a | 0x80));
            setByte(writeIndex++, (int8_t) b);
            setWriteOffset(writeIndex);
        }

        inline int32_t writeIntCount(const int32_t &intValue) {
            uint32_t value = (uint32_t) ((intValue << 1) ^ (intValue >> 31));
            if (value >> 7 == 0) {
                return 1;
            }
            if (value >> 14 == 0) {
                return 2;
            }
            if (value >> 21 == 0) {
                return 3;
            }
            if (value >> 28 == 0) {
                return 4;
            }
            return 5;
        }

        inline int32_t readInt() {
            int32_t readIndex = readOffset;

            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;
                        }
                    }
                }
            }
            setReadOffset(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 = readOffset;

            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;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            setReadOffset(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;
        }

        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 writeBoolArray(const vector &array) {
            if (array.empty()) {
                writeByte(0);
                return;
            }
            int32_t length = array.size();
            writeInt(length);
            for (auto value: array) {
                writeBool(value);
            }
        }

        inline vector readBoolArray() {
            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 writeBoolList(const list &list) {
            if (list.empty()) {
                writeByte(0);
                return;
            }
            int32_t length = list.size();
            writeInt(length);
            for (auto value: list) {
                writeBool(value);
            }
        }

        inline list readBoolList() {

            int32_t length = readInt();
            list list;
            for (auto i = 0; i < length; i++) {
                list.emplace_back(readBool());
            }
            return list;
        }

        inline void writeBoolSet(const set &set) {
            if (set.empty()) {
                writeByte(0);
                return;
            }
            int32_t length = set.size();
            writeInt(length);
            for (auto value: set) {
                writeBool(value);
            }
        }

        inline set readBoolSet() {
            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;
        }

        //---------------------------------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(&buffer[writeOffset], (int8_t *) &value, sizeof(T));
            writeOffset += sizeof(T);
        }

        template
        inline T read() {
            T value = *((T *) &buffer[readOffset]);
            if (IS_LITTLE_ENDIAN) {
                swap_bytes(reinterpret_cast(&value));
            }
            readOffset += 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy