Welcome to mirror list, hosted at ThFree Co, Russian Federation.

metadata.h « metadata « draco « src « draco « draco « extern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 56d05e46a3e0c9edfc6788d92168ba90b92610fe (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// 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 <map>
#include <memory>
#include <string>
#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 (size_t 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);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is int32_t.
  bool GetEntryInt(const std::string &name, int32_t *value) const;

  void AddEntryIntArray(const std::string &name,
                        const std::vector<int32_t> &value);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is a vector of int32_t.
  bool GetEntryIntArray(const std::string &name,
                        std::vector<int32_t> *value) const;

  void AddEntryDouble(const std::string &name, double value);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is double.
  bool GetEntryDouble(const std::string &name, double *value) const;

  void AddEntryDoubleArray(const std::string &name,
                           const std::vector<double> &value);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is a vector of double.
  bool GetEntryDoubleArray(const std::string &name,
                           std::vector<double> *value) const;

  void AddEntryString(const std::string &name, const std::string &value);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is std::string.
  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);

  // Returns false if Metadata does not contain an entry with a key of |name|.
  // This function does not guarantee that entry's type is a vector of uint8_t.
  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::map<std::string, EntryValue> &entries() const { return entries_; }
  const std::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::map<std::string, EntryValue> entries_;
  std::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_