// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_EPHEMERAL_RANGE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_EPHEMERAL_RANGE_H_ #include "third_party/blink/renderer/core/editing/position.h" namespace blink { class Document; class Range; // We should restrict access to the unwanted version of |TraversalRange::end()| // function. template class TraversalRangeNodes : private TraversalRange { STACK_ALLOCATED(); public: using StartNodeType = typename TraversalRange::StartNodeType; TraversalRangeNodes(const StartNodeType* start, const StartNodeType* past_end_node) : TraversalRange(start), past_end_node_(past_end_node) {} using TraversalRange::begin; Iterator end() { return Iterator(past_end_node_); } private: const Member past_end_node_; }; // This class acts like |TraversalNextIterator| but in addition // it allows to set current position and checks |current_| pointer before // dereferencing. template class CheckedTraversalNextIterator : public TraversalIteratorBase { STACK_ALLOCATED(); using TraversalIteratorBase::current_; public: using StartNodeType = typename TraversalNext::TraversalNodeType; explicit CheckedTraversalNextIterator(const StartNodeType* start) : TraversalIteratorBase( const_cast(start)) {} void operator++() { DCHECK(current_); current_ = TraversalNext::Next(*current_); } }; // Unlike |Range| objects, |EphemeralRangeTemplate| objects aren't relocated. // You should not use |EphemeralRangeTemplate| objects after DOM modification. // // EphemeralRangeTemplate is supposed to use returning or passing start and end // position. // // Example usage: // Range* range = produceRange(); // consumeRange(range); // ... no DOM modification ... // consumeRange2(range); // // Above code should be: // EphemeralRangeTemplate range = produceRange(); // consumeRange(range); // ... no DOM modification ... // consumeRange2(range); // // Because of |Range| objects consume heap memory and inserted into |Range| // object list in |Document| for relocation. These operations are redundant // if |Range| objects doesn't live after DOM mutation. // template class EphemeralRangeTemplate final { STACK_ALLOCATED(); public: using RangeTraversal = TraversalRangeNodes>; EphemeralRangeTemplate(const PositionTemplate& start, const PositionTemplate& end); EphemeralRangeTemplate(const EphemeralRangeTemplate& other); // |position| should be |Position::isNull()| or in-document. explicit EphemeralRangeTemplate( const PositionTemplate& /* position */); // When |range| is nullptr, |EphemeralRangeTemplate| is |isNull()|. explicit EphemeralRangeTemplate(const Range* /* range */); EphemeralRangeTemplate(); ~EphemeralRangeTemplate(); EphemeralRangeTemplate& operator=( const EphemeralRangeTemplate& other); bool operator==(const EphemeralRangeTemplate& other) const; bool operator!=(const EphemeralRangeTemplate& other) const; Document& GetDocument() const; PositionTemplate StartPosition() const; PositionTemplate EndPosition() const; Node* CommonAncestorContainer() const; // Returns true if |m_startPosition| == |m_endPosition| or |isNull()|. bool IsCollapsed() const; bool IsNull() const { DCHECK(IsValid()); return start_position_.IsNull(); } bool IsNotNull() const { return !IsNull(); } RangeTraversal Nodes() const; // |node| should be in-document and valid for anchor node of // |PositionTemplate|. static EphemeralRangeTemplate RangeOfContents( const Node& /* node */); #ifndef NDEBUG void ShowTreeForThis() const; #endif private: bool IsValid() const; PositionTemplate start_position_; PositionTemplate end_position_; #if DCHECK_IS_ON() uint64_t dom_tree_version_; #endif }; extern template class CORE_EXTERN_TEMPLATE_EXPORT EphemeralRangeTemplate; using EphemeralRange = EphemeralRangeTemplate; extern template class CORE_EXTERN_TEMPLATE_EXPORT EphemeralRangeTemplate; using EphemeralRangeInFlatTree = EphemeralRangeTemplate; // Returns a newly created |Range| object from |range| or |nullptr| if // |range.isNull()| returns true. CORE_EXPORT Range* CreateRange(const EphemeralRange& /* range */); CORE_EXPORT std::ostream& operator<<(std::ostream&, const EphemeralRange&); CORE_EXPORT std::ostream& operator<<(std::ostream&, const EphemeralRangeInFlatTree&); } // namespace blink #endif