1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "ScriptableContentIterator.h"
8 
9 #include "mozilla/ContentIterator.h"
10 #include "nsINode.h"
11 #include "nsRange.h"
12 
13 namespace mozilla {
14 
15 NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptableContentIterator)
16 NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptableContentIterator)
17 
18 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptableContentIterator)
19   NS_INTERFACE_MAP_ENTRY(nsIScriptableContentIterator)
20   NS_INTERFACE_MAP_ENTRY(nsISupports)
21 NS_INTERFACE_MAP_END
22 
23 NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptableContentIterator)
24 
25 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptableContentIterator)
26   if (tmp->mContentIterator) {
27     switch (tmp->mIteratorType) {
28       case POST_ORDER_ITERATOR:
29       default:
30         ImplCycleCollectionUnlink(
31             static_cast<PostContentIterator&>(*tmp->mContentIterator));
32         break;
33       case PRE_ORDER_ITERATOR:
34         ImplCycleCollectionUnlink(
35             static_cast<PreContentIterator&>(*tmp->mContentIterator));
36         break;
37       case SUBTREE_ITERATOR:
38         ImplCycleCollectionUnlink(
39             static_cast<ContentSubtreeIterator&>(*tmp->mContentIterator));
40         break;
41     }
42   }
43 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
44 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptableContentIterator)
45   if (tmp->mContentIterator) {
46     switch (tmp->mIteratorType) {
47       case POST_ORDER_ITERATOR:
48       default:
49         ImplCycleCollectionTraverse(
50             cb, static_cast<PostContentIterator&>(*tmp->mContentIterator),
51             "mContentIterator");
52         break;
53       case PRE_ORDER_ITERATOR:
54         ImplCycleCollectionTraverse(
55             cb, static_cast<PreContentIterator&>(*tmp->mContentIterator),
56             "mContentIterator");
57         break;
58       case SUBTREE_ITERATOR:
59         ImplCycleCollectionTraverse(
60             cb, static_cast<ContentSubtreeIterator&>(*tmp->mContentIterator),
61             "mContentIterator");
62         break;
63     }
64   }
65 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
66 
ScriptableContentIterator()67 ScriptableContentIterator::ScriptableContentIterator()
68     : mIteratorType(NOT_INITIALIZED) {}
69 
EnsureContentIterator()70 void ScriptableContentIterator::EnsureContentIterator() {
71   if (mContentIterator) {
72     return;
73   }
74   switch (mIteratorType) {
75     case POST_ORDER_ITERATOR:
76     default:
77       mContentIterator = MakeUnique<PostContentIterator>();
78       break;
79     case PRE_ORDER_ITERATOR:
80       mContentIterator = MakeUnique<PreContentIterator>();
81       break;
82     case SUBTREE_ITERATOR:
83       mContentIterator = MakeUnique<ContentSubtreeIterator>();
84       break;
85   }
86 }
87 
88 NS_IMETHODIMP
InitWithRootNode(IteratorType aType,nsINode * aRoot)89 ScriptableContentIterator::InitWithRootNode(IteratorType aType,
90                                             nsINode* aRoot) {
91   if (aType == NOT_INITIALIZED ||
92       (mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
93     return NS_ERROR_INVALID_ARG;
94   }
95   mIteratorType = aType;
96   EnsureContentIterator();
97   return mContentIterator->Init(aRoot);
98 }
99 
100 NS_IMETHODIMP
InitWithRange(IteratorType aType,nsRange * aRange)101 ScriptableContentIterator::InitWithRange(IteratorType aType, nsRange* aRange) {
102   if (aType == NOT_INITIALIZED ||
103       (mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
104     return NS_ERROR_INVALID_ARG;
105   }
106   mIteratorType = aType;
107   EnsureContentIterator();
108   return mContentIterator->Init(aRange);
109 }
110 
111 NS_IMETHODIMP
InitWithPositions(IteratorType aType,nsINode * aStartContainer,uint32_t aStartOffset,nsINode * aEndContainer,uint32_t aEndOffset)112 ScriptableContentIterator::InitWithPositions(IteratorType aType,
113                                              nsINode* aStartContainer,
114                                              uint32_t aStartOffset,
115                                              nsINode* aEndContainer,
116                                              uint32_t aEndOffset) {
117   if (aType == NOT_INITIALIZED ||
118       (mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
119     return NS_ERROR_INVALID_ARG;
120   }
121   mIteratorType = aType;
122   EnsureContentIterator();
123   return mContentIterator->Init(aStartContainer, aStartOffset, aEndContainer,
124                                 aEndOffset);
125 }
126 
127 NS_IMETHODIMP
First()128 ScriptableContentIterator::First() {
129   if (!mContentIterator) {
130     return NS_ERROR_NOT_INITIALIZED;
131   }
132   mContentIterator->First();
133   return NS_OK;
134 }
135 
136 NS_IMETHODIMP
Last()137 ScriptableContentIterator::Last() {
138   if (!mContentIterator) {
139     return NS_ERROR_NOT_INITIALIZED;
140   }
141   mContentIterator->Last();
142   return NS_OK;
143 }
144 
145 NS_IMETHODIMP
Next()146 ScriptableContentIterator::Next() {
147   if (!mContentIterator) {
148     return NS_ERROR_NOT_INITIALIZED;
149   }
150   mContentIterator->Next();
151   return NS_OK;
152 }
153 
154 NS_IMETHODIMP
Prev()155 ScriptableContentIterator::Prev() {
156   if (!mContentIterator) {
157     return NS_ERROR_NOT_INITIALIZED;
158   }
159   mContentIterator->Prev();
160   return NS_OK;
161 }
162 
163 NS_IMETHODIMP
GetCurrentNode(nsINode ** aNode)164 ScriptableContentIterator::GetCurrentNode(nsINode** aNode) {
165   if (!mContentIterator) {
166     return NS_ERROR_NOT_INITIALIZED;
167   }
168   NS_IF_ADDREF(*aNode = mContentIterator->GetCurrentNode());
169   return NS_OK;
170 }
171 
172 NS_IMETHODIMP
GetIsDone(bool * aIsDone)173 ScriptableContentIterator::GetIsDone(bool* aIsDone) {
174   if (!mContentIterator) {
175     return NS_ERROR_NOT_INITIALIZED;
176   }
177   *aIsDone = mContentIterator->IsDone();
178   return NS_OK;
179 }
180 
181 NS_IMETHODIMP
PositionAt(nsINode * aNode)182 ScriptableContentIterator::PositionAt(nsINode* aNode) {
183   if (!mContentIterator) {
184     return NS_ERROR_NOT_INITIALIZED;
185   }
186   return mContentIterator->PositionAt(aNode);
187 }
188 
189 }  // namespace mozilla
190