Changeset View
Changeset View
Standalone View
Standalone View
extern/draco/dracoenc/src/draco/metadata/metadata.h
- This file was added.
| // Copyright 2017 The Draco Authors. | |||||
| // | |||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| // you may not use this file except in compliance with the License. | |||||
| // You may obtain a copy of the License at | |||||
| // | |||||
| // http://www.apache.org/licenses/LICENSE-2.0 | |||||
| // | |||||
| // Unless required by applicable law or agreed to in writing, software | |||||
| // distributed under the License is distributed on an "AS IS" BASIS, | |||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| // See the License for the specific language governing permissions and | |||||
| // limitations under the License. | |||||
| // | |||||
| #ifndef DRACO_METADATA_METADATA_H_ | |||||
| #define DRACO_METADATA_METADATA_H_ | |||||
| #include <cstring> | |||||
| #include <memory> | |||||
| #include <string> | |||||
| #include <unordered_map> | |||||
| #include <vector> | |||||
| #include "draco/core/hash_utils.h" | |||||
| namespace draco { | |||||
| // Class for storing a value of an entry in Metadata. Internally it is | |||||
| // represented by a buffer of data. It can be accessed by various data types, | |||||
| // e.g. int, float, binary data or string. | |||||
| class EntryValue { | |||||
| public: | |||||
| template <typename DataTypeT> | |||||
| explicit EntryValue(const DataTypeT &data) { | |||||
| const size_t data_type_size = sizeof(DataTypeT); | |||||
| data_.resize(data_type_size); | |||||
| memcpy(&data_[0], &data, data_type_size); | |||||
| } | |||||
| template <typename DataTypeT> | |||||
| explicit EntryValue(const std::vector<DataTypeT> &data) { | |||||
| const size_t total_size = sizeof(DataTypeT) * data.size(); | |||||
| data_.resize(total_size); | |||||
| memcpy(&data_[0], &data[0], total_size); | |||||
| } | |||||
| EntryValue(const EntryValue &value); | |||||
| explicit EntryValue(const std::string &value); | |||||
| template <typename DataTypeT> | |||||
| bool GetValue(DataTypeT *value) const { | |||||
| const size_t data_type_size = sizeof(DataTypeT); | |||||
| if (data_type_size != data_.size()) { | |||||
| return false; | |||||
| } | |||||
| memcpy(value, &data_[0], data_type_size); | |||||
| return true; | |||||
| } | |||||
| template <typename DataTypeT> | |||||
| bool GetValue(std::vector<DataTypeT> *value) const { | |||||
| if (data_.empty()) | |||||
| return false; | |||||
| const size_t data_type_size = sizeof(DataTypeT); | |||||
| if (data_.size() % data_type_size != 0) { | |||||
| return false; | |||||
| } | |||||
| value->resize(data_.size() / data_type_size); | |||||
| memcpy(&value->at(0), &data_[0], data_.size()); | |||||
| return true; | |||||
| } | |||||
| const std::vector<uint8_t> &data() const { return data_; } | |||||
| private: | |||||
| std::vector<uint8_t> data_; | |||||
| friend struct EntryValueHasher; | |||||
| }; | |||||
| // Functor for computing a hash from data stored within an EntryValue. | |||||
| struct EntryValueHasher { | |||||
| size_t operator()(const EntryValue &ev) const { | |||||
| size_t hash = ev.data_.size(); | |||||
| for (int i = 0; i < ev.data_.size(); ++i) { | |||||
| hash = HashCombine(ev.data_[i], hash); | |||||
| } | |||||
| return hash; | |||||
| } | |||||
| }; | |||||
| // Class for holding generic metadata. It has a list of entries which consist of | |||||
| // an entry name and an entry value. Each Metadata could also have nested | |||||
| // metadata. | |||||
| class Metadata { | |||||
| public: | |||||
| Metadata() {} | |||||
| Metadata(const Metadata &metadata); | |||||
| // In theory, we support all types of data as long as it could be serialized | |||||
| // to binary data. We provide the following functions for inserting and | |||||
| // accessing entries of common data types. For now, developers need to know | |||||
| // the type of entries they are requesting. | |||||
| void AddEntryInt(const std::string &name, int32_t value); | |||||
| bool GetEntryInt(const std::string &name, int32_t *value) const; | |||||
| void AddEntryIntArray(const std::string &name, | |||||
| const std::vector<int32_t> &value); | |||||
| bool GetEntryIntArray(const std::string &name, | |||||
| std::vector<int32_t> *value) const; | |||||
| void AddEntryDouble(const std::string &name, double value); | |||||
| bool GetEntryDouble(const std::string &name, double *value) const; | |||||
| void AddEntryDoubleArray(const std::string &name, | |||||
| const std::vector<double> &value); | |||||
| bool GetEntryDoubleArray(const std::string &name, | |||||
| std::vector<double> *value) const; | |||||
| void AddEntryString(const std::string &name, const std::string &value); | |||||
| bool GetEntryString(const std::string &name, std::string *value) const; | |||||
| // Add a blob of data as an entry. | |||||
| void AddEntryBinary(const std::string &name, | |||||
| const std::vector<uint8_t> &value); | |||||
| bool GetEntryBinary(const std::string &name, | |||||
| std::vector<uint8_t> *value) const; | |||||
| bool AddSubMetadata(const std::string &name, | |||||
| std::unique_ptr<Metadata> sub_metadata); | |||||
| const Metadata *GetSubMetadata(const std::string &name) const; | |||||
| void RemoveEntry(const std::string &name); | |||||
| int num_entries() const { return static_cast<int>(entries_.size()); } | |||||
| const std::unordered_map<std::string, EntryValue> &entries() const { | |||||
| return entries_; | |||||
| } | |||||
| const std::unordered_map<std::string, std::unique_ptr<Metadata>> | |||||
| &sub_metadatas() const { | |||||
| return sub_metadatas_; | |||||
| } | |||||
| private: | |||||
| // Make this function private to avoid adding undefined data types. | |||||
| template <typename DataTypeT> | |||||
| void AddEntry(const std::string &entry_name, const DataTypeT &entry_value) { | |||||
| const auto itr = entries_.find(entry_name); | |||||
| if (itr != entries_.end()) | |||||
| entries_.erase(itr); | |||||
| entries_.insert(std::make_pair(entry_name, EntryValue(entry_value))); | |||||
| } | |||||
| // Make this function private to avoid adding undefined data types. | |||||
| template <typename DataTypeT> | |||||
| bool GetEntry(const std::string &entry_name, DataTypeT *entry_value) const { | |||||
| const auto itr = entries_.find(entry_name); | |||||
| if (itr == entries_.end()) { | |||||
| return false; | |||||
| } | |||||
| return itr->second.GetValue(entry_value); | |||||
| } | |||||
| std::unordered_map<std::string, EntryValue> entries_; | |||||
| std::unordered_map<std::string, std::unique_ptr<Metadata>> sub_metadatas_; | |||||
| friend struct MetadataHasher; | |||||
| }; | |||||
| // Functor for computing a hash from data stored within a metadata class. | |||||
| struct MetadataHasher { | |||||
| size_t operator()(const Metadata &metadata) const { | |||||
| size_t hash = | |||||
| HashCombine(metadata.entries_.size(), metadata.sub_metadatas_.size()); | |||||
| EntryValueHasher entry_value_hasher; | |||||
| for (const auto &entry : metadata.entries_) { | |||||
| hash = HashCombine(entry.first, hash); | |||||
| hash = HashCombine(entry_value_hasher(entry.second), hash); | |||||
| } | |||||
| MetadataHasher metadata_hasher; | |||||
| for (auto &&sub_metadata : metadata.sub_metadatas_) { | |||||
| hash = HashCombine(sub_metadata.first, hash); | |||||
| hash = HashCombine(metadata_hasher(*sub_metadata.second), hash); | |||||
| } | |||||
| return hash; | |||||
| } | |||||
| }; | |||||
| } // namespace draco | |||||
| #endif // DRACO_METADATA_METADATA_H_ | |||||