#pragma once

#include <stdint.h>
#include <stdlib.h>

#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

using std::ifstream;
using std::ofstream;
using std::ostringstream;
using std::string;
using std::vector;

using namespace std;

// 二进制读写相关
struct BinaryUtil {
    static void WriteInt(ofstream& out, int val) {
        uint32_t i = (uint32_t)val;
        out << (char)(i & 0xFF) << (char)((i >> 8) & 0xFF) << (char)((i >> 16) & 0xFF) << (char)((i >> 24) & 0xFF);
    };

    static void WriteLong(ofstream& out, uint64_t val) {
        uint64_t i = val;
        out << (char)(i & 0xFF) << (char)((i >> 8) & 0xFF) << (char)((i >> 16) & 0xFF) << (char)((i >> 24) & 0xFF) << (char)((i >> 32) & 0xFF)
            << (char)((i >> 40) & 0xFF) << (char)((i >> 48) & 0xFF) << (char)((i >> 56) & 0xFF);
    };

    static void WriteStr(ofstream& out, const string& s) {
        for (int i = 0; i < s.size(); ++i) out << s[i];
        out << (char)0;
    }

    static bool ReadInt(char* buf, uint64_t total, uint64_t* cur, int* res) {
        char b1, b2, b3, b4;
        if (*cur + 4 > total)
            return false;
        b1 = buf[(*cur)++];
        b2 = buf[(*cur)++];
        b3 = buf[(*cur)++];
        b4 = buf[(*cur)++];
        *res = (((uint32_t)(uint8_t)b4) << 24) + (((uint32_t)(uint8_t)b3) << 16) + (((uint32_t)(uint8_t)b2) << 8) + (((uint32_t)(uint8_t)b1));
        return true;
    };

    static bool ReadInt(ifstream& ifs, int* res) {
        // if(ifs.read((char*)res, sizeof(*res))) return true;
        char b[4];
        if (!ifs.read(&b[0], 1))
            return false;
        if (!ifs.read(&b[1], 1))
            return false;
        if (!ifs.read(&b[2], 1))
            return false;
        if (!ifs.read(&b[3], 1))
            return false;
        uint64_t cur = 0;
        return ReadInt((char*)b, 4, &cur, res);
    }

    static bool ReadLong(char* buf, uint64_t total, uint64_t* cur, uint64_t* res) {
        char b1, b2, b3, b4, b5, b6, b7, b8;
        if (*cur + 8 > total)
            return false;
        b1 = buf[(*cur)++];
        b2 = buf[(*cur)++];
        b3 = buf[(*cur)++];
        b4 = buf[(*cur)++];
        b5 = buf[(*cur)++];
        b6 = buf[(*cur)++];
        b7 = buf[(*cur)++];
        b8 = buf[(*cur)++];
        *res = (((uint64_t)(uint8_t)b8) << 56) + (((uint64_t)(uint8_t)b7) << 48) + (((uint64_t)(uint8_t)b6) << 40) + (((uint64_t)(uint8_t)b5) << 32) +
               (((uint64_t)(uint8_t)b4) << 24) + (((uint64_t)(uint8_t)b3) << 16) + (((uint64_t)(uint8_t)b2) << 8) + (((uint64_t)(uint8_t)b1));
        return true;
    };

    static bool ReadLong(ifstream& ifs, uint64_t* res) {
        // if(ifs.read((char*)res, sizeof(*res))) return true;
        char b[8];
        if (!ifs.read(&b[0], 1))
            return false;
        if (!ifs.read(&b[1], 1))
            return false;
        if (!ifs.read(&b[2], 1))
            return false;
        if (!ifs.read(&b[3], 1))
            return false;
        if (!ifs.read(&b[4], 1))
            return false;
        if (!ifs.read(&b[5], 1))
            return false;
        if (!ifs.read(&b[6], 1))
            return false;
        if (!ifs.read(&b[7], 1))
            return false;
        uint64_t cur = 0;
        return ReadLong((char*)b, 8, &cur, res);
    }
    static bool ReadStr(ifstream& ifs, string* res) {
        char b;
        res->clear();
        if (!ifs.read(&b, 1))
            return false;
        while ((int)b != 0) {
            res->push_back(b);
            if (!ifs.read(&b, 1))
                return false;
        }
        return true;
    }
    static bool ReadStr(char* buf, uint64_t total, uint64_t* cur, string* res) {
        char b;
        res->clear();
        if (*cur >= total)
            return false;
        b = buf[(*cur)++];
        while ((int)b != 0) {
            res->push_back(b);
            if (*cur >= total)
                return false;
            b = buf[(*cur)++];
        }
        return true;
    }
};