• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS.  All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #ifndef SRC_RECURSIVE_PARSER_H_
9 #define SRC_RECURSIVE_PARSER_H_
10 
11 #include <cassert>
12 #include <cstdint>
13 #include <memory>
14 #include <utility>
15 
16 #include "src/element_parser.h"
17 #include "webm/callback.h"
18 #include "webm/reader.h"
19 #include "webm/status.h"
20 
21 namespace webm {
22 
23 // Lazily instantiates a parser of type T, and uses that parser to handle all
24 // parsing operations. The parser is allocated when Init is called. This class
25 // is intended to be used with recursive elements, where a parser needs to
26 // recursively instantiate parsers of the same type.
27 template <typename T>
28 class RecursiveParser : public ElementParser {
29  public:
30   explicit RecursiveParser(std::size_t max_recursion_depth = 25)
max_recursion_depth_(max_recursion_depth)31       : max_recursion_depth_(max_recursion_depth){};
32 
33   RecursiveParser(RecursiveParser&&) = default;
34   RecursiveParser& operator=(RecursiveParser&&) = default;
35 
36   RecursiveParser(const RecursiveParser&) = delete;
37   RecursiveParser& operator=(const RecursiveParser&) = delete;
38 
Init(const ElementMetadata & metadata,std::uint64_t max_size)39   Status Init(const ElementMetadata& metadata,
40               std::uint64_t max_size) override {
41     assert(metadata.size == kUnknownElementSize || metadata.size <= max_size);
42 
43     if (max_recursion_depth_ == 0) {
44       return Status(Status::kExceededRecursionDepthLimit);
45     }
46 
47     if (!impl_) {
48       impl_.reset(new T(max_recursion_depth_ - 1));
49     }
50 
51     return impl_->Init(metadata, max_size);
52   }
53 
InitAfterSeek(const Ancestory & child_ancestory,const ElementMetadata & child_metadata)54   void InitAfterSeek(const Ancestory& child_ancestory,
55                      const ElementMetadata& child_metadata) override {
56     assert(max_recursion_depth_ > 0);
57     if (!impl_) {
58       impl_.reset(new T(max_recursion_depth_ - 1));
59     }
60 
61     impl_->InitAfterSeek(child_ancestory, child_metadata);
62   }
63 
Feed(Callback * callback,Reader * reader,std::uint64_t * num_bytes_read)64   Status Feed(Callback* callback, Reader* reader,
65               std::uint64_t* num_bytes_read) override {
66     assert(callback != nullptr);
67     assert(reader != nullptr);
68     assert(num_bytes_read != nullptr);
69     assert(impl_ != nullptr);
70 
71     return impl_->Feed(callback, reader, num_bytes_read);
72   }
73 
value()74   decltype(std::declval<T>().value()) value() const {
75     assert(impl_ != nullptr);
76 
77     return impl_->value();
78   }
79 
mutable_value()80   decltype(std::declval<T>().mutable_value()) mutable_value() {
81     assert(impl_ != nullptr);
82 
83     return impl_->mutable_value();
84   }
85 
86  private:
87   std::unique_ptr<T> impl_;
88   std::size_t max_recursion_depth_;
89 };
90 
91 }  // namespace webm
92 
93 #endif  // SRC_RECURSIVE_PARSER_H_
94