Replace every use of Node::offsetInCharacters() by Node::isCharacterDataNode()
[WebKit-https.git] / Source / WebCore / dom / RangeBoundaryPoint.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #include "Node.h"
29 #include "Position.h"
30
31 namespace WebCore {
32
33 class RangeBoundaryPoint {
34 public:
35     explicit RangeBoundaryPoint(Node* container);
36
37     explicit RangeBoundaryPoint(const RangeBoundaryPoint&);
38
39     const Position toPosition() const;
40
41     Node* container() const;
42     unsigned offset() const;
43     Node* childBefore() const;
44
45     void clear();
46
47     void set(Ref<Node>&& container, unsigned offset, Node* childBefore);
48     void setOffset(unsigned);
49
50     void setToBeforeChild(Node&);
51     void setToAfterChild(Node&);
52     void setToStartOfNode(Ref<Node>&&);
53     void setToEndOfNode(Ref<Node>&&);
54
55     void childBeforeWillBeRemoved();
56     void invalidateOffset() const;
57     void ensureOffsetIsValid() const;
58
59 private:
60     RefPtr<Node> m_containerNode;
61     mutable std::optional<unsigned> m_offsetInContainer { 0 };
62     RefPtr<Node> m_childBeforeBoundary;
63 };
64
65 inline RangeBoundaryPoint::RangeBoundaryPoint(Node* container)
66     : m_containerNode(container)
67 {
68     ASSERT(m_containerNode);
69 }
70
71 inline RangeBoundaryPoint::RangeBoundaryPoint(const RangeBoundaryPoint& other)
72     : m_containerNode(other.container())
73     , m_offsetInContainer(other.offset())
74     , m_childBeforeBoundary(other.childBefore())
75 {
76 }
77
78 inline Node* RangeBoundaryPoint::container() const
79 {
80     return m_containerNode.get();
81 }
82
83 inline Node* RangeBoundaryPoint::childBefore() const
84 {
85     return m_childBeforeBoundary.get();
86 }
87
88 inline void RangeBoundaryPoint::ensureOffsetIsValid() const
89 {
90     if (m_offsetInContainer)
91         return;
92
93     ASSERT(m_childBeforeBoundary);
94     m_offsetInContainer = m_childBeforeBoundary->computeNodeIndex() + 1;
95 }
96
97 inline const Position RangeBoundaryPoint::toPosition() const
98 {
99     ensureOffsetIsValid();
100     return createLegacyEditingPosition(m_containerNode.get(), m_offsetInContainer.value());
101 }
102
103 inline unsigned RangeBoundaryPoint::offset() const
104 {
105     ensureOffsetIsValid();
106     return m_offsetInContainer.value();
107 }
108
109 inline void RangeBoundaryPoint::clear()
110 {
111     m_containerNode = nullptr;
112     m_offsetInContainer = 0;
113     m_childBeforeBoundary = nullptr;
114 }
115
116 inline void RangeBoundaryPoint::set(Ref<Node>&& container, unsigned offset, Node* childBefore)
117 {
118     ASSERT(childBefore == (offset ? container->traverseToChildAt(offset - 1) : 0));
119     m_containerNode = WTFMove(container);
120     m_offsetInContainer = offset;
121     m_childBeforeBoundary = childBefore;
122 }
123
124 inline void RangeBoundaryPoint::setOffset(unsigned offset)
125 {
126     ASSERT(m_containerNode);
127     ASSERT(m_containerNode->isCharacterDataNode());
128     ASSERT(m_offsetInContainer);
129     ASSERT(!m_childBeforeBoundary);
130     m_offsetInContainer = offset;
131 }
132
133 inline void RangeBoundaryPoint::setToBeforeChild(Node& child)
134 {
135     ASSERT(child.parentNode());
136     m_childBeforeBoundary = child.previousSibling();
137     m_containerNode = child.parentNode();
138     m_offsetInContainer = m_childBeforeBoundary ? std::nullopt : std::optional<unsigned>(0);
139 }
140
141 inline void RangeBoundaryPoint::setToAfterChild(Node& child)
142 {
143     ASSERT(child.parentNode());
144     m_childBeforeBoundary = &child;
145     m_containerNode = child.parentNode();
146     m_offsetInContainer = m_childBeforeBoundary ? std::nullopt : std::optional<unsigned>(0);
147 }
148
149 inline void RangeBoundaryPoint::setToStartOfNode(Ref<Node>&& container)
150 {
151     m_containerNode = WTFMove(container);
152     m_offsetInContainer = 0;
153     m_childBeforeBoundary = nullptr;
154 }
155
156 inline void RangeBoundaryPoint::setToEndOfNode(Ref<Node>&& container)
157 {
158     m_containerNode = WTFMove(container);
159     if (m_containerNode->isCharacterDataNode()) {
160         m_offsetInContainer = m_containerNode->maxCharacterOffset();
161         m_childBeforeBoundary = nullptr;
162     } else {
163         m_childBeforeBoundary = m_containerNode->lastChild();
164         m_offsetInContainer = m_childBeforeBoundary ? std::nullopt : std::optional<unsigned>(0);
165     }
166 }
167
168 inline void RangeBoundaryPoint::childBeforeWillBeRemoved()
169 {
170     ASSERT(!m_offsetInContainer || m_offsetInContainer.value());
171     m_childBeforeBoundary = m_childBeforeBoundary->previousSibling();
172     if (!m_childBeforeBoundary)
173         m_offsetInContainer = 0;
174     else if (m_offsetInContainer && m_offsetInContainer.value() > 0)
175         --(m_offsetInContainer.value());
176 }
177
178 inline void RangeBoundaryPoint::invalidateOffset() const
179 {
180     m_offsetInContainer = std::nullopt;
181 }
182
183 inline bool operator==(const RangeBoundaryPoint& a, const RangeBoundaryPoint& b)
184 {
185     if (a.container() != b.container())
186         return false;
187     if (a.childBefore() || b.childBefore()) {
188         if (a.childBefore() != b.childBefore())
189             return false;
190     } else {
191         if (a.offset() != b.offset())
192             return false;
193     }
194     return true;
195 }
196
197 } // namespace WebCore