// Copyright (c) 2016 The WebM project authors. All Rights Reserved. // // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file in the root of the source // tree. An additional intellectual property rights grant can be found // in the file PATENTS. All contributing project authors may // be found in the AUTHORS file in the root of the source tree. #ifndef SRC_ANCESTORY_H_ #define SRC_ANCESTORY_H_ #include #include #include #include "webm/id.h" namespace webm { // Represents an element's ancestory in descending order. For example, the // Id::kTrackNumber element has an ancestory of {Id::kSegment, Id::kTracks, // Id::kTrackEntry}. class Ancestory { public: // Constructs an empty ancestory. Ancestory() = default; Ancestory(const Ancestory&) = default; Ancestory(Ancestory&&) = default; Ancestory& operator=(const Ancestory&) = default; Ancestory& operator=(Ancestory&&) = default; // Returns the ancestory with the top-level parent removed. For example, if // the current ancestory is {Id::kSegment, Id::kTracks, Id::kTrackEntry}, next // will return {Id::kTracks, Id::kTrackEntry}. This must not be called if the // ancestory is empty. Ancestory next() const { assert(begin_ < end_); Ancestory copy = *this; ++copy.begin_; return copy; } // Gets the Id of the top-level parent. For example, if the current ancestory // is {Id::kSegment, Id::kTracks, Id::kTrackEntry}, id will return // Id::kSegment. This must not be called if the ancestory is empty. Id id() const { assert(begin_ < end_); return *begin_; } // Returns true if the ancestory is empty. bool empty() const { return begin_ == end_; } // Looks up the ancestory of the given id. Returns true and sets ancestory if // the element's ancestory could be deduced. Global elements (i.e. Id::kVoid) // and unknown elements can't have their ancestory deduced. static bool ById(Id id, Ancestory* ancestory); private: // Constructs an Ancestory using the first count elements of ancestory. // ancestory must have static storage duration. template Ancestory(const Id (&ancestory)[N], std::size_t count) : begin_(ancestory), end_(ancestory + count) { assert(count <= N); } // The following invariants apply to begin_ and end_: // begin_ <= end_ // (begin_ == end_) || (std::begin(kIds) <= begin_ && end_ <= std::end(kIds)) // The beginning (inclusive) of the sequence of IDs in kIds that defines the // ancestory. const Id* begin_ = nullptr; // The ending (exclusive) of the sequence of IDs in kIds that defines the // ancestory. const Id* end_ = nullptr; }; } // namespace webm #endif // SRC_ANCESTORY_H_