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/* IOArray.h created by rsulack on Thu 11-Sep-1997 */
29/* IOArray.h converted to C++ by gvdl on Fri 1998-10-30 */
30
31#ifndef _OS_OSARRAY_H
32#define _OS_OSARRAY_H
33
34#include <libkern/c++/OSCollection.h>
35#include <libkern/c++/OSPtr.h>
36#include <os/base.h>
37
38class OSSerialize;
39class OSArray;
40
41typedef OSArray* OSArrayPtr;
42
43/*!
44 * @header
45 *
46 * @abstract
47 * This header declares the OSArray collection class.
48 */
49
50
51/*!
52 * @class OSArray
53 *
54 * @abstract
55 * OSArray provides an indexed store of objects.
56 *
57 * @discussion
58 * OSArray is a container for Libkern C++ objects
59 * (those derived from
60 * @link //apple_ref/doc/class/OSMetaClassBase OSMetaClassBase@/link,
61 * in particular
62 * @link //apple_ref/doc/class/OSObject OSObject@/link).
63 * Storage and access are by array index.
64 *
65 * You must generally cast retrieved objects from
66 * @link //apple_ref/cpp/cl/OSObject OSObject@/link
67 * to the desired class using
68 * <code>@link //apple_ref/cpp/macro/OSDynamicCast OSDynamicCast@/link</code>.
69 * This macro returns the object cast to the desired class,
70 * or <code>NULL</code> if the object isn't derived from that class.
71 *
72 * As with all Libkern collection classes,
73 * OSArray retains objects added to it,
74 * and releases objects removed from it (or replaced).
75 * An OSArray also grows as necessary to accommodate new objects,
76 * <i>unlike</i> Core Foundation collections (it does not, however, shrink).
77 *
78 * <b>Use Restrictions</b>
79 *
80 * With very few exceptions in the I/O Kit, all Libkern-based C++
81 * classes, functions, and macros are <b>unsafe</b>
82 * to use in a primary interrupt context.
83 * Consult the I/O Kit documentation related to primary interrupts
84 * for more information.
85 *
86 * OSArray provides no concurrency protection;
87 * it's up to the usage context to provide any protection necessary.
88 * Some portions of the I/O Kit, such as
89 * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link,
90 * handle synchronization via defined member functions for setting
91 * properties.
92 */
93class OSArray : public OSCollection
94{
95 friend class OSSet;
96 friend class OSSerialize;
97
98 OSDeclareDefaultStructors(OSArray);
99
100 typedef OSTaggedPtr<const OSMetaClassBase> ArrayPtrType;
101 typedef OSTaggedSharedPtr<const OSMetaClassBase, OSCollection> ArraySharedPtrType;
102
103#if APPLE_KEXT_ALIGN_CONTAINERS
104
105protected:
106 unsigned int count;
107 unsigned int capacity;
108 unsigned int capacityIncrement;
109 ArrayPtrType * OS_PTRAUTH_SIGNED_PTR("OSArray.array") array;
110
111#else /* APPLE_KEXT_ALIGN_CONTAINERS */
112
113protected:
114 ArrayPtrType * OS_PTRAUTH_SIGNED_PTR("OSArray.array") array;
115 unsigned int count;
116 unsigned int capacity;
117 unsigned int capacityIncrement;
118
119 struct ExpansionData { };
120
121/* Reserved for future use. (Internal use only) */
122 ExpansionData * reserved;
123
124#endif /* APPLE_KEXT_ALIGN_CONTAINERS */
125
126/* OSCollectionIterator interfaces. */
127 virtual unsigned int iteratorSize() const APPLE_KEXT_OVERRIDE;
128 virtual bool initIterator(void * iterator) const APPLE_KEXT_OVERRIDE;
129 virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret) const APPLE_KEXT_OVERRIDE;
130
131public:
132
133/*!
134 * @function withCapacity
135 *
136 * @abstract
137 * Creates and initializes an empty OSArray.
138 *
139 * @param capacity The initial storage capacity of the array object.
140 *
141 * @result
142 * An empty instance of OSArray with a retain count of 1;
143 * <code>NULL</code> on failure.
144 *
145 * @discussion
146 * <code>capacity</code> must be nonzero.
147 * The new array will grow as needed to accommodate more objects
148 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
149 * for which the initial capacity is a hard limit).
150 */
151 static OSPtr<OSArray> withCapacity(unsigned int capacity);
152
153
154/*!
155 * @function withObjects
156 *
157 * @abstract
158 * Creates and initializes an OSArray populated with objects provided.
159 *
160 * @param objects A C array of OSObject-derived instances.
161 * @param count The number of objects to be placed into the array.
162 * @param capacity The initial storage capacity of the array object.
163 * If 0, <code>count</code> is used; otherwise this value
164 * must be greater than or equal to <code>count</code>.
165 *
166 * @result
167 * An instance of OSArray containing the objects provided,
168 * with a retain count of 1;
169 * <code>NULL</code> on failure.
170 *
171 * @discussion
172 * <code>objects</code> must be non-<code>NULL</code>, and <code>count</code> must be nonzero.
173 * If <code>capacity</code> is nonzero,
174 * it must be greater than or equal to <code>count</code>.
175 * The new array will grow as needed to accommodate more objects
176 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
177 * for which the initial capacity is a hard limit).
178 */
179 static OSPtr<OSArray> withObjects(
180 const OSObject * objects[],
181 unsigned int count,
182 unsigned int capacity = 0);
183
184
185/*!
186 * @function withArray
187 *
188 * @abstract
189 * Creates and initializes an OSArray populated with the contents of another array.
190 *
191 * @param array An OSArray whose contents will be stored
192 * in the new instance.
193 * @param capacity The initial storage capacity of the array object.
194 * If 0, the capacity is set to the number of objects
195 * in <code>array</code>;
196 * otherwise <code>capacity</code> must be
197 * greater than or equal to the number of objects
198 * in <code>array</code>.
199 *
200 * @result
201 * An instance of OSArray containing the objects of <code>array</code>,
202 * with a retain count of 1;
203 * <code>NULL</code> on failure.
204 *
205 * @discussion
206 * <code>array</code> must be non-<code>NULL</code>.
207 * If <code>capacity</code> is nonzero,
208 * it must be greater than or equal to <code>count</code>.
209 * The new array will grow as needed to accommodate more objects
210 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
211 * for which the initial capacity is a hard limit).
212 *
213 * The objects in <code>array</code> are retained
214 * for storage in the new OSArray,
215 * not copied.
216 */
217 static OSPtr<OSArray> withArray(
218 const OSArray * array,
219 unsigned int capacity = 0);
220
221
222/*!
223 * @function initWithCapacity
224 *
225 * @abstract
226 * Initializes a new instance of OSArray.
227 *
228 * @param capacity The initial storage capacity of the array object.
229 *
230 * @result
231 * <code>true</code> on success, <code>false</code> on failure.
232 *
233 * @discussion
234 * Not for general use. Use the static instance creation method
235 * <code>@link //apple_ref/cpp/clm/OSArray/withCapacity/staticOSArray*\/(unsignedint)
236 * withCapacity@/link</code>
237 * instead.
238 *
239 * <code>capacity</code> must be nonzero.
240 * The new array will grow as needed to accommodate more objects
241 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
242 * for which the initial capacity is a hard limit).
243 */
244 virtual bool initWithCapacity(unsigned int capacity);
245
246
247/*!
248 * @function initWithObjects
249 *
250 * @abstract
251 * Initializes a new OSArray populated with objects provided.
252 *
253 * @param objects A C array of OSObject-derived objects.
254 * @param count The number of objects to be placed into the array.
255 * @param capacity The initial storage capacity of the array object.
256 * If 0, <code>count</code> is used; otherwise this value
257 * must be greater than or equal to <code>count</code>.
258 *
259 * @result
260 * <code>true</code> on success, <code>false</code> on failure.
261 *
262 * @discussion
263 * Not for general use. Use the static instance creation method
264 * <code>@link
265 * //apple_ref/cpp/clm/OSArray/withObjects/staticOSArray*\/(constOSObject*,unsignedint,unsignedint)
266 * withObjects@/link</code>
267 * instead.
268 *
269 * <code>objects</code> must be non-<code>NULL</code>,
270 * and <code>count</code> must be nonzero.
271 * If <code>capacity</code> is nonzero,
272 * it must be greater than or equal to <code>count</code>.
273 * The new array will grow as needed to accommodate more objects
274 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
275 * for which the initial capacity is a hard limit).
276 */
277 virtual bool initWithObjects(
278 const OSObject * objects[],
279 unsigned int count,
280 unsigned int capacity = 0);
281
282/*!
283 * @function initWithArray
284 *
285 * @abstract
286 * Initializes a new OSArray populated with the contents of another array.
287 *
288 * @param anArray The array whose contents will be placed
289 * in the new instance.
290 * @param capacity The initial storage capacity of the array object.
291 * If 0, the capacity is set to the number of objects
292 * in <code>array</code>;
293 * otherwise <code>capacity</code> must be
294 * greater than or equal to the number of objects
295 * in <code>array</code>.
296 *
297 * @result
298 * <code>true</code> on success, <code>false</code> on failure.
299 *
300 * @discussion
301 * Not for general use. Use the static instance creation method
302 * <code>@link //apple_ref/cpp/clm/OSArray/withArray/staticOSArray*\/(constOSArray*,unsignedint)
303 * withArray@/link</code> instead.
304 *
305 * <code>array</code> must be non-<code>NULL</code>.
306 * If <code>capacity</code> is nonzero,
307 * it must be greater than or equal to <code>count</code>.
308 * The new array will grow as needed to accommodate more objects
309 * (<i>unlike</i> @link //apple_ref/doc/uid/20001502 CFMutableArray@/link,
310 * for which the initial capacity is a hard limit).
311 *
312 * The objects in <code>array</code> are retained for storage in the new OSArray,
313 * not copied.
314 */
315 virtual bool initWithArray(
316 const OSArray * anArray,
317 unsigned int capacity = 0);
318
319
320/*!
321 * @function free
322 *
323 * @abstract
324 * Deallocates or releases any resources
325 * used by the OSArray instance.
326 *
327 * @discussion
328 * This function should not be called directly;
329 * use
330 * <code>@link
331 * //apple_ref/cpp/instm/OSObject/release/virtualvoid/()
332 * release@/link</code>
333 * instead.
334 */
335 virtual void free() APPLE_KEXT_OVERRIDE;
336
337
338/*!
339 * @function getCount
340 *
341 * @abstract
342 * Returns the current number of objects within the array.
343 *
344 * @result
345 * The current number of objects within the array.
346 */
347 virtual unsigned int getCount() const APPLE_KEXT_OVERRIDE;
348
349
350/*!
351 * @function getCapacity
352 *
353 * @abstract
354 * Returns the number of objects the array can store
355 * without reallocating.
356 *
357 * @result
358 * The number objects the array can store
359 * without reallocating.
360 *
361 * @discussion
362 * OSArray objects grow when full to accommodate additional objects.
363 * See
364 * <code>@link
365 * //apple_ref/cpp/instm/OSArray/getCapacity/virtualunsignedint/()
366 * getCapacityIncrement@/link</code>
367 * and
368 * @link
369 * //apple_ref/cpp/instm/OSArray/ensureCapacity/virtualunsignedint/(unsignedint)
370 * <code>ensureCapacity</code>.@/link
371 */
372 virtual unsigned int getCapacity() const APPLE_KEXT_OVERRIDE;
373
374
375/*!
376 * @function getCapacityIncrement
377 *
378 * @abstract
379 * Returns the storage increment of the array.
380 *
381 * @result
382 * The storage increment of the array.
383 *
384 * @discussion
385 * An OSArray allocates storage for objects in multiples
386 * of the capacity increment.
387 */
388 virtual unsigned int getCapacityIncrement() const APPLE_KEXT_OVERRIDE;
389
390
391/*!
392 * @function setCapacityIncrement
393 *
394 * @abstract
395 * Sets the storage increment of the array.
396 *
397 * @result
398 * The new storage increment of the array,
399 * which may be different from the number requested.
400 *
401 * @discussion
402 * An OSArray allocates storage for objects in multiples
403 * of the capacity increment.
404 * Calling this function does not immediately reallocate storage.
405 */
406 virtual unsigned int setCapacityIncrement(unsigned increment) APPLE_KEXT_OVERRIDE;
407
408
409/*!
410 * @function ensureCapacity
411 *
412 * @abstract
413 * Ensures the array has enough space
414 * to store the requested number of objects.
415 *
416 * @param newCapacity The total number of objects the array
417 * should be able to store.
418 *
419 * @result
420 * The new capacity of the array,
421 * which may be different from the number requested
422 * (if smaller, reallocation of storage failed).
423 *
424 * @discussion
425 * This function immediately resizes the array, if necessary,
426 * to accommodate at least <code>newCapacity</code> objects.
427 * If <code>newCapacity</code> is not greater than the current capacity,
428 * or if an allocation error occurs, the original capacity is returned.
429 *
430 * There is no way to reduce the capacity of an OSArray.
431 */
432 virtual unsigned int ensureCapacity(unsigned int newCapacity) APPLE_KEXT_OVERRIDE;
433
434
435/*!
436 * @function flushCollection
437 *
438 * @abstract
439 * Removes and releases all objects within the array.
440 *
441 * @discussion
442 * The array's capacity (and therefore direct memory consumption)
443 * is not reduced by this function.
444 */
445 virtual void flushCollection() APPLE_KEXT_OVERRIDE;
446
447
448/*!
449 * @function setObject
450 *
451 * @abstract
452 * Appends an object onto the end of the array,
453 * increasing storage if necessary.
454 *
455 * @param anObject The object to add to the OSArray instance.
456 *
457 * @result
458 * <code>true</code> if the addition of <code>anObject</code> was successful,
459 * <code>false</code> if not.
460 *
461 * @discussion
462 * The array adds storage to accomodate the new object, if necessary.
463 * If successfully added, the object is retained.
464 */
465 virtual bool setObject(const OSMetaClassBase * anObject);
466
467 bool setObject(OSSharedPtr<const OSMetaClassBase> const& anObject);
468
469
470/*!
471 * @function setObject
472 *
473 * @abstract
474 * Inserts or appends an object into the array
475 * at a particular index.
476 *
477 * @param index The index in the array at which to insert the object.
478 * Must be less than or equal to the array's count.
479 * @param anObject The object to add to the array.
480 *
481 * @result
482 * <code>true</code> if the addition of <code>anObject</code>
483 * was successful, <code>false</code> if not.
484 *
485 * @discussion
486 * This function moves existing objects from <code>index</code> on,
487 * in order to accommodate the new object;
488 * it does not replace an existing object at <code>index</code>. See
489 * <code>@link
490 * //apple_ref/cpp/instm/OSArray/replaceObject/virtualvoid/(unsignedint,constOSMetaClassBase*)
491 * replaceObject@/link</code>.
492 * If successfully added, the object is retained.
493 *
494 * The array adds storage to accomodate the new object, if necessary.
495 * Note, however, that this function does not allow for arbirtrary growth
496 * of an array by specifying an index larger than the current count.
497 * If you need to immediately grow an array by an arbitrary amount,
498 * use
499 * <code>@link
500 * //apple_ref/cpp/instm/OSArray/ensureCapacity/virtualunsignedint/(unsignedint)
501 * ensureCapacity@/link</code>.
502 */
503 virtual bool setObject(
504 unsigned int index,
505 const OSMetaClassBase * anObject);
506
507 bool setObject(
508 unsigned int index,
509 OSSharedPtr<const OSMetaClassBase> const& anObject);
510
511
512/*!
513 * @function merge
514 *
515 * @abstract
516 * Appends the contents of an array onto the receiving array.
517 *
518 * @param otherArray The array whose contents will be appended
519 * to the receiving array.
520 * @result
521 * <code>true</code> if merging was successful, <code>false</code> otherwise.
522 *
523 * @discussion
524 * This function merely appends one array onto another.
525 * Duplicates are not avoided and no sorting is performed.
526 * Objects successfully added to the receiver are retained.
527 */
528 virtual bool merge(const OSArray * otherArray);
529
530
531/*!
532 * @function replaceObject
533 *
534 * @abstract
535 * Replaces an object in an array at a given index.
536 *
537 * @param index The index of the object to be replaced.
538 * Must be less than the array's count.
539 * @param anObject The object to be placed into the array.
540 *
541 * @discussion
542 * The original object is released and the new object is retained.
543 */
544 virtual void replaceObject(
545 unsigned int index,
546 const OSMetaClassBase * anObject);
547
548 void replaceObject(
549 unsigned int index,
550 OSSharedPtr<const OSMetaClassBase> const& anObject);
551
552
553/*!
554 * @function removeObject
555 *
556 * @abstract
557 * Removes an object from the array.
558 *
559 * @param index The index of the object to be removed.
560 *
561 * @discussion
562 * This function moves existing objects to fill the vacated index
563 * so that there are no gaps.
564 * The object removed is released.
565 */
566 virtual void removeObject(unsigned int index);
567
568
569/*!
570 * @function isEqualTo
571 *
572 * @abstract
573 * Tests the equality of two OSArray objects.
574 *
575 * @param anArray The array object being compared against the receiver.
576 *
577 * @result
578 * <code>true</code> if the two arrays are equivalent,
579 *<code>false</code> otherwise.
580 *
581 * @discussion
582 * Two OSArray objects are considered equal if they have same count
583 * and if the objects at corresponding indices compare as equal using
584 * <code>@link
585 * //apple_ref/cpp/instm/OSMetaClassBase/isEqualTo/virtualbool/(constOSMetaClassBase*)
586 * isEqualTo@/link</code>.
587 */
588 virtual bool isEqualTo(const OSArray * anArray) const;
589
590
591/*!
592 * @function isEqualTo
593 *
594 * @abstract
595 * Tests the equality of an OSArray to an arbitrary object.
596 *
597 * @param anObject The object to be compared against the receiver.
598 *
599 * @result
600 * <code>true</code> if the two objects are equivalent,
601 * <code>false</code> otherwise.
602 *
603 * @discussion
604 * An OSArray is considered equal to another object
605 * if that object is derived from OSArray
606 * and contains the same or equivalent objects.
607 */
608 virtual bool isEqualTo(const OSMetaClassBase * anObject) const APPLE_KEXT_OVERRIDE;
609
610
611/*!
612 * @function getObject
613 *
614 * @abstract
615 * Return the object stored at a given index.
616 *
617 * @param index The index of the object to be returned to caller.
618 *
619 * @result
620 * The object stored at <code>index</code>,
621 * or <code>NULL</code> if <code>index</code> lies past the end of the array.
622 *
623 * @discussion
624 * The returned object will be released if removed from the array;
625 * if you plan to store the reference, you should call
626 * <code>@link
627 * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/()
628 * retain@/link</code>
629 * on that object.
630 */
631 virtual OSObject * getObject(unsigned int index) const;
632
633
634/*!
635 * @function getLastObject
636 *
637 * @abstract
638 * Returns the last object in the array.
639 *
640 * @result
641 * The last object in the array,
642 * or <code>NULL</code> if the array is empty.
643 *
644 * @discussion
645 * The returned object will be released if removed from the array;
646 * if you plan to store the reference, you should call
647 * <code>@link
648 * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/()
649 * retain@/link</code>
650 * on that object.
651 */
652 virtual OSObject * getLastObject() const;
653
654
655/*!
656 * @function getNextIndexOfObject
657 *
658 * @abstract
659 * Scans the array for the next instance of a specific object
660 * at or beyond a given index.
661 *
662 * @param anObject The object to scan for.
663 * @param index The index at which to begin the scan.
664 *
665 * @result
666 * The next index of <code>anObject</code> in the array or (-1)
667 * if none is found.
668 *
669 * @discussion
670 * This function uses pointer equivalence, and does not use
671 * <code>@link
672 * //apple_ref/cpp/instm/OSMetaClassBase/isEqualTo/virtualbool/(constOSMetaClassBase*)
673 * isEqualTo@/link</code>.
674 */
675 virtual unsigned int getNextIndexOfObject(
676 const OSMetaClassBase * anObject,
677 unsigned int index) const;
678
679/*!
680 * @function serialize
681 *
682 * @abstract
683 * Archives the receiver into the provided
684 * @link //apple_ref/doc/class/OSSerialize OSSerialize@/link object.
685 *
686 * @param serializer The OSSerialize object.
687 * @result
688 * <code>true</code> if serialization succeeds, <code>false</code> if not.
689 */
690 virtual bool serialize(OSSerialize * serializer) const APPLE_KEXT_OVERRIDE;
691
692
693/*!
694 * @function setOptions
695 *
696 * @abstract
697 * Recursively sets option bits in an array
698 * and all child collections.
699 *
700 * @param options A bitfield whose values turn the options on (1) or off (0).
701 * @param mask A mask indicating which bits
702 * in <code>options</code> to change.
703 * Pass 0 to get the whole current options bitfield
704 * without changing any settings.
705 * @param context Unused.
706 *
707 * @result
708 * The options bitfield as it was before the set operation.
709 *
710 * @discussion
711 * Kernel extensions should not call this function.
712 *
713 * Child collections' options are changed only if the receiving array's
714 * options actually change.
715 */
716 virtual unsigned setOptions(
717 unsigned options,
718 unsigned mask,
719 void * context = NULL) APPLE_KEXT_OVERRIDE;
720
721
722/*!
723 * @function copyCollection
724 *
725 * @abstract
726 * Creates a deep copy of an array and its child collections.
727 *
728 * @param cycleDict A dictionary of all of the collections
729 * that have been copied so far,
730 * which is used to track circular references.
731 * To start the copy at the top level,
732 * pass <code>NULL</code>.
733 *
734 * @result
735 * The newly copied array, with a retain count of 1,
736 * or <code>NULL</code> if there is insufficient memory to do the copy.
737 *
738 * @discussion
739 * The receiving array, and any collections it contains,
740 * recursively, are copied.
741 * Objects that are not derived from OSCollection are retained
742 * rather than copied.
743 */
744 OSPtr<OSCollection> copyCollection(OSDictionary * cycleDict = NULL) APPLE_KEXT_OVERRIDE;
745
746 OSMetaClassDeclareReservedUnused(OSArray, 0);
747 OSMetaClassDeclareReservedUnused(OSArray, 1);
748 OSMetaClassDeclareReservedUnused(OSArray, 2);
749 OSMetaClassDeclareReservedUnused(OSArray, 3);
750 OSMetaClassDeclareReservedUnused(OSArray, 4);
751 OSMetaClassDeclareReservedUnused(OSArray, 5);
752 OSMetaClassDeclareReservedUnused(OSArray, 6);
753 OSMetaClassDeclareReservedUnused(OSArray, 7);
754};
755
756#endif /* !_OS_OSARRAY_H */
757