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_BOOL_PARSER_H_ 9 #define SRC_BOOL_PARSER_H_ 10 11 #include <cassert> 12 #include <cstdint> 13 14 #include "src/element_parser.h" 15 #include "src/parser_utils.h" 16 #include "webm/callback.h" 17 #include "webm/element.h" 18 #include "webm/reader.h" 19 #include "webm/status.h" 20 21 namespace webm { 22 23 // Parses a boolean from a byte stream. EBML does not have a boolean type, but 24 // the Matroska spec defines some unsigned integer elements that have a range of 25 // [0, 1]. The BoolParser parses these unsigned integer elements into 26 // true/false, and reports a Status::kInvalidElementValue error if the integer 27 // is outside of its permitted range. 28 class BoolParser : public ElementParser { 29 public: 30 explicit BoolParser(bool default_value = false) default_value_(default_value)31 : default_value_(default_value) {} 32 Init(const ElementMetadata & metadata,std::uint64_t max_size)33 Status Init(const ElementMetadata& metadata, 34 std::uint64_t max_size) override { 35 assert(metadata.size == kUnknownElementSize || metadata.size <= max_size); 36 37 // Booleans are really just unsigned integers with a range limit of 0-1. 38 // Unsigned integers can't be encoded with more than 8 bytes. 39 if (metadata.size > 8) { 40 return Status(Status::kInvalidElementSize); 41 } 42 43 size_ = num_bytes_remaining_ = static_cast<int>(metadata.size); 44 value_ = default_value_; 45 46 return Status(Status::kOkCompleted); 47 } 48 Feed(Callback * callback,Reader * reader,std::uint64_t * num_bytes_read)49 Status Feed(Callback* callback, Reader* reader, 50 std::uint64_t* num_bytes_read) override { 51 assert(callback != nullptr); 52 assert(reader != nullptr); 53 assert(num_bytes_read != nullptr); 54 55 std::uint64_t uint_value = 0; 56 const Status status = AccumulateIntegerBytes(num_bytes_remaining_, reader, 57 &uint_value, num_bytes_read); 58 num_bytes_remaining_ -= static_cast<int>(*num_bytes_read); 59 60 // Only the last byte should have a value, and it should only be 0 or 1. 61 if ((num_bytes_remaining_ != 0 && uint_value != 0) || uint_value > 1) { 62 return Status(Status::kInvalidElementValue); 63 } 64 65 if (size_ > 0) { 66 value_ = uint_value == 1; 67 } 68 69 return status; 70 } 71 72 // Gets the parsed bool. This must not be called until the parse had been 73 // successfully completed. value()74 bool value() const { 75 assert(num_bytes_remaining_ == 0); 76 return value_; 77 } 78 79 // Gets the parsed bool. This must not be called until the parse had been 80 // successfully completed. mutable_value()81 bool* mutable_value() { 82 assert(num_bytes_remaining_ == 0); 83 return &value_; 84 } 85 86 private: 87 bool value_; 88 bool default_value_; 89 int num_bytes_remaining_ = -1; 90 int size_; 91 }; 92 93 } // namespace webm 94 95 #endif // SRC_BOOL_PARSER_H_ 96