blob: 3bcddbe14b3707f67302e7fe8d5417a877c8df2d [file] [edit]
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "formats/bmff/box_matcher.h"
#include <cstdint>
#include <string>
#include <vector>
#include "formats/bmff/box_header.h"
#include "formats/bmff/xpath.h"
#include "proto/bmff_based_hash_assertion.pb.h"
namespace credentio {
namespace {
uint32_t NetworkUInt24(std::string value) {
uint32_t result = 0;
for (int i = 0; i < 3; ++i) {
uint8_t byte = (i < value.size()) ? static_cast<uint8_t>(value[i]) : 0;
result = (result << 8) | byte;
}
return result;
}
bool MatchLength(const BmffRange& bmff_range, const BmffBoxHeader& header) {
if (!bmff_range.has_length()) {
return true;
}
return header.box_size == bmff_range.length();
}
bool MatchVersion(const BmffRange& bmff_range, const BmffBoxHeader& header) {
if (!bmff_range.has_version()) {
return true;
}
return header.version == bmff_range.version();
}
bool MatchFlags(const BmffRange& bmff_range, const BmffBoxHeader& header) {
if (!bmff_range.has_flags()) {
return true;
}
if (!header.IsFullBox()) {
return false;
}
if (!bmff_range.has_exact() || bmff_range.exact()) {
return header.flags == bmff_range.flags();
}
auto desired_flags = NetworkUInt24(std::string(bmff_range.flags()));
auto box_flags = NetworkUInt24(header.flags);
return (desired_flags & box_flags) == desired_flags;
}
} // namespace
bool BMFFBoxMatcher::Matches(BmffBoxHeader header) const {
if (!(XPathMatcher(bmff_range_.xpath()).Matches(header.xpath)) ||
!MatchLength(bmff_range_, header) || !MatchVersion(bmff_range_, header) ||
!MatchFlags(bmff_range_, header)) {
return false;
}
for (const auto& data : bmff_range_.data()) {
uint64_t offset = header.start + data.offset();
input_.Seek(offset);
if (input_.pos() != offset) {
return false;
}
std::string value;
if (!input_.Read(data.value().size(), value)) {
return false;
}
if (value != data.value()) {
return false;
}
}
return true;
}
std::vector<BMFFBoxMatcher::Range> BMFFBoxMatcher::MatchedRanges(
BmffBoxHeader header) const {
std::vector<Range> ranges;
if (bmff_range_.subsets_size() == 0) {
ranges.push_back({.offset = header.start,
.length = static_cast<int64_t>(header.box_size)});
return ranges;
}
for (const auto& subset : bmff_range_.subsets()) {
int64_t offset = header.start + subset.offset();
int64_t end = header.start + subset.offset() + subset.length();
if (offset > end) {
// Invalid subset.
continue;
}
if (subset.length() == 0 || end > header.start + header.box_size) {
end = header.start + header.box_size;
}
ranges.push_back(
{.offset = header.start + subset.offset(), .length = end - offset});
}
return ranges;
}
} // namespace credentio