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