chenjunfu2-nbt-cpp v2.1.0
一个基于CPP20的NBT(Named Binary Tag)库
载入中...
搜索中...
未找到
NBT_Compound.hpp
浏览该文件的文档.
1#pragma once
2
3#include <vector>
4#include <unordered_map>
5#include <compare>
6#include <type_traits>
7#include <initializer_list>
8
9#include "NBT_Type.hpp"
10
13
14class NBT_Reader;
15class NBT_Writer;
16class NBT_Helper;
17
21{
23 template <typename T>
24 concept HasSpaceship = requires(const T & a, const T & b)
25 {
26 {
27 a <=> b
28 };
29 };
30
32 template <typename T>
33 concept HasRBegin = requires(T t)
34 {
35 t.rbegin();
36 };
37
39 template <typename T>
40 concept HasCRBegin = requires(T t)
41 {
42 t.crbegin();
43 };
44
46 template <typename T>
47 concept HasREnd = requires(T t)
48 {
49 t.rend();
50 };
51
53 template <typename T>
54 concept HasCREnd = requires(T t)
55 {
56 t.crend();
57 };
58}
59
63template<typename Compound>
64class NBT_Compound :protected Compound//Compound is Map
65{
66 friend class NBT_Reader;
67 friend class NBT_Writer;
68 friend class NBT_Helper;
69
70private:
71 //总是允许插入nbt end,但是在写出文件时会忽略end类型
72 //template<typename V>
73 //bool TestType(V vTagVal)
74 //{
75 // if constexpr (std::is_same_v<std::decay_t<V>, Compound::mapped_type>)
76 // {
77 // return vTagVal.GetTag() != NBT_TAG::End;
78 // }
79 // else
80 // {
81 // return NBT_Type::TypeTag_V<std::decay_t<V>> != NBT_TAG::End;
82 // }
83 //}
84public:
85 //完美转发、初始化列表代理构造
86
91 template<typename... Args>
92 NBT_Compound(Args&&... args) : Compound(std::forward<Args>(args)...)
93 {}
94
98 NBT_Compound(std::initializer_list<typename Compound::value_type> init) : Compound(init)
99 {}
100
102 NBT_Compound(void) = default;
104 ~NBT_Compound(void) = default;
105
108 NBT_Compound(NBT_Compound &&_Move) noexcept :Compound(std::move(_Move))
109 {}
110
113 NBT_Compound(const NBT_Compound &_Copy) noexcept :Compound(_Copy)
114 {}
115
120 {
121 Compound::operator=(std::move(_Move));
122 return *this;
123 }
124
129 {
130 Compound::operator=(_Copy);
131 return *this;
132 }
133
136 const Compound &GetData(void) const noexcept
137 {
138 return *this;
139 }
140
145 bool operator==(const NBT_Compound &_Right) const noexcept
146 {
147 return (const Compound &)*this == (const Compound &)_Right;
148 }
149
154 bool operator!=(const NBT_Compound &_Right) const noexcept
155 {
156 return (const Compound &)*this != (const Compound &)_Right;
157 }
158
169 std::partial_ordering operator<=>(const NBT_Compound &_Right) const noexcept
170 {
172 {
173 return (const Compound &)*this <=> (const Compound &)_Right;
174 }
175 else
176 {
177 if (auto _cmpSize = Compound::size() <=> _Right.size(); _cmpSize != 0)
178 {
179 return _cmpSize;
180 }
181
182 //数量相等,比较数据的排序
183 const auto _lSort = this->KeySortIt();
184 const auto _rSort = _Right.KeySortIt();
185 typename Compound::size_type _Size = Compound::size();
186
187 for (typename Compound::size_type _i = 0; _i < _Size; ++_i)
188 {
189 const auto &_lIt = _lSort[_i];
190 const auto &_rIt = _rSort[_i];
191
192 //首先比较名称,如果不同则返回
193 if (auto _cmpKey = _lIt->first <=> _rIt->first; _cmpKey != 0)
194 {
195 return _cmpKey;
196 }
197
198 //然后比较值,如果不同则返回
199 if (auto _cmpVal = _lIt->second <=> _rIt->second; _cmpVal != 0)
200 {
201 return _cmpVal;
202 }
203 }
204
205 //前面都没有返回,那么所有元素都相等
206 return std::partial_ordering::equivalent;
207 }
208 }
209
216 std::vector<typename Compound::iterator> KeySortIt(void)
217 {
218 std::vector<typename Compound::iterator> listSortIt;
219 listSortIt.reserve(Compound::size());
220 for (auto it = Compound::begin(); it != Compound::end(); ++it)
221 {
222 listSortIt.push_back(it);
223 }
224
225 std::sort(listSortIt.begin(), listSortIt.end(),
226 [](const auto &l, const auto &r) -> bool
227 {
228 return l->first < r->first;
229 }
230 );
231
232 return listSortIt;
233 }
234
241 std::vector<typename Compound::const_iterator> KeySortIt(void) const
242 {
243 std::vector<typename Compound::const_iterator> listSortIt;
244 listSortIt.reserve(Compound::size());
245 for (auto it = Compound::cbegin(); it != Compound::cend(); ++it)
246 {
247 listSortIt.push_back(it);
248 }
249
250 std::sort(listSortIt.begin(), listSortIt.end(),
251 [](const auto &l, const auto &r) -> bool
252 {
253 return l->first < r->first;
254 }
255 );
256
257 return listSortIt;
258 }
259
264
265 using Compound::begin;
266 using Compound::end;
267 using Compound::cbegin;
268 using Compound::cend;
269 using Compound::operator[];
270
271 //因为父类不总是有下面内容,所以使用requires检查并暴露或舍弃
272 //using Compound::rbegin;
273 //using Compound::rend;
274 //using Compound::crbegin;
275 //using Compound::crend;
276
277 //存在则映射
279 //-------------------- rbegin --------------------
280 auto rbegin() requires NBT_Compound_Concept::HasRBegin<Compound> {return Compound::rbegin();}
281 auto rbegin() const requires NBT_Compound_Concept::HasRBegin<Compound> {return Compound::rbegin();}
282 auto crbegin() const noexcept requires NBT_Compound_Concept::HasCRBegin<Compound> {return Compound::crbegin();}
283 //-------------------- rend --------------------
284 auto rend() requires NBT_Compound_Concept::HasREnd<Compound> {return Compound::rend();}
285 auto rend() const requires NBT_Compound_Concept::HasREnd<Compound> {return Compound::rend();}
286 auto crend() const noexcept requires NBT_Compound_Concept::HasCREnd<Compound> {return Compound::crend();}
288
290
291 //简化map查询
292
297 typename Compound::mapped_type &Get(const typename Compound::key_type &sTagName)
298 {
299 return Compound::at(sTagName);
300 }
301
306 const typename Compound::mapped_type &Get(const typename Compound::key_type &sTagName) const
307 {
308 return Compound::at(sTagName);
309 }
310
311
316 typename Compound::mapped_type *Has(const typename Compound::key_type &sTagName) noexcept
317 {
318 auto find = Compound::find(sTagName);
319 return find == Compound::end()
320 ? NULL
321 : &(find->second);
322 }
323
328 const typename Compound::mapped_type *Has(const typename Compound::key_type &sTagName) const noexcept
329 {
330 auto find = Compound::find(sTagName);
331 return find == Compound::end()
332 ? NULL
333 : &(find->second);
334 }
335
336 //简化map插入
337 //使用完美转发,不丢失引用、右值信息
338
347 template <typename K, typename V>
348 requires std::constructible_from<typename Compound::key_type, K &&> &&std::constructible_from<typename Compound::mapped_type, V &&>
349 std::pair<typename Compound::iterator, bool> Put(K &&sTagName, V &&vTagVal)
350 {
351 //总是允许插入nbt end,但是在写出文件时会忽略end类型
352 //if (!TestType(vTagVal))
353 //{
354 // return std::pair{ Compound::end(),false };
355 //}
356
357 return Compound::insert_or_assign(std::forward<K>(sTagName), std::forward<V>(vTagVal));
358 }
359
368 template <typename K, typename V>
369 requires std::constructible_from<typename Compound::key_type, K &&> &&std::constructible_from<typename Compound::mapped_type, V &&>
370 std::pair<typename Compound::iterator, bool> TryPut(K &&sTagName, V &&vTagVal)
371 {
372 //总是允许插入nbt end,但是在写出文件时会忽略end类型
373 //if (!TestType(vTagVal))
374 //{
375 // return std::pair{ Compound::end(),false };
376 //}
377
378 return Compound::try_emplace(std::forward<K>(sTagName), std::forward<V>(vTagVal));
379 }
380
384 bool Remove(const typename Compound::key_type &sTagName)
385 {
386 return Compound::erase(sTagName) != 0;//返回1即为成功,否则为0,标准库:返回值为删除的元素数(0 或 1)。
387 }
388
391 void Clear(void)
392 {
393 Compound::clear();
394 }
395
398 bool Empty(void) const noexcept
399 {
400 return Compound::empty();
401 }
402
405 typename Compound::size_type Size(void) const noexcept
406 {
407 return Compound::size();
408 }
409
414 void Merge(const NBT_Compound &_Copy)
415 {
416 Compound::merge(_Copy);
417 }
418
423 void Merge(NBT_Compound &&_Move)
424 {
425 Compound::merge(std::move(_Move));
426 }
427
431 bool Contains(const typename Compound::key_type &sTagName) const noexcept
432 {
433 return Compound::contains(sTagName);
434 }
435
441 template<typename Predicate>
442 bool ContainsIf(Predicate pred) const noexcept
443 {
444 return std::find_if(Compound::begin(), Compound::end(), pred) != Compound::end();
445 }
446
447
448//针对每种类型生成一个方便的函数
449//通过宏定义批量生成
450
454#define TYPE_GET_FUNC(type)\
455\
461bool Contains##type(const typename Compound::key_type &sTagName) const\
462{\
463 auto *p = Has(sTagName);\
464 return p != NULL && p->GetTag() == NBT_TAG::type;\
465}\
466\
467\
474const typename NBT_Type::type &Get##type(const typename Compound::key_type & sTagName) const\
475{\
476 return Compound::at(sTagName).Get##type();\
477}\
478\
479\
486typename NBT_Type::type &Get##type(const typename Compound::key_type & sTagName)\
487{\
488 return Compound::at(sTagName).Get##type();\
489}\
490\
491\
497const typename NBT_Type::type *Has##type(const typename Compound::key_type & sTagName) const noexcept\
499 auto *p = Has(sTagName);\
500 return p != NULL && p->Is##type()\
501 ? &(p->Get##type())\
502 : NULL;\
511typename NBT_Type::type *Has##type(const typename Compound::key_type & sTagName) noexcept\
512{\
513 auto *p = Has(sTagName);\
514 return p != NULL && p->Is##type()\
515 ? &(p->Get##type())\
516 : NULL;\
517}
518
519 /// @name 针对每种类型提供一个方便使用的函数,由宏批量生成
520 /// @brief 具体作用说明:
521 /// - Get开头+类型名的函数:直接获取指定标签名且对应类型的引用,异常由std::unordered_map的at与std::get具体实现决定
522 /// - Has开头 + 类型名的函数:判断指定标签名是否存在,且标签名对应的类型是否是指定类型,都符合则返回对应指针,否则返回NULL指针
523 /// @{
524
535 TYPE_GET_FUNC(String);
536 TYPE_GET_FUNC(List);
537 TYPE_GET_FUNC(Compound);
538
540
541#undef TYPE_GET_FUNC
542
546#define TYPE_PUT_FUNC(type)\
547
551\
556template <typename K>\
557requires std::constructible_from<typename Compound::key_type, K &&>\
558std::pair<typename Compound::iterator, bool> Put##type(K &&sTagName, const typename NBT_Type::type &vTagVal)\
560 return Put(std::forward<K>(sTagName), vTagVal);\
572template <typename K>\
573requires std::constructible_from<typename Compound::key_type, K &&>\
574std::pair<typename Compound::iterator, bool> Put##type(K &&sTagName, typename NBT_Type::type &&vTagVal)\
575{\
576 return Put(std::forward<K>(sTagName), std::move(vTagVal));\
577}\
578\
579\
588template <typename K>\
589requires std::constructible_from<typename Compound::key_type, K &&>\
590std::pair<typename Compound::iterator, bool> TryPut##type(K &&sTagName, const typename NBT_Type::type &vTagVal)\
591{\
592 return TryPut(std::forward<K>(sTagName), vTagVal);\
593}\
594\
595\
604template <typename K>\
605requires std::constructible_from<typename Compound::key_type, K &&>\
606std::pair<typename Compound::iterator, bool> TryPut##type(K &&sTagName, typename NBT_Type::type &&vTagVal)\
607{\
608 return TryPut(std::forward<K>(sTagName), std::move(vTagVal));\
609}
610
615
626 TYPE_PUT_FUNC(String);
627 TYPE_PUT_FUNC(List);
628 TYPE_PUT_FUNC(Compound);
629
631
632#undef TYPE_PUT_FUNC
633};
#define TYPE_PUT_FUNC(type)
不同类型名接口生成宏
定义 NBT_Compound.hpp:519
#define TYPE_GET_FUNC(type)
不同类型名接口生成宏
定义 NBT_Compound.hpp:454
@ Int
对应NBT_Type::Int
定义 NBT_TAG.hpp:21
@ Float
对应NBT_Type::Float
定义 NBT_TAG.hpp:23
@ Compound
对应NBT_Type::Compound
定义 NBT_TAG.hpp:28
@ ByteArray
对应NBT_Type::ByteArray
定义 NBT_TAG.hpp:25
@ Short
对应NBT_Type::Short
定义 NBT_TAG.hpp:20
@ 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
NBT所有类型定义与类型处理工具集
NBT_Compound(std::initializer_list< typename Compound::value_type > init)
初始化列表构造函数
定义 NBT_Compound.hpp:98
std::vector< typename Compound::const_iterator > KeySortIt(void) const
获取按键名排序的常量迭代器向量(常量版本)
定义 NBT_Compound.hpp:241
std::partial_ordering operator<=>(const NBT_Compound &_Right) const noexcept
三路比较运算符
定义 NBT_Compound.hpp:169
void Clear(void)
清空所有标签
定义 NBT_Compound.hpp:391
bool operator!=(const NBT_Compound &_Right) const noexcept
不等比较运算符
定义 NBT_Compound.hpp:154
NBT_Compound(void)=default
默认构造函数
NBT_Compound(NBT_Compound &&_Move) noexcept
移动构造函数
定义 NBT_Compound.hpp:108
NBT_Compound & operator=(const NBT_Compound &_Copy)
拷贝赋值运算符
定义 NBT_Compound.hpp:128
NBT_Compound & operator=(NBT_Compound &&_Move) noexcept
移动赋值运算符
定义 NBT_Compound.hpp:119
std::pair< typename Compound::iterator, bool > TryPut(K &&sTagName, V &&vTagVal)
原位构造键值对
定义 NBT_Compound.hpp:370
Compound::mapped_type & Get(const typename Compound::key_type &sTagName)
根据标签名获取对应的NBT值
定义 NBT_Compound.hpp:297
std::pair< typename Compound::iterator, bool > Put(K &&sTagName, V &&vTagVal)
插入或替换键值对
定义 NBT_Compound.hpp:349
void Merge(NBT_Compound &&_Move)
合并另一个NBT_Compound的内容(移动)
定义 NBT_Compound.hpp:423
const Compound & GetData(void) const noexcept
获取底层容器数据的常量引用
定义 NBT_Compound.hpp:136
const Compound::mapped_type * Has(const typename Compound::key_type &sTagName) const noexcept
搜索标签是否存在(常量版本)
定义 NBT_Compound.hpp:328
const Compound::mapped_type & Get(const typename Compound::key_type &sTagName) const
根据标签名获取对应的NBT值(常量版本)
定义 NBT_Compound.hpp:306
bool Empty(void) const noexcept
检查容器是否为空
定义 NBT_Compound.hpp:398
bool Contains(const typename Compound::key_type &sTagName) const noexcept
检查是否包含指定标签
定义 NBT_Compound.hpp:431
NBT_Compound(const NBT_Compound &_Copy) noexcept
拷贝构造函数
定义 NBT_Compound.hpp:113
bool operator==(const NBT_Compound &_Right) const noexcept
相等比较运算符
定义 NBT_Compound.hpp:145
NBT_Compound(Args &&... args)
完美转发构造函数
定义 NBT_Compound.hpp:92
~NBT_Compound(void)=default
默认析构函数
Compound::mapped_type * Has(const typename Compound::key_type &sTagName) noexcept
搜索标签是否存在
定义 NBT_Compound.hpp:316
bool ContainsIf(Predicate pred) const noexcept
使用谓词检查是否存在满足条件的元素
定义 NBT_Compound.hpp:442
std::vector< typename Compound::iterator > KeySortIt(void)
获取按键名排序的迭代器向量(非常量版本)
定义 NBT_Compound.hpp:216
Compound::size_type Size(void) const noexcept
获取容器中元素的数量
定义 NBT_Compound.hpp:405
void Merge(const NBT_Compound &_Copy)
合并另一个NBT_Compound的内容(拷贝)
定义 NBT_Compound.hpp:414
bool Remove(const typename Compound::key_type &sTagName)
删除指定标签
定义 NBT_Compound.hpp:384
用于格式化打印、序列化、计算哈希等功能
定义 NBT_Helper.hpp:25
这个类用于提供从NBT二进制流读取到NBT_Type::Compound对象的反序列化功能
定义 NBT_Reader.hpp:23
这个类用于提供从NBT_Type::Compound对象写出到NBT二进制流的序列化功能
定义 NBT_Writer.hpp:22
概念约束,检查类型T是否具有crbegin()成员函数
定义 NBT_Compound.hpp:40
概念约束,检查类型T是否具有crend()成员函数
定义 NBT_Compound.hpp:54
概念约束,检查类型T是否具有rbegin()成员函数
定义 NBT_Compound.hpp:33
概念约束,检查类型T是否具有rend()成员函数
定义 NBT_Compound.hpp:47
概念约束,检查类型T是否支持三路比较运算符(<=>)
定义 NBT_Compound.hpp:24
用于存放NBT_Compound使用的,无法存在于类内的概念
定义 NBT_Compound.hpp:21
在std命名空间中添加类的默认hash特化以便unordered_map等容器自动获取
定义 NBT_String.hpp:428