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_MASTER_VALUE_PARSER_H_
9 #define SRC_MASTER_VALUE_PARSER_H_
10 
11 #include <cassert>
12 #include <cstdint>
13 #include <functional>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17 #include <vector>
18 
19 #include "src/master_parser.h"
20 #include "src/recursive_parser.h"
21 #include "src/skip_callback.h"
22 #include "webm/callback.h"
23 #include "webm/element.h"
24 #include "webm/id.h"
25 #include "webm/reader.h"
26 #include "webm/status.h"
27 
28 namespace webm {
29 
30 // Parses Master elements from an EBML stream, storing child values in a
31 // structure of type T. This class differs from MasterParser in that
32 // MasterParser does not collect the parsed data into an object that can then be
33 // retrieved.
34 //
35 // For example, consider the following Foo object, which represents a master
36 // element that contains two booleans:
37 //
38 // struct Foo {
39 //   Element<bool> bar;
40 //   Element<bool> baz;
41 // };
42 //
43 // A FooParser implemented via MasterParser, like below, could be used to parse
44 // the master element and the boolean children, but the boolean values could not
45 // be retrieved from the parser.
46 //
47 // struct FooParser : public MasterParser {
48 //   FooParser()
49 //       : MasterParser({Id::kBar, new BoolParser},     // std::pair<*> types
50 //                      {Id::kBaz, new BoolParser}) {}  // omitted for brevity.
51 // };
52 //
53 // However, if FooParser is implemented via MasterValueParser<Foo>, then the
54 // boolean values will be parsed into a Foo object that can be retrieved from
55 // FooParser via its value() and mutable_value() methods.
56 //
57 // struct FooParser : public MasterValueParser<Foo> {
58 //   FooParser()
59 //       : MasterValueParser(MakeChild<BoolParser>(Id::kBar, &Foo::bar),
60 //                           MakeChild<BoolParser>(Id::kBaz, &Foo::baz)) {}
61 // };
62 template <typename T>
63 class MasterValueParser : public ElementParser {
64  public:
Init(const ElementMetadata & metadata,std::uint64_t max_size)65   Status Init(const ElementMetadata& metadata,
66               std::uint64_t max_size) override {
67     assert(metadata.size == kUnknownElementSize || metadata.size <= max_size);
68 
69     PreInit();
70 
71     const Status status = master_parser_.Init(metadata, max_size);
72     if (!status.completed_ok()) {
73       return status;
74     }
75 
76     return status;
77   }
78 
InitAfterSeek(const Ancestory & child_ancestory,const ElementMetadata & child_metadata)79   void InitAfterSeek(const Ancestory& child_ancestory,
80                      const ElementMetadata& child_metadata) override {
81     PreInit();
82     started_done_ = true;
83     master_parser_.InitAfterSeek(child_ancestory, child_metadata);
84   }
85 
Feed(Callback * callback,Reader * reader,std::uint64_t * num_bytes_read)86   Status Feed(Callback* callback, Reader* reader,
87               std::uint64_t* num_bytes_read) override {
88     assert(callback != nullptr);
89     assert(reader != nullptr);
90     assert(num_bytes_read != nullptr);
91 
92     *num_bytes_read = 0;
93 
94     if (!parse_complete_) {
95       // TODO(mjbshaw): just call Reader::Skip if element's size is known and
96       // action is skip.
97       SkipCallback skip_callback;
98       if (action_ == Action::kSkip) {
99         callback = &skip_callback;
100       }
101 
102       Status status = master_parser_.Feed(callback, reader, num_bytes_read);
103       // Check if we've artificially injected an error code, and if so, switch
104       // into skipping mode.
105       if (status.code == Status::kSwitchToSkip) {
106         assert(started_done_);
107         assert(action_ == Action::kSkip);
108         callback = &skip_callback;
109         std::uint64_t local_num_bytes_read;
110         status = master_parser_.Feed(callback, reader, &local_num_bytes_read);
111         *num_bytes_read += local_num_bytes_read;
112       }
113       if (!status.completed_ok()) {
114         return status;
115       }
116       parse_complete_ = true;
117     }
118 
119     if (!started_done_) {
120       Status status = OnParseStarted(callback, &action_);
121       if (!status.completed_ok()) {
122         return status;
123       }
124       started_done_ = true;
125     }
126 
127     if (action_ != Action::kSkip) {
128       return OnParseCompleted(callback);
129     }
130 
131     return Status(Status::kOkCompleted);
132   }
133 
GetCachedMetadata(ElementMetadata * metadata)134   bool GetCachedMetadata(ElementMetadata* metadata) override {
135     return master_parser_.GetCachedMetadata(metadata);
136   }
137 
WasSkipped()138   bool WasSkipped() const override { return action_ == Action::kSkip; }
139 
value()140   const T& value() const { return value_; }
141 
mutable_value()142   T* mutable_value() { return &value_; }
143 
144  protected:
145   // Users and subclasses are not meant to use the Tag* classes; they're an
146   // internal implementation detail.
147   // A tag that will cause the internal ChildParser to use the parsed child as a
148   // start event.
149   struct TagUseAsStart {};
150   // A tag that will cause the internal ChildParser to call OnChildParsed once
151   // it has been fully parsed.
152   struct TagNotifyOnParseComplete {};
153 
154   // A factory that will create a std::pair<Id, std::unique_ptr<ElementParser>>.
155   // Users and subclasses are not meant to use this class directly, as it is an
156   // internal implementation detail of this class. Subclasses should use
157   // MakeChild instead of using this class directly.
158   template <typename Parser, typename Value, typename... Tags>
159   class SingleChildFactory {
160    public:
SingleChildFactory(Id id,Element<Value> T::* member)161     constexpr SingleChildFactory(Id id, Element<Value> T::*member)
162         : id_(id), member_(member) {}
163 
164     // Builds a std::pair<Id, std::unique_ptr<ElementParser>>. The parent
165     // pointer must be a pointer to the MasterValueParser that is being
166     // constructed. The given value pointer must be the pointer to the fully
167     // constructed MasterValueParser::value_ object.
BuildParser(MasterValueParser * parent,T * value)168     std::pair<Id, std::unique_ptr<ElementParser>> BuildParser(
169         MasterValueParser* parent, T* value) {
170       assert(parent != nullptr);
171       assert(value != nullptr);
172 
173       Element<Value>* child_member = &(value->*member_);
174       auto lambda = [child_member](Parser* parser) {
175         child_member->Set(std::move(*parser->mutable_value()), true);
176       };
177       return {id_, MakeChildParser<Parser, Value, Tags...>(
178                        parent, std::move(lambda), child_member)};
179     }
180 
181     // If called, OnParseStarted will be called on the parent element when this
182     // particular element is encountered.
183     constexpr SingleChildFactory<Parser, Value, TagUseAsStart, Tags...>
UseAsStartEvent()184     UseAsStartEvent() const {
185       return {id_, member_};
186     }
187 
188     // If called, OnChildParsed will be called on the parent element when this
189     // particular element is fully parsed.
190     constexpr SingleChildFactory<Parser, Value, TagNotifyOnParseComplete,
191                                  Tags...>
NotifyOnParseComplete()192     NotifyOnParseComplete() const {
193       return {id_, member_};
194     }
195 
196    private:
197     Id id_;
198     Element<Value> T::*member_;
199   };
200 
201   template <typename Parser, typename Value, typename... Tags>
202   class RepeatedChildFactory {
203    public:
RepeatedChildFactory(Id id,std::vector<Element<Value>> T::* member)204     constexpr RepeatedChildFactory(Id id,
205                                    std::vector<Element<Value>> T::*member)
206         : id_(id), member_(member) {}
207 
208     // Builds a std::pair<Id, std::unique_ptr<ElementParser>>. The parent
209     // pointer must be a pointer to the MasterValueParser that is being
210     // constructed. The given value pointer must be the pointer to the fully
211     // constructed MasterValueParser::value_ object.
BuildParser(MasterValueParser * parent,T * value)212     std::pair<Id, std::unique_ptr<ElementParser>> BuildParser(
213         MasterValueParser* parent, T* value) {
214       assert(parent != nullptr);
215       assert(value != nullptr);
216 
217       std::vector<Element<Value>>* child_member = &(value->*member_);
218       auto lambda = [child_member](Parser* parser) {
219         if (child_member->size() == 1 && !child_member->front().is_present()) {
220           child_member->clear();
221         }
222         child_member->emplace_back(std::move(*parser->mutable_value()), true);
223       };
224       return {id_, MakeChildParser<Parser, Value, Tags...>(
225                        parent, std::move(lambda), child_member)};
226     }
227 
228     // If called, OnParseStarted will be called on the parent element when this
229     // particular element is encountered.
230     constexpr RepeatedChildFactory<Parser, Value, TagUseAsStart, Tags...>
UseAsStartEvent()231     UseAsStartEvent() const {
232       return {id_, member_};
233     }
234 
235     // If called, OnChildParsed will be called on the parent element when this
236     // particular element is fully parsed.
237     constexpr RepeatedChildFactory<Parser, Value, TagNotifyOnParseComplete,
238                                    Tags...>
NotifyOnParseComplete()239     NotifyOnParseComplete() const {
240       return {id_, member_};
241     }
242 
243    private:
244     Id id_;
245     std::vector<Element<Value>> T::*member_;
246   };
247 
248   template <typename Parser, typename... Tags>
249   class RecursiveChildFactory {
250    public:
RecursiveChildFactory(Id id,std::vector<Element<T>> T::* member,std::size_t max_recursion_depth)251     constexpr RecursiveChildFactory(Id id, std::vector<Element<T>> T::*member,
252                                     std::size_t max_recursion_depth)
253         : id_(id), member_(member), max_recursion_depth_(max_recursion_depth) {}
254 
255     // Builds a std::pair<Id, std::unique_ptr<ElementParser>>. The parent
256     // pointer must be a pointer to the MasterValueParser that is being
257     // constructed. The given value pointer must be the pointer to the fully
258     // constructed MasterValueParser::value_ object.
BuildParser(MasterValueParser * parent,T * value)259     std::pair<Id, std::unique_ptr<ElementParser>> BuildParser(
260         MasterValueParser* parent, T* value) {
261       assert(parent != nullptr);
262       assert(value != nullptr);
263 
264       std::vector<Element<T>>* child_member = &(value->*member_);
265       auto lambda = [child_member](RecursiveParser<Parser>* parser) {
266         if (child_member->size() == 1 && !child_member->front().is_present()) {
267           child_member->clear();
268         }
269         child_member->emplace_back(std::move(*parser->mutable_value()), true);
270       };
271 
272       return {id_, std::unique_ptr<ElementParser>(
273                        new ChildParser<RecursiveParser<Parser>,
274                                        decltype(lambda), Tags...>(
275                            parent, std::move(lambda), max_recursion_depth_))};
276     }
277 
278     // If called, OnParseStarted will be called on the parent element when this
279     // particular element is encountered.
280     constexpr RecursiveChildFactory<Parser, TagUseAsStart, Tags...>
UseAsStartEvent()281     UseAsStartEvent() const {
282       return {id_, member_, max_recursion_depth_};
283     }
284 
285     // If called, OnChildParsed will be called on the parent element when this
286     // particular element is fully parsed.
287     constexpr RecursiveChildFactory<Parser, TagNotifyOnParseComplete, Tags...>
NotifyOnParseComplete()288     NotifyOnParseComplete() const {
289       return {id_, member_, max_recursion_depth_};
290     }
291 
292    private:
293     Id id_;
294     std::vector<Element<T>> T::*member_;
295     std::size_t max_recursion_depth_;
296   };
297 
298   // Constructs a new parser. Each argument must be a *ChildFactory, constructed
299   // from the MakeChild method.
300   template <typename... Args>
MasterValueParser(Args &&...args)301   explicit MasterValueParser(Args&&... args)
302       : master_parser_(args.BuildParser(this, &value_)...) {}
303 
304   // Returns a factory that will produce a
305   // std::pair<Id, std::unique_ptr<ElementParser>>. When a child element of the
306   // given ID is encountered, a parser of type Parser will be used to parse it,
307   // and store its value in the member pointer when the parse is complete. The
308   // given default value will be used in the event that the child element has a
309   // zero size. This method is only meant to be used by subclasses to provide
310   // the necessary factories to the constructor.
311   template <typename Parser, typename Value>
MakeChild(Id id,Element<Value> T::* member)312   static SingleChildFactory<Parser, Value> MakeChild(
313       Id id, Element<Value> T::*member) {
314     static_assert(std::is_base_of<ElementParser, Parser>::value,
315                   "Parser must derive from ElementParser");
316     static_assert(!std::is_base_of<MasterValueParser<T>, Parser>::value,
317                   "Recursive elements should be contained in a std::vector");
318     return SingleChildFactory<Parser, Value>(id, member);
319   }
320 
321   template <typename Parser, typename Value>
MakeChild(Id id,std::vector<Element<Value>> T::* member)322   static RepeatedChildFactory<Parser, Value> MakeChild(
323       Id id, std::vector<Element<Value>> T::*member) {
324     static_assert(std::is_base_of<ElementParser, Parser>::value,
325                   "Parser must derive from ElementParser");
326     static_assert(!std::is_base_of<MasterValueParser<T>, Parser>::value,
327                   "Recursive elements require a maximum recursion depth");
328     return RepeatedChildFactory<Parser, Value>(id, member);
329   }
330 
331   template <typename Parser>
MakeChild(Id id,std::vector<Element<T>> T::* member,std::size_t max_recursion_depth)332   static RecursiveChildFactory<Parser> MakeChild(
333       Id id, std::vector<Element<T>> T::*member,
334       std::size_t max_recursion_depth) {
335     static_assert(std::is_base_of<MasterValueParser<T>, Parser>::value,
336                   "Child must be recusrive to use maximum recursion depth");
337     return RecursiveChildFactory<Parser>(id, member, max_recursion_depth);
338   }
339 
340   // Gets the metadata for this element, setting the EBML element ID to id. Only
341   // call after Init() has been called.
metadata(Id id)342   ElementMetadata metadata(Id id) const {
343     return {id, master_parser_.header_size(), master_parser_.size(),
344             master_parser_.position()};
345   }
346 
347   // This method will be called once the element has been fully parsed, or a
348   // particular child element of interest (see UseAsStartEvent()) is
349   // encountered. By default it just sets *action to Action::kRead and returns
350   // Status::kOkCompleted. May be overridden (i.e. in order to call a Callback
351   // method). Returning anything other than Status::kOkCompleted will stop
352   // parsing and the status to be returned by Init or Feed (whichever originated
353   // the call to this method). In this case, resuming parsing will result in
354   // this method being called again.
OnParseStarted(Callback * callback,Action * action)355   virtual Status OnParseStarted(Callback* callback, Action* action) {
356     assert(callback != nullptr);
357     assert(action != nullptr);
358     *action = Action::kRead;
359     return Status(Status::kOkCompleted);
360   }
361 
362   // This method is the companion to OnParseStarted, and will only be called
363   // after OnParseStarted has already been called and parsing has completed.
364   // This will not be called if OnParseStarted set the action to Action::kSkip.
365   // By default it just returns Status::kOkCompleted. Returning anything other
366   // than Status::kOkCompleted will stop parsing and the status to be returned
367   // by Init or Feed (whichever originated the call to this method). In this
368   // case, resuming parsing will result in this method being called again.
OnParseCompleted(Callback * callback)369   virtual Status OnParseCompleted(Callback* callback) {
370     assert(callback != nullptr);
371     return Status(Status::kOkCompleted);
372   }
373 
374   // Returns true if the OnParseStarted method has already been called and has
375   // completed.
parse_started_event_completed()376   bool parse_started_event_completed() const { return started_done_; }
377 
378   // Derived classes may manually call OnParseStarted before calling Feed, in
379   // which case this method should be called to inform this class that
380   // OnParseStarted has already been called and it should not be called again.
set_parse_started_event_completed_with_action(Action action)381   void set_parse_started_event_completed_with_action(Action action) {
382     assert(!started_done_);
383 
384     action_ = action;
385     started_done_ = true;
386   }
387 
388   // This method will be called for each child element that has been fully
389   // parsed for which NotifyOnParseComplete() was requested. The provided
390   // metadata is for the child element that has just completed parsing. By
391   // default this method does nothing.
OnChildParsed(const ElementMetadata &)392   virtual void OnChildParsed(const ElementMetadata& /* metadata */) {}
393 
394  private:
395   T value_;
396   Action action_ = Action::kRead;
397   bool parse_complete_;
398   bool started_done_;
399   // master_parser_ must be after value_ to ensure correct initialization order.
400   MasterParser master_parser_;
401 
child_metadata()402   const ElementMetadata& child_metadata() const {
403     return master_parser_.child_metadata();
404   }
405 
406   // Helper struct that will be std::true_type if Tag is in Tags, or
407   // std::false_type otherwise.
408   template <typename Tag, typename... Tags>
409   struct HasTag;
410 
411   // Base condition: Tags is empty, so it trivially does not contain Tag.
412   template <typename Tag>
413   struct HasTag<Tag> : std::false_type {};
414 
415   // If the head of the Tags list is a different tag, skip it and check the
416   // remaining tags.
417   template <typename Tag, typename DifferentTag, typename... Tags>
418   struct HasTag<Tag, DifferentTag, Tags...> : HasTag<Tag, Tags...> {};
419 
420   // If the head of the Tags list is the same as Tag, then we're done.
421   template <typename Tag, typename... Tags>
422   struct HasTag<Tag, Tag, Tags...> : std::true_type {};
423 
424   template <typename Base, typename F, typename... Tags>
425   class ChildParser : public Base {
426    public:
427     using Base::WasSkipped;
428 
429     template <typename... Args>
430     explicit ChildParser(MasterValueParser* parent, F consume_element_value,
431                          Args&&... base_args)
432         : Base(std::forward<Args>(base_args)...),
433           parent_(parent),
434           consume_element_value_(std::move(consume_element_value)) {}
435 
436     ChildParser() = delete;
437     ChildParser(const ChildParser&) = delete;
438     ChildParser& operator=(const ChildParser&) = delete;
439 
440     Status Feed(Callback* callback, Reader* reader,
441                 std::uint64_t* num_bytes_read) override {
442       *num_bytes_read = 0;
443 
444       Status status = Prepare(callback);
445       if (!status.completed_ok()) {
446         return status;
447       }
448 
449       status = Base::Feed(callback, reader, num_bytes_read);
450       if (status.completed_ok() && parent_->action_ != Action::kSkip &&
451           !WasSkipped()) {
452         consume_element_value_(this);
453         if (has_tag<TagNotifyOnParseComplete>()) {
454           parent_->OnChildParsed(parent_->child_metadata());
455         }
456       }
457       return status;
458     }
459 
460    private:
461     MasterValueParser* parent_;
462     F consume_element_value_;
463 
464     Status Prepare(Callback* callback) {
465       if (has_tag<TagUseAsStart>() && !parent_->started_done_) {
466         const Status status =
467             parent_->OnParseStarted(callback, &parent_->action_);
468         if (!status.completed_ok()) {
469           return status;
470         }
471         parent_->started_done_ = true;
472         if (parent_->action_ == Action::kSkip) {
473           return Status(Status::kSwitchToSkip);
474         }
475       }
476       return Status(Status::kOkCompleted);
477     }
478 
479     template <typename Tag>
480     constexpr static bool has_tag() {
481       return MasterValueParser::HasTag<Tag, Tags...>::value;
482     }
483   };
484 
485   // Returns a std::unique_ptr<ElementParser> that points to a ChildParser
486   // when the Parser's constructor does not take a Value parameter.
487   template <typename Parser, typename Value, typename... Tags, typename F>
488   static typename std::enable_if<!std::is_constructible<Parser, Value>::value,
489                                  std::unique_ptr<ElementParser>>::type
490   MakeChildParser(MasterValueParser* parent, F consume_element_value, ...) {
491     return std::unique_ptr<ElementParser>(new ChildParser<Parser, F, Tags...>(
492         parent, std::move(consume_element_value)));
493   }
494 
495   // Returns a std::unique_ptr<ElementParser> that points to a ChildParser
496   // when the Parser's constructor does take a Value parameter.
497   template <typename Parser, typename Value, typename... Tags, typename F>
498   static typename std::enable_if<std::is_constructible<Parser, Value>::value,
499                                  std::unique_ptr<ElementParser>>::type
500   MakeChildParser(MasterValueParser* parent, F consume_element_value,
501                   const Element<Value>* default_value) {
502     return std::unique_ptr<ElementParser>(new ChildParser<Parser, F, Tags...>(
503         parent, std::move(consume_element_value), default_value->value()));
504   }
505 
506   // Returns a std::unique_ptr<ElementParser> that points to a ChildParser
507   // when the Parser's constructor does take a Value parameter.
508   template <typename Parser, typename Value, typename... Tags, typename F>
509   static typename std::enable_if<std::is_constructible<Parser, Value>::value,
510                                  std::unique_ptr<ElementParser>>::type
511   MakeChildParser(MasterValueParser* parent, F consume_element_value,
512                   const std::vector<Element<Value>>* member) {
513     Value default_value{};
514     if (!member->empty()) {
515       default_value = member->front().value();
516     }
517     return std::unique_ptr<ElementParser>(new ChildParser<Parser, F, Tags...>(
518         parent, std::move(consume_element_value), std::move(default_value)));
519   }
520 
521   // Initializes object state. Call immediately before initializing
522   // master_parser_.
523   void PreInit() {
524     value_ = {};
525     action_ = Action::kRead;
526     parse_complete_ = false;
527     started_done_ = false;
528   }
529 };
530 
531 }  // namespace webm
532 
533 #endif  // SRC_MASTER_VALUE_PARSER_H_
534