1/*
2 * Copyright (c) 2019 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/* IOCollectionIterator.h created by gvdl on Fri 1998-10-30 */
29
30#ifndef _OS_OSCOLLECTIONITERATOR_H
31#define _OS_OSCOLLECTIONITERATOR_H
32
33#include <libkern/c++/OSIterator.h>
34#include <libkern/c++/OSCollection.h>
35#include <libkern/c++/OSPtr.h>
36
37class OSCollectionIterator;
38
39typedef OSCollectionIterator* OSCollectionIteratorPtr;
40
41#if XNU_KERNEL_PRIVATE
42
43__enum_closed_decl(OSCollectionIteratorStorageType, uint8_t, {
44 OSCollectionIteratorStorageUnallocated = 0,
45 OSCollectionIteratorStorageInvalid = 1,
46 OSCollectionIteratorStorageInline = 2,
47 OSCollectionIteratorStoragePointer = 3, /* two bits set, matches top bits of kernel pointer */
48});
49
50#endif /* XNU_KERNEL_PRIVATE */
51
52/*!
53 * @header
54 *
55 * @abstract
56 * This header declares the OSCollectionIterator collection class.
57 */
58
59
60/*!
61 * @class OSCollectionIterator
62 *
63 * @discussion
64 * OSCollectionIterator defines a consistent mechanism to iterate
65 * through the objects of an OSCollection.
66 * It expands on the basic interface of
67 * @link //apple_ref/cpp/class/OSIterator OSIterator@/link
68 * to allow association of an iterator with a specific collection.
69 *
70 * To use an OSCollectionIterator, you create it with the collection
71 * to be iterated, then call
72 * @link //apple_ref/cpp/class/OSIterator OSIterator@/link
73 * as long as it returns an object:
74 *
75 * @textblock
76 * <pre>
77 * OSPtr <OSCollectionIterator> iterator =
78 * OSCollectionIterator::withCollection(myCollection);
79 * OSObject * object;
80 * while (object = iterator->getNextObject()) {
81 * // do something with object
82 * }
83 * // optional
84 * if (!iterator->isValid()) {
85 * // report that collection changed during iteration
86 * }
87 * iterator = nullptr;
88 * </pre>
89 * @/textblock
90 *
91 * Note that when iterating associative collections,
92 * the objects returned by <code>getNextObject</code> are keys;
93 * if you want to work with the associated values,
94 * simply look them up in the collection with the keys.
95 *
96 * <b>Use Restrictions</b>
97 *
98 * With very few exceptions in the I/O Kit, all Libkern-based C++
99 * classes, functions, and macros are <b>unsafe</b>
100 * to use in a primary interrupt context.
101 * Consult the I/O Kit documentation related to primary interrupts
102 * for more information.
103 *
104 * OSCollectionIterator provides no concurrency protection.
105 */
106class OSCollectionIterator : public OSIterator
107{
108 OSDeclareDefaultStructors(OSCollectionIterator);
109
110protected:
111// xx-review: Do we want to document these?
112 OSPtr<const OSCollection> collection;
113#if __LP64__ && XNU_KERNEL_PRIVATE
114 union {
115 struct {
116 uint8_t inlineStorage[4];
117 uint8_t __padding[4];
118 };
119 void * collIterator;
120 };
121#else
122 void * collIterator;
123#endif /* __LP64__ && XNU_KERNEL_PRIVATE */
124 unsigned int initialUpdateStamp;
125 bool valid;
126
127#if XNU_KERNEL_PRIVATE
128private:
129 /*
130 * Returns true if this object is an instance of a OSCollectionIterator subclass
131 */
132 bool isSubclassed();
133
134 /*
135 * Initialize iterator storage.
136 *
137 * If storage is already initialized, return false. Otherwise, return true.
138 */
139 bool initializeIteratorStorage();
140
141 /*
142 * Get the iterator storage. If storage is not initialized, this returns NULL.
143 */
144 void * getIteratorStorage();
145
146 /*
147 * Free iterator storage. If storage is not initialized, this has no effect.
148 */
149 void freeIteratorStorage();
150
151 /*
152 * Determine if storage is unallocated, allocated, or inline.
153 */
154 OSCollectionIteratorStorageType getStorageType();
155
156 /*
157 * Set the storage type. The expectation is that this is called AFTER the conditions
158 * for the storage type have been set. For example, collIterator must be set to a valid
159 * pointer before calling setStorageType(OSCollectionIteratorStoragePointer)
160 */
161 void setStorageType(OSCollectionIteratorStorageType storageType);
162#endif
163
164public:
165/*!
166 * @function withCollection
167 *
168 * @abstract
169 * Creates and initializes an OSCollectionIterator
170 * for the provided collection object.
171 *
172 * @param inColl The OSCollection-derived collection object to be iteratated.
173 *
174 * @result
175 * A new instance of OSCollectionIterator, or <code>NULL</code> on failure.
176 */
177 static OSPtr<OSCollectionIterator> withCollection(const OSCollection * inColl);
178
179
180/*!
181 * @function initWithCollection
182 *
183 * @abstract
184 * Initializes an OSCollectionIterator
185 * for the provided collection object.
186 *
187 * @param inColl The OSCollection-derived collection object to be iteratated.
188 * @result
189 * <code>true</code> if the initialization was successful,
190 * or <code>false</code> on failure.
191 *
192 * @discussion
193 * Not for general use. Use the static instance creation method
194 * <code>@link withCollection withCollection@/link</code> instead.
195 */
196 virtual bool initWithCollection(const OSCollection * inColl);
197
198
199/*!
200 * @function free
201 *
202 * @abstract
203 * Releases or deallocates any resources used
204 * by the OSCollectionIterator object.
205 *
206 * @discussion
207 * This function should not be called directly;
208 * use
209 * <code>@link
210 * //apple_ref/cpp/instm/OSObject/release/virtualvoid/()
211 * release@/link</code>
212 * instead.
213 */
214 virtual void free() APPLE_KEXT_OVERRIDE;
215
216
217/*!
218 * @function reset
219 *
220 * @abstract
221 * Resets the iterator to the beginning of the collection,
222 * as if it had just been created.
223 */
224 virtual void reset() APPLE_KEXT_OVERRIDE;
225
226
227/*!
228 * @function isValid
229 *
230 * @abstract
231 * Checks that the collection hasn't been modified during iteration.
232 *
233 * @return
234 * <code>true</code> if the iterator is valid for continued use,
235 * <code>false</code> otherwise
236 * (typically because the iteration context has been modified).
237 */
238 virtual bool isValid() APPLE_KEXT_OVERRIDE;
239
240
241/*!
242 * @function getNextObject
243 *
244 * @abstract
245 * Advances to and returns the next object in the iteration.
246 *
247 * @return
248 * The next object in the iteration context,
249 * <code>NULL</code> if there is no next object
250 * or if the iterator is no longer valid.
251 *
252 * @discussion
253 * This function first calls
254 * <code>@link //apple_ref/cpp/instm/OSCollectionIterator/isValid/virtualbool/()
255 * isValid@/link</code>
256 * and returns <code>NULL</code> if that function
257 * returns <code>false</code>.
258 *
259 * Subclasses must implement this pure virtual function
260 * to check for validity with
261 * <code>@link
262 * //apple_ref/cpp/instm/OSCollectionIterator/isValid/virtualbool/()
263 * isValid@/link</code>,
264 * and then to advance the iteration context to the next object (if any)
265 * and return that next object, or <code>NULL</code> if there is none.
266 */
267 virtual OSObject * getNextObject() APPLE_KEXT_OVERRIDE;
268};
269
270#endif /* !_OS_OSCOLLECTIONITERATOR_H */
271