1 // Copyright 2017 The Draco Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 #include "draco/metadata/metadata_decoder.h"
16
17 #include <string>
18
19 #include "draco/core/varint_decoding.h"
20
21 namespace draco {
22
MetadataDecoder()23 MetadataDecoder::MetadataDecoder() : buffer_(nullptr) {}
24
DecodeMetadata(DecoderBuffer * in_buffer,Metadata * metadata)25 bool MetadataDecoder::DecodeMetadata(DecoderBuffer *in_buffer,
26 Metadata *metadata) {
27 if (!metadata) {
28 return false;
29 }
30 buffer_ = in_buffer;
31 return DecodeMetadata(metadata);
32 }
33
DecodeGeometryMetadata(DecoderBuffer * in_buffer,GeometryMetadata * metadata)34 bool MetadataDecoder::DecodeGeometryMetadata(DecoderBuffer *in_buffer,
35 GeometryMetadata *metadata) {
36 if (!metadata) {
37 return false;
38 }
39 buffer_ = in_buffer;
40 uint32_t num_att_metadata = 0;
41 if (!DecodeVarint(&num_att_metadata, buffer_)) {
42 return false;
43 }
44 // Decode attribute metadata.
45 for (uint32_t i = 0; i < num_att_metadata; ++i) {
46 uint32_t att_unique_id;
47 if (!DecodeVarint(&att_unique_id, buffer_)) {
48 return false;
49 }
50 std::unique_ptr<AttributeMetadata> att_metadata =
51 std::unique_ptr<AttributeMetadata>(new AttributeMetadata());
52 att_metadata->set_att_unique_id(att_unique_id);
53 if (!DecodeMetadata(static_cast<Metadata *>(att_metadata.get()))) {
54 return false;
55 }
56 metadata->AddAttributeMetadata(std::move(att_metadata));
57 }
58 return DecodeMetadata(static_cast<Metadata *>(metadata));
59 }
60
DecodeMetadata(Metadata * metadata)61 bool MetadataDecoder::DecodeMetadata(Metadata *metadata) {
62 struct MetadataPair {
63 Metadata *parent_metadata;
64 Metadata *decoded_metadata;
65 };
66 std::vector<MetadataPair> metadata_stack;
67 metadata_stack.push_back({nullptr, metadata});
68 while (!metadata_stack.empty()) {
69 const MetadataPair mp = metadata_stack.back();
70 metadata_stack.pop_back();
71 metadata = mp.decoded_metadata;
72
73 if (mp.parent_metadata != nullptr) {
74 std::string sub_metadata_name;
75 if (!DecodeName(&sub_metadata_name)) {
76 return false;
77 }
78 std::unique_ptr<Metadata> sub_metadata =
79 std::unique_ptr<Metadata>(new Metadata());
80 metadata = sub_metadata.get();
81 if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name,
82 std::move(sub_metadata))) {
83 return false;
84 }
85 }
86 if (metadata == nullptr) {
87 return false;
88 }
89
90 uint32_t num_entries = 0;
91 if (!DecodeVarint(&num_entries, buffer_)) {
92 return false;
93 }
94 for (uint32_t i = 0; i < num_entries; ++i) {
95 if (!DecodeEntry(metadata)) {
96 return false;
97 }
98 }
99 uint32_t num_sub_metadata = 0;
100 if (!DecodeVarint(&num_sub_metadata, buffer_)) {
101 return false;
102 }
103 if (num_sub_metadata > buffer_->remaining_size()) {
104 // The decoded number of metadata items is unreasonably high.
105 return false;
106 }
107 for (uint32_t i = 0; i < num_sub_metadata; ++i) {
108 metadata_stack.push_back({metadata, nullptr});
109 }
110 }
111 return true;
112 }
113
DecodeEntry(Metadata * metadata)114 bool MetadataDecoder::DecodeEntry(Metadata *metadata) {
115 std::string entry_name;
116 if (!DecodeName(&entry_name)) {
117 return false;
118 }
119 uint32_t data_size = 0;
120 if (!DecodeVarint(&data_size, buffer_)) {
121 return false;
122 }
123 if (data_size == 0) {
124 return false;
125 }
126 std::vector<uint8_t> entry_value(data_size);
127 if (!buffer_->Decode(&entry_value[0], data_size)) {
128 return false;
129 }
130 metadata->AddEntryBinary(entry_name, entry_value);
131 return true;
132 }
133
DecodeName(std::string * name)134 bool MetadataDecoder::DecodeName(std::string *name) {
135 uint8_t name_len = 0;
136 if (!buffer_->Decode(&name_len)) {
137 return false;
138 }
139 name->resize(name_len);
140 if (name_len == 0) {
141 return true;
142 }
143 if (!buffer_->Decode(&name->at(0), name_len)) {
144 return false;
145 }
146 return true;
147 }
148 } // namespace draco
149