15#ifdef CJF2_NBT_CPP_USE_ZLIB
31 NBT_IO(
void) =
delete;
33 ~NBT_IO(
void) =
delete;
43 template <
typename T = std::vector<u
int8_t>>
57 static_assert(
sizeof(
ValueType) == 1,
"Error ValueType Size");
58 static_assert(std::is_trivially_copyable_v<ValueType>,
"ValueType Must Be Trivially Copyable");
87 return tData[szIndex];
95 return tData[szIndex++];
104 memcpy(pDest, &tData[szIndex], szSize);
123 return &(tData[szIndex]);
132 return szIndex += szSize;
141 return szIndex -= szSize;
148 return szIndex >= tData.size();
163 return (tData.size() - szIndex) >= szSize;
202 template <
typename T = std::vector<u
int8_t>>
215 static_assert(
sizeof(
ValueType) == 1,
"Error ValueType Size");
216 static_assert(std::is_trivially_copyable_v<ValueType>,
"ValueType Must Be Trivially Copyable");
224 tData.resize(szStartIdx);
244 return tData[szIndex];
252 requires(std::is_constructible_v<ValueType, V &&>)
255 tData.push_back(std::forward<V>(c));
267 size_t szCurSize = tData.size();
268 tData.resize(szCurSize + szSize);
269 memcpy(&tData.data()[szCurSize], &pData[0], szSize);
278 tData.reserve(tData.size() + szAddSize);
289 size_t Size(
void)
const noexcept
302 const T &
Data(
void)
const noexcept
324 template<
typename T = std::vector<u
int8_t>>
325 requires (
sizeof(
typename T::value_type) == 1 && std::is_trivially_copyable_v<typename T::value_type>)
326 static bool WriteFile(
const std::filesystem::path &pathFileName,
const T &tData)
329 fWrite.open(pathFileName, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
336 uint64_t qwFileSize = tData.size();
337 if (!fWrite.write((
const char *)tData.data(),
sizeof(tData[0]) * qwFileSize))
355 template<
typename T = std::vector<u
int8_t>>
356 requires (
sizeof(
typename T::value_type) == 1 && std::is_trivially_copyable_v<typename T::value_type>)
357 static bool ReadFile(
const std::filesystem::path &pathFileName, T &tData)
360 fRead.open(pathFileName, std::ios_base::binary | std::ios_base::in);
368 if (!fRead.seekg(0, std::ios::end))
374 size_t szFileSize = fRead.tellg();
377 if (!fRead.seekg(0, std::ios::beg))
383 tData.resize(szFileSize);
384 if (!fRead.read((
char *)tData.data(),
sizeof(tData[0]) * szFileSize))
400 static bool IsFileExist(
const std::filesystem::path &pathFileName)
403 bool bExists = std::filesystem::exists(pathFileName, ec);
405 return !ec && bExists;
408#ifdef CJF2_NBT_CPP_USE_ZLIB
415 static bool IsZlib(uint8_t u8DataFirst, uint8_t u8DataSecond)
417 return u8DataFirst == (uint8_t)0x78 &&
419 u8DataSecond == (uint8_t)0x9C ||
420 u8DataSecond == (uint8_t)0x01 ||
421 u8DataSecond == (uint8_t)0xDA ||
422 u8DataSecond == (uint8_t)0x5E
431 static bool IsGzip(uint8_t u8DataFirst, uint8_t u8DataSecond)
433 return u8DataFirst == (uint8_t)0x1F && u8DataSecond == (uint8_t)0x8B;
443 requires (
sizeof(
typename T::value_type) == 1 && std::is_trivially_copyable_v<typename T::value_type>)
446 if (tData.size() <= 2)
451 uint8_t u8DataFirst = (uint8_t)tData[0];
452 uint8_t u8DataSecond = (uint8_t)tData[1];
454 return IsZlib(u8DataFirst, u8DataSecond) ||
IsGzip(u8DataFirst, u8DataSecond);
464 template<
typename I,
typename O>
465 requires (
sizeof(
typename I::value_type) == 1 && std::is_trivially_copyable_v<typename I::value_type> &&
466 sizeof(
typename O::value_type) == 1 && std::is_trivially_copyable_v<typename O::value_type>)
469 if (std::addressof(oData) == std::addressof(iData))
471 throw std::runtime_error(
"The oData object cannot be the iData object");
493 .zalloc = (alloc_func)Z_NULL,
494 .zfree = (free_func)Z_NULL,
495 .opaque = (voidpf)Z_NULL,
497 .data_type = Z_BINARY,
503 if (inflateInit2(&zs, 32 + 15) != Z_OK)
505 throw std::runtime_error(
"Failed to initialize zlib decompression");
511 zs.next_in = (z_const Bytef *)iData.data();
514 oData.resize(iData.size());
517 size_t szDecompressedSize = 0;
518 size_t szRemainingSize = iData.size();
523 size_t szOut = oData.size() - szDecompressedSize;
526 oData.resize(oData.size() * 2);
527 szOut = oData.size() - szDecompressedSize;
533 zs.next_out = (Bytef *)(&oData.data()[szDecompressedSize]);
536 if (zs.avail_in == 0)
538 constexpr uInt uIntMax = (uInt)-1;
539 zs.avail_in = szRemainingSize > (size_t)uIntMax ? uIntMax : (uInt)szRemainingSize;
540 szRemainingSize -= zs.avail_in;
544 if (zs.avail_out == 0)
546 constexpr uInt uIntMax = (uInt)-1;
547 zs.avail_out = szOut > (size_t)uIntMax ? uIntMax : (uInt)szOut;
552 iRet = inflate(&zs, szRemainingSize != 0 ? Z_NO_FLUSH : Z_FINISH);
555 szDecompressedSize += szOut - zs.avail_out;
556 }
while (iRet == Z_OK || iRet == Z_BUF_ERROR);
559 oData.resize(szDecompressedSize);
562 if (iRet != Z_STREAM_END)
566 throw std::runtime_error(std::string(
"Zlib decompression failed with error message: ") + std::string(zs.msg));
570 throw std::runtime_error(std::string(
"Zlib decompression failed with error code: ") + std::to_string(iRet));
583 template<
typename I,
typename O>
584 requires (
sizeof(
typename I::value_type) == 1 && std::is_trivially_copyable_v<typename I::value_type> &&
585 sizeof(
typename O::value_type) == 1 && std::is_trivially_copyable_v<typename O::value_type>)
586 static void CompressData(O &oData,
const I &iData,
int iLevel = Z_DEFAULT_COMPRESSION)
588 if (std::addressof(oData) == std::addressof(iData))
590 throw std::runtime_error(
"The oData object cannot be the iData object");
612 .zalloc = (alloc_func)Z_NULL,
613 .zfree = (free_func)Z_NULL,
614 .opaque = (voidpf)Z_NULL,
616 .data_type = Z_BINARY,
622 if (deflateInit2(&zs, iLevel, Z_DEFLATED, 16 + 15, 8, Z_DEFAULT_STRATEGY) != Z_OK)
624 throw std::runtime_error(
"Failed to initialize zlib compression");
628 zs.next_in = (z_const Bytef *)iData.data();
642 constexpr uLong uLongMax = (uLong)-1;
643 if (iData.size() > (
size_t)uLongMax)
645 size_t szNeedSize = iData.size() + 12;
648 szNeedSize += (szNeedSize + (1000 - 1)) / 1000;
650 oData.resize((szNeedSize + (2 - 1)) / 2);
656 oData.resize(deflateBound(&zs, (uLong)iData.size()));
660 size_t szCompressedSize = 0;
661 size_t szRemainingSize = iData.size();
666 size_t szOut = oData.size() - szCompressedSize;
669 oData.resize(oData.size() * 2);
670 szOut = oData.size() - szCompressedSize;
674 zs.next_out = (Bytef *)(&oData.data()[szCompressedSize]);
677 if (zs.avail_in == 0)
679 constexpr uInt uIntMax = (uInt)-1;
680 zs.avail_in = szRemainingSize > (size_t)uIntMax ? uIntMax : (uInt)szRemainingSize;
681 szRemainingSize -= zs.avail_in;
685 if (zs.avail_out == 0)
687 constexpr uInt uIntMax = (uInt)-1;
688 zs.avail_out = szOut > (size_t)uIntMax ? uIntMax : (uInt)szOut;
693 iRet = deflate(&zs, szRemainingSize != 0 ? Z_NO_FLUSH : Z_FINISH);
696 szCompressedSize += szOut - zs.avail_out;
697 }
while (iRet == Z_OK || iRet == Z_BUF_ERROR);
701 oData.resize(szCompressedSize);
704 if (iRet != Z_STREAM_END)
708 throw std::runtime_error(std::string(
"Zlib compression failed with error message: ") + std::string(zs.msg));
712 throw std::runtime_error(std::string(
"Zlib compression failed with error code: ") + std::to_string(iRet));
728 template<
typename I,
typename O,
typename ErrInfoFunc = NBT_Pr
int>
729 requires (
sizeof(
typename I::value_type) == 1 && std::is_trivially_copyable_v<typename I::value_type> &&
730 sizeof(
typename O::value_type) == 1 && std::is_trivially_copyable_v<typename O::value_type>)
738 catch (
const std::bad_alloc &e)
740 funcErrInfo(
"std::bad_alloc:[{}]\n", e.what());
743 catch (
const std::exception &e)
745 funcErrInfo(
"std::exception:[{}]\n", e.what());
750 funcErrInfo(
"Unknown Error\n");
767 template<
typename I,
typename O,
typename ErrInfoFunc = NBT_Pr
int>
768 requires (
sizeof(
typename I::value_type) == 1 && std::is_trivially_copyable_v<typename I::value_type> &&
769 sizeof(
typename O::value_type) == 1 && std::is_trivially_copyable_v<typename O::value_type>)
777 catch (
const std::bad_alloc &e)
779 funcErrInfo(
"std::bad_alloc:[{}]\n", e.what());
782 catch (
const std::exception &e)
784 funcErrInfo(
"std::exception:[{}]\n", e.what());
789 funcErrInfo(
"Unknown Error\n");
DefaultOutputStream & operator=(DefaultOutputStream &&)=delete
禁止移动赋值
void PutRange(const ValueType *pData, size_t szSize)
向流中写入一段数据
定义 NBT_IO.hpp:262
void UnPut(void) noexcept
删除(撤销)最后一个写入的字节
定义 NBT_IO.hpp:282
typename T::value_type ValueType
容器值类型
定义 NBT_IO.hpp:212
const T & Data(void) const noexcept
获取底层数据的常量引用
定义 NBT_IO.hpp:302
T StreamType
容器类型
定义 NBT_IO.hpp:210
void PutOnce(V &&c)
向流中写入写入单个值
定义 NBT_IO.hpp:253
T & Data(void) noexcept
获取底层数据的非常量引用
定义 NBT_IO.hpp:309
DefaultOutputStream(DefaultOutputStream &&)=delete
禁止移动构造
size_t Size(void) const noexcept
获取当前字节流中已有的数据大小
定义 NBT_IO.hpp:289
DefaultOutputStream(T &_tData, size_t szStartIdx=0)
构造函数
定义 NBT_IO.hpp:222
DefaultOutputStream & operator=(const DefaultOutputStream &)=delete
禁止拷贝赋值
const ValueType & operator[](size_t szIndex) const noexcept
下标访问运算符
定义 NBT_IO.hpp:242
DefaultOutputStream(const DefaultOutputStream &)=delete
禁止拷贝构造
void AddReserve(size_t szAddSize)
预分配额外容量
定义 NBT_IO.hpp:276
~DefaultOutputStream(void)=default
默认析构函数
void Reset(void) noexcept
重置流,清空所有数据
定义 NBT_IO.hpp:295
static bool DecompressDataNoThrow(O &oData, const I &iData, ErrInfoFunc funcErrInfo=NBT_Print{ stderr }) noexcept
解压数据,但是不抛出异常,而是通过funcErrInfo打印异常信息并返回成功与否
定义 NBT_IO.hpp:731
static bool ReadFile(const std::filesystem::path &pathFileName, T &tData)
从指定文件名的文件中读取字节流数据到任意顺序容器中
定义 NBT_IO.hpp:357
static bool WriteFile(const std::filesystem::path &pathFileName, const T &tData)
从任意顺序容器写出字节流数据到指定文件名的文件中
定义 NBT_IO.hpp:326
static bool CompressDataNoThrow(O &oData, const I &iData, int iLevel=Z_DEFAULT_COMPRESSION, ErrInfoFunc funcErrInfo=NBT_Print{ stderr }) noexcept
压缩数据,但是不抛出异常,而是通过funcErrInfo打印异常信息并返回成功与否
定义 NBT_IO.hpp:770
static bool IsFileExist(const std::filesystem::path &pathFileName)
判断指定文件名的文件是否存在
定义 NBT_IO.hpp:400
static bool IsDataZipped(const T &tData)
判断一个顺序容器存储的字节流是否可能存在压缩
定义 NBT_IO.hpp:444
static void DecompressData(O &oData, const I &iData)
解压数据,自动判断Zlib或Gzip并解压,如果失败则抛出异常
定义 NBT_IO.hpp:467
static bool IsGzip(uint8_t u8DataFirst, uint8_t u8DataSecond)
通过字节流开始的两个字节判断是否可能是Gzip压缩
定义 NBT_IO.hpp:431
static bool IsZlib(uint8_t u8DataFirst, uint8_t u8DataSecond)
通过字节流开始的两个字节判断是否可能是Zlib压缩
定义 NBT_IO.hpp:415
static void CompressData(O &oData, const I &iData, int iLevel=Z_DEFAULT_COMPRESSION)
压缩数据,默认压缩为Gzip,也就是NBT格式的标准压缩类型,如果失败则抛出异常
定义 NBT_IO.hpp:586
一个用于打印信息到指定的C文件对象的工具类,作为库内大部分存在信息输出接口的默认实现。 实际可被使用此类为默认值参数的函数的调用方,以类似此类的仿函数参数重写的其它类型替换, 比如调用方实现了一个My_...
定义 NBT_Print.hpp:24