diff options
Diffstat (limited to 'extern/draco/dracoenc/src/draco/metadata/metadata.h')
-rw-r--r-- | extern/draco/dracoenc/src/draco/metadata/metadata.h | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/extern/draco/dracoenc/src/draco/metadata/metadata.h b/extern/draco/dracoenc/src/draco/metadata/metadata.h new file mode 100644 index 00000000000..b4dd202c991 --- /dev/null +++ b/extern/draco/dracoenc/src/draco/metadata/metadata.h @@ -0,0 +1,190 @@ +// 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_ |