1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*
* libnbt++ - A library for the Minecraft Named Binary Tag format.
* Copyright (C) 2013, 2015 ljfa-ag
*
* This file is part of libnbt++.
*
* libnbt++ is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libnbt++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libnbt++. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TAG_COMPOUND_H_INCLUDED
#define TAG_COMPOUND_H_INCLUDED
#include "crtp_tag.h"
#include "value_initializer.h"
#include <map>
#include <string>
namespace nbt
{
///Tag that contains multiple unordered named tags of arbitrary types
class NBT_EXPORT tag_compound final : public detail::crtp_tag<tag_compound>
{
typedef std::map<std::string, value> map_t_;
public:
//Iterator types
typedef map_t_::iterator iterator;
typedef map_t_::const_iterator const_iterator;
///The type of the tag
static constexpr tag_type type = tag_type::Compound;
///Constructs an empty compound
tag_compound() {}
///Constructs a compound with the given key-value pairs
tag_compound(std::initializer_list<std::pair<std::string, value_initializer>> init);
/**
* @brief Accesses a tag by key with bounds checking
*
* Returns a value to the tag with the specified key, or throws an
* exception if it does not exist.
* @throw std::out_of_range if given key does not exist
*/
value& at(const std::string& key);
const value& at(const std::string& key) const;
/**
* @brief Accesses a tag by key
*
* Returns a value to the tag with the specified key. If it does not exist,
* creates a new uninitialized entry under the key.
*/
value& operator[](const std::string& key) { return tags[key]; }
/**
* @brief Inserts or assigns a tag
*
* If the given key already exists, assigns the tag to it.
* Otherwise, it is inserted under the given key.
* @return a pair of the iterator to the value and a bool indicating
* whether the key did not exist
*/
std::pair<iterator, bool> put(const std::string& key, value_initializer&& val);
/**
* @brief Inserts a tag if the key does not exist
* @return a pair of the iterator to the value with the key and a bool
* indicating whether the value was actually inserted
*/
std::pair<iterator, bool> insert(const std::string& key, value_initializer&& val);
/**
* @brief Constructs and assigns or inserts a tag into the compound
*
* Constructs a new tag of type @c T with the given args and inserts
* or assigns it to the given key.
* @note Unlike std::map::emplace, this will overwrite existing values
* @return a pair of the iterator to the value and a bool indicating
* whether the key did not exist
*/
template<class T, class... Args>
std::pair<iterator, bool> emplace(const std::string& key, Args&&... args);
/**
* @brief Erases a tag from the compound
* @return true if a tag was erased
*/
bool erase(const std::string& key);
///Returns true if the given key exists in the compound
bool has_key(const std::string& key) const;
///Returns true if the given key exists and the tag has the given type
bool has_key(const std::string& key, tag_type type) const;
///Returns the number of tags in the compound
size_t size() const { return tags.size(); }
///Erases all tags from the compound
void clear() { tags.clear(); }
//Iterators
iterator begin() { return tags.begin(); }
iterator end() { return tags.end(); }
const_iterator begin() const { return tags.begin(); }
const_iterator end() const { return tags.end(); }
const_iterator cbegin() const { return tags.cbegin(); }
const_iterator cend() const { return tags.cend(); }
void read_payload(io::stream_reader& reader) override;
void write_payload(io::stream_writer& writer) const override;
friend bool operator==(const tag_compound& lhs, const tag_compound& rhs)
{ return lhs.tags == rhs.tags; }
friend bool operator!=(const tag_compound& lhs, const tag_compound& rhs)
{ return !(lhs == rhs); }
private:
map_t_ tags;
};
template<class T, class... Args>
std::pair<tag_compound::iterator, bool> tag_compound::emplace(const std::string& key, Args&&... args)
{
return put(key, value(make_unique<T>(std::forward<Args>(args)...)));
}
}
#endif // TAG_COMPOUND_H_INCLUDED
|