chenjunfu2-nbt-cpp v2.1.0
一个基于CPP20的NBT(Named Binary Tag)库
载入中...
搜索中...
未找到
NBT_Helper.hpp
浏览该文件的文档.
1#pragma once
2
3#include <bit>
4#include <concepts>
5#include <iterator>
6#include <algorithm>
7
8#include "NBT_Print.hpp"//打印输出
9#include "NBT_Endian.hpp"
10#include "NBT_Node.hpp"
11#include "NBT_Node_View.hpp"
12
13#include "vcpkg_config.h"//包含vcpkg生成的配置以确认库安装情况
14
15#ifdef CJF2_NBT_CPP_USE_XXHASH
16#include "NBT_Hash.hpp"
17#endif
18
21
24class NBT_Helper
25{
27 NBT_Helper(void) = delete;
29 ~NBT_Helper(void) = delete;
30
31public:
39 template<bool bSortCompound = true, typename PrintFunc = NBT_Print>
40 static void Print(const NBT_Node_View<true> nRoot, size_t szPaddingStartLevel = 0, const std::string & strLevelPadding = " ", PrintFunc funcPrint = NBT_Print{})
41 {
42 PrintSwitch<true, bSortCompound>(nRoot, szPaddingStartLevel, strLevelPadding, funcPrint);
43 }
44
52 template<bool bSortCompound = true, bool bHexNumType = true, bool bSnbtType = false>
53 static std::conditional_t<bSnbtType, NBT_Type::String, std::string> Serialize(const NBT_Node_View<true> nRoot)
54 {
55 std::conditional_t<bSnbtType, NBT_Type::String, std::string> sRet{};
56 SerializeSwitch<true, bSortCompound, bHexNumType, bSnbtType>(nRoot, sRet);
57 return sRet;
58 }
59
60#ifdef CJF2_NBT_CPP_USE_XXHASH
64 static void DefaultFunc(NBT_Hash &nbtHash)
65 {
66 return;
67 }
68
70 using DefaultFuncType = std::decay_t<decltype(DefaultFunc)>;
71
82 template<bool bSortCompound = true, typename TB = DefaultFuncType, typename TA = DefaultFuncType>//两个函数,分别在前后调用,可以用于插入哈希数据
83 static NBT_Hash::HASH_T Hash(const NBT_Node_View<true> nRoot, NBT_Hash nbtHash, TB funBefore = DefaultFunc, TA funAfter = DefaultFunc)
84 {
85 funBefore(nbtHash);
86 HashSwitch<true, bSortCompound>(nRoot, nbtHash);
87 funAfter(nbtHash);
88
89 return nbtHash.Digest();
90
91 //调用可行性检测
92 static_assert(std::is_invocable_v<TB, decltype(nbtHash)&>, "TB is not a callable object or parameter type mismatch.");
93 static_assert(std::is_invocable_v<TA, decltype(nbtHash)&>, "TA is not a callable object or parameter type mismatch.");
94 }
95#endif
96
97protected:
99 template<typename PrintFunc>
100 static void PrintPadding(size_t szLevel, bool bSubLevel, bool bNewLine, const std::string &strLevelPadding, PrintFunc &funcPrint)//bSubLevel会让缩进多一层
101 {
102 if (szLevel == (size_t)-1)//跳过打印
103 {
104 return;
105 }
106
107 if (bNewLine)
108 {
109 funcPrint("\n");
110 }
111
112 for (size_t i = 0; i < szLevel; ++i)
113 {
114 funcPrint("{}", strLevelPadding);
115 }
116
117 if (bSubLevel)
118 {
119 funcPrint("{}", strLevelPadding);
120 }
121 }
122
123 template<typename T>
124 requires(std::is_arithmetic_v<T>)
125 static void NumericToHexString(const T &value, std::string &result)
126 {
127 //映射
128 static constexpr char hex_chars[] = "0123456789ABCDEF";
129
130 //前缀
131 result += "0x";
132
133 //按照原始字节序处理
134 using Raw_T = decltype([](void) -> auto
135 {
136 if constexpr (NBT_Type::IsNumericType_V<T>)
137 {
139 }
140 else
141 {
142 return T{};
143 }
144 }());
145 Raw_T uintVal = std::bit_cast<Raw_T>(value);
146
147 for (size_t i = 0; i < sizeof(T); ++i)
148 {
149 uint8_t u8Byte = (uintVal >> 8 * (sizeof(T) - i - 1)) & 0xFF;//遍历字节,从高到低
150
151 result += hex_chars[(u8Byte >> 4) & 0x0F];//高4
152 result += hex_chars[(u8Byte >> 0) & 0x0F];//低4
153 }
154 }
155
156 template<typename T, typename STR_T>
157 requires(NBT_Type::IsNumericType_V<T> && (std::is_same_v<STR_T, NBT_Type::String> || std::is_same_v<STR_T, std::string>))
158 static void NumericToDecString(const T &value, STR_T &result)
159 {
160 std::string tmp{};
161 if constexpr (NBT_Type::IsFloatingType_V<T>)
162 {
163 tmp = std::format("{:.{}g}", value, std::numeric_limits<T>::max_digits10);
164 }
165 else if constexpr (NBT_Type::IsIntegerType_V<T>)
166 {
167 tmp = std::format("{:d}", value);
168 }
169 else
170 {
171 static_assert(false,"T type unknown");
172 }
173
174 if constexpr (std::is_same_v<STR_T, NBT_Type::String>)
175 {
176 result += (NBT_Type::String)tmp;//转换为NBT字符串
177 }
178 else if constexpr(std::is_same_v<STR_T, std::string>)
179 {
180 result += tmp;
181 }
182 else
183 {
184 static_assert(false, "STR_T type unknown");
185 }
186 }
188
189protected:
191 //首次调用默认为true,二次调用开始内部主动变为false
192 template<bool bRoot, bool bSortCompound, typename PrintFunc = NBT_Print>//首次使用NBT_Node_View解包,后续直接使用NBT_Node引用免除额外初始化开销
193 static void PrintSwitch(std::conditional_t<bRoot, const NBT_Node_View<true> &, const NBT_Node &>nRoot, size_t szLevel, const std::string &strLevelPadding, PrintFunc &funcPrint)
194 {
195 static auto PrintArray = [](const std::string strBeg, const auto &vArr, const std::string strEnd, PrintFunc &funcPrint) -> void
196 {
197 funcPrint("{}", strBeg);
198 bool bFirst = true;
199 for (const auto &it : vArr)
200 {
201 if (bFirst)
202 {
203 bFirst = false;
204 funcPrint("{}", it);
205 }
206 funcPrint(",{}", it);
207 }
208 funcPrint("{}", strEnd);
209 };
210
211
212 auto tag = nRoot.GetTag();
213 switch (tag)
214 {
215 case NBT_TAG::End:
216 {
217 funcPrint("[End]");
218 }
219 break;
220 case NBT_TAG::Byte:
221 {
222 funcPrint("{}B", nRoot.template Get<NBT_Type::Byte>());
223 }
224 break;
225 case NBT_TAG::Short:
226 {
227 funcPrint("{}S", nRoot.template Get<NBT_Type::Short>());
228 }
229 break;
230 case NBT_TAG::Int:
231 {
232 funcPrint("{}I", nRoot.template Get<NBT_Type::Int>());
233 }
234 break;
235 case NBT_TAG::Long:
236 {
237 funcPrint("{}L", nRoot.template Get<NBT_Type::Long>());
238 }
239 break;
240 case NBT_TAG::Float:
241 {
242 funcPrint("{}F", nRoot.template Get<NBT_Type::Float>());
243 }
244 break;
245 case NBT_TAG::Double:
246 {
247 funcPrint("{}D", nRoot.template Get<NBT_Type::Double>());
248 }
249 break;
251 {
252 const auto &arr = nRoot.template Get<NBT_Type::ByteArray>();
253 PrintArray("[B;", arr, "]", funcPrint);
254 }
255 break;
257 {
258 const auto &arr = nRoot.template Get<NBT_Type::IntArray>();
259 PrintArray("[I;", arr, "]", funcPrint);
260 }
261 break;
263 {
264 const auto &arr = nRoot.template Get<NBT_Type::LongArray>();
265 PrintArray("[L;", arr, "]", funcPrint);
266 }
267 break;
268 case NBT_TAG::String:
269 {
270 funcPrint("\"{}\"", nRoot.template Get<NBT_Type::String>().ToCharTypeUTF8());
271 }
272 break;
273 case NBT_TAG::List://需要打印缩进的地方
274 {
275 const auto &list = nRoot.template Get<NBT_Type::List>();
276 PrintPadding(szLevel, false, !bRoot, strLevelPadding, funcPrint);//不是根部则打印开头换行
277 funcPrint("[");
278
279 bool bFirst = true;
280 for (const auto &it : list)
281 {
282 if (bFirst)
283 {
284 bFirst = false;
285 }
286 else
287 {
288 funcPrint(",");
289 }
290
291 PrintPadding(szLevel, true, it.GetTag() != NBT_TAG::Compound && it.GetTag() != NBT_TAG::List, strLevelPadding, funcPrint);
292 PrintSwitch<false, bSortCompound, PrintFunc>(it, szLevel + 1, strLevelPadding, funcPrint);
293 }
294
295 if (list.Size() != 0)//空列表无需换行以及对齐
296 {
297 PrintPadding(szLevel, false, true, strLevelPadding, funcPrint);
298 }
299
300 funcPrint("]");
301 }
302 break;
303 case NBT_TAG::Compound://需要打印缩进的地方
304 {
305 const auto &cpd = nRoot.template Get<NBT_Type::Compound>();
306 PrintPadding(szLevel, false, !bRoot, strLevelPadding, funcPrint);//不是根部则打印开头换行
307 funcPrint("{{");//大括号转义
308
309 if constexpr (!bSortCompound)
310 {
311 bool bFirst = true;
312 for (const auto &it : cpd)
313 {
314 if (bFirst)
315 {
316 bFirst = false;
317 }
318 else
319 {
320 funcPrint(",");
321 }
322
323 PrintPadding(szLevel, true, true, strLevelPadding, funcPrint);
324 funcPrint("\"{}\":", it.first.ToCharTypeUTF8());
325 PrintSwitch<false, bSortCompound, PrintFunc>(it.second, szLevel + 1, strLevelPadding, funcPrint);
326 }
327 }
328 else
329 {
330 auto vSort = cpd.KeySortIt();
331
332 bool bFirst = true;
333 for (const auto &it : vSort)
334 {
335 if (bFirst)
336 {
337 bFirst = false;
338 }
339 else
340 {
341 funcPrint(",");
342 }
343
344 PrintPadding(szLevel, true, true, strLevelPadding, funcPrint);
345 funcPrint("\"{}\":", it->first.ToCharTypeUTF8());
346 PrintSwitch<false, bSortCompound, PrintFunc>(it->second, szLevel + 1, strLevelPadding, funcPrint);
347 }
348 }
349
350 if (cpd.Size() != 0)//空集合无需换行以及对齐
351 {
352 PrintPadding(szLevel, false, true, strLevelPadding, funcPrint);
353 }
354
355 funcPrint("}}");//大括号转义
356 }
357 break;
358 default:
359 {
360 funcPrint("[Unknown NBT Tag Type [{:02X}({})]]", (NBT_TAG_RAW_TYPE)tag, (NBT_TAG_RAW_TYPE)tag);
361 }
362 break;
363 }
364 }
365
366 //首次调用默认为true,二次调用开始内部主动变为false
367 template<bool bRoot, bool bSortCompound, bool bHexNumType, bool bSnbtType>//首次使用NBT_Node_View解包,后续直接使用NBT_Node引用免除额外初始化开销
368 static void SerializeSwitch(std::conditional_t<bRoot, const NBT_Node_View<true> &, const NBT_Node &>nRoot, std::conditional_t<bSnbtType, NBT_Type::String, std::string> &sRet)
369 {
370 auto tag = nRoot.GetTag();
371 switch (tag)
372 {
373 case NBT_TAG::End:
374 {
375 if constexpr (bSnbtType)
376 {
377 sRet += MU8STR("[End]");
378 }
379 else
380 {
381 sRet += "[End]";
382 }
383 }
384 break;
385 case NBT_TAG::Byte:
386 {
387 if constexpr (bSnbtType || !bHexNumType)//snbt必须是dec
388 {
389 NumericToDecString(nRoot.template Get<NBT_Type::Byte>(), sRet);
390 }
391 else
392 {
393 NumericToHexString(nRoot.template Get<NBT_Type::Byte>(), sRet);
394 }
395 sRet += 'B';
396 }
397 break;
398 case NBT_TAG::Short:
399 {
400 if constexpr (bSnbtType || !bHexNumType)
401 {
402 NumericToDecString(nRoot.template Get<NBT_Type::Short>(), sRet);
403 }
404 else
405 {
406 NumericToHexString(nRoot.template Get<NBT_Type::Short>(), sRet);
407 }
408 sRet += 'S';
409 }
410 break;
411 case NBT_TAG::Int:
412 {
413 if constexpr (bSnbtType || !bHexNumType)
414 {
415 NumericToDecString(nRoot.template Get<NBT_Type::Int>(), sRet);
416 }
417 else
418 {
419 NumericToHexString(nRoot.template Get<NBT_Type::Int>(), sRet);
420 }
421 sRet += 'I';
422 }
423 break;
424 case NBT_TAG::Long:
425 {
426 if constexpr (bSnbtType || !bHexNumType)
427 {
428 NumericToDecString(nRoot.template Get<NBT_Type::Long>(), sRet);
429 }
430 else
431 {
432 NumericToHexString(nRoot.template Get<NBT_Type::Long>(), sRet);
433 }
434 sRet += 'L';
435 }
436 break;
437 case NBT_TAG::Float:
438 {
439 if constexpr (bSnbtType || !bHexNumType)
440 {
441 NumericToDecString(nRoot.template Get<NBT_Type::Float>(), sRet);
442 }
443 else
444 {
445 NumericToHexString(nRoot.template Get<NBT_Type::Float>(), sRet);
446 }
447 sRet += 'F';
448 }
449 break;
450 case NBT_TAG::Double:
451 {
452 if constexpr (bSnbtType || !bHexNumType)
453 {
454 NumericToDecString(nRoot.template Get<NBT_Type::Double>(), sRet);
455 }
456 else
457 {
458 NumericToHexString(nRoot.template Get<NBT_Type::Double>(), sRet);
459 }
460 sRet += 'D';
461 }
462 break;
464 {
465 const auto &arr = nRoot.template Get<NBT_Type::ByteArray>();
466
467 if constexpr (bSnbtType)
468 {
469 sRet += MU8STR("[B;");
470 }
471 else
472 {
473 sRet += "[B;";
474 }
475
476 for (const auto &it : arr)
477 {
478 if constexpr (bSnbtType || !bHexNumType)
479 {
480 NumericToDecString(it, sRet);
481 }
482 else
483 {
484 NumericToHexString(it, sRet);
485 }
486 sRet += ',';
487 }
488 if (arr.size() != 0)
489 {
490 sRet.pop_back();//删掉最后一个逗号
491 }
492
493 sRet += ']';
494 }
495 break;
497 {
498 const auto &arr = nRoot.template Get<NBT_Type::IntArray>();
499
500 if constexpr (bSnbtType)
501 {
502 sRet += MU8STR("[I;");
503 }
504 else
505 {
506 sRet += "[I;";
507 }
508
509 for (const auto &it : arr)
510 {
511 if constexpr (bSnbtType || !bHexNumType)
512 {
513 NumericToDecString(it, sRet);
514 }
515 else
516 {
517 NumericToHexString(it, sRet);
518 }
519 sRet += ',';
520 }
521 if (arr.size() != 0)
522 {
523 sRet.pop_back();//删掉最后一个逗号
524 }
525
526 sRet += ']';
527 }
528 break;
530 {
531 const auto &arr = nRoot.template Get<NBT_Type::LongArray>();
532
533 if constexpr (bSnbtType)
534 {
535 sRet += MU8STR("[L;");
536 }
537 else
538 {
539 sRet += "[L;";
540 }
541
542 for (const auto &it : arr)
543 {
544 if constexpr (bSnbtType || !bHexNumType)
545 {
546 NumericToDecString(it, sRet);
547 }
548 else
549 {
550 NumericToHexString(it, sRet);
551 }
552 sRet += ',';
553 }
554 if (arr.size() != 0)
555 {
556 sRet.pop_back();//删掉最后一个逗号
557 }
558
559 sRet += ']';
560 }
561 break;
562 case NBT_TAG::String:
563 {
564 sRet += '\"';
565 if constexpr (bSnbtType)
566 {
567 sRet += nRoot.template Get<NBT_Type::String>();
568 }
569 else
570 {
571 sRet += nRoot.template Get<NBT_Type::String>().ToCharTypeUTF8();
572 }
573 sRet += '\"';
574 }
575 break;
576 case NBT_TAG::List:
577 {
578 const auto &list = nRoot.template Get<NBT_Type::List>();
579 sRet += '[';
580 for (const auto &it : list)
581 {
582 SerializeSwitch<false, bSortCompound, bHexNumType, bSnbtType>(it, sRet);
583 sRet += ',';
584 }
585
586 if (list.Size() != 0)
587 {
588 sRet.pop_back();//删掉最后一个逗号
589 }
590 sRet += ']';
591 }
592 break;
593 case NBT_TAG::Compound://需要打印缩进的地方
594 {
595 const auto &cpd = nRoot.template Get<NBT_Type::Compound>();
596 sRet += '{';
597
598 if constexpr (!bSortCompound)
599 {
600 for (const auto &it : cpd)
601 {
602 sRet += '\"';
603 if constexpr (bSnbtType)
604 {
605 sRet += it.first;
606 sRet += MU8STR("\":");
607 }
608 else
609 {
610 sRet += it.first.ToCharTypeUTF8();
611 sRet += "\":";
612 }
613 SerializeSwitch<false, bSortCompound, bHexNumType, bSnbtType>(it.second, sRet);
614 sRet += ',';
615 }
616 }
617 else
618 {
619 auto vSort = cpd.KeySortIt();
620
621 for (const auto &it : vSort)
622 {
623 sRet += '\"';
624 if constexpr (bSnbtType)
625 {
626 sRet += it->first;
627 sRet += MU8STR("\":");
628 }
629 else
630 {
631 sRet += it->first.ToCharTypeUTF8();
632 sRet += "\":";
633 }
634 SerializeSwitch<false, bSortCompound, bHexNumType, bSnbtType>(it->second, sRet);
635 sRet += ',';
636 }
637 }
638
639 if (cpd.Size() != 0)
640 {
641 sRet.pop_back();//删掉最后一个逗号
642 }
643 sRet += '}';
644 }
645 break;
646 default:
647 {
648 if constexpr (bSnbtType)
649 {
650 //Ignore Error
651 }
652 else
653 {
654 sRet += "[Unknown NBT Tag Type [";
655 NumericToHexString((NBT_TAG_RAW_TYPE)tag, sRet);
656 sRet += "]]";
657 }
658 }
659 break;
660 }
661 }
662
663#ifdef CJF2_NBT_CPP_USE_XXHASH
664 template<bool bRoot, bool bSortCompound>//首次使用NBT_Node_View解包,后续直接使用NBT_Node引用免除额外初始化开销
665 static void HashSwitch(std::conditional_t<bRoot, const NBT_Node_View<true> &, const NBT_Node &>nRoot, NBT_Hash &nbtHash)
666 {
667 auto tag = nRoot.GetTag();
668
669 //把tag本身作为数据
670 {
671 const auto &tmp = tag;
672 nbtHash.Update(tmp);
673 }
674
675 //再读出实际内容作为数据
676 switch (tag)
677 {
678 case NBT_TAG::End:
679 {
680 //end类型无负载,所以什么也不做
681 }
682 break;
683 case NBT_TAG::Byte:
684 {
685 const auto &tmp = nRoot.template Get<NBT_Type::Byte>();
686 nbtHash.Update(tmp);
687 }
688 break;
689 case NBT_TAG::Short:
690 {
691 const auto &tmp = nRoot.template Get<NBT_Type::Short>();
692 nbtHash.Update(tmp);
693 }
694 break;
695 case NBT_TAG::Int:
696 {
697 const auto &tmp = nRoot.template Get<NBT_Type::Int>();
698 nbtHash.Update(tmp);
699 }
700 break;
701 case NBT_TAG::Long:
702 {
703 const auto &tmp = nRoot.template Get<NBT_Type::Long>();
704 nbtHash.Update(tmp);
705 }
706 break;
707 case NBT_TAG::Float:
708 {
709 const auto &tmp = nRoot.template Get<NBT_Type::Float>();
710 nbtHash.Update(tmp);
711 }
712 break;
713 case NBT_TAG::Double:
714 {
715 const auto &tmp = nRoot.template Get<NBT_Type::Double>();
716 nbtHash.Update(tmp);
717 }
718 break;
720 {
721 const auto &arr = nRoot.template Get<NBT_Type::ByteArray>();
722 for (const auto &it : arr)
723 {
724 const auto &tmp = it;
725 nbtHash.Update(tmp);
726 }
727 }
728 break;
730 {
731 const auto &arr = nRoot.template Get<NBT_Type::IntArray>();
732 for (const auto &it : arr)
733 {
734 const auto &tmp = it;
735 nbtHash.Update(tmp);
736 }
737 }
738 break;
740 {
741 const auto &arr = nRoot.template Get<NBT_Type::LongArray>();
742 for (const auto &it : arr)
743 {
744 const auto &tmp = it;
745 nbtHash.Update(tmp);
746 }
747 }
748 break;
749 case NBT_TAG::String:
750 {
751 const auto &tmp = nRoot.template Get<NBT_Type::String>();
752 nbtHash.Update(tmp.data(), tmp.size());
753 }
754 break;
755 case NBT_TAG::List:
756 {
757 const auto &list = nRoot.template Get<NBT_Type::List>();
758 for (const auto &it : list)
759 {
760 HashSwitch<false, bSortCompound>(it, nbtHash);
761 }
762 }
763 break;
764 case NBT_TAG::Compound://需要打印缩进的地方
765 {
766 const auto &cpd = nRoot.template Get<NBT_Type::Compound>();
767
768 if constexpr (!bSortCompound)
769 {
770 for (const auto &it : cpd)
771 {
772 const auto &tmp = it.first;
773 nbtHash.Update(tmp.data(), tmp.size());
774 HashSwitch<false, bSortCompound>(it.second, nbtHash);
775 }
776 }
777 else//对compound迭代器进行排序,以使得hash获得一致性结果
778 {
779 auto vSort = cpd.KeySortIt();
780
781 //遍历有序结构
782 for (const auto &it : vSort)
783 {
784 const auto &tmp = it->first;
785 nbtHash.Update(tmp.data(), tmp.size());
786 HashSwitch<false, bSortCompound>(it->second, nbtHash);
787 }
788 }
789 }
790 break;
791 default:
792 {}
793 break;
794 }
795 }
796#endif
798
799};
端序工具集
哈希工具集
NBT节点类型,支持存储所有NBT类型的变体
#define MU8STR(charLiteralString)
从C风格字符串获取M-UTF-8的字符串
定义 NBT_Node.hpp:21
NBT节点类型的视图,支持指向所有NBT类型的变体视图,不持有对象
用于处理NBT信息打印的默认实现
uint8_t NBT_TAG_RAW_TYPE
NBT_TAG的原始类型,用于二进制读写或判断等
定义 NBT_TAG.hpp:12
@ Int
对应NBT_Type::Int
定义 NBT_TAG.hpp:21
@ Float
对应NBT_Type::Float
定义 NBT_TAG.hpp:23
@ Compound
对应NBT_Type::Compound
定义 NBT_TAG.hpp:28
@ String
对应NBT_Type::String
定义 NBT_TAG.hpp:26
@ ByteArray
对应NBT_Type::ByteArray
定义 NBT_TAG.hpp:25
@ Short
对应NBT_Type::Short
定义 NBT_TAG.hpp:20
@ List
对应NBT_Type::List
定义 NBT_TAG.hpp:27
@ Long
对应NBT_Type::Long
定义 NBT_TAG.hpp:22
@ End
对应NBT_Type::End
定义 NBT_TAG.hpp:18
@ LongArray
对应NBT_Type::LongArray
定义 NBT_TAG.hpp:30
@ Byte
对应NBT_Type::Byte
定义 NBT_TAG.hpp:19
@ IntArray
对应NBT_Type::IntArray
定义 NBT_TAG.hpp:29
@ Double
对应NBT_Type::Double
定义 NBT_TAG.hpp:24
一个封装xxhash调用的用于计算哈希的辅助类
定义 NBT_Hash.hpp:12
XXH64_hash_t HASH_T
类型别名,xxhash类型封装,类型必须是uint64_t
定义 NBT_Hash.hpp:15
HASH_T Digest(void) const
根据之前已添加的数据,获取当前的哈希值
定义 NBT_Hash.hpp:71
void Update(const void *pData, size_t szSize)
添加指针指向的数据更新哈希
定义 NBT_Hash.hpp:80
static NBT_Hash::HASH_T Hash(const NBT_Node_View< true > nRoot, NBT_Hash nbtHash, TB funBefore=DefaultFunc, TA funAfter=DefaultFunc)
对NBT对象进行递归计算哈希
定义 NBT_Helper.hpp:83
static void DefaultFunc(NBT_Hash &nbtHash)
用于插入哈希的示例函数
定义 NBT_Helper.hpp:64
static std::conditional_t< bSnbtType, NBT_Type::String, std::string > Serialize(const NBT_Node_View< true > nRoot)
直接序列化,按照一定规则输出为String并返回
定义 NBT_Helper.hpp:53
static void Print(const NBT_Node_View< true > nRoot, size_t szPaddingStartLevel=0, const std::string &strLevelPadding=" ", PrintFunc funcPrint=NBT_Print{})
格式化对齐打印NBT对象
定义 NBT_Helper.hpp:40
std::decay_t< decltype(DefaultFunc)> DefaultFuncType
函数的类型,用于模板默认值
定义 NBT_Helper.hpp:70
NBT节点的视图,用于指向而不持有对象,类似于标准库的std::string与std::string_view的关系
定义 NBT_Node_View.hpp:24
NBT_TAG GetTag() const noexcept
获取当前视图指向的NBT类型的枚举值
定义 NBT_Node_View.hpp:369
一个用于打印信息到指定的C文件对象的工具类,作为库内大部分存在信息输出接口的默认实现。 实际可被使用此类为默认值参数的函数的调用方,以类似此类的仿函数参数重写的其它类型替换, 比如调用方实现了一个My_...
定义 NBT_Print.hpp:24
static constexpr bool IsNumericType_V
判断类型是否为NBT数值类型(包含所有整数和浮点数类型)
定义 NBT_Type.hpp:260
static constexpr bool IsIntegerType_V
判断类型是否为NBT整数类型(包含所有整数类型)
定义 NBT_Type.hpp:272
NBT_String< std::basic_string< uint8_t >, std::basic_string_view< uint8_t > > String
字符串类型,存储Java M-UTF-8字符串
定义 NBT_Type.hpp:64
typename BuiltinRawType< T >::Type BuiltinRawType_T
映射内建类型到方便读写的raw类型:编译期获得内建类型到可以进行二进制读写的原始类型
定义 NBT_Type.hpp:341
static constexpr bool IsFloatingType_V
判断类型是否为NBT浮点数类型(包含所有浮点数类型)
定义 NBT_Type.hpp:282
根据已安装的可选依赖提供定义