xref: /xnu-8019.80.24/libkern/libkern/c++/OSData.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2000-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 /* IOData.h created by rsulack on Wed 17-Sep-1997 */
29 /* IOData.h converted to C++ by gvdl on Fri 1998-10-30 */
30 
31 #ifndef _OS_OSDATA_H
32 #define _OS_OSDATA_H
33 
34 #include <libkern/c++/OSObject.h>
35 #include <libkern/c++/OSPtr.h>
36 #include <os/base.h>
37 
38 class OSData;
39 class OSString;
40 
41 typedef OSData* OSDataPtr;
42 typedef OSData const* OSDataConstPtr;
43 
44 /*!
45  * @header
46  *
47  * @abstract
48  * This header declares the OSData container class.
49  */
50 
51 
52 /*!
53  * @class OSData
54  *
55  * @abstract
56  * OSData wraps an array of bytes in a C++ object
57  * for use in Libkern collections.
58  *
59  * @discussion
60  * OSData represents an array of bytes as a Libkern C++ object.
61  * OSData objects are mutable:
62  * You can add bytes to them and
63  * overwrite portions of the byte array.
64  *
65  * <b>Use Restrictions</b>
66  *
67  * With very few exceptions in the I/O Kit, all Libkern-based C++
68  * classes, functions, and macros are <b>unsafe</b>
69  * to use in a primary interrupt context.
70  * Consult the I/O Kit documentation related to primary interrupts
71  * for more information.
72  *
73  * OSData provides no concurrency protection;
74  * it's up to the usage context to provide any protection necessary.
75  * Some portions of the I/O Kit, such as
76  * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link,
77  * handle synchronization via defined member functions for setting
78  * properties.
79  */
80 class OSData : public OSObject
81 {
82 	friend class OSSerialize;
83 
84 	OSDeclareDefaultStructors(OSData);
85 
86 #if APPLE_KEXT_ALIGN_CONTAINERS
87 
88 protected:
89 	unsigned int   length;
90 	unsigned int   capacity;
91 	unsigned int   capacityIncrement;
92 	void         * OS_PTRAUTH_SIGNED_PTR("OSData.data") data;
93 
94 #else /* APPLE_KEXT_ALIGN_CONTAINERS */
95 
96 protected:
97 	void         * OS_PTRAUTH_SIGNED_PTR("OSData.data") data;
98 	unsigned int   length;
99 	unsigned int   capacity;
100 	unsigned int   capacityIncrement;
101 
102 #endif /* APPLE_KEXT_ALIGN_CONTAINERS */
103 
104 #ifdef XNU_KERNEL_PRIVATE
105 /* Available within xnu source only */
106 public:
107 	typedef void (*DeallocFunction)(void * ptr, unsigned int length);
108 protected:
109 	struct ExpansionData {
110 		DeallocFunction deallocFunction;
111 		bool            disableSerialization;
112 	};
113 #else /* XNU_KERNEL_PRIVATE */
114 private:
115 	typedef void (*DeallocFunction)(void * ptr, unsigned int length);
116 protected:
117 	struct ExpansionData;
118 #endif /* XNU_KERNEL_PRIVATE */
119 
120 /* Reserved for future use. (Internal use only)  */
121 	ExpansionData * reserved;
122 
123 public:
124 
125 /*!
126  * @function withCapacity
127  *
128  * @abstract
129  * Creates and initializes an empty instance of OSData.
130  *
131  * @param capacity  The initial capacity of the OSData object in bytes.
132  *
133  * @result
134  * An instance of OSData with a reference count of 1;
135  * <code>NULL</code> on failure.
136  *
137  * @discussion
138  * <code>capacity</code> may be zero.
139  * The OSData object will allocate a buffer internally
140  * when necessary, and will grow as needed to accommodate more bytes
141  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
142  * for which a nonzero initial capacity is a hard limit).
143  */
144 	static OSPtr<OSData> withCapacity(unsigned int capacity);
145 
146 
147 /*!
148  * @function withBytes
149  *
150  * @abstract
151  * Creates and initializes an instance of OSData
152  * with a copy of the provided data buffer.
153  *
154  * @param bytes     The buffer of data to copy.
155  * @param numBytes  The length of <code>bytes</code>.
156  *
157  * @result
158  * An instance of OSData containing a copy of the provided byte array,
159  * with a reference count of 1;
160  * <code>NULL</code> on failure.
161  *
162  * @discussion
163  * The new OSData object will grow as needed to accommodate more bytes
164  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
165  * for which a nonzero initial capacity is a hard limit).
166  */
167 	static OSPtr<OSData> withBytes(
168 		const void   * bytes,
169 		unsigned int   numBytes);
170 
171 
172 /*!
173  * @function withBytesNoCopy
174  *
175  * @abstract
176  * Creates and initializes an instance of OSData
177  * that shares the provided data buffer.
178  *
179  * @param bytes     The buffer of data to represent.
180  * @param numBytes  The length of <code>bytes</code>.
181  *
182  * @result
183  * A instance of OSData that shares the provided byte array,
184  * with a reference count of 1;
185  * <code>NULL</code> on failure.
186  *
187  * @discussion
188  * An OSData object created with this function
189  * does not claim ownership
190  * of the data buffer, but shares it with the caller.
191  * When the caller determines that the OSData object has actually been freed,
192  * it can safely dispose of the data buffer.
193  * Conversely, if it frees the shared data buffer,
194  * it must not attempt to use the OSData object and should release it.
195  *
196  * An OSData object created with shared external data cannot append bytes,
197  * but you can get the byte pointer and
198  * modify bytes within the shared buffer.
199  */
200 	static OSPtr<OSData> withBytesNoCopy(
201 		void         * bytes,
202 		unsigned int   numBytes);
203 
204 
205 /*!
206  * @function withData
207  *
208  * @abstract
209  * Creates and initializes an instance of OSData
210  * with contents copied from another OSData object.
211  *
212  * @param inData An OSData object that provides the initial data.
213  *
214  * @result
215  * An instance of OSData containing a copy of the data in <code>inData</code>,
216  * with a reference count of 1;
217  * <code>NULL</code> on failure.
218  *
219  * @discussion
220  * The new OSData object will grow as needed to accommodate more bytes
221  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
222  * for which a nonzero initial capacity is a hard limit).
223  */
224 	static OSPtr<OSData> withData(const OSData * inData);
225 
226 
227 /*!
228  * @function withData
229  *
230  * @abstract
231  * Creates and initializes an instance of OSData
232  * with contents copied from a range within another OSData object.
233  *
234  * @param inData    An OSData object that provides the initial data.
235  * @param start     The starting index from which bytes will be copied.
236  * @param numBytes  The number of bytes to be copied from <code>start</code>.
237  *
238  * @result
239  * An instance of OSData containing a copy
240  * of the specified data range from <code>inData</code>,
241  * with a reference count of 1;
242  * <code>NULL</code> on failure.
243  *
244  * @discussion
245  * The new OSData object will grow as needed to accommodate more bytes
246  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
247  * for which a nonzero initial capacity is a hard limit).
248  */
249 	static OSPtr<OSData> withData(
250 		const OSData * inData,
251 		unsigned int   start,
252 		unsigned int   numBytes);
253 
254 
255 /*!
256  * @function initWithCapacity
257  *
258  * @abstract
259  * Initializes an instance of OSData.
260  *
261  * @param capacity The initial capacity of the OSData object in bytes.
262  *
263  * @result
264  * <code>true</code> on success, <code>false</code> on failure.
265  *
266  * @discussion
267  * Not for general use. Use the static instance creation method
268  * <code>@link
269  * //apple_ref/cpp/clm/OSData/withCapacity/staticOSData*\/(unsignedint)
270  * withCapacity@/link</code> instead.
271  *
272  * <code>capacity</code> may be zero.
273  * The OSData object will allocate a buffer internally
274  * when necessary, and will grow as needed to accommodate more bytes
275  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
276  * for which a nonzero initial capacity is a hard limit).
277  */
278 	virtual bool initWithCapacity(unsigned int capacity);
279 
280 
281 /*!
282  * @function initWithBytes
283  *
284  * @abstract
285  * Initializes an instance of OSData
286  * with a copy of the provided data buffer.
287  *
288  * @param bytes     The buffer of data to copy.
289  * @param numBytes  The length of <code>bytes</code>.
290  *
291  * @result
292  * <code>true</code> on success, <code>false</code> on failure.
293  *
294  * @discussion
295  * Not for general use. Use the static instance creation method
296  * <code>@link withBytes withBytes@/link</code> instead.
297  *
298  * The new OSData object will grow as needed to accommodate more bytes
299  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
300  * for which a nonzero initial capacity is a hard limit).
301  */
302 	virtual bool initWithBytes(
303 		const void   * bytes,
304 		unsigned int   numBytes);
305 
306 
307 /*!
308  * @function initWithBytesNoCopy
309  *
310  * @abstract
311  * Initializes an instance of OSData
312  * to share the provided data buffer.
313  *
314  * @param bytes     The buffer of data to represent.
315  * @param numBytes  The length of <code>bytes</code>.
316  *
317  * @result
318  * <code>true</code> on success, <code>false</code> on failure.
319  *
320  * @discussion
321  * Not for general use. Use the static instance creation method
322  * <code>@link withBytesNoCopy withBytesNoCopy@/link</code> instead.
323  *
324  * An OSData object initialized with this function
325  * does not claim ownership
326  * of the data buffer, but merely shares it with the caller.
327  *
328  * An OSData object created with shared external data cannot append bytes,
329  * but you can get the byte pointer and
330  * modify bytes within the shared buffer.
331  */
332 	virtual bool initWithBytesNoCopy(
333 		void         * bytes,
334 		unsigned int   numBytes);
335 
336 
337 /*!
338  * @function initWithData
339  *
340  * @abstract
341  * Creates and initializes an instance of OSData
342  * with contents copied from another OSData object.
343  *
344  * @param inData An OSData object that provides the initial data.
345  *
346  * @result
347  * <code>true</code> on success, <code>false</code> on failure.
348  *
349  * @discussion
350  * Not for general use. Use the static instance creation method
351  * <code>@link
352  * //apple_ref/cpp/clm/OSData/withData/staticOSData*\/(constOSData*)
353  * withData(OSData *)@/link</code>
354  * instead.
355  *
356  * The new OSData object will grow as needed to accommodate more bytes
357  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
358  * for which a nonzero initial capacity is a hard limit).
359  */
360 	virtual bool initWithData(const OSData * inData);
361 
362 
363 /*!
364  * @function initWithData
365  *
366  * @abstract
367  * Initializes an instance of OSData
368  * with contents copied from a range within another OSData object.
369  *
370  * @param inData    An OSData object that provides the initial data.
371  * @param start     The starting index from which bytes will be copied.
372  * @param numBytes  The number of bytes to be copied from <code>start</code>.
373  *
374  * @result
375  * Returns <code>true</code> on success, <code>false</code> on failure.
376  *
377  * @discussion
378  * Not for general use. Use the static instance creation method
379  * <code>@link
380  * //apple_ref/cpp/clm/OSData/withData/staticOSData*\/(constOSData*,unsignedint,unsignedint)
381  * withData(OSData *, unsigned int, unsigned int)@/link</code>
382  * instead.
383  *
384  * The new OSData object will grow as needed to accommodate more bytes
385  * (<i>unlike</i> @link //apple_ref/doc/uid/20001498 CFMutableData@/link,
386  * for which a nonzero initial capacity is a hard limit).
387  */
388 	virtual bool initWithData(
389 		const OSData * inData,
390 		unsigned int   start,
391 		unsigned int   numBytes);
392 
393 
394 /*!
395  * @function free
396  *
397  * @abstract
398  * Deallocates or releases any resources
399  * used by the OSData instance.
400  *
401  * @discussion
402  * This function should not be called directly;
403  * use
404  * <code>@link
405  * //apple_ref/cpp/instm/OSObject/release/virtualvoid/()
406  * release@/link</code>
407  * instead.
408  */
409 	virtual void free() APPLE_KEXT_OVERRIDE;
410 
411 
412 /*!
413  * @function getLength
414  *
415  * @abstract
416  * Returns the number of bytes in or referenced by the OSData object.
417  *
418  * @result
419  * The number of bytes in or referenced by the OSData object.
420  */
421 	virtual unsigned int getLength() const;
422 
423 
424 /*!
425  * @function getCapacity
426  *
427  * @abstract
428  * Returns the total number of bytes the OSData can store without reallocating.
429  *
430  * @result
431  * The total number bytes the OSData can store without reallocating.
432  *
433  * @discussion
434  * OSData objects grow when full to accommodate additional bytes.
435  * See
436  * <code>@link
437  * //apple_ref/cpp/instm/OSData/getCapacityIncrement/virtualunsignedint/()
438  * getCapacityIncrement@/link</code>
439  * and
440  * <code>@link
441  * //apple_ref/cpp/instm/OSData/ensureCapacity/virtualunsignedint/(unsignedint)
442  * ensureCapacity@/link</code>.
443  *
444  * OSData objects created or initialized to use a shared buffer
445  * do not make use of this attribute, and return -1 from this function.
446  */
447 	virtual unsigned int getCapacity() const;
448 
449 
450 /*!
451  * @function getCapacityIncrement
452  *
453  * @abstract
454  * Returns the storage increment of the OSData object.
455  *
456  * @result
457  * The storage increment of the OSData object.
458  *
459  * @discussion
460  * An OSData object allocates storage for bytes in multiples
461  * of the capacity increment.
462  *
463  * OSData objects created or initialized to use a shared buffer
464  * do not make use of this attribute.
465  */
466 	virtual unsigned int getCapacityIncrement() const;
467 
468 
469 /*!
470  * @function setCapacityIncrement
471  *
472  * @abstract
473  * Sets the storage increment of the array.
474  *
475  * @result
476  * The original storage increment of the array.
477  *
478  * @discussion
479  * An OSArray allocates storage for objects in multiples
480  * of the capacity increment.
481  *
482  * OSData objects created or initialized to use a shared buffer
483  * do not make use of this attribute.
484  */
485 	virtual unsigned int setCapacityIncrement(unsigned increment);
486 
487 
488 // xx-review: does not check for capacity == EXTERNAL
489 
490 /*!
491  * @function ensureCapacity
492  *
493  * @abstract
494  * Ensures the array has enough space
495  * to store the requested number of bytes.
496  *
497  * @param newCapacity The total number of bytes the OSData object
498  *                    should be able to store.
499  *
500  * @result
501  * Returns the new capacity of the OSData object,
502  * which may be different from the number requested
503  * (if smaller, reallocation of storage failed).
504  *
505  * @discussion
506  * This function immediately resizes the OSData's buffer, if necessary,
507  * to accommodate at least <code>newCapacity</code> bytes.
508  * If <code>newCapacity</code> is not greater than the current capacity,
509  * or if an allocation error occurs, the original capacity is returned.
510  *
511  * There is no way to reduce the capacity of an OSData.
512  *
513  * An OSData object created "NoCopy" does not allow resizing.
514  */
515 	virtual unsigned int ensureCapacity(unsigned int newCapacity);
516 
517 
518 /*!
519  * @function appendBytes
520  *
521  * @abstract
522  * Appends a buffer of bytes to the OSData object's internal data buffer.
523  *
524  * @param bytes     A pointer to the data to append.
525  *                  If <code>bytes</code> is <code>NULL</code>
526  *                  then a zero-filled buffer of length <code>numBytes</code>
527  *                  is appended.
528  * @param numBytes  The number of bytes from <code>bytes</code> to append.
529  *
530  * @result
531  * <code>true</code> if the new data was successfully added,
532  * <code>false</code> on failure.
533  *
534  * @discussion
535  * This function immediately resizes the OSData's buffer, if necessary,
536  * to accommodate the new total size.
537  *
538  * An OSData object created "NoCopy" does not allow bytes
539  * to be appended.
540  */
541 	virtual bool appendBytes(
542 		const void   * bytes,
543 		unsigned int   numBytes);
544 
545 
546 /*!
547  * @function appendBytes
548  *
549  * @abstract
550  * Appends the data contained in another OSData object.
551  *
552  * @param aDataObj  The OSData object whose contents will be appended.
553  *
554  * @result
555  * <code>true</code> if the new data was successfully added,
556  * <code>false</code> on failure.
557  *
558  * @discussion
559  * This function immediately resizes the OSData's buffer, if necessary,
560  * to accommodate the new total size.
561  *
562  * An OSData object created "NoCopy" does not allow bytes
563  * to be appended.
564  */
565 	virtual bool appendBytes(const OSData * aDataObj);
566 
567 
568 /*!
569  * @function getBytesNoCopy
570  *
571  * @abstract
572  * Returns a pointer to the OSData object's internal data buffer.
573  *
574  * @result
575  * A pointer to the OSData object's internal data buffer.
576  *
577  * @discussion
578  * You can modify the existing contents of an OSData object
579  * via this function.
580  * It works with OSData objects that have their own data buffers
581  * as well as with OSData objects that have shared buffers.
582  *
583  * If you append bytes or characters to an OSData object,
584  * it may have to reallocate its internal storage,
585  * rendering invalid an extrated pointer to that storage.
586  */
587 	virtual const void * getBytesNoCopy() const;
588 
589 
590 /*!
591  * @function getBytesNoCopy
592  *
593  * @abstract
594  * Returns a pointer into the OSData object's internal data buffer
595  * with a given offset and length.
596  *
597  * @param start    The offset from the base of the internal data buffer.
598  * @param numBytes The length of the  window.
599  *
600  * @result
601  * A pointer to the bytes in the specified range
602  * within the OSData object,
603  * or 0 if that range does not lie completely
604  * within the object's buffer.
605  *
606  * @discussion
607  * You can modify the existing contents of an OSData object
608  * via this function.
609  * It works with OSData objects that have their own data buffers
610  * as well as with OSData objects that have shared buffers.
611  *
612  * If you append bytes or characters to an OSData object,
613  * it may have to reallocate its internal storage,
614  * rendering invalid an extrated pointer to that storage.
615  */
616 	virtual const void * getBytesNoCopy(
617 		unsigned int start,
618 		unsigned int numBytes) const;
619 
620 
621 /*!
622  * @function isEqualTo
623  *
624  * @abstract
625  * Tests the equality of two OSData objects.
626  *
627  * @param aDataObj The OSData object being compared against the receiver.
628  *
629  * @result
630  * <code>true</code> if the two OSData objects are equivalent,
631  * <code>false</code> otherwise.
632  *
633  * @discussion
634  * Two OSData objects are considered equal
635  * if they have same length and if their
636  * byte buffers hold the same contents.
637  */
638 	virtual bool isEqualTo(const OSData * aDataObj) const;
639 
640 
641 /*!
642  * @function isEqualTo
643  *
644  * @abstract
645  * Tests the equality of an OSData object's contents
646  * to a C array of bytes.
647  *
648  * @param bytes    A pointer to the bytes to compare.
649  * @param numBytes The number of bytes to compare.
650  *
651  * @result
652  * <code>true</code> if the data buffers are equal
653  * over the given length,
654  * <code>false</code> otherwise.
655  */
656 	virtual bool isEqualTo(
657 		const void   * bytes,
658 		unsigned int   numBytes) const;
659 
660 
661 /*!
662  * @function isEqualTo
663  *
664  * @abstract
665  * Tests the equality of an OSData object to an arbitrary object.
666  *
667  * @param anObject The object to be compared against the receiver.
668  *
669  * @result
670  * <code>true</code> if the two objects are equivalent,
671  * <code>false</code> otherwise.
672  *
673  * @discussion
674  * An OSData is considered equal to another object
675  * if that object is derived from OSData
676  * and contains the equivalent bytes of the same length.
677  */
678 	virtual bool isEqualTo(const OSMetaClassBase * anObject) const APPLE_KEXT_OVERRIDE;
679 
680 
681 /*!
682  * @function isEqualTo
683  *
684  * @abstract
685  * Tests the equality of an OSData object to an OSString.
686  *
687  * @param aString  The string object to be compared against the receiver.
688  *
689  * @result
690  * <code>true</code> if the two objects are equivalent,
691  * <code>false</code> otherwise.
692  *
693  * @discussion
694  * This function compares the bytes of the OSData object
695  * against those of the OSString,
696  * accounting for the possibility that an OSData
697  * might explicitly include a nul
698  * character as part of its total length.
699  * Thus, for example, an OSData object containing
700  * either the bytes <'u', 's', 'b', '\0'>
701  * or  <'u', 's', 'b'>
702  * will compare as equal to the OSString containing "usb".
703  */
704 	virtual bool isEqualTo(const OSString * aString) const;
705 
706 
707 /*!
708  * @function serialize
709  *
710  * @abstract
711  * Archives the receiver into the provided
712  * @link //apple_ref/doc/class/IORegistryEntry OSSerialize@/link object.
713  *
714  * @param serializer The OSSerialize object.
715  *
716  * @result
717  * <code>true</code> if serialization succeeds, <code>false</code> if not.
718  */
719 	virtual bool serialize(OSSerialize * serializer) const APPLE_KEXT_OVERRIDE;
720 
721 
722 /*!
723  * @function appendByte
724  *
725  * @abstract
726  * Appends a single byte value
727  * to the OSData object's internal data buffer
728  * a specified number of times.
729  *
730  * @param byte     The byte value to append.
731  * @param numBytes The number of copies of <code>byte</code> to append.
732  *
733  * @result
734  * <code>true</code> if the new data was successfully added,
735  * <code>false</code> if not.
736  *
737  * @discussion
738  * This function immediately resizes the OSData's buffer, if necessary,
739  * to accommodate the new total size.
740  *
741  * An OSData object created "NoCopy" does not allow bytes
742  * to be appended.
743  */
744 	virtual bool appendByte(
745 		unsigned char byte,
746 		unsigned int  numBytes);
747 
748 
749 	void setSerializable(bool serializable);
750 
751 #ifdef XNU_KERNEL_PRIVATE
752 /* Available within xnu source only */
753 public:
754 #else
755 private:
756 #endif
757 	virtual void setDeallocFunction(DeallocFunction func);
758 	bool isSerializable(void);
759 
760 private:
761 	OSMetaClassDeclareReservedUsedX86(OSData, 0);
762 	OSMetaClassDeclareReservedUnused(OSData, 1);
763 	OSMetaClassDeclareReservedUnused(OSData, 2);
764 	OSMetaClassDeclareReservedUnused(OSData, 3);
765 	OSMetaClassDeclareReservedUnused(OSData, 4);
766 	OSMetaClassDeclareReservedUnused(OSData, 5);
767 	OSMetaClassDeclareReservedUnused(OSData, 6);
768 	OSMetaClassDeclareReservedUnused(OSData, 7);
769 };
770 
771 #endif /* !_OS_OSDATA_H */
772