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