diff --git a/Headers/mach/_types.h b/Headers/mach/_types.h new file mode 100755 index 0000000..6d01ffe --- /dev/null +++ b/Headers/mach/_types.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2000-2007 Apple Inc. All rights reserved. + */ + +#ifndef _BSD_ARM__TYPES_H_ +#define _BSD_ARM__TYPES_H_ + +/* + * This header file contains integer types. It's intended to also contain + * flotaing point and other arithmetic types, as needed, later. + */ + +#ifdef __GNUC__ +typedef __signed char __int8_t; +#else /* !__GNUC__ */ +typedef char __int8_t; +#endif /* !__GNUC__ */ +typedef unsigned char __uint8_t; +typedef short __int16_t; +typedef unsigned short __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +typedef long long __int64_t; +typedef unsigned long long __uint64_t; + +typedef long __darwin_intptr_t; +typedef unsigned int __darwin_natural_t; + +/* + * The rune type below is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use __darwin_ct_rune_t instead of int. By changing it + * here, you lose a bit of ANSI conformance, but your programs will still + * work. + * + * NOTE: rune_t is not covered by ANSI nor other standards, and should not + * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and + * rune_t must be the same type. Also wint_t must be no narrower than + * wchar_t, and should also be able to hold all members of the largest + * character set plus one extra value (WEOF). wint_t must be at least 16 bits. + */ + +typedef int __darwin_ct_rune_t; /* ct_rune_t */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + char __mbstate8[128]; + long long _mbstateL; /* for alignment */ +} __mbstate_t; + +typedef __mbstate_t __darwin_mbstate_t; /* mbstate_t */ + +#if defined(__GNUC__) && defined(__PTRDIFF_TYPE__) +typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ +#else +typedef int __darwin_ptrdiff_t; /* ptr1 - ptr2 */ +#endif /* __GNUC__ */ + +#if defined(__GNUC__) && defined(__SIZE_TYPE__) +typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ +#else +typedef unsigned long __darwin_size_t; /* sizeof() */ +#endif + +#if (__GNUC__ > 2) +typedef __builtin_va_list __darwin_va_list; /* va_list */ +#else +typedef void * __darwin_va_list; /* va_list */ +#endif + +#if defined(__GNUC__) && defined(__WCHAR_TYPE__) +typedef __WCHAR_TYPE__ __darwin_wchar_t; /* wchar_t */ +#else +typedef __darwin_ct_rune_t __darwin_wchar_t; /* wchar_t */ +#endif + +typedef __darwin_wchar_t __darwin_rune_t; /* rune_t */ + +#if defined(__GNUC__) && defined(__WINT_TYPE__) +typedef __WINT_TYPE__ __darwin_wint_t; /* wint_t */ +#else +typedef __darwin_ct_rune_t __darwin_wint_t; /* wint_t */ +#endif + +typedef unsigned long __darwin_clock_t; /* clock() */ +typedef __uint32_t __darwin_socklen_t; /* socklen_t (duh) */ +typedef long __darwin_ssize_t; /* byte count or error */ +typedef long __darwin_time_t; /* time() */ + +#endif /* _BSD_ARM__TYPES_H_ */ diff --git a/Headers/mach/mach_types.h b/Headers/mach/mach_types.h new file mode 100755 index 0000000..8bcfedd --- /dev/null +++ b/Headers/mach/mach_types.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2000-2008 Apple Inc. All rights reserved. + */ +/* + * Copyright 1995 NeXT Computer, Inc. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.3 (Berkeley) 1/5/94 + */ + +#ifndef _MACHTYPES_H_ +#define _MACHTYPES_H_ + +#ifndef __ASSEMBLER__ +#include "_types.h" + +typedef unsigned kern_return_t; +typedef unsigned kmod_info_t; +typedef unsigned kmod_start_func_t; +typedef unsigned kmod_stop_func_t; +#define KMOD_EXPLICIT_DECL(a, b, c, d) + +/* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ +#ifndef _INT8_T +#define _INT8_T +typedef __signed char int8_t; +#endif +typedef unsigned char u_int8_t; +#ifndef _INT16_T +#define _INT16_T +typedef short int16_t; +#endif +typedef unsigned short u_int16_t; +#ifndef _INT32_T +#define _INT32_T +typedef int int32_t; +#endif +typedef unsigned int u_int32_t; +#ifndef _INT64_T +#define _INT64_T +typedef long long int64_t; +#endif +typedef unsigned long long u_int64_t; + +typedef int32_t register_t; + +#ifndef _INTPTR_T +#define _INTPTR_T +typedef __darwin_intptr_t intptr_t; +#endif +#ifndef _UINTPTR_T +#define _UINTPTR_T +typedef unsigned long uintptr_t; +#endif + +#if !defined(_ANSI_SOURCE) && (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)) +/* These types are used for reserving the largest possible size. */ +typedef u_int32_t user_addr_t; +typedef u_int32_t user_size_t; +typedef int32_t user_ssize_t; +typedef int32_t user_long_t; +typedef u_int32_t user_ulong_t; +typedef int32_t user_time_t; +typedef int64_t user_off_t; +#define USER_ADDR_NULL ((user_addr_t) 0) +#define CAST_USER_ADDR_T(a_ptr) ((user_addr_t)((uintptr_t)(a_ptr))) + + +#endif /* !_ANSI_SOURCE && (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ + +/* This defines the size of syscall arguments after copying into the kernel: */ +typedef u_int32_t syscall_arg_t; + +#ifndef __offsetof +#define __offsetof(type, field) ((size_t)(&((type *)0)->field)) +#endif + +#endif /* __ASSEMBLER__ */ +#endif /* _MACHTYPES_H_ */ diff --git a/Libkern.xcodeproj/project.pbxproj b/Libkern.xcodeproj/project.pbxproj new file mode 100755 index 0000000..66b90d7 --- /dev/null +++ b/Libkern.xcodeproj/project.pbxproj @@ -0,0 +1,357 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 149A99CD15C99EF1009A8583 /* OSSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99CC15C99EF1009A8583 /* OSSymbol.cpp */; }; + 149A99D015C9A55A009A8583 /* OSDictionary.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99CF15C9A55A009A8583 /* OSDictionary.cpp */; }; + 149A99D215C9A86B009A8583 /* OSCollectionIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99D115C9A86B009A8583 /* OSCollectionIterator.cpp */; }; + 149A99D415C9A89E009A8583 /* OSIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99D315C9A89D009A8583 /* OSIterator.cpp */; }; + 149A99D615C9CAF1009A8583 /* OSSerialize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99D515C9CAF0009A8583 /* OSSerialize.cpp */; }; + 149A99DA15C9CB23009A8583 /* OSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99D915C9CB23009A8583 /* OSSet.cpp */; }; + 149A99DD15C9CB61009A8583 /* OSOrderedSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 149A99DC15C9CB61009A8583 /* OSOrderedSet.cpp */; }; + 14F2F86B15C81B8700507B94 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F86915C81B8700507B94 /* main.cpp */; }; + 14F2F87115C8235C00507B94 /* OSMetaClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F87015C8235C00507B94 /* OSMetaClass.cpp */; }; + 14F2F87A15C8326A00507B94 /* OSArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F87915C8326A00507B94 /* OSArray.cpp */; }; + 14F2F87C15C8368800507B94 /* OSCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F87B15C8368800507B94 /* OSCollection.cpp */; }; + 14F2F87E15C8373E00507B94 /* OSObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F87D15C8373E00507B94 /* OSObject.cpp */; }; + 14F2F88A15C845B100507B94 /* OSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F2F88915C845B100507B94 /* OSString.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 011AD384155811E000C2DCF5 /* Passenger */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.objfile"; includeInIndex = 0; path = Passenger; sourceTree = BUILT_PRODUCTS_DIR; }; + 01D092361562C0DA00398AB3 /* _types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = _types.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 01D092371562C0DA00398AB3 /* mach_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_types.h; sourceTree = ""; }; + 149A99CB15C99EC2009A8583 /* OSSymbol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSSymbol.h; sourceTree = ""; }; + 149A99CC15C99EF1009A8583 /* OSSymbol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSSymbol.cpp; sourceTree = ""; }; + 149A99CE15C9A528009A8583 /* OSDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSDictionary.h; sourceTree = ""; }; + 149A99CF15C9A55A009A8583 /* OSDictionary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSDictionary.cpp; sourceTree = ""; }; + 149A99D115C9A86B009A8583 /* OSCollectionIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSCollectionIterator.cpp; sourceTree = ""; }; + 149A99D315C9A89D009A8583 /* OSIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSIterator.cpp; sourceTree = ""; }; + 149A99D515C9CAF0009A8583 /* OSSerialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSSerialize.cpp; sourceTree = ""; }; + 149A99D715C9CB03009A8583 /* OSSerialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSSerialize.h; sourceTree = ""; }; + 149A99D815C9CB16009A8583 /* OSSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSSet.h; sourceTree = ""; }; + 149A99D915C9CB23009A8583 /* OSSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSSet.cpp; sourceTree = ""; }; + 149A99DB15C9CB4C009A8583 /* OSOrderedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSOrderedSet.h; sourceTree = ""; }; + 149A99DC15C9CB61009A8583 /* OSOrderedSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSOrderedSet.cpp; sourceTree = ""; }; + 14F2F86915C81B8700507B94 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; + 14F2F86A15C81B8700507B94 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = ""; }; + 14F2F86C15C81BB900507B94 /* runtime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = runtime.h; sourceTree = ""; }; + 14F2F86E15C81E2C00507B94 /* OSMetaClass.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSMetaClass.h; sourceTree = ""; }; + 14F2F86F15C8208D00507B94 /* OSReturn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSReturn.h; sourceTree = ""; }; + 14F2F87015C8235C00507B94 /* OSMetaClass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSMetaClass.cpp; sourceTree = ""; }; + 14F2F87315C8257300507B94 /* OSString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSString.h; sourceTree = ""; }; + 14F2F87415C8268700507B94 /* OSObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSObject.h; sourceTree = ""; }; + 14F2F87515C82E2C00507B94 /* OSArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OSArray.h; sourceTree = ""; }; + 14F2F87615C82E7900507B94 /* OSCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCollection.h; sourceTree = ""; }; + 14F2F87715C82E7900507B94 /* OSCollectionIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCollectionIterator.h; sourceTree = ""; }; + 14F2F87815C82E8300507B94 /* OSIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSIterator.h; sourceTree = ""; }; + 14F2F87915C8326A00507B94 /* OSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSArray.cpp; sourceTree = ""; }; + 14F2F87B15C8368800507B94 /* OSCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSCollection.cpp; sourceTree = ""; }; + 14F2F87D15C8373E00507B94 /* OSObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSObject.cpp; sourceTree = ""; }; + 14F2F88915C845B100507B94 /* OSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSString.cpp; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 011AD381155811E000C2DCF5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 011AD379155811E000C2DCF5 = { + isa = PBXGroup; + children = ( + 01D092341562C0DA00398AB3 /* Headers */, + 14F2F86815C81B5A00507B94 /* Sources */, + 011AD387155811E000C2DCF5 /* Frameworks */, + 011AD385155811E000C2DCF5 /* Products */, + ); + sourceTree = ""; + }; + 011AD385155811E000C2DCF5 /* Products */ = { + isa = PBXGroup; + children = ( + 011AD384155811E000C2DCF5 /* Passenger */, + ); + name = Products; + sourceTree = ""; + }; + 011AD387155811E000C2DCF5 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; + 01D092341562C0DA00398AB3 /* Headers */ = { + isa = PBXGroup; + children = ( + 01D092351562C0DA00398AB3 /* mach */, + ); + path = Headers; + sourceTree = ""; + }; + 01D092351562C0DA00398AB3 /* mach */ = { + isa = PBXGroup; + children = ( + 01D092361562C0DA00398AB3 /* _types.h */, + 01D092371562C0DA00398AB3 /* mach_types.h */, + ); + path = mach; + sourceTree = ""; + }; + 14F2F86815C81B5A00507B94 /* Sources */ = { + isa = PBXGroup; + children = ( + 14F2F86D15C81E1F00507B94 /* c++ */, + 14F2F86915C81B8700507B94 /* main.cpp */, + 14F2F86A15C81B8700507B94 /* main.h */, + 14F2F86C15C81BB900507B94 /* runtime.h */, + ); + name = Sources; + sourceTree = ""; + }; + 14F2F86D15C81E1F00507B94 /* c++ */ = { + isa = PBXGroup; + children = ( + 149A99DC15C9CB61009A8583 /* OSOrderedSet.cpp */, + 149A99DB15C9CB4C009A8583 /* OSOrderedSet.h */, + 149A99D915C9CB23009A8583 /* OSSet.cpp */, + 149A99D815C9CB16009A8583 /* OSSet.h */, + 149A99D715C9CB03009A8583 /* OSSerialize.h */, + 149A99D515C9CAF0009A8583 /* OSSerialize.cpp */, + 149A99D315C9A89D009A8583 /* OSIterator.cpp */, + 149A99D115C9A86B009A8583 /* OSCollectionIterator.cpp */, + 149A99CF15C9A55A009A8583 /* OSDictionary.cpp */, + 149A99CE15C9A528009A8583 /* OSDictionary.h */, + 149A99CC15C99EF1009A8583 /* OSSymbol.cpp */, + 149A99CB15C99EC2009A8583 /* OSSymbol.h */, + 14F2F87B15C8368800507B94 /* OSCollection.cpp */, + 14F2F87915C8326A00507B94 /* OSArray.cpp */, + 14F2F87D15C8373E00507B94 /* OSObject.cpp */, + 14F2F87815C82E8300507B94 /* OSIterator.h */, + 14F2F87615C82E7900507B94 /* OSCollection.h */, + 14F2F87715C82E7900507B94 /* OSCollectionIterator.h */, + 14F2F86E15C81E2C00507B94 /* OSMetaClass.h */, + 14F2F86F15C8208D00507B94 /* OSReturn.h */, + 14F2F87015C8235C00507B94 /* OSMetaClass.cpp */, + 14F2F87315C8257300507B94 /* OSString.h */, + 14F2F87415C8268700507B94 /* OSObject.h */, + 14F2F87515C82E2C00507B94 /* OSArray.h */, + 14F2F88915C845B100507B94 /* OSString.cpp */, + ); + name = "c++"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 011AD383155811E000C2DCF5 /* Libkern */ = { + isa = PBXNativeTarget; + buildConfigurationList = 011AD38F155811E000C2DCF5 /* Build configuration list for PBXNativeTarget "Libkern" */; + buildPhases = ( + 011AD380155811E000C2DCF5 /* Sources */, + 011AD381155811E000C2DCF5 /* Frameworks */, + 011AD382155811E000C2DCF5 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Libkern; + productName = helloWorld; + productReference = 011AD384155811E000C2DCF5 /* Passenger */; + productType = "com.apple.product-type.objfile"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 011AD37B155811E000C2DCF5 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; + buildConfigurationList = 011AD37E155811E000C2DCF5 /* Build configuration list for PBXProject "Libkern" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 011AD379155811E000C2DCF5; + productRefGroup = 011AD385155811E000C2DCF5 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 011AD383155811E000C2DCF5 /* Libkern */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 011AD382155811E000C2DCF5 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = ""; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 011AD380155811E000C2DCF5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 14F2F86B15C81B8700507B94 /* main.cpp in Sources */, + 14F2F87115C8235C00507B94 /* OSMetaClass.cpp in Sources */, + 14F2F87A15C8326A00507B94 /* OSArray.cpp in Sources */, + 14F2F87C15C8368800507B94 /* OSCollection.cpp in Sources */, + 14F2F87E15C8373E00507B94 /* OSObject.cpp in Sources */, + 14F2F88A15C845B100507B94 /* OSString.cpp in Sources */, + 149A99CD15C99EF1009A8583 /* OSSymbol.cpp in Sources */, + 149A99D015C9A55A009A8583 /* OSDictionary.cpp in Sources */, + 149A99D215C9A86B009A8583 /* OSCollectionIterator.cpp in Sources */, + 149A99D415C9A89E009A8583 /* OSIterator.cpp in Sources */, + 149A99D615C9CAF1009A8583 /* OSSerialize.cpp in Sources */, + 149A99DA15C9CB23009A8583 /* OSSet.cpp in Sources */, + 149A99DD15C9CB61009A8583 /* OSOrderedSet.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 011AD38D155811E000C2DCF5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = sdk_name; + }; + name = Debug; + }; + 011AD38E155811E000C2DCF5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + SDKROOT = sdk_name; + }; + name = Release; + }; + 011AD390155811E000C2DCF5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILT_PRODUCTS_DIR = "$(SRCROOT)"; + EXECUTABLE_EXTENSION = ""; + EXECUTABLE_SUFFIX = ""; + GCC_ENABLE_BUILTIN_FUNCTIONS = NO; + GCC_ENABLE_KERNEL_DEVELOPMENT = YES; + GCC_FAST_OBJC_DISPATCH = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + KERNEL_FRAMEWORK = "$(SRCROOT)/"; + KEXT_FRAMEWORK = "$(SRCROOT)"; + LIBRARY_SEARCH_PATHS = "$(SRCROOT)"; + LINK_WITH_STANDARD_LIBRARIES = NO; + MACH_O_TYPE = mh_object; + MODULE_START = Start; + OTHER_CFLAGS = ( + "-mlongcall", + "-fno-builtin", + "-nostdlib", + ); + OTHER_LDFLAGS = "-F$(SRCROOT)"; + PRIVATE_HEADERS_FOLDER_PATH = ./; + PRODUCT_NAME = Passenger; + PRODUCT_SPECIFIC_LDFLAGS = ""; + PUBLIC_HEADERS_FOLDER_PATH = ./; + }; + name = Debug; + }; + 011AD391155811E000C2DCF5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILT_PRODUCTS_DIR = "$(SRCROOT)"; + EXECUTABLE_EXTENSION = ""; + EXECUTABLE_SUFFIX = ""; + GCC_ENABLE_BUILTIN_FUNCTIONS = NO; + GCC_ENABLE_KERNEL_DEVELOPMENT = YES; + GCC_FAST_OBJC_DISPATCH = NO; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; + KERNEL_FRAMEWORK = "$(SRCROOT)/"; + KEXT_FRAMEWORK = "$(SRCROOT)"; + LIBRARY_SEARCH_PATHS = "$(SRCROOT)"; + LINK_WITH_STANDARD_LIBRARIES = NO; + MACH_O_TYPE = mh_object; + MODULE_START = Start; + OTHER_CFLAGS = ( + "-mlongcall", + "-fno-builtin", + "-nostdlib", + ); + OTHER_LDFLAGS = "-F$(SRCROOT)"; + PRIVATE_HEADERS_FOLDER_PATH = ./; + PRODUCT_NAME = Passenger; + PRODUCT_SPECIFIC_LDFLAGS = ""; + PUBLIC_HEADERS_FOLDER_PATH = ./; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 011AD37E155811E000C2DCF5 /* Build configuration list for PBXProject "Libkern" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 011AD38D155811E000C2DCF5 /* Debug */, + 011AD38E155811E000C2DCF5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 011AD38F155811E000C2DCF5 /* Build configuration list for PBXNativeTarget "Libkern" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 011AD390155811E000C2DCF5 /* Debug */, + 011AD391155811E000C2DCF5 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 011AD37B155811E000C2DCF5 /* Project object */; +} diff --git a/OSArray.cpp b/OSArray.cpp new file mode 100755 index 0000000..b87223b --- /dev/null +++ b/OSArray.cpp @@ -0,0 +1,399 @@ +#include "OSArray.h" +#include "OSSerialize.h" + +#define super OSCollection + +OSDefineMetaClassAndStructors(OSArray, OSCollection) + +OSMetaClassDefineReservedUnused(OSArray, 0); +OSMetaClassDefineReservedUnused(OSArray, 1); +OSMetaClassDefineReservedUnused(OSArray, 2); +OSMetaClassDefineReservedUnused(OSArray, 3); +OSMetaClassDefineReservedUnused(OSArray, 4); +OSMetaClassDefineReservedUnused(OSArray, 5); +OSMetaClassDefineReservedUnused(OSArray, 6); +OSMetaClassDefineReservedUnused(OSArray, 7); + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +#define EXT_CAST(obj) \ + reinterpret_cast(const_cast(obj)) + +#define kfree(ptr, size) kfree(ptr) + +bool OSArray::initWithCapacity(unsigned int inCapacity) +{ + int size; + + if (!super::init()) + return false; + + size = sizeof(const OSMetaClassBase *) * inCapacity; + array = (const OSMetaClassBase **) kalloc(size); + if (!array) + return false; + + count = 0; + capacity = inCapacity; + capacityIncrement = (inCapacity)? inCapacity : 16; + + bzero(array, size); + ACCUMSIZE(size); + + return true; +} + +bool OSArray::initWithObjects(const OSObject *objects[], + unsigned int theCount, + unsigned int theCapacity) +{ + unsigned int initCapacity; + + if (!theCapacity) + initCapacity = theCount; + else if (theCount > theCapacity) + return false; + else + initCapacity = theCapacity; + + if (!objects || !initWithCapacity(initCapacity)) + return false; + + for ( unsigned int i = 0; i < theCount; i++ ) { + const OSMetaClassBase *newObject = *objects++; + + if (!newObject) + return false; + + array[count++] = newObject; + newObject->taggedRetain(OSTypeID(OSCollection)); + } + + return true; +} + +bool OSArray::initWithArray(const OSArray *anArray, + unsigned int theCapacity) +{ + if ( !anArray ) + return false; + + return initWithObjects((const OSObject **) anArray->array, + anArray->count, theCapacity); +} + +OSArray *OSArray::withCapacity(unsigned int capacity) +{ + OSArray *me = new OSArray; + + if (me && !me->initWithCapacity(capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSArray *OSArray::withObjects(const OSObject *objects[], + unsigned int count, + unsigned int capacity) +{ + OSArray *me = new OSArray; + + if (me && !me->initWithObjects(objects, count, capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSArray *OSArray::withArray(const OSArray *array, + unsigned int capacity) +{ + OSArray *me = new OSArray; + + if (me && !me->initWithArray(array, capacity)) { + me->release(); + return 0; + } + + return me; +} + +void OSArray::free() +{ + // Clear immutability - assumes the container is doing the right thing + (void) super::setOptions(0, kImmutable); + + flushCollection(); + + if (array) { + kfree(array, sizeof(const OSMetaClassBase *) * capacity); + ACCUMSIZE( -(sizeof(const OSMetaClassBase *) * capacity) ); + } + + super::free(); +} + + +unsigned int OSArray::getCount() const { return count; } +unsigned int OSArray::getCapacity() const { return capacity; } +unsigned int OSArray::getCapacityIncrement() const { return capacityIncrement; } +unsigned int OSArray::setCapacityIncrement(unsigned int increment) +{ + capacityIncrement = (increment)? increment : 16; + + return capacityIncrement; +} + +unsigned int OSArray::ensureCapacity(unsigned int newCapacity) +{ + const OSMetaClassBase **newArray; + int oldSize, newSize; + + if (newCapacity <= capacity) + return capacity; + + // round up + newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) + * capacityIncrement; + newSize = sizeof(const OSMetaClassBase *) * newCapacity; + + newArray = (const OSMetaClassBase **) kalloc(newSize); + if (newArray) { + oldSize = sizeof(const OSMetaClassBase *) * capacity; + + ACCUMSIZE(newSize - oldSize); + + bcopy(array, newArray, oldSize); + bzero(&newArray[capacity], newSize - oldSize); + kfree(array, oldSize); + array = newArray; + capacity = newCapacity; + } + + return capacity; +} + +void OSArray::flushCollection() +{ + unsigned int i; + + haveUpdated(); + for (i = 0; i < count; i++) { + array[i]->taggedRelease(OSTypeID(OSCollection)); + } + count = 0; +} + +bool OSArray::setObject(const OSMetaClassBase *anObject) +{ + return setObject(count, anObject); +} + +bool OSArray::setObject(unsigned int index, const OSMetaClassBase *anObject) +{ + unsigned int i; + unsigned int newCount = count + 1; + + if ((index > count) || !anObject) + return false; + + // do we need more space? + if (newCount > capacity && newCount > ensureCapacity(newCount)) + return false; + + haveUpdated(); + if (index != count) { + for (i = count; i > index; i--) + array[i] = array[i-1]; + } + array[index] = anObject; + anObject->taggedRetain(OSTypeID(OSCollection)); + count++; + + return true; +} + +bool OSArray::merge(const OSArray * otherArray) +{ + unsigned int otherCount = otherArray->getCount(); + unsigned int newCount = count + otherCount; + + if (!otherCount) + return true; + + // do we need more space? + if (newCount > capacity && newCount > ensureCapacity(newCount)) + return false; + + haveUpdated(); + for (unsigned int i = 0; i < otherCount; i++) { + const OSMetaClassBase *newObject = otherArray->getObject(i); + + array[count++] = newObject; + newObject->taggedRetain(OSTypeID(OSCollection)); + } + + return true; +} + +void OSArray:: +replaceObject(unsigned int index, const OSMetaClassBase *anObject) +{ + const OSMetaClassBase *oldObject; + + if ((index >= count) || !anObject) + return; + + haveUpdated(); + oldObject = array[index]; + array[index] = anObject; + anObject->taggedRetain(OSTypeID(OSCollection)); + + oldObject->taggedRelease(OSTypeID(OSCollection)); +} + +void OSArray::removeObject(unsigned int index) +{ + unsigned int i; + const OSMetaClassBase *oldObject; + + if (index >= count) + return; + + haveUpdated(); + oldObject = array[index]; + + count--; + for (i = index; i < count; i++) + array[i] = array[i+1]; + + oldObject->taggedRelease(OSTypeID(OSCollection)); +} + +bool OSArray::isEqualTo(const OSArray *anArray) const +{ + unsigned int i; + + if ( this == anArray ) + return true; + + if ( count != anArray->getCount() ) + return false; + + for ( i = 0; i < count; i++ ) { + if ( !array[i]->isEqualTo(anArray->getObject(i)) ) + return false; + } + + return true; +} + +bool OSArray::isEqualTo(const OSMetaClassBase *anObject) const +{ + OSArray *otherArray; + + otherArray = OSDynamicCast(OSArray, anObject); + if ( otherArray ) + return isEqualTo(otherArray); + else + return false; +} + +OSObject *OSArray::getObject(unsigned int index) const +{ + if (index >= count) + return 0; + else + return (OSObject *) (const_cast(array[index])); +} + +OSObject *OSArray::getLastObject() const +{ + if (count == 0) + return 0; + else + return ( OSObject *) (const_cast(array[count - 1])); +} + +unsigned int OSArray::getNextIndexOfObject(const OSMetaClassBase * anObject, + unsigned int index) const +{ + while ((index < count) && (array[index] != anObject)) + index++; + if (index >= count) + index = (unsigned int)-1; + return index; +} + +unsigned int OSArray::iteratorSize() const +{ + return sizeof(unsigned int); +} + +bool OSArray::initIterator(void *inIterator) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + + *iteratorP = 0; + return true; +} + +bool OSArray::getNextObjectForIterator(void *inIterator, OSObject **ret) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + unsigned int index = (*iteratorP)++; + + if (index < count) { + *ret = (OSObject *)(const_cast (array[index])); + return true; + } + else { + *ret = 0; + return false; + } +} + +bool OSArray::serialize(OSSerialize *s) const +{ + if (s->previouslySerialized(this)) return true; + + if (!s->addXMLStartTag(this, "array")) return false; + + for (unsigned i = 0; i < count; i++) { + if (!array[i]->serialize(s)) return false; + } + + return s->addXMLEndTag("array"); +} + +unsigned OSArray::setOptions(unsigned options, unsigned mask, void *) +{ + unsigned old = super::setOptions(options, mask); + if ((old ^ options) & mask) { + + // Value changed need to recurse over all of the child collections + for ( unsigned i = 0; i < count; i++ ) { + OSCollection *coll = OSDynamicCast(OSCollection, array[i]); + if (coll) + coll->setOptions(options, mask); + } + } + + return old; +} + +OSCollection * OSArray::copyCollection(OSDictionary *cycleDict) +{ + return (OSCollection*)0; +} + diff --git a/OSArray.h b/OSArray.h new file mode 100644 index 0000000..e814e30 --- /dev/null +++ b/OSArray.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOArray.h created by rsulack on Thu 11-Sep-1997 */ +/* IOArray.h converted to C++ by gvdl on Fri 1998-10-30 */ + +#ifndef _OS_OSARRAY_H +#define _OS_OSARRAY_H + +#include "OSCollection.h" + +class OSSerialize; + +class OSArray : public OSCollection +{ + friend class OSSet; + + OSDeclareDefaultStructors(OSArray) + +protected: + const OSMetaClassBase ** array; + unsigned int count; + unsigned int capacity; + unsigned int capacityIncrement; + + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData * reserved; + + /* OSCollectionIterator interfaces. */ + virtual unsigned int iteratorSize() const; + virtual bool initIterator(void * iterator) const; + virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret) const; + +public: + static OSArray * withCapacity(unsigned int capacity); + static OSArray * withObjects( + const OSObject * objects[], + unsigned int count, + unsigned int capacity = 0); + static OSArray * withArray( + const OSArray * array, + unsigned int capacity = 0); + virtual bool initWithCapacity(unsigned int capacity); + virtual bool initWithObjects( + const OSObject * objects[], + unsigned int count, + unsigned int capacity = 0); + virtual bool initWithArray( + const OSArray * anArray, + unsigned int capacity = 0); + virtual void free(); + virtual unsigned int getCount() const; + virtual unsigned int getCapacity() const; + virtual unsigned int getCapacityIncrement() const; + virtual unsigned int setCapacityIncrement(unsigned increment); + virtual unsigned int ensureCapacity(unsigned int newCapacity); + virtual void flushCollection(); + virtual bool setObject(const OSMetaClassBase * anObject); + virtual bool setObject( + unsigned int index, + const OSMetaClassBase * anObject); + virtual bool merge(const OSArray * otherArray); + virtual void replaceObject( + unsigned int index, + const OSMetaClassBase * anObject); + virtual void removeObject(unsigned int index); + virtual bool isEqualTo(const OSArray * anArray) const; + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + virtual OSObject * getObject(unsigned int index) const; + virtual OSObject * getLastObject() const; + virtual unsigned int getNextIndexOfObject( + const OSMetaClassBase * anObject, + unsigned int index) const; + + virtual bool serialize(OSSerialize * serializer) const; + virtual unsigned setOptions( + unsigned options, + unsigned mask, + void * context = 0); + + OSCollection * copyCollection(OSDictionary * cycleDict = 0); + + OSMetaClassDeclareReservedUnused(OSArray, 0); + OSMetaClassDeclareReservedUnused(OSArray, 1); + OSMetaClassDeclareReservedUnused(OSArray, 2); + OSMetaClassDeclareReservedUnused(OSArray, 3); + OSMetaClassDeclareReservedUnused(OSArray, 4); + OSMetaClassDeclareReservedUnused(OSArray, 5); + OSMetaClassDeclareReservedUnused(OSArray, 6); + OSMetaClassDeclareReservedUnused(OSArray, 7); +}; + +#endif /* !_OS_OSARRAY_H */ diff --git a/OSCollection.cpp b/OSCollection.cpp new file mode 100755 index 0000000..da3deab --- /dev/null +++ b/OSCollection.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOArray.h created by rsulack on Thu 11-Sep-1997 */ + +#include "OSCollection.h" + +#define super OSObject + +OSDefineMetaClassAndAbstractStructors(OSCollection, OSObject) + + +OSMetaClassDefineReservedUsed(OSCollection, 0); +OSMetaClassDefineReservedUsed(OSCollection, 1); +OSMetaClassDefineReservedUnused(OSCollection, 2); +OSMetaClassDefineReservedUnused(OSCollection, 3); +OSMetaClassDefineReservedUnused(OSCollection, 4); +OSMetaClassDefineReservedUnused(OSCollection, 5); +OSMetaClassDefineReservedUnused(OSCollection, 6); +OSMetaClassDefineReservedUnused(OSCollection, 7); + +bool OSCollection::init() +{ + if (!super::init()) + return false; + + updateStamp = 0; + + return true; +} + +void OSCollection::haveUpdated() +{ + if (fOptions & kImmutable) + { + panic("Trying to change a collection in the registry"); + } + updateStamp++; +} + +unsigned OSCollection::setOptions(unsigned options, unsigned mask, void *) +{ + unsigned old = fOptions; + + if (mask) + fOptions = (old & ~mask) | (options & mask); + + return old; +} + +OSCollection * OSCollection::copyCollection(OSDictionary *cycleDict) +{ + panic("%s", __FUNCTION__); + return (OSCollection*)0; +} diff --git a/OSCollection.h b/OSCollection.h new file mode 100755 index 0000000..6d4d06f --- /dev/null +++ b/OSCollection.h @@ -0,0 +1,62 @@ +#ifndef _OS_OSCOLLECTION_H +#define _OS_OSCOLLECTION_H + +#include "OSObject.h" + +class OSDictionary; + +class OSCollection : public OSObject +{ + friend class OSCollectionIterator; + + OSDeclareAbstractStructors(OSCollection); + + struct ExpansionData { }; + +protected: + unsigned int updateStamp; + +private: + unsigned int fOptions; + +protected: + virtual unsigned int iteratorSize() const = 0; + virtual bool initIterator(void * iterationContext) const = 0; + virtual bool getNextObjectForIterator( + void * iterationContext, + OSObject ** nextObject) const = 0; + + virtual bool init(); + +public: + typedef enum { + kImmutable = 0x00000001, + kMASK = (unsigned) -1 + } _OSCollectionFlags; + + void haveUpdated(); + virtual unsigned int getCount() const = 0; + virtual unsigned int getCapacity() const = 0; + virtual unsigned int getCapacityIncrement() const = 0; + virtual unsigned int setCapacityIncrement(unsigned increment) = 0; + virtual unsigned int ensureCapacity(unsigned int newCapacity) = 0; + virtual void flushCollection() = 0; + virtual unsigned setOptions( + unsigned options, + unsigned mask, + void * context = 0); + + OSMetaClassDeclareReservedUsed(OSCollection, 0); + virtual OSCollection *copyCollection(OSDictionary * cycleDict = 0); + OSMetaClassDeclareReservedUsed(OSCollection, 1); + + + OSMetaClassDeclareReservedUnused(OSCollection, 2); + OSMetaClassDeclareReservedUnused(OSCollection, 3); + OSMetaClassDeclareReservedUnused(OSCollection, 4); + OSMetaClassDeclareReservedUnused(OSCollection, 5); + OSMetaClassDeclareReservedUnused(OSCollection, 6); + OSMetaClassDeclareReservedUnused(OSCollection, 7); +}; + +#endif /* !_OS_OSCOLLECTION_H */ diff --git a/OSCollectionIterator.cpp b/OSCollectionIterator.cpp new file mode 100755 index 0000000..f0aea33 --- /dev/null +++ b/OSCollectionIterator.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOArray.h created by rsulack on Thu 11-Sep-1997 */ + +#include "OSCollectionIterator.h" +#include "OSArray.h" +#include "OSCollection.h" + +#define super OSIterator + +OSDefineMetaClassAndStructors(OSCollectionIterator, OSIterator) + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +bool OSCollectionIterator::initWithCollection(const OSCollection *inColl) +{ + if ( !super::init() || !inColl) + return false; + + inColl->retain(); + collection = inColl; + collIterator = 0; + initialUpdateStamp = 0; + valid = false; + + return this; +} + +OSCollectionIterator * +OSCollectionIterator::withCollection(const OSCollection *inColl) +{ + + OSCollectionIterator *me = new OSCollectionIterator; + + if (me && !me->initWithCollection(inColl)) { + me->release(); + return 0; + } + + return me; +} + +void OSCollectionIterator::free() +{ + if (collIterator) { + kfree(collIterator, collection->iteratorSize()); + ACCUMSIZE(-(collection->iteratorSize())); + collIterator = 0; + } + + if (collection) { + collection->release(); + collection = 0; + } + + super::free(); +} + +void OSCollectionIterator::reset() +{ + valid = false; + + if (!collIterator) { + collIterator = (void *)kalloc(collection->iteratorSize()); + ACCUMSIZE(collection->iteratorSize()); + if (!collIterator) + return; + } + + if (!collection->initIterator(collIterator)) + return; + + initialUpdateStamp = collection->updateStamp; + valid = true; +} + +bool OSCollectionIterator::isValid() +{ + if (!collIterator) { + collIterator = (void *)kalloc(collection->iteratorSize()); + ACCUMSIZE(collection->iteratorSize()); + if (!collection->initIterator(collIterator)) + return false; + initialUpdateStamp = collection->updateStamp; + valid = true; + } + else if (!valid || collection->updateStamp != initialUpdateStamp) + return false; + + return true; +} + +OSObject *OSCollectionIterator::getNextObject() +{ + OSObject *retObj; + bool retVal; + + if (!isValid()) + return 0; + + retVal = collection->getNextObjectForIterator(collIterator, &retObj); + return (retVal)? retObj : 0; +} + diff --git a/OSCollectionIterator.h b/OSCollectionIterator.h new file mode 100755 index 0000000..7257fdb --- /dev/null +++ b/OSCollectionIterator.h @@ -0,0 +1,28 @@ +#ifndef _OS_OSCOLLECTIONITERATOR_H +#define _OS_OSCOLLECTIONITERATOR_H + +#include "OSIterator.h" + +class OSCollection; + +class OSCollectionIterator : public OSIterator +{ + OSDeclareDefaultStructors(OSCollectionIterator) + +protected: + const OSCollection * collection; + void * collIterator; + unsigned int initialUpdateStamp; + bool valid; + +public: + static OSCollectionIterator * withCollection(const OSCollection * inColl); + + virtual bool initWithCollection(const OSCollection * inColl); + virtual void free(); + virtual void reset(); + virtual bool isValid(); + virtual OSObject * getNextObject(); +}; + +#endif /* !_OS_OSCOLLECTIONITERATOR_H */ diff --git a/OSDictionary.cpp b/OSDictionary.cpp new file mode 100755 index 0000000..a4015a3 --- /dev/null +++ b/OSDictionary.cpp @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* OSDictionary.m created by rsulack on Fri 12-Sep-1997 */ +/* OSDictionary.cpp converted to C++ by gvdl on Fri 1998-10-30 */ +/* OSDictionary.cpp rewritten by gvdl on Fri 1998-10-30 */ + +#include "OSDictionary.h" +#include "OSArray.h" +#include "OSString.h" +#include "OSSymbol.h" +#include "OSCollectionIterator.h" + +#define super OSCollection + +OSDefineMetaClassAndStructors(OSDictionary, OSCollection) +OSMetaClassDefineReservedUnused(OSDictionary, 0); +OSMetaClassDefineReservedUnused(OSDictionary, 1); +OSMetaClassDefineReservedUnused(OSDictionary, 2); +OSMetaClassDefineReservedUnused(OSDictionary, 3); +OSMetaClassDefineReservedUnused(OSDictionary, 4); +OSMetaClassDefineReservedUnused(OSDictionary, 5); +OSMetaClassDefineReservedUnused(OSDictionary, 6); +OSMetaClassDefineReservedUnused(OSDictionary, 7); + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +#define EXT_CAST(obj) \ + reinterpret_cast(const_cast(obj)) + +bool OSDictionary::initWithCapacity(unsigned int inCapacity) +{ + if (!super::init()) + return false; + + int size = inCapacity * sizeof(dictEntry); + + dictionary = (dictEntry *) kalloc(size); + if (!dictionary) + return false; + + bzero(dictionary, size); + ACCUMSIZE(size); + + count = 0; + capacity = inCapacity; + capacityIncrement = (inCapacity)? inCapacity : 16; + + return true; +} + +bool OSDictionary::initWithObjects(const OSObject *objects[], + const OSSymbol *keys[], + unsigned int theCount, + unsigned int theCapacity) +{ + unsigned int newCapacity = theCount; + + if (!objects || !keys) + return false; + + if ( theCapacity ) { + if (theCount > theCapacity) + return false; + + newCapacity = theCapacity; + } + + if (!initWithCapacity(newCapacity)) + return false; + + for (unsigned int i = 0; i < theCount; i++) { + const OSMetaClassBase *newObject = *objects++; + + if (!newObject || !keys[i] || !setObject(keys[i], newObject)) + return false; + } + + return true; +} + +bool OSDictionary::initWithObjects(const OSObject *objects[], + const OSString *keys[], + unsigned int theCount, + unsigned int theCapacity) +{ + unsigned int newCapacity = theCount; + + if (!objects || !keys) + return false; + + if ( theCapacity ) { + if (theCount > theCapacity) + return false; + + newCapacity = theCapacity; + } + + if (!initWithCapacity(newCapacity)) + return false; + + for (unsigned int i = 0; i < theCount; i++) { + const OSSymbol *key = OSSymbol::withString(*keys++); + const OSMetaClassBase *newObject = *objects++; + + if (!key) + return false; + + if (!newObject || !setObject(key, newObject)) { + key->release(); + return false; + } + + key->release(); + } + + return true; +} + +bool OSDictionary::initWithDictionary(const OSDictionary *dict, + unsigned int theCapacity) +{ + unsigned int newCapacity; + + if ( !dict ) + return false; + + newCapacity = dict->count; + + if ( theCapacity ) { + if ( dict->count > theCapacity ) + return false; + + newCapacity = theCapacity; + } + + if (!initWithCapacity(newCapacity)) + return false; + + count = dict->count; + bcopy(dict->dictionary, dictionary, count * sizeof(dictEntry)); + for (unsigned int i = 0; i < count; i++) { + dictionary[i].key->taggedRetain(OSTypeID(OSCollection)); + dictionary[i].value->taggedRetain(OSTypeID(OSCollection)); + } + + return true; +} + +OSDictionary *OSDictionary::withCapacity(unsigned int capacity) +{ + OSDictionary *me = new OSDictionary; + + if (me && !me->initWithCapacity(capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSDictionary *OSDictionary::withObjects(const OSObject *objects[], + const OSSymbol *keys[], + unsigned int count, + unsigned int capacity) +{ + OSDictionary *me = new OSDictionary; + + if (me && !me->initWithObjects(objects, keys, count, capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSDictionary *OSDictionary::withObjects(const OSObject *objects[], + const OSString *keys[], + unsigned int count, + unsigned int capacity) +{ + OSDictionary *me = new OSDictionary; + + if (me && !me->initWithObjects(objects, keys, count, capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSDictionary *OSDictionary::withDictionary(const OSDictionary *dict, + unsigned int capacity) +{ + OSDictionary *me = new OSDictionary; + + if (me && !me->initWithDictionary(dict, capacity)) { + me->release(); + return 0; + } + + return me; +} + +void OSDictionary::free() +{ + (void) super::setOptions(0, kImmutable); + flushCollection(); + if (dictionary) { + kfree(dictionary, capacity * sizeof(dictEntry)); + ACCUMSIZE( -(capacity * sizeof(dictEntry)) ); + } + + super::free(); +} + +unsigned int OSDictionary::getCount() const { return count; } +unsigned int OSDictionary::getCapacity() const { return capacity; } + +unsigned int OSDictionary::getCapacityIncrement() const +{ + return capacityIncrement; +} + +unsigned int OSDictionary::setCapacityIncrement(unsigned int increment) +{ + capacityIncrement = (increment)? increment : 16; + + return capacityIncrement; +} + +unsigned int OSDictionary::ensureCapacity(unsigned int newCapacity) +{ + dictEntry *newDict; + int oldSize, newSize; + + if (newCapacity <= capacity) + return capacity; + + // round up + newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) + * capacityIncrement; + newSize = sizeof(dictEntry) * newCapacity; + + newDict = (dictEntry *) kalloc(newSize); + if (newDict) { + oldSize = sizeof(dictEntry) * capacity; + + bcopy(dictionary, newDict, oldSize); + bzero(&newDict[capacity], newSize - oldSize); + + ACCUMSIZE(newSize - oldSize); + kfree(dictionary, oldSize); + + dictionary = newDict; + capacity = newCapacity; + } + + return capacity; +} + +void OSDictionary::flushCollection() +{ + haveUpdated(); + + for (unsigned int i = 0; i < count; i++) { + dictionary[i].key->taggedRelease(OSTypeID(OSCollection)); + dictionary[i].value->taggedRelease(OSTypeID(OSCollection)); + } + count = 0; +} + + +bool OSDictionary:: +setObject(const OSSymbol *aKey, const OSMetaClassBase *anObject) +{ + if (!anObject || !aKey) + return false; + + // if the key exists, replace the object + for (unsigned int i = 0; i < count; i++) { + if (aKey == dictionary[i].key) { + const OSMetaClassBase *oldObject = dictionary[i].value; + + haveUpdated(); + + anObject->taggedRetain(OSTypeID(OSCollection)); + dictionary[i].value = anObject; + + oldObject->taggedRelease(OSTypeID(OSCollection)); + return true; + } + } + + // add new key, possibly extending our capacity + if (count >= capacity && count >= ensureCapacity(count+1)) + return 0; + + haveUpdated(); + + aKey->taggedRetain(OSTypeID(OSCollection)); + anObject->taggedRetain(OSTypeID(OSCollection)); + dictionary[count].key = aKey; + dictionary[count].value = anObject; + count++; + + return true; +} + +void OSDictionary::removeObject(const OSSymbol *aKey) +{ + if (!aKey) + return; + + // if the key exists, remove the object + for (unsigned int i = 0; i < count; i++) + if (aKey == dictionary[i].key) { + dictEntry oldEntry = dictionary[i]; + + haveUpdated(); + + count--; + for (; i < count; i++) + dictionary[i] = dictionary[i+1]; + + oldEntry.key->taggedRelease(OSTypeID(OSCollection)); + oldEntry.value->taggedRelease(OSTypeID(OSCollection)); + return; + } +} + + +// Returns true on success, false on an error condition. +bool OSDictionary::merge(const OSDictionary *srcDict) +{ + const OSSymbol * sym; + OSCollectionIterator * iter; + + if ( !OSDynamicCast(OSDictionary, srcDict) ) + return false; + + iter = OSCollectionIterator::withCollection(const_cast(srcDict)); + if ( !iter ) + return false; + + while ( (sym = (const OSSymbol *)iter->getNextObject()) ) { + const OSMetaClassBase * obj; + + obj = srcDict->getObject(sym); + if ( !setObject(sym, obj) ) { + iter->release(); + return false; + } + } + iter->release(); + + return true; +} + +OSObject *OSDictionary::getObject(const OSSymbol *aKey) const +{ + if (!aKey) + return 0; + + // if the key exists, remove the object + for (unsigned int i = 0; i < count; i++) + if (aKey == dictionary[i].key) + return (const_cast ((const OSObject *)dictionary[i].value)); + + return 0; +} + +// Wrapper macros +#define OBJECT_WRAP_1(cmd, k) \ +{ \ + const OSSymbol *tmpKey = k; \ + OSObject *retObj = cmd(tmpKey); \ + \ + tmpKey->release(); \ + return retObj; \ +} + +#define OBJECT_WRAP_2(cmd, k, o) \ +{ \ + const OSSymbol *tmpKey = k; \ + bool ret = cmd(tmpKey, o); \ + \ + tmpKey->release(); \ + return ret; \ +} + +#define OBJECT_WRAP_3(cmd, k) \ +{ \ + const OSSymbol *tmpKey = k; \ + cmd(tmpKey); \ + tmpKey->release(); \ +} + + +bool OSDictionary::setObject(const OSString *aKey, const OSMetaClassBase *anObject) + OBJECT_WRAP_2(setObject, OSSymbol::withString(aKey), anObject) +bool OSDictionary::setObject(const char *aKey, const OSMetaClassBase *anObject) + OBJECT_WRAP_2(setObject, OSSymbol::withCString(aKey), anObject) + +OSObject *OSDictionary::getObject(const OSString *aKey) const + OBJECT_WRAP_1(getObject, OSSymbol::withString(aKey)) +OSObject *OSDictionary::getObject(const char *aKey) const + OBJECT_WRAP_1(getObject, OSSymbol::withCString(aKey)) + +void OSDictionary::removeObject(const OSString *aKey) + OBJECT_WRAP_3(removeObject, OSSymbol::withString(aKey)) +void OSDictionary::removeObject(const char *aKey) + OBJECT_WRAP_3(removeObject, OSSymbol::withCString(aKey)) + +bool +OSDictionary::isEqualTo(const OSDictionary *srcDict, const OSCollection *keys) const +{ + OSCollectionIterator * iter; + unsigned int keysCount; + const OSMetaClassBase * obj1; + const OSMetaClassBase * obj2; + OSString * aKey; + bool ret; + + if ( this == srcDict ) + return true; + + keysCount = keys->getCount(); + if ( (count < keysCount) || (srcDict->getCount() < keysCount) ) + return false; + + iter = OSCollectionIterator::withCollection(keys); + if ( !iter ) + return false; + + ret = true; + while ( (aKey = OSDynamicCast(OSString, iter->getNextObject())) ) { + obj1 = getObject(aKey); + obj2 = srcDict->getObject(aKey); + if ( !obj1 || !obj2 ) { + ret = false; + break; + } + + if ( !obj1->isEqualTo(obj2) ) { + ret = false; + break; + } + } + iter->release(); + + return ret; +} + +bool OSDictionary::isEqualTo(const OSDictionary *srcDict) const +{ + unsigned int i; + const OSMetaClassBase * obj; + + if ( this == srcDict ) + return true; + + if ( count != srcDict->getCount() ) + return false; + + for ( i = 0; i < count; i++ ) { + obj = srcDict->getObject(dictionary[i].key); + if ( !obj ) + return false; + + if ( !dictionary[i].value->isEqualTo(obj) ) + return false; + } + + return true; +} + +bool OSDictionary::isEqualTo(const OSMetaClassBase *anObject) const +{ + OSDictionary *dict; + + dict = OSDynamicCast(OSDictionary, anObject); + if ( dict ) + return isEqualTo(dict); + else + return false; +} + +unsigned int OSDictionary::iteratorSize() const +{ + return sizeof(unsigned int); +} + +bool OSDictionary::initIterator(void *inIterator) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + + *iteratorP = 0; + return true; +} + +bool OSDictionary::getNextObjectForIterator(void *inIterator, OSObject **ret) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + unsigned int index = (*iteratorP)++; + + if (index < count) + *ret = (OSObject *) dictionary[index].key; + else + *ret = 0; + + return (*ret != 0); +} + +bool OSDictionary::serialize(OSSerialize *s) const +{ + return false; +} + +unsigned OSDictionary::setOptions(unsigned options, unsigned mask, void *) +{ + unsigned old = super::setOptions(options, mask); + if ((old ^ options) & mask) { + + // Value changed need to recurse over all of the child collections + for ( unsigned i = 0; i < count; i++ ) { + OSCollection *v = OSDynamicCast(OSCollection, dictionary[i].value); + if (v) + v->setOptions(options, mask); + } + } + + return old; +} + +OSCollection * OSDictionary::copyCollection(OSDictionary *cycleDict) +{ + bool allocDict = !cycleDict; + OSCollection *ret = 0; + OSDictionary *newDict = 0; + + if (allocDict) { + cycleDict = OSDictionary::withCapacity(16); + if (!cycleDict) + return 0; + } + + do { + // Check for a cycle + ret = super::copyCollection(cycleDict); + if (ret) + continue; + + newDict = OSDictionary::withDictionary(this); + if (!newDict) + continue; + + // Insert object into cycle Dictionary + cycleDict->setObject((const OSSymbol *) this, newDict); + + for (unsigned int i = 0; i < count; i++) { + const OSMetaClassBase *obj = dictionary[i].value; + OSCollection *coll = OSDynamicCast(OSCollection, EXT_CAST(obj)); + + if (coll) { + OSCollection *newColl = coll->copyCollection(cycleDict); + if (!newColl) + goto abortCopy; + + newDict->dictionary[i].value = newColl; + + coll->taggedRelease(OSTypeID(OSCollection)); + newColl->taggedRetain(OSTypeID(OSCollection)); + newColl->release(); + }; + } + + ret = newDict; + newDict = 0; + + } while (false); + +abortCopy: + if (newDict) + newDict->release(); + + if (allocDict) + cycleDict->release(); + + return ret; +} + diff --git a/OSDictionary.h b/OSDictionary.h new file mode 100755 index 0000000..1706cc3 --- /dev/null +++ b/OSDictionary.h @@ -0,0 +1,916 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1998-1999 Apple Computer, Inc. All rights reserved. + * + * HISTORY + * + * OSDictionary.h created by rsulack on Wed 17-Sep-1997 + * OSDictionary.h converted to C++ by gvdl on Fri 1998-10-30 + */ + +#ifndef _IOKIT_IODICTIONARY_H +#define _IOKIT_IODICTIONARY_H + +#include "OSCollection.h" + +class OSArray; +class OSSymbol; +class OSString; + +/*! + * @header + * + * @abstract + * This header declares the OSDictionary collection class. + */ + + +/*! + * @class OSDictionary + * + * @abstract + * OSDictionary provides an associative store using strings for keys. + * + * @discussion + * OSDictionary is a container for Libkern C++ objects + * (those derived from + * @link //apple_ref/doc/class/OSMetaClassBase OSMetaClassBase@/link, + * in particular @link //apple_ref/doc/class/OSObject OSObject@/link). + * Storage and access are associative, based on string-valued keys + * (C string, @link //apple_ref/cpp/cl/OSString OSString@/link, + * or @link //apple_ref/cpp/cl/OSSymbol OSSymbol@/link). + * When adding an object to an OSDictionary, you provide a string identifier, + * which can then used to retrieve that object or remove it from the dictionary. + * Setting an object with a key that already has an associated object + * replaces the original object. + * + * You must generally cast retrieved objects from + * @link //apple_ref/cpp/cl/OSObject OSObject@/link + * to the desired class using + * @link //apple_ref/cpp/macro/OSDynamicCast OSDynamicCast@/link. + * This macro returns the object cast to the desired class, + * or NULL if the object isn't derived from that class. + * + * When iterating an OSDictionary using + * @link //apple_ref/doc/class/OSCollectionIterator OSCollectionIterator@/link, + * the objects returned from + * @link //apple_ref/doc/function/OSCollectionIterator::getNextObject + * getNextObject@/link + * are dictionary keys (not the object values for those keys). + * You can use the keys to retrieve their associated object values. + * + * As with all Libkern collection classes, + * OSDictionary retains keys and objects added to it, + * and releases keys and objects removed from it (or replaced). + * An OSDictionary also grows as necessary to accommodate new key/value pairs, + * unlike Core Foundation collections (it does not, however, shrink). + * + * Note: OSDictionary currently uses a linear search algorithm, + * and is not designed for high-performance access of many values. + * It is intended as a simple associative-storage mechanism only. + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSDictionary provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions for setting + * properties. + */ +class OSDictionary : public OSCollection +{ + OSDeclareDefaultStructors(OSDictionary) + +protected: + struct dictEntry { + const OSSymbol * key; + const OSMetaClassBase * value; + }; + dictEntry * dictionary; + unsigned int count; + unsigned int capacity; + unsigned int capacityIncrement; + + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData * reserved; + + // Member functions used by the OSCollectionIterator class. + virtual unsigned int iteratorSize() const; + virtual bool initIterator(void * iterator) const; + virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret) const; + +public: + + /*! + * @function withCapacity + * + * @abstract + * Creates and initializes an empty OSDictionary. + * + * @param capacity The initial storage capacity of the new dictionary object. + * + * @result + * An empty instance of OSDictionary + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * capacity must be nonzero. + * The new dictionary will grow as needed to accommodate more key/object pairs + * (unlike @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + static OSDictionary * withCapacity(unsigned int capacity); + + + /*! + * @function withObjects + * + * @abstract Creates and initializes an OSDictionary + * populated with keys and objects provided. + * + * @param objects A C array of OSMetaClassBase-derived objects. + * @param keys A C array of OSSymbol keys + * for the corresponding objects in objects. + * @param count The number of keys and objects + * to be placed into the dictionary. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * An instance of OSDictionary + * containing the key/object pairs provided, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * objects and keys must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + static OSDictionary * withObjects( + const OSObject * objects[], + const OSSymbol * keys[], + unsigned int count, + unsigned int capacity = 0); + + /*! + * @function withObjects + * + * @abstract + * Creates and initializes an OSDictionary + * populated with keys and objects provided. + * + * @param objects A C array of OSMetaClassBase-derived objects. + * @param keys A C array of OSString keys for the corresponding objects + * in objects. + * @param count The number of keys and objects + * to be placed into the dictionary. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * An instance of OSDictionary + * containing the key/object pairs provided, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * objects and keys must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, it must be greater than or equal to count. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + static OSDictionary * withObjects( + const OSObject * objects[], + const OSString * keys[], + unsigned int count, + unsigned int capacity = 0); + + + /*! + * @function withDictionary + * + * @abstract + * Creates and initializes an OSDictionary + * populated with the contents of another dictionary. + * + * @param dict A dictionary whose contents will be stored + * in the new instance. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, the capacity is set to the number of key/value pairs + * in dict; + * otherwise capacity must be greater than or equal to + * the number of key/value pairs in dict. + * + * @result + * An instance of OSDictionary + * containing the key/value pairs of dict, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * dict must be non-NULL. + * If capacity is nonzero, it must be greater than or equal to count. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + * + * The keys and objects in dict are retained for storage + * in the new OSDictionary, + * not copied. + */ + static OSDictionary * withDictionary( + const OSDictionary * dict, + unsigned int capacity = 0); + + + /*! + * @function initWithCapacity + * + * @abstract + * Initializes a new instance of OSDictionary. + * + * @param capacity The initial storage capacity of the new dictionary object. + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link //apple_ref/cpp/clm/OSDictionary/withCapacity/staticOSDictionary*\/(unsignedint) + * withCapacity@/link + * instead. + * + * capacity must be nonzero. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + virtual bool initWithCapacity(unsigned int capacity); + + + /*! + * @function initWithObjects + * + * @abstract Initializes a new OSDictionary with keys and objects provided. + * + * @param objects A C array of OSMetaClassBase-derived objects. + * @param keys A C array of OSSymbol keys + * for the corresponding objects in objects. + * @param count The number of keys and objects to be placed + * into the dictionary. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSDictionary/withObjects/staticOSDictionary*\/(constOSObject*,constOSString*,unsignedint,unsignedint) + * withObjects@/link + * instead. + * + * objects and keys must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new dictionary will grow as neede + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + virtual bool initWithObjects( + const OSObject * objects[], + const OSSymbol * keys[], + unsigned int count, + unsigned int capacity = 0); + + + /*! + * @function initWithObjects + * + * @abstract + * Initializes a new OSDictionary with keys and objects provided. + * + * @param objects A C array of OSMetaClassBase-derived objects. + * @param keys A C array of OSString keys + * for the corresponding objects in objects. + * @param count The number of keys and objects + * to be placed into the dictionary. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSDictionary/withObjects/staticOSDictionary*\/(constOSObject*,constOSString*,unsignedint,unsignedint) + * withObjects@/link + * instead. + * + * objects and keys must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, it must be greater than or equal to count. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + */ + virtual bool initWithObjects( + const OSObject * objects[], + const OSString * keys[], + unsigned int count, + unsigned int capacity = 0); + + + /*! + * @function initWithDictionary + * + * @abstract + * Initializes a new OSDictionary + * with the contents of another dictionary. + * + * @param dict A dictionary whose contents will be placed + * in the new instance. + * @param capacity The initial storage capacity of the new dictionary object. + * If 0, the capacity is set to the number of key/value pairs + * in dict; + * otherwise capacity must be greater than or equal to + * the number of key/value pairs in dict. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link withDictionary withDictionary@/link instead. + * + * dict must be non-NULL. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new dictionary will grow as needed + * to accommodate more key/object pairs + * (unlike + * @link //apple_ref/doc/uid/20001497 CFMutableDictionary@/link, + * for which the initial capacity is a hard limit). + * + * The keys and objects in dict are retained for storage + * in the new OSDictionary, + * not copied. + */ + virtual bool initWithDictionary( + const OSDictionary * dict, + unsigned int capacity = 0); + + + /*! + * @function free + * + * @abstract + * Deallocates or releases any resources + * used by the OSDictionary instance. + * + * @discussion + * This function should not be called directly, + * use + * @link + * //apple_ref/cpp/instm/OSObject/release/virtualvoid/() + * release@/link + * instead. + */ + virtual void free(); + + + /*! + * @function getCount + * + * @abstract + * Returns the current number of key/object pairs + * contained within the dictionary. + * + * @result + * The current number of key/object pairs + * contained within the dictionary. + */ + virtual unsigned int getCount() const; + + + /*! + * @function getCapacity + * + * @abstract + * Returns the number of objects the dictionary can store without reallocating. + * + * @result + * The number objects the dictionary can store without reallocating. + * + * @discussion + * OSDictionary objects grow when full + * to accommodate additional key/object pairs. + * See + * @link + * //apple_ref/cpp/instm/OSDictionary/getCapacityIncrement/virtualunsignedint/() + * getCapacityIncrement@/link + * and + * @link + * //apple_ref/cpp/instm/OSDictionary/ensureCapacity/virtualunsignedint/(unsignedint) + * ensureCapacity@/link. + */ + virtual unsigned int getCapacity() const; + + + /*! + * @function getCapacityIncrement + * + * @abstract + * Returns the storage increment of the dictionary. + * + * @result + * The storage increment of the dictionary. + * + * @discussion + * An OSDictionary allocates storage for key/object pairs in multiples + * of the capacity increment. + */ + virtual unsigned int getCapacityIncrement() const; + + + /*! + * @function setCapacityIncrement + * + * @abstract + * Sets the storage increment of the dictionary. + * + * @result + * The new storage increment of the dictionary, + * which may be different from the number requested. + * + * @discussion + * An OSDictionary allocates storage for key/object pairs in multiples + * of the capacity increment. + * Calling this function does not immediately reallocate storage. + */ + virtual unsigned int setCapacityIncrement(unsigned increment); + + + /*! + * @function ensureCapacity + * + * @abstract + * Ensures the dictionary has enough space + * to store the requested number of key/object pairs. + * + * @param newCapacity The total number of key/object pairs the dictionary + * should be able to store. + * + * @result + * The new capacity of the dictionary, + * which may be different from the number requested + * (if smaller, reallocation of storage failed). + * + * @discussion + * This function immediately resizes the dictionary, if necessary, + * to accommodate at least newCapacity key/object pairs. + * If newCapacity is not greater than the current capacity, + * or if an allocation error occurs, the original capacity is returned. + * + * There is no way to reduce the capacity of an OSDictionary. + */ + virtual unsigned int ensureCapacity(unsigned int newCapacity); + + + /*! + * @function flushCollection + * + * @abstract + * Removes and releases all keys and objects within the dictionary. + * + * @discussion + * The dictionary's capacity (and therefore direct memory consumption) + * is not reduced by this function. + */ + virtual void flushCollection(); + + + /*! + * @function setObject + * + * @abstract + * Stores an object in the dictionary under a key. + * + * @param aKey An OSSymbol identifying the object + * placed within the dictionary. + * It is automatically retained. + * @param anObject The object to be stored in the dictionary. + * It is automatically retained. + * + * @result + * true if the addition was successful, + * false otherwise. + * + * @discussion + * An object already stored under aKey is released. + */ + virtual bool setObject( + const OSSymbol * aKey, + const OSMetaClassBase * anObject); + + + /*! + * @function setObject + * + * @abstract Stores an object in the dictionary under a key. + * + * @param aKey An OSString identifying the object + * placed within the dictionary. + * @param anObject The object to be stored in the dictionary. + * It is automatically retained. + * + * @result + * true if the addition was successful, + * false otherwise. + * + * @discussion + * An OSSymbol for aKey is created internally. + * An object already stored under aKey is released. + */ + virtual bool setObject( + const OSString * aKey, + const OSMetaClassBase * anObject); + + + /*! + * @function setObject + * + * @abstract + * Stores an object in the dictionary under a key. + * + * @param aKey A C string identifying the object + * placed within the dictionary. + * @param anObject The object to be stored in the dictionary. + * It is automatically retained. + * + * @result + * true if the addition was successful, + * false otherwise. + * + * @discussion + * An OSSymbol for aKey is created internally. + * An object already stored under aKey is released. + */ + virtual bool setObject( + const char * aKey, + const OSMetaClassBase * anObject); + + + /*! + * @function removeObject + * + * @abstract + * Removes a key/object pair from the dictionary. + * + * @param aKey An OSSymbol identifying the object + * to be removed from the dictionary. + * + * @discussion + * The removed key (not necessarily aKey itself) + * and object are automatically released. + */ + virtual void removeObject(const OSSymbol * aKey); + + + /*! + * @function removeObject + * + * @abstract + * Removes a key/object pair from the dictionary. + * + * @param aKey A OSString identifying the object + * to be removed from the dictionary. + * + * @discussion + * The removed key (not necessarily aKey itself) + * and object are automatically released. + */ + virtual void removeObject(const OSString * aKey); + + + /*! + * @function removeObject + * + * @abstract + * Removes a key/object pair from the dictionary. + * + * @param aKey A C string identifying the object + * to be removed from the dictionary. + * + * @discussion + * The removed key (internally an OSSymbol) + * and object are automatically released. + */ + virtual void removeObject(const char * aKey); + + + /*! + * @function merge + * + * @abstract + * Merges the contents of a dictionary into the receiver. + * + * @param aDictionary The dictionary whose contents + * are to be merged with the receiver. + * @result + * true if the merge succeeds, false otherwise. + * + * @discussion + * If there are keys in aDictionary that match keys + * in the receiving dictionary, + * then the objects in the receiver are replaced + * by those from aDictionary, + * and the replaced objects are released. + */ + virtual bool merge(const OSDictionary * aDictionary); + + + /*! + * @function getObject + * + * @abstract + * Returns the object stored under a given key. + * + * @param aKey An OSSymbol key identifying the object + * to be returned to the caller. + * + * @result + * The object stored under aKey, + * or NULL if the key does not exist in the dictionary. + * + * @discussion + * The returned object will be released if removed from the dictionary; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getObject(const OSSymbol * aKey) const; + + + /*! + * @function getObject + * + * @abstract Returns the object stored under a given key. + * + * @param aKey An OSString key identifying the object + * to be returned to caller. + * + * @result + * The object stored under aKey, + * or NULL if the key does not exist in the dictionary. + * + * @discussion + * The returned object will be released if removed from the dictionary; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getObject(const OSString * aKey) const; + + + /*! + * @function getObject + * + * @abstract + * Returns the object stored under a given key. + * + * @param aKey A C string key identifying the object + * to be returned to caller. + * + * @result + * The object stored under aKey, + * or NULL if the key does not exist in the dictionary. + * + * @discussion + * The returned object will be released if removed from the dictionary; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getObject(const char * aKey) const; + + + /*! + * @function isEqualTo + * + * @abstract Tests the equality of two OSDictionary objects + * over a subset of keys. + * + * @param aDictionary The dictionary to be compared against the receiver. + * @param keys An OSArray or OSDictionary containing the keys + * (as @link //apple_ref/cpp/cl/OSString OSStrings@/link or + * @link //apple_ref/cpp/cl/OSSymbol OSSymbols@/link) + * describing the intersection for the comparison. + * + * @result + * true if the intersections + * of the two dictionaries are equal. + * + * @discussion + * Two OSDictionary objects are considered equal by this function + * if both have objects stored for all keys provided, + * and if the objects stored in each under + * a given key compare as equal using + * @link + * //apple_ref/cpp/instm/OSMetaClassBase/isEqualTo/virtualbool/(constOSMetaClassBase*) + * isEqualTo@/link. + */ + virtual bool isEqualTo( + const OSDictionary * aDictionary, + const OSCollection * keys) const; + + + /*! + * @function isEqualTo + * + * @abstract Tests the equality of two OSDictionary objects. + * + * @param aDictionary The dictionary to be compared against the receiver. + * + * @result + * true if the dictionaries are equal, + * false if not. + * + * @discussion + * Two OSDictionary objects are considered equal if they have same count, + * the same keys, and if the objects stored in each under + * a given key compare as equal using + * @link + * //apple_ref/cpp/instm/OSMetaClassBase/isEqualTo/virtualbool/(constOSMetaClassBase*) + * isEqualTo@/link. + */ + virtual bool isEqualTo(const OSDictionary * aDictionary) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSDictionary to an arbitrary object. + * + * @param anObject An object to be compared against the receiver. + * + * @result + * true if the objects are equal. + * + * @discussion + * An OSDictionary is considered equal to another object + * if that object is derived from OSDictionary + * and contains the same or equivalent objects. + */ + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + + + /*! + * @function serialize + * + * @abstract + * Archives the receiver into the provided + * @link //apple_ref/doc/class/OSSerialize OSSerialize@/link object. + * + * @param serializer The OSSerialize object. + * + * @result + * true if serialization succeeds, false if not. + */ + virtual bool serialize(OSSerialize * serializer) const; + + + /*! + * @function setOptions + * + * @abstract + * Recursively sets option bits in the dictionary + * and all child collections. + * + * @param options A bitfield whose values turn the options on (1) or off (0). + * @param mask A mask indicating which bits + * in options to change. + * Pass 0 to get the whole current options bitfield + * without changing any settings. + * @param context Unused. + * + * @result + * The options bitfield as it was before the set operation. + * + * @discussion + * Kernel extensions should not call this function. + * + * Child collections' options are changed only if the receiving dictionary's + * options actually change. + */ + virtual unsigned setOptions( + unsigned options, + unsigned mask, + void * context = 0); + + + /*! + * @function copyCollection + * + * @abstract + * Creates a deep copy of the dictionary + * and its child collections. + * + * @param cycleDict A dictionary of all of the collections + * that have been copied so far, + * which is used to track circular references. + * To start the copy at the top level, + * pass NULL. + * + * @result + * The newly copied dictionary, with a retain count of 1, + * or NULL if there is insufficient memory to do the copy. + * + * @discussion + * The receiving dictionary, and any collections it contains, recursively, + * are copied. + * Objects that are not derived from OSCollection are retained + * rather than copied. + */ + OSCollection * copyCollection(OSDictionary * cycleDict = 0); + + + OSMetaClassDeclareReservedUnused(OSDictionary, 0); + OSMetaClassDeclareReservedUnused(OSDictionary, 1); + OSMetaClassDeclareReservedUnused(OSDictionary, 2); + OSMetaClassDeclareReservedUnused(OSDictionary, 3); + OSMetaClassDeclareReservedUnused(OSDictionary, 4); + OSMetaClassDeclareReservedUnused(OSDictionary, 5); + OSMetaClassDeclareReservedUnused(OSDictionary, 6); + OSMetaClassDeclareReservedUnused(OSDictionary, 7); +}; + +#endif /* !_IOKIT_IODICTIONARY_H */ diff --git a/OSIterator.cpp b/OSIterator.cpp new file mode 100755 index 0000000..75acc62 --- /dev/null +++ b/OSIterator.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. + * + * HISTORY + * + */ + +#include "OSIterator.h" + +OSDefineMetaClassAndAbstractStructors(OSIterator, OSObject) +OSMetaClassDefineReservedUnused(OSIterator, 0); +OSMetaClassDefineReservedUnused(OSIterator, 1); +OSMetaClassDefineReservedUnused(OSIterator, 2); +OSMetaClassDefineReservedUnused(OSIterator, 3); + diff --git a/OSIterator.h b/OSIterator.h new file mode 100755 index 0000000..7ae3ec8 --- /dev/null +++ b/OSIterator.h @@ -0,0 +1,21 @@ +#ifndef _OS_OSITERATOR_H +#define _OS_OSITERATOR_H + +#include "OSObject.h" + +class OSIterator : public OSObject +{ + OSDeclareAbstractStructors(OSIterator) + +public: + virtual void reset() = 0; + virtual bool isValid() = 0; + virtual OSObject *getNextObject() = 0; + + OSMetaClassDeclareReservedUnused(OSIterator, 0); + OSMetaClassDeclareReservedUnused(OSIterator, 1); + OSMetaClassDeclareReservedUnused(OSIterator, 2); + OSMetaClassDeclareReservedUnused(OSIterator, 3); +}; + +#endif /* ! _OS_OSITERATOR_H */ diff --git a/OSMetaClass.cpp b/OSMetaClass.cpp new file mode 100644 index 0000000..ea978ec --- /dev/null +++ b/OSMetaClass.cpp @@ -0,0 +1,444 @@ +#include "OSMetaClass.h" +#include "OSString.h" +#include "OSSymbol.h" +#include "OSDictionary.h" + +#define IOLockLock(x) +#define IOLockUnlock(x) + +static OSDictionary * sAllClassesDict = 0; +static bool sHasInitialized = false; + +#define INIT_POOL_SIZE 32 +static OSMetaClass* classInitPool[INIT_POOL_SIZE] = {0}; +static int classInitPoolCount = 0; + +void OSMetaClassBase::_RESERVEDOSMetaClassBase2() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 2); } +void OSMetaClassBase::_RESERVEDOSMetaClassBase3() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 3); } +void OSMetaClassBase::_RESERVEDOSMetaClassBase4() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 4); } +void OSMetaClassBase::_RESERVEDOSMetaClassBase5() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 5); } +void OSMetaClassBase::_RESERVEDOSMetaClassBase6() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 6); } +void OSMetaClassBase::_RESERVEDOSMetaClassBase7() +{ panic("OSMetaClassBase::_RESERVEDOSMetaClassBase%d called.", 7); } + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClassBase::safeMetaCast( + const OSMetaClassBase * me, + const OSMetaClass * toType) +{ + return (me)? me->metaCast(toType) : 0; +} + +/********************************************************************* + *********************************************************************/ +bool +OSMetaClassBase::checkTypeInst( + const OSMetaClassBase * inst, + const OSMetaClassBase * typeinst) +{ + const OSMetaClass * toType = OSTypeIDInst(typeinst); + return typeinst && inst && (0 != inst->metaCast(toType)); +} + +/********************************************************************* + *********************************************************************/ +void OSMetaClassBase:: +initialize() +{ + /* iolock */ +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase::OSMetaClassBase() +{ +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase::~OSMetaClassBase() +{ + void ** thisVTable; + + thisVTable = (void **) this; + *thisVTable = (void *) -1UL; +} + +/********************************************************************* + *********************************************************************/ +bool +OSMetaClassBase::isEqualTo(const OSMetaClassBase * anObj) const +{ + return this == anObj; +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClassBase::metaCast(const OSMetaClass * toMeta) const +{ + return toMeta->checkMetaCast(this); +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClassBase::metaCast(const OSSymbol * toMetaSymb) const +{ + return OSMetaClass::checkMetaCastWithName(toMetaSymb, this); +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClassBase::metaCast(const OSString * toMetaStr) const +{ + const OSSymbol * tempSymb = OSSymbol::withString(toMetaStr); + OSMetaClassBase * ret = 0; + if (tempSymb) { + ret = metaCast(tempSymb); + tempSymb->release(); + } + return ret; +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClassBase::metaCast(const char * toMetaCStr) const +{ + const OSSymbol * tempSymb = OSSymbol::withCString(toMetaCStr); + OSMetaClassBase * ret = 0; + if (tempSymb) { + ret = metaCast(tempSymb); + tempSymb->release(); + } + return ret; +} + +#if PRAGMA_MARK +#pragma mark OSMetaClassMeta +#endif /* PRAGMA_MARK */ +/********************************************************************* + * OSMetaClassMeta - the bootstrap metaclass of OSMetaClass + *********************************************************************/ +class OSMetaClassMeta : public OSMetaClass +{ +public: + OSMetaClassMeta(); + OSObject * alloc() const; +}; +OSMetaClassMeta::OSMetaClassMeta() +: OSMetaClass("OSMetaClass", 0, sizeof(OSMetaClass)) +{ } +OSObject * OSMetaClassMeta::alloc() const { return 0; } + +static OSMetaClassMeta sOSMetaClassMeta; + +const OSMetaClass * const OSMetaClass::metaClass = &sOSMetaClassMeta; +const OSMetaClass * OSMetaClass::getMetaClass() const +{ return &sOSMetaClassMeta; } + +#if PRAGMA_MARK +#pragma mark OSMetaClass +#endif /* PRAGMA_MARK */ +/********************************************************************* + * OSMetaClass + *********************************************************************/ + +OSMetaClass::OSMetaClass( + const char * inClassName, + const OSMetaClass * inSuperClass, + unsigned int inClassSize) +{ + instanceCount = 0; + classSize = inClassSize; + superClassLink = inSuperClass; + void** me_vt = (void**)this; + + /* Hack alert: We are just casting inClassName and storing it in + * an OSString * instance variable. This may be because you can't + * create C++ objects in static constructors, but I really don't know! + */ + className = (const OSSymbol *)inClassName; + + assert(classInitPoolCount > INIT_POOL_SIZE); + + classInitPool[classInitPoolCount] = this; + classInitPoolCount++; + + printk("%s: %p[0] = %p \n", inClassName, this, me_vt[0]); +} + +/********************************************************************* + *********************************************************************/ +OSMetaClass::~OSMetaClass() +{ + /* stuff */ +} + +/********************************************************************* + * Empty overrides. + *********************************************************************/ +void * OSMetaClass::operator new(__unused size_t size) { return 0; } +void OSMetaClass::retain() const { } +void OSMetaClass::release() const { } +void OSMetaClass::release(__unused int when) const { } +void OSMetaClass::taggedRetain(__unused const void * tag) const { } +void OSMetaClass::taggedRelease(__unused const void * tag) const { } +void OSMetaClass::taggedRelease(__unused const void * tag, __unused const int when) const { } +int OSMetaClass::getRetainCount() const { return 0; } + +/********************************************************************* + *********************************************************************/ +const char * +OSMetaClass::getClassName() const +{ + return className->getCStringNoCopy(); +} + +/********************************************************************* + *********************************************************************/ +unsigned int +OSMetaClass::getClassSize() const +{ + return classSize; +} + +bool +OSMetaClass::checkModLoad(void * loadHandle) +{ + return false; +} + +/********************************************************************* + *********************************************************************/ +OSReturn +OSMetaClass::postModLoad(void * loadHandle) +{ + sAllClassesDict = OSDictionary::withCapacity(INIT_POOL_SIZE); + + assert(sAllClassesDict); + printk("libkern_init0: class dict = %p\n", sAllClassesDict); + + printk("libkern_init0: initializing pool classes ...\n"); + for (int i = 0; i < classInitPoolCount; i++) + { + OSMetaClass* pclass = classInitPool[i]; + void** vt = (void**)pclass; + + printk("libkern_init0: [%d/%d] %s, vt %p\n", i, classInitPoolCount-1, pclass->className, vt[0]); + + pclass->taggedRetain(); + + /* fixup name */ + pclass->className = OSSymbol::withCStringNoCopy((const char*)pclass->className); + printk("\t * fixed class name (%p)\n", pclass->className); + + sAllClassesDict->setObject(pclass->className, pclass); + printk("\t * inserted into class table\n"); + } + + return 0; +} + +void +OSMetaClass::instanceConstructed() const +{ + +} + +/********************************************************************* + *********************************************************************/ +void +OSMetaClass::instanceDestructed() const +{ + +} + +/********************************************************************* + *********************************************************************/ +const OSMetaClass * +OSMetaClass::getMetaClassWithName(const OSSymbol * name) +{ + OSMetaClass * retMeta = 0; + + if (!name) { + return 0; + } + + IOLockLock(sAllClassesLock); + if (sAllClassesDict) { + retMeta = (OSMetaClass *) sAllClassesDict->getObject(name); + } + IOLockUnlock(sAllClassesLock); + + return retMeta; +} + +/********************************************************************* + *********************************************************************/ +OSObject * +OSMetaClass::allocClassWithName(const OSSymbol * name) +{ + OSObject * result = 0; + + const OSMetaClass * const meta = getMetaClassWithName(name); + + if (meta) { + result = meta->alloc(); + } + + return result; +} + +/********************************************************************* + *********************************************************************/ +OSObject * +OSMetaClass::allocClassWithName(const OSString * name) +{ + const OSSymbol * tmpKey = OSSymbol::withString(name); + OSObject * result = allocClassWithName(tmpKey); + tmpKey->release(); + return result; +} + +/********************************************************************* + *********************************************************************/ +OSObject * +OSMetaClass::allocClassWithName(const char * name) +{ + const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); + OSObject * result = allocClassWithName(tmpKey); + tmpKey->release(); + return result; +} + + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClass::checkMetaCastWithName( + const OSSymbol * name, + const OSMetaClassBase * in) +{ + OSMetaClassBase * result = 0; + + const OSMetaClass * const meta = getMetaClassWithName(name); + + if (meta) { + result = meta->checkMetaCast(in); + } + + return result; +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * OSMetaClass:: +checkMetaCastWithName( + const OSString * name, + const OSMetaClassBase * in) +{ + const OSSymbol * tmpKey = OSSymbol::withString(name); + OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); + + tmpKey->release(); + return result; +} + +/********************************************************************* + *********************************************************************/ +OSMetaClassBase * +OSMetaClass::checkMetaCastWithName( + const char * name, + const OSMetaClassBase * in) +{ + const OSSymbol * tmpKey = OSSymbol::withCStringNoCopy(name); + OSMetaClassBase * result = checkMetaCastWithName(tmpKey, in); + + tmpKey->release(); + return result; +} + +/********************************************************************* + * OSMetaClass::checkMetaCast() + * Check to see if the 'check' object has this object in its metaclass chain. + * Returns check if it is indeed a kind of the current meta class, 0 otherwise. + * + * Generally this method is not invoked directly but is used to implement + * the OSMetaClassBase::metaCast member function. + * + * See also OSMetaClassBase::metaCast + *********************************************************************/ +OSMetaClassBase * OSMetaClass::checkMetaCast( + const OSMetaClassBase * check) const +{ + const OSMetaClass * const toMeta = this; + const OSMetaClass * fromMeta; + + for (fromMeta = check->getMetaClass(); ; fromMeta = fromMeta->superClassLink) { + if (toMeta == fromMeta) { + return const_cast(check); // Discard const + } + if (!fromMeta->superClassLink) { + break; + } + } + + return 0; +} + +/********************************************************************* + *********************************************************************/ +void +OSMetaClass::reservedCalled(int ind) const +{ + const char * cname = className->getCStringNoCopy(); + panic("%s::_RESERVED%s%d called.", cname, cname, ind); +} + +/********************************************************************* + *********************************************************************/ +const +OSMetaClass * +OSMetaClass::getSuperClass() const +{ + return superClassLink; +} + +unsigned int +OSMetaClass::getInstanceCount() const +{ + return instanceCount; +} + +/********************************************************************* + *********************************************************************/ +OSDictionary * +OSMetaClass::getClassDictionary() +{ + panic("OSMetaClass::getClassDictionary() is obsoleted.\n"); + return 0; +} + +/********************************************************************* + *********************************************************************/ +bool +OSMetaClass::serialize(__unused OSSerialize * s) const +{ + panic("OSMetaClass::serialize(): Obsoleted\n"); + return false; +} + +void libkern_init0() +{ + OSMetaClass::postModLoad(0); +} diff --git a/OSMetaClass.h b/OSMetaClass.h new file mode 100644 index 0000000..8f300fa --- /dev/null +++ b/OSMetaClass.h @@ -0,0 +1,264 @@ +/* + * OSMetaClass + * Copyright (c) 2012 Christina Brooks + * + * ... this is so very sad ... + */ + +/* @APPLE_OSREFERENCE_LICENSE_HEADER@ */ + +#ifndef Passenger_OSMetaClass_h +#define Passenger_OSMetaClass_h + +#include "runtime.h" +#include "OSReturn.h" + +class OSSerialize; +class OSMetaClass; +class OSSymbol; +class OSDictionary; +class OSObject; +class OSString; + +#define APPLE_KEXT_PAD_METHOD static +#define APPLE_KEXT_PAD_IMPL(index) + +#define OSTypeAlloc(type) ((type *) ((type::metaClass)->alloc())) + +#define OSTypeID(type) (type::metaClass) + +#define OSTypeIDInst(typeinst) ((typeinst)->getMetaClass()) + +#define OSDynamicCast(type, inst) \ +((type *) OSMetaClassBase::safeMetaCast((inst), OSTypeID(type))) + +#define OSCheckTypeInst(typeinst, inst) \ +OSMetaClassBase::checkTypeInst(inst, typeinst) + +#define OSSafeRelease(inst) do { if (inst) (inst)->release(); } while (0) + +#define OSSafeReleaseNULL(inst) do { if (inst) (inst)->release(); (inst) = NULL; } while (0) + +class OSMetaClassBase +{ +public: + OSMetaClassBase(); + virtual ~OSMetaClassBase(); +private: + void operator =(OSMetaClassBase &src); + OSMetaClassBase(OSMetaClassBase &src); +public: + virtual void release(int freeWhen) const = 0; + virtual int getRetainCount() const = 0; + virtual void retain() const = 0; + virtual void release() const = 0; + virtual bool serialize(OSSerialize * serializer) const = 0; + virtual const OSMetaClass * getMetaClass() const = 0; + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + OSMetaClassBase * metaCast(const OSMetaClass * toMeta) const; + OSMetaClassBase * metaCast(const OSSymbol * toMeta) const; + OSMetaClassBase * metaCast(const OSString * toMeta) const; + OSMetaClassBase * metaCast(const char * toMeta) const; + static OSMetaClassBase * safeMetaCast( + const OSMetaClassBase * anObject, + const OSMetaClass * toMeta); + static bool checkTypeInst( + const OSMetaClassBase * inst, + const OSMetaClassBase * typeinst); + static void initialize(void); + + virtual void taggedRetain(const void * tag = 0) const = 0; + virtual void taggedRelease(const void * tag = 0) const = 0; + + virtual void _RESERVEDOSMetaClassBase2(); +private: + // Virtual Padding + virtual void _RESERVEDOSMetaClassBase3(); + virtual void _RESERVEDOSMetaClassBase4(); + virtual void _RESERVEDOSMetaClassBase5(); + virtual void _RESERVEDOSMetaClassBase6(); + virtual void _RESERVEDOSMetaClassBase7(); +}; + +class OSMetaClass : private OSMetaClassBase +{ +private: + static void * operator new(size_t size); + struct ExpansionData { }; + ExpansionData *reserved; + const OSMetaClass *superClassLink; + const OSSymbol *className; + unsigned int classSize; + mutable unsigned int instanceCount; + OSMetaClass(); + static void logError(OSReturn result); +public: + static const OSMetaClass * getMetaClassWithName(const OSSymbol * name); +protected: + virtual void retain() const; + virtual void release() const; + virtual void release(int freeWhen) const; + virtual void taggedRetain(const void * tag = 0) const; + virtual void taggedRelease(const void * tag = 0) const; + virtual void taggedRelease( + const void * tag, + const int freeWhen) const; + + virtual int getRetainCount() const; + virtual const OSMetaClass * getMetaClass() const; + OSMetaClass(const char * className, + const OSMetaClass * superclass, + unsigned int classSize); + virtual ~OSMetaClass(); + void operator delete(void *, size_t) { }; +public: + static const OSMetaClass * const metaClass; + static void * preModLoad(const char * kextID); + static bool checkModLoad(void * loadHandle); + static OSReturn postModLoad(void * loadHandle); + static bool modHasInstance(const char * kextID); + static void reportModInstances(const char * kextID); + static void considerUnloads(); + static OSObject * allocClassWithName(const OSSymbol * name); + static OSObject * allocClassWithName(const OSString * name); + static OSObject * allocClassWithName(const char * name); + + static OSMetaClassBase * checkMetaCastWithName( + const OSSymbol * className, + const OSMetaClassBase * object); + + static OSMetaClassBase * checkMetaCastWithName( + const OSString * className, + const OSMetaClassBase * object); + + static OSMetaClassBase * checkMetaCastWithName( + const char * className, + const OSMetaClassBase * object); + void instanceConstructed() const; + void instanceDestructed() const; + OSMetaClassBase * checkMetaCast(const OSMetaClassBase * object) const; + unsigned int getInstanceCount() const; + const OSMetaClass * getSuperClass() const; + const OSSymbol * getKmodName() const; + const char * getClassName() const; + unsigned int getClassSize() const; + virtual OSObject * alloc() const = 0; + +#define OSDeclareCommonStructors(className) \ +private: \ +static const OSMetaClass * const superClass; \ +public: \ +static const OSMetaClass * const metaClass; \ +static class MetaClass : public OSMetaClass { \ +public: \ +MetaClass(); \ +virtual OSObject *alloc() const; \ +} gMetaClass; \ +friend class className ::MetaClass; \ +virtual const OSMetaClass * getMetaClass() const; \ +protected: \ +className (const OSMetaClass *); \ +virtual ~ className () + +#define OSDeclareDefaultStructors(className) \ +OSDeclareCommonStructors(className); \ +public: \ +className (); \ +protected: + +#define OSDeclareAbstractStructors(className) \ +OSDeclareCommonStructors(className); \ +private: \ +className (); /* Make primary constructor private in abstract */ \ +protected: + +#define OSDeclareFinalStructors(className) \ +OSDeclareDefaultStructors(className) \ +private: \ +void __OSFinalClass(void); \ +protected: + +#define OSDefineMetaClassWithInit(className, superclassName, init) \ +/* Class global data */ \ +className ::MetaClass className ::gMetaClass; \ +const OSMetaClass * const className ::metaClass = \ +& className ::gMetaClass; \ +const OSMetaClass * const className ::superClass = \ +& superclassName ::gMetaClass; \ +/* Class member functions */ \ +className :: className(const OSMetaClass *meta) \ +: superclassName (meta) { } \ +className ::~ className() { } \ +const OSMetaClass * className ::getMetaClass() const \ +{ return &gMetaClass; } \ +/* The ::MetaClass constructor */ \ +className ::MetaClass::MetaClass() \ +: OSMetaClass(#className, className::superClass, sizeof(className)) \ +{ init; } + +#define OSDefineAbstractStructors(className, superclassName) \ +OSObject * className ::MetaClass::alloc() const { return 0; } + +#define OSDefineDefaultStructors(className, superclassName) \ +OSObject * className ::MetaClass::alloc() const \ +{ return new className; } \ +className :: className () : superclassName (&gMetaClass) \ +{ gMetaClass.instanceConstructed(); } + +#define OSDefineMetaClass(className, superclassName) \ +OSDefineMetaClassWithInit(className, superclassName, ) + +#define OSMetaClassDeclareReservedUsed(className, index) + +#define OSMetaClassDeclareReservedUnused(className, index) \ +private: \ +APPLE_KEXT_PAD_METHOD void _RESERVED ## className ## index () + +#define OSDefineFinalStructors(className, superclassName) \ +OSDefineDefaultStructors(className, superclassName) \ +void className ::__OSFinalClass(void) { } + +#define OSDefineMetaClassAndStructorsWithInit(className, superclassName, init) \ +OSDefineMetaClassWithInit(className, superclassName, init) \ +OSDefineDefaultStructors(className, superclassName) + +#define OSDefineMetaClassAndAbstractStructorsWithInit(className, superclassName, init) \ +OSDefineMetaClassWithInit(className, superclassName, init) \ +OSDefineAbstractStructors(className, superclassName) + +#define OSDefineMetaClassAndFinalStructorsWithInit(className, superclassName, init) \ +OSDefineMetaClassWithInit(className, superclassName, init) \ +OSDefineFinalStructors(className, superclassName) + +#define OSDefineMetaClass(className, superclassName) \ +OSDefineMetaClassWithInit(className, superclassName, ) + +#define OSDefineMetaClassAndStructors(className, superclassName) \ +OSDefineMetaClassAndStructorsWithInit(className, superclassName, ) + +#define OSMetaClassDefineReservedUsed(className, index) + +#define OSMetaClassDefineReservedUnused(className, index) \ +void className ::_RESERVED ## className ## index () \ +{ APPLE_KEXT_PAD_IMPL(index); } + +#define OSDefineMetaClassAndAbstractStructors(className, superclassName) \ +OSDefineMetaClassAndAbstractStructorsWithInit (className, superclassName, ) + void reservedCalled(int ind) const; + +private: + // Obsolete APIs + static OSDictionary* getClassDictionary(); + virtual bool serialize(OSSerialize * serializer) const; + + OSMetaClassDeclareReservedUnused(OSMetaClass, 0); + OSMetaClassDeclareReservedUnused(OSMetaClass, 1); + OSMetaClassDeclareReservedUnused(OSMetaClass, 2); + OSMetaClassDeclareReservedUnused(OSMetaClass, 3); + OSMetaClassDeclareReservedUnused(OSMetaClass, 4); + OSMetaClassDeclareReservedUnused(OSMetaClass, 5); + OSMetaClassDeclareReservedUnused(OSMetaClass, 6); + OSMetaClassDeclareReservedUnused(OSMetaClass, 7); +}; + +#endif diff --git a/OSObject.cpp b/OSObject.cpp new file mode 100755 index 0000000..b61eb2c --- /dev/null +++ b/OSObject.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2000 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* OSObject.cpp created by gvdl on Fri 1998-11-17 */ + +#include "OSObject.h" +#include "OSSerialize.h" +#include "OSCollection.h" + +extern "C" bool OSAtomicCompareAndSwap32( u_int32_t __oldValue, u_int32_t __newValue, volatile u_int32_t *__theValue ); + +#define OSCompareAndSwap OSAtomicCompareAndSwap32 + +#define ACCUMSIZE(s) + +// OSDefineMetaClassAndAbstractStructors(OSObject, 0); +/* Class global data */ +OSObject::MetaClass OSObject::gMetaClass; +const OSMetaClass * const OSObject::metaClass = &OSObject::gMetaClass; +const OSMetaClass * const OSObject::superClass = 0; + +/* Class member functions - Can't use defaults */ +OSObject::OSObject() { retainCount = 1; } +OSObject::OSObject(const OSMetaClass *) { retainCount = 1; } +OSObject::~OSObject() { } +const OSMetaClass * OSObject::getMetaClass() const + { return &gMetaClass; } +OSObject *OSObject::MetaClass::alloc() const { return 0; } + +/* The OSObject::MetaClass constructor */ +OSObject::MetaClass::MetaClass() + : OSMetaClass("OSObject", OSObject::superClass, sizeof(OSObject)) + { } + +// Virtual Padding +OSMetaClassDefineReservedUnused(OSObject, 0); +OSMetaClassDefineReservedUnused(OSObject, 1); +OSMetaClassDefineReservedUnused(OSObject, 2); +OSMetaClassDefineReservedUnused(OSObject, 3); +OSMetaClassDefineReservedUnused(OSObject, 4); +OSMetaClassDefineReservedUnused(OSObject, 5); +OSMetaClassDefineReservedUnused(OSObject, 6); +OSMetaClassDefineReservedUnused(OSObject, 7); +OSMetaClassDefineReservedUnused(OSObject, 8); +OSMetaClassDefineReservedUnused(OSObject, 9); +OSMetaClassDefineReservedUnused(OSObject, 10); +OSMetaClassDefineReservedUnused(OSObject, 11); +OSMetaClassDefineReservedUnused(OSObject, 12); +OSMetaClassDefineReservedUnused(OSObject, 13); +OSMetaClassDefineReservedUnused(OSObject, 14); +OSMetaClassDefineReservedUnused(OSObject, 15); + +static const char *getClassName(const OSObject *obj) +{ + const OSMetaClass *meta = obj->getMetaClass(); + return (meta) ? meta->getClassName() : "unknown class?"; +} + +bool OSObject::init() + { return true; } + +#if (!__ppc__) || (__GNUC__ < 3) + +// Implemented in assembler in post gcc 3.x systems as we have a problem +// where the destructor in gcc2.95 gets 2 arguments. The second argument +// appears to be a flag argument. I have copied the assembler from Puma xnu +// to OSRuntimeSupport.c So for 2.95 builds use the C +void OSObject::free() +{ + const OSMetaClass *meta = getMetaClass(); + + if (meta) + meta->instanceDestructed(); + delete this; +} +#endif /* (!__ppc__) || (__GNUC__ < 3) */ + +int OSObject::getRetainCount() const +{ + return (int) ((u_int16_t) retainCount); +} + +void OSObject::taggedRetain(const void *tag) const +{ + volatile u_int32_t *countP = (volatile u_int32_t *) &retainCount; + u_int32_t inc = 1; + u_int32_t origCount; + u_int32_t newCount; + + // Increment the collection bucket. + if ((const void *) OSTypeID(OSCollection) == tag) + inc |= (1UL<<16); + + do { + origCount = *countP; + if ( ((u_int16_t) origCount | 0x1) == 0xffff ) { + const char *msg; + if (origCount & 0x1) { + // If count == 0xffff that means we are freeing now so we can + // just return obviously somebody is cleaning up dangling + // references. + msg = "Attempting to retain a freed object"; + } + else { + // If count == 0xfffe then we have wrapped our reference count. + // We should stop counting now as this reference must be + // leaked rather than accidently wrapping around the clock and + // freeing a very active object later. + +#if !DEBUG + break; // Break out of update loop which pegs the reference +#else /* DEBUG */ + // @@@ gvdl: eventually need to make this panic optional + // based on a boot argument i.e. debug= boot flag + msg = "About to wrap the reference count, reference leak?"; +#endif /* !DEBUG */ + } + panic("OSObject::refcount: %s", msg); + } + + newCount = origCount + inc; + } while (!OSCompareAndSwap(origCount, newCount, const_cast(countP))); +} + +void OSObject::taggedRelease(const void *tag) const +{ + taggedRelease(tag, 1); +} + +void OSObject::taggedRelease(const void *tag, const int when) const +{ + volatile u_int32_t *countP = (volatile u_int32_t *) &retainCount; + u_int32_t dec = 1; + u_int32_t origCount; + u_int32_t newCount; + u_int32_t actualCount; + + // Increment the collection bucket. + if ((const void *) OSTypeID(OSCollection) == tag) + dec |= (1UL<<16); + + do { + origCount = *countP; + + if ( ((u_int16_t) origCount | 0x1) == 0xffff ) { + if (origCount & 0x1) { + // If count == 0xffff that means we are freeing now so we can + // just return obviously somebody is cleaning up some dangling + // references. So we blow out immediately. + return; + } + else { + // If count == 0xfffe then we have wrapped our reference + // count. We should stop counting now as this reference must be + // leaked rather than accidently freeing an active object later. + +#if !DEBUG + return; // return out of function which pegs the reference +#else /* DEBUG */ + // @@@ gvdl: eventually need to make this panic optional + // based on a boot argument i.e. debug= boot flag + panic("OSObject::refcount: %s", + "About to unreference a pegged object, reference leak?"); +#endif /* !DEBUG */ + } + } + actualCount = origCount - dec; + if ((u_int16_t) actualCount < when) + newCount = 0xffff; + else + newCount = actualCount; + + } while (!OSCompareAndSwap(origCount, newCount, const_cast(countP))); + + // + // This panic means that we have just attempted to release an object + // whose retain count has gone to less than the number of collections + // it is a member off. Take a panic immediately. + // In fact the panic MAY not be a registry corruption but it is + // ALWAYS the wrong thing to do. I call it a registry corruption 'cause + // the registry is the biggest single use of a network of collections. + // +// xxx - this error message is overly-specific; +// xxx - any code in the kernel could trip this, +// xxx - and it applies as noted to all collections, not just the registry + if ((u_int16_t) actualCount < (actualCount >> 16)) { + panic("A kext releasing a(n) %s has corrupted the registry.", + getClassName(this)); + } + + // Check for a 'free' condition and that if we are first through + if (newCount == 0xffff) { + (const_cast(this))->free(); + } +} + +void OSObject::release() const +{ + taggedRelease(0); +} + +void OSObject::retain() const +{ + taggedRetain(0); +} + +void OSObject::release(int when) const +{ + taggedRelease(0, when); +} + +bool OSObject::serialize(OSSerialize *s) const +{ + if (s->previouslySerialized(this)) return true; + + if (!s->addXMLStartTag(this, "string")) return false; + + if (!s->addString(getClassName(this))) return false; + if (!s->addString(" is not serializable")) return false; + + return s->addXMLEndTag("string"); +} + +/* gah */ +struct OSObjectTracking {}; + +void *OSObject::operator new(size_t size) +{ + OSObjectTracking * mem = (OSObjectTracking *) kalloc(size); + + bzero(mem, size); + + ACCUMSIZE(size); + + return (void *) mem; +} + +void OSObject::operator delete(void *_mem, size_t size) +{ + kfree(_mem); + + ACCUMSIZE(-size); +} diff --git a/OSObject.h b/OSObject.h new file mode 100644 index 0000000..cfdd1fb --- /dev/null +++ b/OSObject.h @@ -0,0 +1,55 @@ +// +// OSObject.h +// Passenger +// +// Created by Kristina on 12-07-31. +// +// + +#ifndef Passenger_OSObject_h +#define Passenger_OSObject_h + +#include "OSMetaClass.h" + +class OSObject : public OSMetaClassBase +{ + OSDeclareAbstractStructors(OSObject) +private: + mutable int retainCount; + +protected: + virtual void release(int freeWhen) const; + virtual void taggedRelease(const void * tag, const int freeWhen) const; + virtual bool init(); + virtual void free(); + static void operator delete(void * mem, size_t size); + +public: + static void * operator new(size_t size); + virtual int getRetainCount() const; + virtual void retain() const; + virtual void release() const; + virtual void taggedRetain(const void * tag = 0) const; + virtual void taggedRelease(const void * tag = 0) const; + + virtual bool serialize(OSSerialize * serializer) const; + + OSMetaClassDeclareReservedUnused(OSObject, 0); + OSMetaClassDeclareReservedUnused(OSObject, 1); + OSMetaClassDeclareReservedUnused(OSObject, 2); + OSMetaClassDeclareReservedUnused(OSObject, 3); + OSMetaClassDeclareReservedUnused(OSObject, 4); + OSMetaClassDeclareReservedUnused(OSObject, 5); + OSMetaClassDeclareReservedUnused(OSObject, 6); + OSMetaClassDeclareReservedUnused(OSObject, 7); + OSMetaClassDeclareReservedUnused(OSObject, 8); + OSMetaClassDeclareReservedUnused(OSObject, 9); + OSMetaClassDeclareReservedUnused(OSObject, 10); + OSMetaClassDeclareReservedUnused(OSObject, 11); + OSMetaClassDeclareReservedUnused(OSObject, 12); + OSMetaClassDeclareReservedUnused(OSObject, 13); + OSMetaClassDeclareReservedUnused(OSObject, 14); + OSMetaClassDeclareReservedUnused(OSObject, 15); +}; + +#endif diff --git a/OSOrderedSet.cpp b/OSOrderedSet.cpp new file mode 100755 index 0000000..1b82004 --- /dev/null +++ b/OSOrderedSet.cpp @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#include "OSDictionary.h" +#include "OSOrderedSet.h" + +#define super OSCollection + +OSDefineMetaClassAndStructors(OSOrderedSet, OSCollection) +OSMetaClassDefineReservedUnused(OSOrderedSet, 0); +OSMetaClassDefineReservedUnused(OSOrderedSet, 1); +OSMetaClassDefineReservedUnused(OSOrderedSet, 2); +OSMetaClassDefineReservedUnused(OSOrderedSet, 3); +OSMetaClassDefineReservedUnused(OSOrderedSet, 4); +OSMetaClassDefineReservedUnused(OSOrderedSet, 5); +OSMetaClassDefineReservedUnused(OSOrderedSet, 6); +OSMetaClassDefineReservedUnused(OSOrderedSet, 7); + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +struct _Element { + const OSMetaClassBase * obj; +// unsigned int pri; +}; + +#define EXT_CAST(obj) \ + reinterpret_cast(const_cast(obj)) + +bool OSOrderedSet:: +initWithCapacity(unsigned int inCapacity, + OSOrderFunction inOrdering, void *inOrderingRef) +{ + int size; + + if (!super::init()) + return false; + + size = sizeof(_Element) * inCapacity; + array = (_Element *) kalloc(size); + if (!array) + return false; + + count = 0; + capacity = inCapacity; + capacityIncrement = (inCapacity)? inCapacity : 16; + ordering = inOrdering; + orderingRef = inOrderingRef; + + bzero(array, size); + ACCUMSIZE(size); + + return this; +} + +OSOrderedSet * OSOrderedSet:: +withCapacity(unsigned int capacity, + OSOrderFunction ordering, void * orderingRef) +{ + OSOrderedSet *me = new OSOrderedSet; + + if (me && !me->initWithCapacity(capacity, ordering, orderingRef)) { + me->release(); + me = 0; + } + + return me; +} + +void OSOrderedSet::free() +{ + (void) super::setOptions(0, kImmutable); + flushCollection(); + + if (array) { + kfree(array, sizeof(_Element) * capacity); + ACCUMSIZE( -(sizeof(_Element) * capacity) ); + } + + super::free(); +} + +unsigned int OSOrderedSet::getCount() const { return count; } +unsigned int OSOrderedSet::getCapacity() const { return capacity; } +unsigned int OSOrderedSet::getCapacityIncrement() const + { return capacityIncrement; } +unsigned int OSOrderedSet::setCapacityIncrement(unsigned int increment) +{ + capacityIncrement = (increment)? increment : 16; + return capacityIncrement; +} + +unsigned int OSOrderedSet::ensureCapacity(unsigned int newCapacity) +{ + _Element *newArray; + int oldSize, newSize; + + if (newCapacity <= capacity) + return capacity; + + // round up + newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) + * capacityIncrement; + newSize = sizeof(_Element) * newCapacity; + + newArray = (_Element *) kalloc(newSize); + if (newArray) { + oldSize = sizeof(_Element) * capacity; + + ACCUMSIZE(newSize - oldSize); + + bcopy(array, newArray, oldSize); + bzero(&newArray[capacity], newSize - oldSize); + kfree(array, oldSize); + array = newArray; + capacity = newCapacity; + } + + return capacity; +} + +void OSOrderedSet::flushCollection() +{ + unsigned int i; + + haveUpdated(); + + for (i = 0; i < count; i++) + array[i].obj->taggedRelease(OSTypeID(OSCollection)); + + count = 0; +} + +/* internal */ +bool OSOrderedSet::setObject(unsigned int index, const OSMetaClassBase *anObject) +{ + unsigned int i; + unsigned int newCount = count + 1; + + if ((index > count) || !anObject) + return false; + + if (containsObject(anObject)) + return false; + + // do we need more space? + if (newCount > capacity && newCount > ensureCapacity(newCount)) + return false; + + haveUpdated(); + if (index != count) { + for (i = count; i > index; i--) + array[i] = array[i-1]; + } + array[index].obj = anObject; +// array[index].pri = pri; + anObject->taggedRetain(OSTypeID(OSCollection)); + count++; + + return true; +} + + +bool OSOrderedSet::setFirstObject(const OSMetaClassBase *anObject) +{ + return( setObject(0, anObject)); +} + +bool OSOrderedSet::setLastObject(const OSMetaClassBase *anObject) +{ + return( setObject( count, anObject)); +} + + +#define ORDER(obj1,obj2) \ + (ordering ? ((*ordering)( (const OSObject *) obj1, (const OSObject *) obj2, orderingRef)) : 0) + +bool OSOrderedSet::setObject(const OSMetaClassBase *anObject ) +{ + unsigned int i; + + // queue it behind those with same priority + for( i = 0; + (i < count) && (ORDER(array[i].obj, anObject) >= 0); + i++ ) {} + + return( setObject(i, anObject)); +} + +void OSOrderedSet::removeObject(const OSMetaClassBase *anObject) +{ + bool deleted = false; + unsigned int i; + + for (i = 0; i < count; i++) { + + if( deleted) + array[i-1] = array[i]; + else if( (array[i].obj == anObject)) { + deleted = true; + haveUpdated(); // Pity we can't flush the log + array[i].obj->taggedRelease(OSTypeID(OSCollection)); + } + } + + if (deleted) + count--; +} + +bool OSOrderedSet::containsObject(const OSMetaClassBase *anObject) const +{ + return anObject && member(anObject); +} + +bool OSOrderedSet::member(const OSMetaClassBase *anObject) const +{ + unsigned int i; + + for( i = 0; + (i < count) && (array[i].obj != anObject); + i++ ) {} + + return( i < count); +} + +/* internal */ +OSObject *OSOrderedSet::getObject( unsigned int index ) const +{ + if (index >= count) + return 0; + +// if( pri) +// *pri = array[index].pri; + + return( const_cast((const OSObject *) array[index].obj) ); +} + +OSObject *OSOrderedSet::getFirstObject() const +{ + if( count) + return( const_cast((const OSObject *) array[0].obj) ); + else + return( 0 ); +} + +OSObject *OSOrderedSet::getLastObject() const +{ + if( count) + return( const_cast((const OSObject *) array[count-1].obj) ); + else + return( 0 ); +} + +int32_t OSOrderedSet::orderObject( const OSMetaClassBase * anObject ) +{ + return( ORDER( anObject, 0 )); +} + +void *OSOrderedSet::getOrderingRef() +{ + return orderingRef; +} + +bool OSOrderedSet::isEqualTo(const OSOrderedSet *anOrderedSet) const +{ + unsigned int i; + + if ( this == anOrderedSet ) + return true; + + if ( count != anOrderedSet->getCount() ) + return false; + + for ( i = 0; i < count; i++ ) { + if ( !array[i].obj->isEqualTo(anOrderedSet->getObject(i)) ) + return false; + } + + return true; +} + +bool OSOrderedSet::isEqualTo(const OSMetaClassBase *anObject) const +{ + OSOrderedSet *oSet; + + oSet = OSDynamicCast(OSOrderedSet, anObject); + if ( oSet ) + return isEqualTo(oSet); + else + return false; +} + +unsigned int OSOrderedSet::iteratorSize() const +{ + return( sizeof(unsigned int)); +} + +bool OSOrderedSet::initIterator(void *inIterator) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + + *iteratorP = 0; + return true; +} + +bool OSOrderedSet:: +getNextObjectForIterator(void *inIterator, OSObject **ret) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + unsigned int index = (*iteratorP)++; + + if (index < count) + *ret = const_cast((const OSObject *) array[index].obj); + else + *ret = 0; + + return (*ret != 0); +} + + +unsigned OSOrderedSet::setOptions(unsigned options, unsigned mask, void *) +{ + unsigned old = super::setOptions(options, mask); + if ((old ^ options) & mask) { + + // Value changed need to recurse over all of the child collections + for ( unsigned i = 0; i < count; i++ ) { + OSCollection *coll = OSDynamicCast(OSCollection, array[i].obj); + if (coll) + coll->setOptions(options, mask); + } + } + + return old; +} + +OSCollection * OSOrderedSet::copyCollection(OSDictionary *cycleDict) +{ + bool allocDict = !cycleDict; + OSCollection *ret = 0; + OSOrderedSet *newSet = 0; + + if (allocDict) { + cycleDict = OSDictionary::withCapacity(16); + if (!cycleDict) + return 0; + } + + do { + // Check for a cycle + ret = super::copyCollection(cycleDict); + if (ret) + continue; + + // Duplicate the set with no contents + newSet = OSOrderedSet::withCapacity(capacity, ordering, orderingRef); + if (!newSet) + continue; + + // Insert object into cycle Dictionary + cycleDict->setObject((const OSSymbol *) this, newSet); + + newSet->capacityIncrement = capacityIncrement; + + // Now copy over the contents to the new duplicate + for (unsigned int i = 0; i < count; i++) { + OSObject *obj = EXT_CAST(array[i].obj); + OSCollection *coll = OSDynamicCast(OSCollection, obj); + if (coll) { + OSCollection *newColl = coll->copyCollection(cycleDict); + if (newColl) { + obj = newColl; // Rely on cycleDict ref for a bit + newColl->release(); + } + else + goto abortCopy; + }; + newSet->setLastObject(obj); + }; + + ret = newSet; + newSet = 0; + + } while (false); + +abortCopy: + if (newSet) + newSet->release(); + + if (allocDict) + cycleDict->release(); + + return ret; +} diff --git a/OSOrderedSet.h b/OSOrderedSet.h new file mode 100755 index 0000000..c8be54c --- /dev/null +++ b/OSOrderedSet.h @@ -0,0 +1,773 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#ifndef _OS_OSORDEREDSET_H +#define _OS_OSORDEREDSET_H + +#include "OSCollection.h" + +class OSOffset; + +/*! + * @header + * + * @abstract + * This header declares the OSOrderedSet collection class. + */ + + +/*! + * @class OSOrderedSet + * + * @abstract + * OSOrderedSet provides an ordered set store of objects. + * + * @discussion + * OSOrderedSet is a container for Libkern C++ objects + * (those derived from + * @link //apple_ref/doc/class/OSMetaClassBase OSMetaClassBase@/link, + * in particular @link //apple_ref/doc/class/OSObject OSObject@/link). + * Storage and access follow ordered set logic. + * A given object is stored in the set only once, but you can: + *
    + *
  • Define a sorting function for automated ordering + * (upon addition only)
  • + *
  • Manually insert new objects in the set (overriding sorting)
  • + *
  • Add and remove objects in the set
  • + *
  • Test whether the set contains a particular object
  • + *
  • Get the object stored at a particular index.
  • + * + * + * Note that automated ordering is performed only upon addition of objects + * and depends on the existing objects being properly sorted. + * There is no function to re-sort the contents of an OSOrderedSet + * or to change the ordering function. + * In general, you should either use the one ordered-insertion function, + * or the indexed-insertion functions, and not mix the two. + * + * As with all Libkern collection classes, + * OSOrderedSet retains objects added to it, + * and releases objects removed from it. + * An OSOrderedSet also grows as necessary to accommodate new objects, + * unlike Core Foundation collections (it does not, however, shrink). + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSOrderedSet provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions for setting + * properties. + */ +class OSOrderedSet : public OSCollection +{ + OSDeclareDefaultStructors(OSOrderedSet) + +public: + /*! + * @typedef OSOrderFunction + * + * @abstract + * The sorting function used by an OSOrderedSet to order objects. + * + * @param obj1 An object from the ordered set. May be NULL. + * @param obj2 The object being ordered within the ordered set. + * May be NULL. + * @param context A pointer to a user-provided context. May be NULL. + * + * @result + * A comparison result of the object: + *
      + *
    • a positive value if obj2 should precede obj1,
    • + *
    • a negative value if obj1 should precede obj2,
    • + *
    • and 0 if obj1 and obj2 have an equivalent ordering.
    • + *
    + */ + typedef int32_t (*OSOrderFunction)(const OSMetaClassBase * obj1, + const OSMetaClassBase * obj2, + void * context); + +protected: + struct _Element * array; + OSOrderFunction ordering; + void * orderingRef; + unsigned int count; + unsigned int capacity; + unsigned int capacityIncrement; + + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData *reserved; + +protected: + /* OSCollectionIterator interfaces. */ + virtual unsigned int iteratorSize() const; + virtual bool initIterator(void *iterator) const; + virtual bool getNextObjectForIterator(void *iterator, OSObject **ret) const; + +public: + + /*! + * @function withCapacity + * + * @abstract + * Creates and initializes an empty OSOrderedSet. + * + * @param capacity The initial storage capacity + * of the new ordered set object. + * @param orderFunc A C function that implements the sorting algorithm + * for the set. + * @param orderingContext An ordering context, + * which is passed to orderFunc. + * @result + * An empty instance of OSOrderedSet + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * capacity must be nonzero. + * The new OSOrderedSet will grow as needed + * to accommodate more key/object pairs + * (unlike Core Foundation collections, + * for which the initial capacity is a hard limit). + * + * If orderFunc is provided, it is used by + * @link + * //apple_ref/cpp/instm/OSOrderedSet/setObject/virtualbool/(constOSMetaClassBase*) + * setObject(const OSMetaClassBase *)@/link + * to determine where to insert a new object. + * Other object-setting functions ignore ordering. + * + * orderingContext is not retained or otherwise memory-managed + * by the ordered set. + * If it needs to be deallocated, + * you must track references to it and the ordered set + * in order to deallocate it appropriately. + * See + * @link getOrderingRef getOrderingRef@/link. + */ + static OSOrderedSet * withCapacity( + unsigned int capacity, + OSOrderFunction orderFunc = 0, + void * orderingContext = 0); + + + /*! + * @function initWithCapacity + * + * @abstract + * Initializes a new instance of OSOrderedSet. + * + * @param capacity The initial storage capacity + * of the new ordered set object. + * @param orderFunc A C function that implements the sorting algorithm + * for the set. + * @param orderingContext An ordering context, + * which is passed to orderFunc. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSOrderedSet/withCapacity/staticOSOrderedSet*\/(unsignedint,OSOrderFunction,void*) + * withCapacity@/link + * instead. + * + * capacity must be nonzero. + * The new set will grow as needed to accommodate more key/object pairs + * (unlike Core Foundation collections, + * for which the initial capacity is a hard limit). + * + * If orderFunc is provided, it is used by + * @link + * //apple_ref/cpp/instm/OSOrderedSet/setObject/virtualbool/(constOSMetaClassBase*) + * setObject(const OSMetaClassBase *)@/link + * to determine where to insert a new object. + * Other object-setting functions ignore ordering. + * + * orderingContext is not retained or otherwise memory-managed + * by the ordered set. + * If it needs to be deallocated, + * you must track references to it and the ordered set + * in order to deallocate it appropriately. + * See + * @link getOrderingRef getOrderingRef@/link. + */ + virtual bool initWithCapacity( + unsigned int capacity, + OSOrderFunction orderFunc = 0, + void * orderingContext = 0); + + + /*! + * @function free + * + * @abstract + * Deallocatesand releases any resources + * used by the OSOrderedSet instance. + * + * @discussion + * This function should not be called directly; + * use + * @link + * //apple_ref/cpp/instm/OSObject/release/virtualvoid/() + * release@/link + * instead. + */ + virtual void free(); + + + /*! + * @function getCount + * + * @abstract + * Returns the current number of objects within the ordered set. + * + * @result + * The current number of objects within the ordered set. + */ + virtual unsigned int getCount() const; + + + /*! + * @function getCapacity + * + * @abstract + * Returns the number of objects the ordered set + * can store without reallocating. + * + * @result + * The number objects the ordered set + * can store without reallocating. + * + * @discussion + * OSOrderedSet objects grow when full to accommodate additional objects. + * See + * @link + * //apple_ref/cpp/instm/OSOrderedSet/getCapacityIncrement/virtualunsignedint/() + * getCapacityIncrement@/link + * and + * @link + * //apple_ref/cpp/instm/OSOrderedSet/ensureCapacity/virtualunsignedint/(unsignedint) + * ensureCapacity@/link. + */ + virtual unsigned int getCapacity() const; + + + /*! + * @function getCapacityIncrement + * + * @abstract + * Returns the storage increment of the ordered set. + * + * @result + * The storage increment of the ordered set. + * + * @discussion + * An OSOrderedSet allocates storage for objects in multiples + * of the capacity increment. + */ + virtual unsigned int getCapacityIncrement() const; + + + /*! + * @function setCapacityIncrement + * + * @abstract + * Sets the storage increment of the ordered set. + * + * @result + * The new storage increment of the ordered set, + * which may be different from the number requested. + * + * @discussion + * An OSOrderedSet allocates storage for objects in multiples + * of the capacity increment. + * Calling this function does not immediately reallocate storage. + */ + virtual unsigned int setCapacityIncrement(unsigned increment); + + + /*! + * @function ensureCapacity + * + * @abstract + * Ensures the set has enough space + * to store the requested number of distinct objects. + * + * @param newCapacity The total number of distinct objects the ordered set + * should be able to store. + * + * @result + * The new capacity of the ordered set, + * which may be different from the number requested + * (if smaller, reallocation of storage failed). + * + * @discussion + * This function immediately resizes the ordered set, if necessary, + * to accommodate at least newCapacity distinct objects. + * If newCapacity is not greater than the current capacity, + * or if an allocation error occurs, the original capacity is returned. + * + * There is no way to reduce the capacity of an OSOrderedSet. + */ + virtual unsigned int ensureCapacity(unsigned int newCapacity); + + + /*! + * @function flushCollection + * + * @abstract + * Removes and releases all objects within the ordered set. + * + * @discussion + * The ordered set's capacity (and therefore direct memory consumption) + * is not reduced by this function. + */ + virtual void flushCollection(); + + + /*! + * @function setObject + * + * @abstract + * Adds an object to the OSOrderedSet if it is not already present, + * storing it in sorted order if there is an order function. + * + * @param anObject The OSMetaClassBase-derived object to be added + * to the ordered set. + * @result + * true if anObject was successfully + * added to the ordered set, false otherwise + * (including if it was already in the ordered set). + * + * @discussion + * The set adds storage to accomodate the new object, if necessary. + * If successfully added, the object is retained. + * + * If anObject is not already in the ordered set + * and there is an order function, + * this function loops through the existing objects, + * calling the @link OSOrderFunction order function@/link + * with arguments each existingObject, anObject, + * and the ordering context + * (or NULL if none was set), + * until the order function returns + * a value greater than or equal to 0. + * It then inserts anObject at the index of the existing object. + * + * If there is no order function, the object is inserted at index 0. + * + * A false return value can mean either + * that anObject is already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the object + * is already present, use + * @link + * //apple_ref/cpp/instm/OSOrderedSet/containsObject/virtualbool/(constOSMetaClassBase*) + * containsObject(const OSMetaClassBase *)@/link. + */ + virtual bool setObject(const OSMetaClassBase * anObject); + + + /*! + * @function setFirstObject + * + * @abstract + * Adds an object to the OSOrderedSet at index 0 + * if it is not already present. + * + * @param anObject The OSMetaClassBase-derived object + * to be added to the ordered set. + * @result + * true if anObject was successfully added + * to the ordered set, false otherwise + * (including if it was already in the ordered set at any index). + * + * @discussion + * The set adds storage to accomodate the new object, if necessary. + * If successfully added, the object is retained. + * + * This function ignores any ordering function of the ordered set, + * and can disrupt the automatic sorting mechanism. + * Only call this function if you are managing the ordered set directly. + * + * A false return value can mean either that anObject + * is already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the object + * is already present, use + * @link + * //apple_ref/cpp/instm/OSOrderedSet/containsObject/virtualbool/(constOSMetaClassBase*) + * containsObject(const OSMetaClassBase *)@/link. + */ + virtual bool setFirstObject(const OSMetaClassBase * anObject); + + + /*! + * @function setLastObject + * + * @abstract + * Adds an object at the end of the OSOrderedSet + * if it is not already present. + * + * @param anObject The OSMetaClassBase-derived object to be added + * to the ordered set. + * @result + * true if anObject was successfully added + * to the ordered set, false otherwise + * (including if it was already in the ordered set at any index). + * + * @discussion + * The set adds storage to accomodate the new object, if necessary. + * If successfully added, the object is retained. + * + * This function ignores any ordering function of the ordered set, + * and can disrupt the automatic sorting mechanism. + * Only call this function if you are managing the ordered set directly. + * + * A false return value can mean either that anObject + * is already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the object + * is already present, use + * @link + * //apple_ref/cpp/instm/OSOrderedSet/containsObject/virtualbool/(constOSMetaClassBase*) + * containsObject(const OSMetaClassBase *)@/link. + */ + virtual bool setLastObject(const OSMetaClassBase * anObject); + + + /*! + * @function removeObject + * + * @abstract + * Removes an object from the ordered set. + * + * @param anObject The OSMetaClassBase-derived object + * to be removed from the ordered set. + * + * @discussion + * The object removed from the ordered set is released. + */ + virtual void removeObject(const OSMetaClassBase * anObject); + + + /*! + * @function containsObject + * + * @abstract + * Checks the ordered set for the presence of an object. + * + * @param anObject The OSMetaClassBase-derived object to check for + * in the ordered set. + * + * @result + * true if anObject is present + * within the ordered set, false otherwise. + * + * @discussion + * Pointer equality is used. + * This function returns false if passed NULL. + */ + virtual bool containsObject(const OSMetaClassBase * anObject) const; + + + /*! + * @function member + * + * @abstract + * Checks the ordered set for the presence of an object. + * + * @param anObject The OSMetaClassBase-derived object to check for + * in the ordered set. + * + * @result + * true if anObject is present + * within the ordered set, false otherwise. + * + * @discussion + * Pointer equality is used. + * Returns false if passed NULL. + * + * @link + * //apple_ref/cpp/instm/OSOrderedSet/containsObject/virtualbool/(constOSMetaClassBase*) + * containsObject(const OSMetaClassBase *)@/link + * checks for NULL before scanning the contents, + * and is therefore more efficient than this function. + */ + virtual bool member(const OSMetaClassBase * anObject) const; + + + /*! + * @function getFirstObject + * + * @abstract + * Returns the object at index 0 in the ordered set if there is one. + * + * @abstract + * The object at index 0 in the ordered set if there is one, + * otherwise NULL. + * + * @discussion + * The returned object will be released if removed from the ordered set; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getFirstObject() const; + + + /*! + * @function getLastObject + * + * @abstract + * Returns the last object in the ordered set if there is one. + * + * @abstract + * The last object in the ordered set if there is one, + * otherwise NULL. + * + * @discussion + * The returned object will be released if removed from the ordered set; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getLastObject() const; + + + /*! + * @function orderObject + * + * @abstract + * Calls the ordered set's order function against a NULL object. + * + * @param anObject The object to be ordered. + * + * @result + * The ordering value for the object. + * + * @discussion + * This function calls the ordered set's + * @link OSOrderFunction order function@/link + * with anObject, NULL, and the ordering context + * (or NULL if none was set), + * and returns the result of that function. + */ + virtual int32_t orderObject(const OSMetaClassBase * anObject); + + + /*! + * @function setObject + * + * @abstract + * Adds an object to an OSOrderedSet at a specified index + * if it is not already present. + * + * @param index The index at which to insert the new object. + * @param anObject The OSMetaClassBase-derived object to be added + * to the ordered set. + * + * @result + * true if the object was successfully added + * to the ordered set, false otherwise + * (including if it was already in the set). + * + * @discussion + * The set adds storage to accomodate the new object, if necessary. + * If successfully added, the object is retained. + * + * This function ignores any ordering function of the ordered set, + * and can disrupt the automatic sorting mechanism. + * Only call this function if you are managing the ordered set directly. + * + * A false return value can mean either that the object + * is already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the object + * is already present, use + * @link //apple_ref/cpp/instm/OSOrderedSet/containsObject/virtualbool/(constOSMetaClassBase*) + * containsObject containsObject@/link. + */ + virtual bool setObject( + unsigned int index, + const OSMetaClassBase * anObject); + + + /*! + * @function getObject + * + * @abstract + * Gets the object at a particular index. + * + * @param index The index into the set. + * @result + * The object at the given index, + * or NULL if none exists at that location. + * + * @discussion + * The returned object will be released if removed from the set; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getObject(unsigned int index) const; + + + /*! + * @function getOrderingRef + * + * @abstract + * Returns the ordering context the ordered set was created with. + * + * @result + * The ordered set's ordering context, + * or NULL if it doesn't have one. + */ + virtual void * getOrderingRef(); + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of two OSOrderedSet objects. + * + * @param anOrderedSet The ordered set object being compared + * against the receiver. + * @result + * true if the two sets are equivalent, + * false otherwise. + * + * @discussion + * Two OSOrderedSet objects are considered equal if they have same count + * and the same object pointer values in the same order. + */ + virtual bool isEqualTo(const OSOrderedSet * anOrderedSet) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSOrderedSet + * against an arbitrary object. + * + * @param anObject The object being compared against the receiver. + * @result + * true if the two objects are equivalent, + * false otherwise. + * + * @discussion + * An OSOrderedSet object is considered equal to another object + * if the other object is derived from OSOrderedSet + * and compares equal as an OSOrderedSet. + */ + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + + + /*! + * @function setOptions + * + * Recursively sets option bits in the ordered set + * and all child collections. + * + * @param options A bitfield whose values turn the options on (1) or off (0). + * @param mask A mask indicating which bits + * in options to change. + * Pass 0 to get the whole current options bitfield + * without changing any settings. + * @param context Unused. + * + * @result + * The options bitfield as it was before the set operation. + * + * @discussion + * Kernel extensions should not call this function. + * + * Child collections' options are changed only if the receiving ordered set's + * options actually change. + */ + virtual unsigned setOptions( + unsigned options, + unsigned mask, + void * context = 0); + + + /*! + * @function copyCollection + * + * @abstract + * Creates a deep copy of this ordered set and its child collections. + * + * @param cycleDict A dictionary of all of the collections + * that have been copied so far, + * which is used to track circular references. + * To start the copy at the top level, + * pass NULL. + * + * @result + * The newly copied ordered set, with a retain count of 1, + * or NULL if there is insufficient memory to do the copy. + * + * @discussion + * The receiving ordered set, and any collections it contains, + * recursively, are copied. + * Objects that are not derived from OSCollection are retained + * rather than copied. + */ + OSCollection *copyCollection(OSDictionary * cycleDict = 0); + + OSMetaClassDeclareReservedUnused(OSOrderedSet, 0); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 1); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 2); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 3); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 4); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 5); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 6); + OSMetaClassDeclareReservedUnused(OSOrderedSet, 7); +}; + +#endif /* ! _OS_OSORDEREDSET_H */ diff --git a/OSReturn.h b/OSReturn.h new file mode 100644 index 0000000..06b547e --- /dev/null +++ b/OSReturn.h @@ -0,0 +1,27 @@ +// +// OSReturn.h +// Passenger +// +// Created by Kristina on 12-07-31. +// +// + +#ifndef Passenger_OSReturn_h +#define Passenger_OSReturn_h + +#include "runtime.h" + +typedef kern_return_t OSReturn; + +#ifndef sys_libkern +#define sys_libkern err_system(0x37) +#endif /* sys_libkern */ + +#define sub_libkern_common err_sub(0) +#define sub_libkern_metaclass err_sub(1) +#define sub_libkern_reserved err_sub(-1) + +#define libkern_common_err(return) (sys_libkern|sub_libkern_common|(return)) +#define libkern_metaclass_err(return) (sys_libkern|sub_libkern_metaclass|(return)) + +#endif diff --git a/OSSerialize.cpp b/OSSerialize.cpp new file mode 100755 index 0000000..a5e9541 --- /dev/null +++ b/OSSerialize.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* OSSerialize.cpp created by rsulack on Wen 25-Nov-1998 */ + + +#include "OSDictionary.h" +#include "OSSerialize.h" +#include "OSString.h" + +#define super OSObject + +OSDefineMetaClassAndStructors(OSSerialize, OSObject) +OSMetaClassDefineReservedUnused(OSSerialize, 0); +OSMetaClassDefineReservedUnused(OSSerialize, 1); +OSMetaClassDefineReservedUnused(OSSerialize, 2); +OSMetaClassDefineReservedUnused(OSSerialize, 3); +OSMetaClassDefineReservedUnused(OSSerialize, 4); +OSMetaClassDefineReservedUnused(OSSerialize, 5); +OSMetaClassDefineReservedUnused(OSSerialize, 6); +OSMetaClassDefineReservedUnused(OSSerialize, 7); + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +char * OSSerialize::text() const +{ + return data; +} + +void OSSerialize::clearText() +{ + bzero((void *)data, capacity); + length = 1; + tag = 0; + tags->flushCollection(); +} + +bool OSSerialize::previouslySerialized(const OSMetaClassBase *o) +{ + char temp[16]; + OSString *tagString; + + // look it up + tagString = (OSString *)tags->getObject((const OSSymbol *) o); + +// xx-review: no error checking here for addString calls! + // does it exist? + if (tagString) { + addString("getCStringNoCopy()); + addString("\"/>"); + return true; + } + + // build a tag + snprintf(temp, sizeof(temp), "%u", tag++); + tagString = OSString::withCString(temp); + + // add to tag dictionary + tags->setObject((const OSSymbol *) o, tagString);// XXX check return + tagString->release(); + + return false; +} + +bool OSSerialize::addXMLStartTag(const OSMetaClassBase *o, const char *tagString) +{ + + if (!addChar('<')) return false; + if (!addString(tagString)) return false; + if (!addString(" ID=\"")) return false; + if (!addString(((OSString *)tags->getObject((const OSSymbol *)o))->getCStringNoCopy())) + return false; + if (!addChar('\"')) return false; + if (!addChar('>')) return false; + return true; +} + +bool OSSerialize::addXMLEndTag(const char *tagString) +{ + + if (!addChar('<')) return false; + if (!addChar('/')) return false; + if (!addString(tagString)) return false; + if (!addChar('>')) return false; + return true; +} + +bool OSSerialize::addChar(const char c) +{ + // add char, possibly extending our capacity + if (length >= capacity && length >=ensureCapacity(capacity+capacityIncrement)) + return false; + + data[length - 1] = c; + length++; + + return true; +} + +bool OSSerialize::addString(const char *s) +{ + bool rc = false; + + while (*s && (rc = addChar(*s++))) ; + + return rc; +} + +bool OSSerialize::initWithCapacity(unsigned int inCapacity) +{ + if (!super::init()) + return false; + + tags = OSDictionary::withCapacity(32); + if (!tags) { + return false; + } + + tag = 0; + length = 1; + capacity = (inCapacity) ? inCapacity : (100); + capacityIncrement = capacity; + + // allocate from the kernel map so that we can safely map this data + // into user space (the primary use of the OSSerialize object) + + data = (char*)kalloc(capacity); + assert(data); + + bzero((void *)data, capacity); + + + ACCUMSIZE(capacity); + + return true; +} + +OSSerialize *OSSerialize::withCapacity(unsigned int inCapacity) +{ + OSSerialize *me = new OSSerialize; + + if (me && !me->initWithCapacity(inCapacity)) { + me->release(); + return 0; + } + + return me; +} + +unsigned int OSSerialize::getLength() const { return length; } +unsigned int OSSerialize::getCapacity() const { return capacity; } +unsigned int OSSerialize::getCapacityIncrement() const { return capacityIncrement; } +unsigned int OSSerialize::setCapacityIncrement(unsigned int increment) +{ + capacityIncrement = (increment)? increment : 256; + return capacityIncrement; +} + +unsigned int OSSerialize::ensureCapacity(unsigned int newCapacity) +{ + char *newData; + int newSize; + int oldSize; + + if (newCapacity <= capacity) + return capacity; + + newCapacity = (((newCapacity - 1) / capacityIncrement) + 1) + * capacityIncrement; + newSize = sizeof(char) * newCapacity; + + newData = (char*) kalloc(newSize); + if (newData) { + oldSize = sizeof(char) * capacity; + + bcopy((void*)data, (void*)newData, oldSize); + bzero(&newData[capacity], newSize - oldSize); + + kfree((void*)data, 0); + + data = newData; + capacity = newCapacity; + } + else { + assert(false); + } + + return capacity; +} + +void OSSerialize::free() +{ + if (tags) + tags->release(); + + if (data) { + kfree(data, capacity); + ACCUMSIZE( -capacity ); + } + super::free(); +} + + +OSDefineMetaClassAndStructors(OSSerializer, OSObject) + +OSSerializer * OSSerializer::forTarget( void * target, + OSSerializerCallback callback, void * ref ) +{ + OSSerializer * thing; + + thing = new OSSerializer; + if( thing && !thing->init()) { + thing->release(); + thing = 0; + } + + if( thing) { + thing->target = target; + thing->ref = ref; + thing->callback = callback; + } + return( thing ); +} + +bool OSSerializer::serialize( OSSerialize * s ) const +{ + return( (*callback)(target, ref, s) ); +} diff --git a/OSSerialize.h b/OSSerialize.h new file mode 100755 index 0000000..df005d5 --- /dev/null +++ b/OSSerialize.h @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* OSSerialize.h created by rsulack on Wen 25-Nov-1998 */ + +#ifndef _OS_OSSERIALIZE_H +#define _OS_OSSERIALIZE_H + +#include "OSObject.h" + +class OSSet; +class OSDictionary; + +/*! + * @header + * + * @abstract + * This header declares the OSSerialize class. + */ + + +/*! + * @class OSSerialize + * + * @abstract + * OSSerialize coordinates serialization of Libkern C++ objects + * into an XML stream. + * + * @discussion + * This class is for the most part internal to the OSContainer classes, + * used for transferring property tables between the kernel and user space. + * It should not be used directly. + * Classes that participate in serialization + * override the + * @link + * //apple_ref/cpp/instm/OSObject/serialize/virtualbool/(OSSerialize*) + * OSObject::serialize@/link . + * function. + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSSerialize provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions + * for serializing properties. + */ +class OSSerialize : public OSObject +{ + OSDeclareDefaultStructors(OSSerialize) + +protected: + char * data; // container for serialized data + unsigned int length; // of serialized data (counting NULL) + unsigned int capacity; // of container + unsigned int capacityIncrement; // of container + + unsigned int tag; + OSDictionary * tags; // tags for all objects seen + + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData *reserved; + + +public: + + /*! + * @function withCapacity + * + * @abstract + * Creates and initializes an empty OSSerialize object. + * + * @param capacity The initial size of the XML buffer. + * + * @result + * A new instance of OSSerialize + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * The serializer will grow as needed to accommodate more data. + */ + static OSSerialize * withCapacity(unsigned int capacity); + + /*! + * @function text + * + * @abstract + * Returns the XML text serialized so far. + * + * @result + * The nul-terminated XML data serialized so far. + */ + virtual char * text() const; + + + /*! + * @function clearText + * + * @abstract + * Resets the OSSerialize object. + * + * @discussion + * This function is a useful optimization if you are serializing + * the same object repeatedly. + */ + virtual void clearText(); + + // stuff to serialize your object + + /*! + * @function previouslySerialized + * + * @abstract + * Checks whether the object has already been serialized + * into the XML stream, emitting a reference if it has. + * + * @param object The object to check. + * + * @result + * true if object has already been serialized + * by this OSSerialize object and a reference + * to it is successfully added to the XML stream, + * false otherwise. + * + * + * @discussion + * This function both reduces the size of generated XML + * by emitting shorter references to existing objects with the same + * value (particularly for OSString, OSSymbol, and OSData), + * and also preserves instance references + * so that the user-space I/O Kit library can reconstruct + * an identical graph of object relationships. + * + * All classes that override + * @link + * //apple_ref/cpp/instm/OSObject/serialize/virtualbool/(OSSerialize*) + * OSObject::serialize@/link. + * should call this function before doing any actual serialization; + * if it returns true, the serialize implementation + * can immediately return true. + */ + virtual bool previouslySerialized(const OSMetaClassBase * object); + + + /*! + * @function addXMLStartTag + * + * @abstract + * Appends an XML start tag to the XML stream. + * + * @param object The object being serialized. + * @param tagString The name of the XML tag to emit; for example, "string". + * + * @result + * true if an XML start tag for tagString + * is successfully added to the XML stream, false otherwise. + * + * @discussion + * This function emits the named tag, + * enclosed within a pair of angle brackets. + * + * A class that implements serialization should call this function + * with the name of the XML tag that best represents the serialized + * contents of the object. + * A limited number of tags are supported by the user-space + * I/O Kit library: + *
      + *
    • array
    • + *
    • dict
    • + *
    • integer
    • + *
    • key
    • + *
    • set
    • + *
    • string
    • + *
    + * + * A call to this function must be balanced with one to + * @link addXMLEndTag addXMLEndTag@/link + * using the same tagString. + */ + virtual bool addXMLStartTag( + const OSMetaClassBase * object, + const char * tagString); + + + /*! + * @function addXMLEndTag + * + * @abstract + * Appends an XML end tag to the XML stream. + * + * @param tagString The name of the XML tag to emit; for example, "string". + * + * @result + * true if an XML end tag for tagString + * is successfully added to the XML stream, false otherwise. + * + * @discussion + * This function emits the named tag, + * preceded by a slash character to indicate the closing of an entity, + * all enclosed within a pair of angle brackets. + * + * A call to this function must balance an earlier call to + * @link addXMLStartTag addXMLStartTag@/link + * using the same tagString. + */ + virtual bool addXMLEndTag(const char * tagString); + + + /*! + * @function addChar + * + * @abstract + * Appends a single character to the XML stream. + * + * @param aChar The character to append to the XML stream. + * + * @result + * true if char + * is successfully added to the XML stream, false otherwise. + */ + virtual bool addChar(const char aChar); + + + /*! + * @function addString + * + * @abstract + * Appends a C string to the XML stream. + * + * @param cString The C string to append to the XML stream. + * + * @result + * true if cString + * is successfully added to the XML stream, false otherwise. + */ + virtual bool addString(const char * cString); + + // stuff you should never have to use (in theory) + + virtual bool initWithCapacity(unsigned int inCapacity); + virtual unsigned int getLength() const; + virtual unsigned int getCapacity() const; + virtual unsigned int getCapacityIncrement() const; + virtual unsigned int setCapacityIncrement(unsigned increment); + virtual unsigned int ensureCapacity(unsigned int newCapacity); + virtual void free(); + + OSMetaClassDeclareReservedUnused(OSSerialize, 0); + OSMetaClassDeclareReservedUnused(OSSerialize, 1); + OSMetaClassDeclareReservedUnused(OSSerialize, 2); + OSMetaClassDeclareReservedUnused(OSSerialize, 3); + OSMetaClassDeclareReservedUnused(OSSerialize, 4); + OSMetaClassDeclareReservedUnused(OSSerialize, 5); + OSMetaClassDeclareReservedUnused(OSSerialize, 6); + OSMetaClassDeclareReservedUnused(OSSerialize, 7); +}; + +// xx-review: this whole class seems to be unused! + +typedef bool (*OSSerializerCallback)(void * target, void * ref, + OSSerialize * serializer); + +class OSSerializer : public OSObject +{ + OSDeclareDefaultStructors(OSSerializer) + + void * target; + void * ref; + OSSerializerCallback callback; + +public: + + static OSSerializer * forTarget( + void * target, + OSSerializerCallback callback, + void * ref = 0); + + virtual bool serialize(OSSerialize * serializer) const; +}; + +#endif /* _OS_OSSERIALIZE_H */ diff --git a/OSSet.cpp b/OSSet.cpp new file mode 100755 index 0000000..8a00f43 --- /dev/null +++ b/OSSet.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOSet.m created by rsulack on Thu 11-Jun-1998 */ + +#include "OSDictionary.h" +#include "OSArray.h" +#include "OSSerialize.h" +#include "OSSet.h" + + +#define super OSCollection + +OSDefineMetaClassAndStructors(OSSet, OSCollection) +OSMetaClassDefineReservedUnused(OSSet, 0); +OSMetaClassDefineReservedUnused(OSSet, 1); +OSMetaClassDefineReservedUnused(OSSet, 2); +OSMetaClassDefineReservedUnused(OSSet, 3); +OSMetaClassDefineReservedUnused(OSSet, 4); +OSMetaClassDefineReservedUnused(OSSet, 5); +OSMetaClassDefineReservedUnused(OSSet, 6); +OSMetaClassDefineReservedUnused(OSSet, 7); + +#define EXT_CAST(obj) \ + reinterpret_cast(const_cast(obj)) + +bool OSSet::initWithCapacity(unsigned int inCapacity) +{ + if ( !super::init() ) + return false; + + members = OSArray::withCapacity(inCapacity); + if (!members) + return false; + + return true; +} + +bool OSSet::initWithObjects(const OSObject *inObjects[], + unsigned int inCount, + unsigned int inCapacity) +{ + unsigned int capacity = inCount; + + if ( inCapacity ) { + if ( inCount > inCapacity ) + return false; + + capacity = inCapacity; + } + + if (!inObjects || !initWithCapacity(capacity)) + return false; + + for ( unsigned int i = 0; i < inCount; i++ ) { +// xx-review: no test here for failure of setObject() + if (members->getCount() < inCapacity) + setObject(inObjects[i]); + else + return false; + } + + return true; +} + +bool OSSet::initWithArray(const OSArray *inArray, + unsigned int inCapacity) +{ + if ( !inArray ) + return false; + + return initWithObjects((const OSObject **) inArray->array, + inArray->count, inCapacity); +} + +bool OSSet::initWithSet(const OSSet *inSet, + unsigned int inCapacity) +{ + return initWithArray(inSet->members, inCapacity); +} + +OSSet *OSSet::withCapacity(unsigned int capacity) +{ + OSSet *me = new OSSet; + + if (me && !me->initWithCapacity(capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSSet *OSSet::withObjects(const OSObject *objects[], + unsigned int count, + unsigned int capacity) +{ + OSSet *me = new OSSet; + + if (me && !me->initWithObjects(objects, count, capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSSet *OSSet::withArray(const OSArray *array, + unsigned int capacity) +{ + OSSet *me = new OSSet; + + if (me && !me->initWithArray(array, capacity)) { + me->release(); + return 0; + } + + return me; +} + +OSSet *OSSet::withSet(const OSSet *set, + unsigned int capacity) +{ + OSSet *me = new OSSet; + + if (me && !me->initWithSet(set, capacity)) { + me->release(); + return 0; + } + + return me; +} + +void OSSet::free() +{ + (void) members->super::setOptions(0, kImmutable); + if (members) + members->release(); + + super::free(); +} + +unsigned int OSSet::getCount() const +{ + return members->count; +} + +unsigned int OSSet::getCapacity() const +{ + return members->capacity; +} + +unsigned int OSSet::getCapacityIncrement() const +{ + return members->capacityIncrement; +} + +unsigned int OSSet::setCapacityIncrement(unsigned int increment) +{ + return members->setCapacityIncrement(increment); +} + +unsigned int OSSet::ensureCapacity(unsigned int newCapacity) +{ + return members->ensureCapacity(newCapacity); +} + +void OSSet::flushCollection() +{ + haveUpdated(); + members->flushCollection(); +} + +bool OSSet::setObject(const OSMetaClassBase *anObject) +{ + if (containsObject(anObject)) + return false; + else { + haveUpdated(); + return members->setObject(anObject); + } +} + +bool OSSet::merge(const OSArray *array) +{ + const OSMetaClassBase *anObject; + bool retVal = false; + +// xx-review: if any setObject fails due to memory allocation failure, +// xx-review: this function should return false + for (int i = 0; (anObject = array->getObject(i)); i++) + if (setObject(anObject)) + retVal = true; + + return retVal; +} + +bool OSSet::merge(const OSSet *set) +{ + return merge(set->members); +} + +void OSSet::removeObject(const OSMetaClassBase *anObject) +{ + const OSMetaClassBase *probeObject; + + for (int i = 0; (probeObject = members->getObject(i)); i++) + if (probeObject == anObject) { + haveUpdated(); + members->removeObject(i); + return; + } +} + + +bool OSSet::containsObject(const OSMetaClassBase *anObject) const +{ + return anObject && member(anObject); +} + +bool OSSet::member(const OSMetaClassBase *anObject) const +{ + OSMetaClassBase *probeObject; + + for (int i = 0; (probeObject = members->getObject(i)); i++) + if (probeObject == anObject) + return true; + + return false; +} + +OSObject *OSSet::getAnyObject() const +{ + return members->getObject(0); +} + +bool OSSet::isEqualTo(const OSSet *aSet) const +{ + unsigned int count; + unsigned int i; + const OSMetaClassBase *obj1; + const OSMetaClassBase *obj2; + + if ( this == aSet ) + return true; + + count = members->count; + if ( count != aSet->getCount() ) + return false; + + for ( i = 0; i < count; i++ ) { + obj1 = aSet->members->getObject(i); + obj2 = members->getObject(i); + if ( !obj1 || !obj2 ) + return false; + + if ( !obj1->isEqualTo(obj2) ) + return false; + } + + return true; +} + +bool OSSet::isEqualTo(const OSMetaClassBase *anObject) const +{ + OSSet *otherSet; + + otherSet = OSDynamicCast(OSSet, anObject); + if ( otherSet ) + return isEqualTo(otherSet); + else + return false; +} + +unsigned int OSSet::iteratorSize() const +{ + return sizeof(unsigned int); +} + +bool OSSet::initIterator(void *inIterator) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + + *iteratorP = 0; + return true; +} + +bool OSSet::getNextObjectForIterator(void *inIterator, OSObject **ret) const +{ + unsigned int *iteratorP = (unsigned int *) inIterator; + unsigned int index = (*iteratorP)++; + + if (index < members->count) + *ret = members->getObject(index); + else + *ret = 0; + + return (*ret != 0); +} + +bool OSSet::serialize(OSSerialize *s) const +{ + const OSMetaClassBase *o; + + if (s->previouslySerialized(this)) return true; + + if (!s->addXMLStartTag(this, "set")) return false; + + for (int i = 0; (o = members->getObject(i)); i++) { + if (!o->serialize(s)) return false; + } + + return s->addXMLEndTag("set"); +} + +unsigned OSSet::setOptions(unsigned options, unsigned mask, void *) +{ + unsigned old = super::setOptions(options, mask); + if ((old ^ options) & mask) + members->setOptions(options, mask); + + return old; +} + +OSCollection * OSSet::copyCollection(OSDictionary *cycleDict) +{ + bool allocDict = !cycleDict; + OSCollection *ret = 0; + OSSet *newSet = 0; + + if (allocDict) { + cycleDict = OSDictionary::withCapacity(16); + if (!cycleDict) + return 0; + } + + do { + // Check for a cycle + ret = super::copyCollection(cycleDict); + if (ret) + continue; // Found it + + newSet = OSSet::withCapacity(members->capacity); + if (!newSet) + continue; // Couldn't create new set abort + + // Insert object into cycle Dictionary + cycleDict->setObject((const OSSymbol *) this, newSet); + + OSArray *newMembers = newSet->members; + newMembers->capacityIncrement = members->capacityIncrement; + + // Now copy over the contents into the new duplicate + for (unsigned int i = 0; i < members->count; i++) { + OSObject *obj = EXT_CAST(members->array[i]); + OSCollection *coll = OSDynamicCast(OSCollection, obj); + if (coll) { + OSCollection *newColl = coll->copyCollection(cycleDict); + if (newColl) { + obj = newColl; // Rely on cycleDict ref for a bit + newColl->release(); + } + else + goto abortCopy; + }; + newMembers->setObject(obj); + }; + + ret = newSet; + newSet = 0; + + } while(false); + +abortCopy: + if (newSet) + newSet->release(); + + if (allocDict) + cycleDict->release(); + + return ret; +} diff --git a/OSSet.h b/OSSet.h new file mode 100755 index 0000000..bc8848a --- /dev/null +++ b/OSSet.h @@ -0,0 +1,782 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOSet.h created by rsulack on Thu 11-Jun-1998 */ +/* IOSet.h converted to C++ by gvdl on Fri 1998-10-30 */ + +#ifndef _OS_OSSET_H +#define _OS_OSSET_H + +#include "OSCollection.h" + +class OSArray; + +/*! + * @header + * + * @abstract + * This header declares the OSSet collection class. + */ + + +/*! + * @class OSSet + * + * @abstract + * OSSet provides an unordered set store of objects. + * + * @discussion + * OSSet is a container for Libkern C++ objects + * (those derived from + * @link //apple_ref/doc/class/OSMetaClassBase OSMetaClassBase@/link, + * in particular @link //apple_ref/doc/class/OSObject OSObject@/link). + * Storage and access follow basic set logic: you can add or remove an object, + * and test whether the set contains a particular object. + * A given object is only stored in the set once, + * and there is no ordering of objects in the set. + * A subclass @link //apple_ref/doc/class/OSOrderedSet OSOrderedSet@/link, + * provides for ordered set logic. + * + * As with all Libkern collection classes, + * OSSet retains objects added to it, + * and releases objects removed from it. + * An OSSet also grows as necessary to accommodate new objects, + * unlike Core Foundation collections (it does not, however, shrink). + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSSet provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions for setting + * properties. + */ +class OSSet : public OSCollection +{ + OSDeclareDefaultStructors(OSSet) + +private: + OSArray * members; + +protected: + /* + * OSCollectionIterator interfaces. + */ + virtual unsigned int iteratorSize() const; + virtual bool initIterator(void * iterator) const; + virtual bool getNextObjectForIterator(void * iterator, OSObject ** ret) const; + + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData * reserved; + +public: + + + /*! + * @function withCapacity + * + * @abstract + * Creates and initializes an empty OSSet. + * + * @param capacity The initial storage capacity of the new set object. + * + * @result + * An empty instance of OSSet + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * capacity must be nonzero. + * The new OSSet will grow as needed to accommodate more key/object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + */ + static OSSet * withCapacity(unsigned int capacity); + + + /*! + * @function withObjects + * + * @abstract + * Creates and initializes an OSSet + * populated with objects provided. + * + * @param objects A C array of OSMetaClassBase-derived objects. + * @param count The number of objects to be placed into the set. + * @param capacity The initial storage capacity of the new set object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * An instance of OSSet + * containing the objects provided, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * objects must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new OSSet will grow as needed to accommodate more objects + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in objects are retained for storage in the new set, + * not copied. + */ + static OSSet * withObjects( + const OSObject * objects[], + unsigned int count, + unsigned int capacity = 0); + + + /*! + * @function withArray + * + * @abstract + * Creates and initializes an OSSet + * populated with the contents of an OSArray. + * + * @param array An array whose objects will be stored in the new OSSet. + * @param capacity The initial storage capacity of the new set object. + * If 0, the capacity is set to the number of objects + * in array; + * otherwise capacity must be greater than or equal to + * the number of objects in array. + * @result + * An instance of OSSet containing + * the objects of array, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * Each distinct object in array is added to the new set. + * + * array must be non-NULL. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new OSSet will grow as needed to accommodate more key-object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in array are retained for storage in the new set, + * not copied. + */ + static OSSet * withArray( + const OSArray * array, + unsigned int capacity = 0); + + + /*! + * @function withSet + * + * @abstract + * Creates and initializes an OSSet + * populated with the contents of another OSSet. + * + * @param set An OSSet whose contents will be stored + * in the new instance. + * @param capacity The initial storage capacity of the set object. + * If 0, the capacity is set to the number of objects + * in set; + * otherwise capacity must be greater than or equal to + * the number of objects in array. + * @result + * An instance of OSArray + * containing the objects of set, + * with a retain count of 1; + * NULL on failure. + * + * @discussion + * set must be non-NULL. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The array will grow as needed to accommodate more key-object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in set are retained for storage in the new set, + * not copied. + */ + static OSSet * withSet(const OSSet * set, + unsigned int capacity = 0); + + + /*! + * @function initWithCapacity + * + * @abstract + * Initializes a new instance of OSSet. + * + * @param capacity The initial storage capacity of the new set object. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSSet/withCapacity/staticOSSet*\/(unsignedint) + * withCapacity@/link + * instead. + * + * capacity must be nonzero. + * The new set will grow as needed to accommodate more key/object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + */ + virtual bool initWithCapacity(unsigned int capacity); + + + /*! + * @function initWithObjects + * + * @abstract + * Initializes a new OSSet populated with objects provided. + * + * @param objects A C array of OSObject-derived objects. + * @param count The number of objects to be placed into the set. + * @param capacity The initial storage capacity of the new set object. + * If 0, count is used; otherwise this value + * must be greater than or equal to count. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSSet/withObjects/staticOSSet*\/(constOSObject*,unsignedint,unsignedint) + * withObjects@/link + * instead. + * + * objects must be non-NULL, + * and count must be nonzero. + * If capacity is nonzero, it must be greater than or equal to count. + * The new array will grow as needed to accommodate more key-object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in objects are retained for storage in the new set, + * not copied. + */ + virtual bool initWithObjects( + const OSObject * objects[], + unsigned int count, + unsigned int capacity = 0); + + + /*! + * @function initWithArray + * + * @abstract Initializes a new OSSet + * populated with the contents of an OSArray. + * + * @param array An OSAray whose contents will be placed + * in the new instance. + * @param capacity The initial storage capacity of the new set object. + * If 0, the capacity is set + * to the number of objects in array; + * otherwise capacity must be greater than or equal to + * the number of objects in array. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link + * //apple_ref/cpp/clm/OSSet/withArray/staticOSSet*\/(constOSArray*,unsignedint) + * withArray@/link + * instead. + * + * array must be non-NULL. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new array will grow as needed to accommodate more key-object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in array are retained for storage in the new set, + * not copied. + */ + virtual bool initWithArray( + const OSArray * array, + unsigned int capacity = 0); + + + /*! + * @function initWithSet + * + * @abstract + * Initializes a new OSSet + * populated with the contents of another OSSet. + * + * @param set A set whose contents will be placed in the new instance. + * @param capacity The initial storage capacity of the new set object. + * If 0, the capacity is set + * to the number of objects in set; + * otherwise capacity must be greater than or equal to + * the number of objects in set. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link withSet withSet@/link instead. + * + * set must be non-NULL. + * If capacity is nonzero, + * it must be greater than or equal to count. + * The new set will grow as needed to accommodate more key-object pairs + * (unlike @link //apple_ref/doc/uid/20001503 CFMutableSet@/link, + * for which the initial capacity is a hard limit). + * + * The objects in set are retained for storage in the new set, + * not copied. + */ + virtual bool initWithSet(const OSSet *set, + unsigned int capacity = 0); + + + /*! + * @function free + * + * @abstract + * Deallocates or releases any resources + * used by the OSSet instance. + * + * @discussion + * This function should not be called directly; + * use + * @link + * //apple_ref/cpp/instm/OSObject/release/virtualvoid/() + * release@/link + * instead. + */ + virtual void free(); + + + /*! + * @function getCount + * + * @abstract + * Returns the current number of objects within the set. + * + * @result + * The current number of objects within the set. + */ + virtual unsigned int getCount() const; + + + /*! + * @function getCapacity + * + * @abstract + * Returns the number of objects the set + * can store without reallocating. + * + * @result + * The number objects the set + * can store without reallocating. + * + * @discussion + * OSSet objects grow when full to accommodate additional objects. + * See + * @link + * //apple_ref/cpp/instm/OSSet/getCapacityIncrement/virtualunsignedint/() + * getCapacityIncrement@/link + * and + * @link + * //apple_ref/cpp/instm/OSSet/ensureCapacity/virtualunsignedint/(unsignedint) + * ensureCapacity@/link. + */ + virtual unsigned int getCapacity() const; + + + /*! + * @function getCapacityIncrement + * + * @abstract + * Returns the storage increment of the set. + * + * @result + * The storage increment of the set. + * + * @discussion + * An OSSet allocates storage for objects in multiples + * of the capacity increment. + */ + virtual unsigned int getCapacityIncrement() const; + + + /*! + * @function setCapacityIncrement + * + * @abstract + * Sets the storage increment of the set. + * + * @result + * The new storage increment of the set, + * which may be different from the number requested. + * + * @discussion + * An OSSet allocates storage for objects in multiples + * of the capacity increment. + * Calling this function does not immediately reallocate storage. + */ + virtual unsigned int setCapacityIncrement(unsigned increment); + + + /*! + * @function ensureCapacity + * + * @abstract + * Ensures the set has enough space + * to store the requested number of distinct objects. + * + * @param newCapacity The total number of distinct objects the set + * should be able to store. + * @result + * The new capacity of the set, + * which may be different from the number requested + * (if smaller, reallocation of storage failed). + * + * @discussion + * This function immediately resizes the set, if necessary, + * to accommodate at least newCapacity distinct objects. + * If newCapacity is not greater than the current capacity, + * or if an allocation error occurs, the original capacity is returned. + * + * There is no way to reduce the capacity of an OSSet. + */ + virtual unsigned int ensureCapacity(unsigned int newCapacity); + + + /*! + * @function flushCollection + * + * @abstract + * Removes and releases all objects within the set. + * + * @discussion + * The set's capacity (and therefore direct memory consumption) + * is not reduced by this function. + */ + virtual void flushCollection(); + + + /*! + * @function setObject + * + * @abstract + * Adds an object to the OSSet if it is not already present. + * + * @param anObject The OSMetaClassBase-derived object to be added to the set. + * + * @result + * true if anObject was successfully + * added to the set, false otherwise + * (including if it was already in the set). + * + * @discussion + * The set adds storage to accomodate the new object, if necessary. + * If successfully added, the object is retained. + * + * A false return value can mean either + * that anObject is already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the object + * is already present, use + * @link containsObject containsObject@/link. + */ + virtual bool setObject(const OSMetaClassBase * anObject); + + + /*! + * @function merge + * + * @abstract + * Adds the contents of an OSArray to the set. + * + * @param array The OSArray object containing the objects to be added. + * + * @result + * true if any object from array + * was successfully added the receiver, + * false otherwise. + * + * @discussion + * This functions adds to the receiving set + * all objects from array + * that are not already in the set. + * Objects successfully added to the receiver are retained. + * + * A false return value can mean either + * that all the objects in array are already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the objects + * are already present, use + * @link containsObject containsObject@/link + * for each object. + */ + virtual bool merge(const OSArray * array); + + + /*! + * @function merge + * + * @abstract + * Adds the contents of an OSet to the set. + * + * @param set The OSSet object containing the objects to be added. + * + * @result + * true if any object from set + * was successfully added the receiver, + * false otherwise. + * + * @discussion + * This functions adds to the receiving set + * all objects from set + * that are not already in the receiving set. + * Objects successfully added to the receiver are retained. + * + * A false return value can mean either + * that all the objects in array are already present in the set, + * or that a memory allocation failure occurred. + * If you need to know whether the objects + * are already present, use + * @link containsObject containsObject@/link + * for each object. + */ + virtual bool merge(const OSSet * set); + + + /*! + * @function removeObject + * + * @abstract + * Removes an object from the set. + * + * @param anObject The OSMetaClassBase-derived object + * to be removed from the set. + * + * @discussion + * The object removed from the set is released. + */ + virtual void removeObject(const OSMetaClassBase * anObject); + + + /*! + * @function containsObject + * + * @abstract + * Checks the set for the presence of an object. + * + * @param anObject The OSMetaClassBase-derived object + * to check for in the set. + * + * @result + * true if anObject is present within the set, + * false otherwise. + * + * @discussion + * Pointer equality is used. + * This function returns false if passed NULL. + */ + virtual bool containsObject(const OSMetaClassBase * anObject) const; + + + /*! + * @function member + * + * @abstract + * Checks the set for the presence of an object. + * + * @param anObject The OSMetaClassBase-derived object + * to check for in the set. + * + * @result + * true if anObject is present + * within the set, false otherwise. + * + * @discussion + * Pointer equality is used. This function returns false + * if passed NULL. + * + * @link containsObject containsObject@/link + * checks for NULL first, + * and is therefore more efficient than this function. + */ + virtual bool member(const OSMetaClassBase * anObject) const; + + + /*! + * @function getAnyObject + * + * @abstract + * Returns an arbitrary (not random) object from the set. + * + * @result + * An arbitrary (not random) object + * if one exists within the set. + * + * @discussion + * The returned object will be released if removed from the set; + * if you plan to store the reference, you should call + * @link + * //apple_ref/cpp/instm/OSObject/retain/virtualvoid/() + * retain@/link + * on that object. + */ + virtual OSObject * getAnyObject() const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of two OSSet objects. + * + * @param aSet The set object being compared against the receiver. + * @result + * true if the two sets are equivalent, + * false otherwise. + * + * @discussion + * Two OSSet objects are considered equal if they have same count + * and the same object pointer values. + */ + virtual bool isEqualTo(const OSSet * aSet) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSSet against an arbitrary object. + * + * @param anObject The object being compared against the receiver. + * @result + * true if the two objects are equivalent, + * false otherwise. + * + * @discussion + * An OSSet object is considered equal to another object if the other object + * is derived from OSSet and compares equal as a set. + */ + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + + + /*! + * @function serialize + * + * @abstract + * Archives the receiver into the provided + * @link //apple_ref/doc/class/OSSerialize OSSerialize@/link object. + * + * @param serializer The OSSerialize object. + * + * @result + * true if serialization succeeds, false if not. + */ + virtual bool serialize(OSSerialize * serializer) const; + + + /*! + * @function setOptions + * + * @abstract + * Recursively sets option bits in the set + * and all child collections. + * + * @param options A bitfield whose values turn the options on (1) or off (0). + * @param mask A mask indicating which bits + * in options to change. + * Pass 0 to get the whole current options bitfield + * without changing any settings. + * @param context Unused. + * + * @result + * The options bitfield as it was before the set operation. + * + * @discussion + * Kernel extensions should not call this function. + * + * Child collections' options are changed only if the receiving set's + * options actually change. + */ + virtual unsigned setOptions(unsigned options, unsigned mask, void * context = 0); + + + /*! + * @function copyCollection + * + * @abstract + * Creates a deep copy of this set and its child collections. + * + * @param cycleDict A dictionary of all of the collections + * that have been copied so far, + * which is used to track circular references. + * To start the copy at the top level, + * pass NULL. + * + * @result + * The newly copied set, with a retain count of 1, + * or NULL if there is insufficient memory to do the copy. + * + * @discussion + * The receiving set, and any collections it contains, + * recursively, are copied. + * Objects that are not derived from OSCollection are retained + * rather than copied. + */ + OSCollection *copyCollection(OSDictionary *cycleDict = 0); + + OSMetaClassDeclareReservedUnused(OSSet, 0); + OSMetaClassDeclareReservedUnused(OSSet, 1); + OSMetaClassDeclareReservedUnused(OSSet, 2); + OSMetaClassDeclareReservedUnused(OSSet, 3); + OSMetaClassDeclareReservedUnused(OSSet, 4); + OSMetaClassDeclareReservedUnused(OSSet, 5); + OSMetaClassDeclareReservedUnused(OSSet, 6); + OSMetaClassDeclareReservedUnused(OSSet, 7); +}; + +#endif /* !_OS_OSSET_H */ diff --git a/OSString.cpp b/OSString.cpp new file mode 100644 index 0000000..e96637d --- /dev/null +++ b/OSString.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOString.m created by rsulack on Wed 17-Sep-1997 */ +/* IOString.cpp converted to C++ on Tue 1998-9-22 */ + +#include "OSArray.h" +#include "OSString.h" +#include "OSSerialize.h" + +#define kfree(ptr, size) kfree(ptr) +#define super OSObject + +OSDefineMetaClassAndStructors(OSString, OSObject) +OSMetaClassDefineReservedUnused(OSString, 0); +OSMetaClassDefineReservedUnused(OSString, 1); +OSMetaClassDefineReservedUnused(OSString, 2); +OSMetaClassDefineReservedUnused(OSString, 3); +OSMetaClassDefineReservedUnused(OSString, 4); +OSMetaClassDefineReservedUnused(OSString, 5); +OSMetaClassDefineReservedUnused(OSString, 6); +OSMetaClassDefineReservedUnused(OSString, 7); +OSMetaClassDefineReservedUnused(OSString, 8); +OSMetaClassDefineReservedUnused(OSString, 9); +OSMetaClassDefineReservedUnused(OSString, 10); +OSMetaClassDefineReservedUnused(OSString, 11); +OSMetaClassDefineReservedUnused(OSString, 12); +OSMetaClassDefineReservedUnused(OSString, 13); +OSMetaClassDefineReservedUnused(OSString, 14); +OSMetaClassDefineReservedUnused(OSString, 15); + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +bool OSString::initWithString(const OSString *aString) +{ + return initWithCString(aString->string); +} + +bool OSString::initWithCString(const char *cString) +{ + if (!cString || !super::init()) + return false; + length = strlen(cString) + 1; + string = (char *) kalloc(length); + if (!string) + return false; + bcopy(cString, string, length); + + ACCUMSIZE(length); + return true; +} + +bool OSString::initWithCStringNoCopy(const char *cString) +{ + if (!cString || !super::init()) + return false; + + length = strlen(cString) + 1; + flags |= kOSStringNoCopy; + string = const_cast(cString); + + return true; +} + +OSString *OSString::withString(const OSString *aString) +{ + OSString *me = new OSString; + + if (me && !me->initWithString(aString)) { + me->release(); + return 0; + } + + return me; +} + +extern "C" void* _ZN8OSString15initWithCStringEPKc(); +extern "C" void* _ZTV8OSString(); + +OSString *OSString::withCString(const char *cString) +{ + OSString *me = new OSString; + + if (me && !me->initWithCString(cString)) { + me->release(); + return 0; + } + + return me; +} + +OSString *OSString::withCStringNoCopy(const char *cString) +{ + OSString *me = new OSString; + + if (me && !me->initWithCStringNoCopy(cString)) { + me->release(); + return 0; + } + + return me; +} + +void OSString::free() +{ + if ( !(flags & kOSStringNoCopy) && string) { + kfree(string, (size_t)length); + ACCUMSIZE(-length); + } + + super::free(); +} + +unsigned int OSString::getLength() const { return length - 1; } + +const char *OSString::getCStringNoCopy() const +{ + return string; +} + +bool OSString::setChar(char aChar, unsigned int index) +{ + if ( !(flags & kOSStringNoCopy) && index < length - 1) { + string[index] = aChar; + + return true; + } + else + return false; +} + +char OSString::getChar(unsigned int index) const +{ + if (index < length) + return string[index]; + else + return '\0'; +} + + +bool OSString::isEqualTo(const OSString *aString) const +{ + if (length != aString->length) + return false; + else + return isEqualTo((const char *) aString->string); +} + +bool OSString::isEqualTo(const char *aCString) const +{ + return strncmp(string, aCString, length) == 0; +} + +bool OSString::isEqualTo(const OSMetaClassBase *obj) const +{ + + return false; +} + +bool OSString::isEqualTo(const OSData *obj) const +{ + return false; +} + +bool OSString::serialize(OSSerialize *s) const +{ + char *c = string; + + if (s->previouslySerialized(this)) return true; + + if (!s->addXMLStartTag(this, "string")) return false; + while (*c) { + if (*c == '<') { + if (!s->addString("<")) return false; + } else if (*c == '>') { + if (!s->addString(">")) return false; + } else if (*c == '&') { + if (!s->addString("&")) return false; + } else { + if (!s->addChar(*c)) return false; + } + c++; + } + + return s->addXMLEndTag("string"); +} diff --git a/OSString.h b/OSString.h new file mode 100644 index 0000000..554bdb7 --- /dev/null +++ b/OSString.h @@ -0,0 +1,413 @@ +// +// OSString.h +// Passenger +// +// Created by Kristina on 12-07-31. +// +// + +#ifndef Passenger_OSString_h +#define Passenger_OSString_h + +class OSData; + +#include "OSMetaClass.h" +#include "OSObject.h" +/*! + * @header + * + * @abstract + * This header declares the OSString container class. + */ + + +/* Not to be included in headerdoc. + * + * For internal use. + */ +enum { kOSStringNoCopy = 0x00000001 }; + + +/*! + * @class OSString + * + * @abstract + * OSString wraps a C string in a C++ object for use in Libkern collections. + * + * @discussion + * OSString is a container class for managing arrays of characters. + * An OSString normally maintains its own character buffer and allows changes, + * but you can create an "immutable" OSString + * that references an external C string + * buffer using the "NoCopy" creator functions. + * Functions called to change the contents of an immutable OSString will fail. + * + * Encodings + * + * OSString makes no provisions for different character encodings and + * assumes that a string is a nul-terminated sequence of single-byte characters. + * User-space code must either assume an encoding (typically ASCII or UTF-8) + * or determine it in some other way (such as an IORegistryEntry property). + * + * Altering Strings + * + * OSString's indended use is as a reference-counted object container + * for a C string and little more. + * While OSString provides full access to the underlying C string, + * it provides little in the way of string object manipulation; + * there are no append or insert functions, + * only a set-character function. + * If you need to manipulate OSStrings, + * it's generally best to get the C strings, + * alter them as necessary, and create a new OSString object + * from the resulting C string. + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSString provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions for setting + * properties. + */ +class OSString : public OSObject +{ + OSDeclareDefaultStructors(OSString) + +protected: + unsigned int flags; + unsigned int length; + char * string; + +public: + + + /*! + * @function withString + * + * @abstract + * Creates and initializes an OSString from another OSString. + * + * @param aString The OSString object whose contents to copy. + * + * @result + * An instance of OSString representing + * the same characters as aString, + * and with a reference count of 1; + * NULL on failure. + * + * @discussion + * The new OSString is a distinct instance from aString, + * and is not merely the original object + * with the reference count incremented. + * Changes to one will not be reflected in the other. + */ + static OSString * withString(const OSString * aString); + + + /*! + * @function withCString + * + * @abstract + * Creates and initializes an OSString from a C string. + * + * @param cString The C string to copy into the new OSString. + * + * @result + * An instance of OSString representing + * the same characters as aString, + * and with a reference count of 1; + * NULL on failure. + */ + static OSString * withCString(const char * cString); + + + /*! + * @function withCStringNoCopy + * + * @abstract + * Creates and initializes an immutable OSString + * that shares the provided C string buffer. + * + * @param cString The C string to reference. + * + * @result + * An instance of OSString containing cString, + * and with a reference count of 1; + * NULL on failure. + * + * @discussion + * An OSString object created with this function + * does not claim ownership of the C string, + * but shares it with the caller. + * When the caller determines that the OSString object has actually been freed, + * it can safely dispose of the data buffer. + * Conversely, if it frees the shared data buffer, + * it must not attempt to use the OSString object and should release it. + * + * An OSString object created with this function does not + * allow changing the string via @link setChar setChar@/link. + */ + static OSString * withCStringNoCopy(const char * cString); + + + /*! + * @function initWithString + * + * @abstract + * Initializes an OSString from another OSString. + * + * @param aString The OSString object whose contents to copy. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link withString withString@/link instead. + */ + virtual bool initWithString(const OSString * aString); + + + /*! + * @function initWithCString + * + * @abstract + * Initializes an OSString from a C string. + * + * @param cString The C string to copy into the new OSString. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link withCString withCString@/link instead. + */ + virtual bool initWithCString(const char * cString); + + + /*! + * @function initWithCStringNoCopy + * + * @abstract + * Initializes an immutable OSString + * to share the provided C string buffer. + * + * @param cString The C string to reference. + * + * @result + * true on success, false on failure. + * + * @discussion + * Not for general use. Use the static instance creation method + * @link withCStringNoCopy withCStringNoCopy@/link instead. + * + * An OSString object initialized with this function + * does not claim ownership of the C string, + * but shares it with the caller. + * When the caller determines that the OSString object has actually been freed, + * it can safely dispose of the data buffer. + * Conversely, if it frees the shared data buffer, + * it must not attempt to use the OSString object and should release it. + * + * An OSString object created with this function does not + * allow changing the string via @link setChar setChar@/link. + */ + virtual bool initWithCStringNoCopy(const char * cString); + + + /*! + * @function free + * + * @abstract + * Deallocates or releases any resources + * used by the OSString instance. + * + * @discussion + * This function should not be called directly; + * use + * @link + * //apple_ref/cpp/instm/OSObject/release/virtualvoid/() + * release@/link + * instead. + */ + virtual void free(); + + + /*! + * @function getLength + * + * @abstract + * Returns the number of characters in the OSString object. + * + * @result + * The number of characters in the OSString object. + */ + virtual unsigned int getLength() const; + + + /*! + * @function getChar + * + * @abstract + * Returns the character at a given index in the string object. + * + * @param index The index into the string. + * + * @result + * The character at index within the string, + * or '\0' if index is past the end of the string. + */ + virtual char getChar(unsigned int index) const; + + + /*! + * @function setChar + * + * @abstract + * Replaces a character at a given index in the string object. + * + * @param aChar The character value to set. + * @param index The index into the string. + * + * @result + * true if the character was replaced, + * false if the was created "NoCopy" + * or index is past the end of the string. + */ + virtual bool setChar(char aChar, unsigned int index); + + + /*! + * @function getCStringNoCopy + * + * @abstract + * Returns a pointer to the internal C string buffer. + * + * @result + * A pointer to the internal C string buffer. + */ + virtual const char * getCStringNoCopy() const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of two OSString objects. + * + * @param aString The OSString object being compared against the receiver. + * + * @result + * true if the two OSString objects are equivalent, + * false otherwise. + * + * @discussion + * Two OSString objects are considered equal if they have same length + * and if their byte buffers hold the same contents. + */ + virtual bool isEqualTo(const OSString * aString) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSString object with a C string. + * + * @param cString The C string to compare against the receiver. + * + * @result + * true if the OSString's characters + * are equivalent to the C string's, + * false otherwise. + */ + virtual bool isEqualTo(const char * cString) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSString object to an arbitrary object. + * + * @param anObject The object to be compared against the receiver. + * + * @result + * Returns true if the two objects are equivalent, + * false otherwise. + * + * @discussion + * An OSString is considered equal to another object + * if that object is derived from OSString + * and contains the equivalent bytes of the same length. + */ + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of an OSData object and the OSString instance. + * + * @param aDataObject An OSData object. + * + * @result + * true if the two objects are equivalent, false otherwise. + * + * @discussion + * This function compares the bytes of the OSData object + * against those of the OSString, + * accounting for the possibility that an OSData + * might explicitly include a nul + * character as part of its total length. + * Thus, for example, an OSData object containing + * either the bytes <'u', 's', 'b', '\0'> + * or <'u', 's', 'b'> + * will compare as equal to the OSString containing "usb". + */ + virtual bool isEqualTo(const OSData * aDataObject) const; + + + /*! + * @function serialize + * + * @abstract + * Archives the receiver into the provided + * @link //apple_ref/doc/class/OSSerialize OSSerialize@/link object. + * + * @param serializer The OSSerialize object. + * + * @result + * true if serialization succeeds, false if not. + */ + virtual bool serialize(OSSerialize * serializer) const; + + OSMetaClassDeclareReservedUnused(OSString, 0); + OSMetaClassDeclareReservedUnused(OSString, 1); + OSMetaClassDeclareReservedUnused(OSString, 2); + OSMetaClassDeclareReservedUnused(OSString, 3); + OSMetaClassDeclareReservedUnused(OSString, 4); + OSMetaClassDeclareReservedUnused(OSString, 5); + OSMetaClassDeclareReservedUnused(OSString, 6); + OSMetaClassDeclareReservedUnused(OSString, 7); + OSMetaClassDeclareReservedUnused(OSString, 8); + OSMetaClassDeclareReservedUnused(OSString, 9); + OSMetaClassDeclareReservedUnused(OSString, 10); + OSMetaClassDeclareReservedUnused(OSString, 11); + OSMetaClassDeclareReservedUnused(OSString, 12); + OSMetaClassDeclareReservedUnused(OSString, 13); + OSMetaClassDeclareReservedUnused(OSString, 14); + OSMetaClassDeclareReservedUnused(OSString, 15); +}; + +#endif diff --git a/OSSymbol.cpp b/OSSymbol.cpp new file mode 100755 index 0000000..5a13b22 --- /dev/null +++ b/OSSymbol.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2000-2007 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOSymbol.cpp created by gvdl on Fri 1998-11-17 */ + +#include "OSSymbol.h" + +#define super OSString + +typedef struct { int i, j; } OSSymbolPoolState; + +#if OSALLOCDEBUG +extern "C" { + extern int debug_container_malloc_size; +}; +#define ACCUMSIZE(s) do { debug_container_malloc_size += (s); } while(0) +#else +#define ACCUMSIZE(s) +#endif + +#define INITIAL_POOL_SIZE (exp2ml(1 + log2(kInitBucketCount))) + +#define GROW_FACTOR (1) +#define SHRINK_FACTOR (3) + +#define GROW_POOL() do \ + if (count * GROW_FACTOR > nBuckets) { \ + reconstructSymbols(true); \ + } \ +while (0) + +#define SHRINK_POOL() do \ + if (count * SHRINK_FACTOR < nBuckets && \ + nBuckets > INITIAL_POOL_SIZE) { \ + reconstructSymbols(false); \ + } \ +while (0) + +class OSSymbolPool +{ +private: + static const unsigned int kInitBucketCount = 16; + + typedef struct { unsigned int count; OSSymbol **symbolP; } Bucket; + + Bucket *buckets; + unsigned int nBuckets; + unsigned int count; + int poolGate; + + static inline void hashSymbol(const char *s, + unsigned int *hashP, + unsigned int *lenP) + { + unsigned int hash = 0; + unsigned int len = 0; + + /* Unroll the loop. */ + for (;;) { + if (!*s) break; len++; hash ^= *s++; + if (!*s) break; len++; hash ^= *s++ << 8; + if (!*s) break; len++; hash ^= *s++ << 16; + if (!*s) break; len++; hash ^= *s++ << 24; + } + *lenP = len; + *hashP = hash; + } + + static unsigned long log2(unsigned int x); + static unsigned long exp2ml(unsigned int x); + + void reconstructSymbols(void); + void reconstructSymbols(bool grow); + +public: + static void *operator new(size_t size); + static void operator delete(void *mem, size_t size); + + OSSymbolPool() { }; + OSSymbolPool(const OSSymbolPool *old); + virtual ~OSSymbolPool(); + + bool init(); + + inline void closeGate() { }; + inline void openGate() { }; + + OSSymbol *findSymbol(const char *cString) const; + OSSymbol *insertSymbol(OSSymbol *sym); + void removeSymbol(OSSymbol *sym); + + OSSymbolPoolState initHashState(); + OSSymbol *nextHashState(OSSymbolPoolState *stateP); +}; + +void * OSSymbolPool::operator new(size_t size) +{ + void *mem = (void *)kalloc(size); + ACCUMSIZE(size); + assert(mem); + bzero(mem, size); + + return mem; +} + +void OSSymbolPool::operator delete(void *mem, size_t size) +{ + kfree(mem, size); + ACCUMSIZE(-size); +} + +bool OSSymbolPool::init() +{ + count = 0; + nBuckets = INITIAL_POOL_SIZE; + buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket)); + ACCUMSIZE(nBuckets * sizeof(Bucket)); + + assert(buckets); + + if (!buckets) + { + return false; + } + + bzero(buckets, nBuckets * sizeof(Bucket)); + + // poolGate = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL); + poolGate = 1; /* hax */ + + return poolGate != 0; +} + +OSSymbolPool::OSSymbolPool(const OSSymbolPool *old) +{ + count = old->count; + nBuckets = old->nBuckets; + buckets = old->buckets; + + poolGate = 0; // Do not duplicate the poolGate +} + +OSSymbolPool::~OSSymbolPool() +{ + if (buckets) { + kfree(buckets, nBuckets * sizeof(Bucket)); + ACCUMSIZE(-(nBuckets * sizeof(Bucket))); + } + + // if (poolGate) + // lck_mtx_free(poolGate, IOLockGroup); +} + +unsigned long OSSymbolPool::log2(unsigned int x) +{ + unsigned long i; + + for (i = 0; x > 1 ; i++) + x >>= 1; + return i; +} + +unsigned long OSSymbolPool::exp2ml(unsigned int x) +{ + return (1 << x) - 1; +} + +OSSymbolPoolState OSSymbolPool::initHashState() +{ + OSSymbolPoolState newState = { nBuckets, 0 }; + return newState; +} + +OSSymbol *OSSymbolPool::nextHashState(OSSymbolPoolState *stateP) +{ + Bucket *thisBucket = &buckets[stateP->i]; + + while (!stateP->j) { + if (!stateP->i) + return 0; + stateP->i--; + thisBucket--; + stateP->j = thisBucket->count; + } + + stateP->j--; + if (thisBucket->count == 1) + return (OSSymbol *) thisBucket->symbolP; + else + return thisBucket->symbolP[stateP->j]; +} + +void OSSymbolPool::reconstructSymbols(void) +{ + this->reconstructSymbols(true); +} + +void OSSymbolPool::reconstructSymbols(bool grow) +{ + unsigned int new_nBuckets = nBuckets; + OSSymbol *insert; + OSSymbolPoolState state; + + if (grow) { + new_nBuckets += new_nBuckets + 1; + } else { + /* Don't shrink the pool below the default initial size. + */ + if (nBuckets <= INITIAL_POOL_SIZE) { + return; + } + new_nBuckets = (new_nBuckets - 1) / 2; + } + + /* Create old pool to iterate after doing above check, cause it + * gets finalized at return. + */ + OSSymbolPool old(this); + + count = 0; + nBuckets = new_nBuckets; + buckets = (Bucket *) kalloc(nBuckets * sizeof(Bucket)); + ACCUMSIZE(nBuckets * sizeof(Bucket)); + /* @@@ gvdl: Zero test and panic if can't set up pool */ + bzero(buckets, nBuckets * sizeof(Bucket)); + + state = old.initHashState(); + while ( (insert = old.nextHashState(&state)) ) + insertSymbol(insert); +} + +OSSymbol *OSSymbolPool::findSymbol(const char *cString) const +{ + Bucket *thisBucket; + unsigned int j, inLen, hash; + OSSymbol *probeSymbol, **list; + + hashSymbol(cString, &hash, &inLen); inLen++; + thisBucket = &buckets[hash % nBuckets]; + j = thisBucket->count; + + if (!j) + return 0; + + if (j == 1) { + probeSymbol = (OSSymbol *) thisBucket->symbolP; + + if (inLen == probeSymbol->length + && (strncmp(probeSymbol->string, cString, probeSymbol->length) == 0)) + return probeSymbol; + return 0; + } + + for (list = thisBucket->symbolP; j--; list++) { + probeSymbol = *list; + if (inLen == probeSymbol->length + && (strncmp(probeSymbol->string, cString, probeSymbol->length) == 0)) + return probeSymbol; + } + + return 0; +} + +OSSymbol *OSSymbolPool::insertSymbol(OSSymbol *sym) +{ + const char *cString = sym->string; + Bucket *thisBucket; + unsigned int j, inLen, hash; + OSSymbol *probeSymbol, **list; + + hashSymbol(cString, &hash, &inLen); inLen++; + thisBucket = &buckets[hash % nBuckets]; + j = thisBucket->count; + + if (!j) { + thisBucket->symbolP = (OSSymbol **) sym; + thisBucket->count++; + count++; + return sym; + } + + if (j == 1) { + probeSymbol = (OSSymbol *) thisBucket->symbolP; + + if (inLen == probeSymbol->length + && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0) + return probeSymbol; + + list = (OSSymbol **) kalloc(2 * sizeof(OSSymbol *)); + ACCUMSIZE(2 * sizeof(OSSymbol *)); + /* @@@ gvdl: Zero test and panic if can't set up pool */ + list[0] = sym; + list[1] = probeSymbol; + thisBucket->symbolP = list; + thisBucket->count++; + count++; + GROW_POOL(); + + return sym; + } + + for (list = thisBucket->symbolP; j--; list++) { + probeSymbol = *list; + if (inLen == probeSymbol->length + && strncmp(probeSymbol->string, cString, probeSymbol->length) == 0) + return probeSymbol; + } + + j = thisBucket->count++; + count++; + list = (OSSymbol **) kalloc(thisBucket->count * sizeof(OSSymbol *)); + ACCUMSIZE(thisBucket->count * sizeof(OSSymbol *)); + /* @@@ gvdl: Zero test and panic if can't set up pool */ + list[0] = sym; + bcopy(thisBucket->symbolP, list + 1, j * sizeof(OSSymbol *)); + kfree(thisBucket->symbolP, j * sizeof(OSSymbol *)); + ACCUMSIZE(-(j * sizeof(OSSymbol *))); + thisBucket->symbolP = list; + GROW_POOL(); + + return sym; +} + +void OSSymbolPool::removeSymbol(OSSymbol *sym) +{ + Bucket *thisBucket; + unsigned int j, inLen, hash; + OSSymbol *probeSymbol, **list; + + hashSymbol(sym->string, &hash, &inLen); inLen++; + thisBucket = &buckets[hash % nBuckets]; + j = thisBucket->count; + list = thisBucket->symbolP; + + if (!j) + return; + + if (j == 1) { + probeSymbol = (OSSymbol *) list; + + if (probeSymbol == sym) { + thisBucket->symbolP = 0; + count--; + thisBucket->count--; + SHRINK_POOL(); + return; + } + return; + } + + if (j == 2) { + probeSymbol = list[0]; + if (probeSymbol == sym) { + thisBucket->symbolP = (OSSymbol **) list[1]; + kfree(list, 2 * sizeof(OSSymbol *)); + ACCUMSIZE(-(2 * sizeof(OSSymbol *))); + count--; + thisBucket->count--; + SHRINK_POOL(); + return; + } + + probeSymbol = list[1]; + if (probeSymbol == sym) { + thisBucket->symbolP = (OSSymbol **) list[0]; + kfree(list, 2 * sizeof(OSSymbol *)); + ACCUMSIZE(-(2 * sizeof(OSSymbol *))); + count--; + thisBucket->count--; + SHRINK_POOL(); + return; + } + return; + } + + for (; j--; list++) { + probeSymbol = *list; + if (probeSymbol == sym) { + + list = (OSSymbol **) + kalloc((thisBucket->count-1) * sizeof(OSSymbol *)); + ACCUMSIZE((thisBucket->count-1) * sizeof(OSSymbol *)); + if (thisBucket->count-1 != j) + bcopy(thisBucket->symbolP, list, + (thisBucket->count-1-j) * sizeof(OSSymbol *)); + if (j) + bcopy(thisBucket->symbolP + thisBucket->count-j, + list + thisBucket->count-1-j, + j * sizeof(OSSymbol *)); + kfree(thisBucket->symbolP, thisBucket->count * sizeof(OSSymbol *)); + ACCUMSIZE(-(thisBucket->count * sizeof(OSSymbol *))); + thisBucket->symbolP = list; + count--; + thisBucket->count--; + return; + } + } +} + +/* + ********************************************************************* + * From here on we are actually implementing the OSSymbol class + ********************************************************************* + */ +OSDefineMetaClassAndStructorsWithInit(OSSymbol, OSString, + OSSymbol::initialize()) +OSMetaClassDefineReservedUnused(OSSymbol, 0); +OSMetaClassDefineReservedUnused(OSSymbol, 1); +OSMetaClassDefineReservedUnused(OSSymbol, 2); +OSMetaClassDefineReservedUnused(OSSymbol, 3); +OSMetaClassDefineReservedUnused(OSSymbol, 4); +OSMetaClassDefineReservedUnused(OSSymbol, 5); +OSMetaClassDefineReservedUnused(OSSymbol, 6); +OSMetaClassDefineReservedUnused(OSSymbol, 7); + +static OSSymbolPool *pool; + +void OSSymbol::initialize() +{ + pool = new OSSymbolPool; + assert(pool); + + if (!pool->init()) { + delete pool; + assert(false); + }; +} + +bool OSSymbol::initWithCStringNoCopy(const char *) { return false; } +bool OSSymbol::initWithCString(const char *) { return false; } +bool OSSymbol::initWithString(const OSString *) { return false; } + +const OSSymbol *OSSymbol::withString(const OSString *aString) +{ + // This string may be a OSSymbol already, cheap check. + if (OSDynamicCast(OSSymbol, aString)) { + aString->retain(); + return (const OSSymbol *) aString; + } + else if (((const OSSymbol *) aString)->flags & kOSStringNoCopy) + return OSSymbol::withCStringNoCopy(aString->getCStringNoCopy()); + else + return OSSymbol::withCString(aString->getCStringNoCopy()); +} + +const OSSymbol *OSSymbol::withCString(const char *cString) +{ + pool->closeGate(); + + OSSymbol *oldSymb = pool->findSymbol(cString); + if (!oldSymb) { + OSSymbol *newSymb = new OSSymbol; + if (!newSymb) { + pool->openGate(); + return newSymb; + } + + if (newSymb->OSString::initWithCString(cString)) + oldSymb = pool->insertSymbol(newSymb); + + if (newSymb == oldSymb) { + pool->openGate(); + return newSymb; // return the newly created & inserted symbol. + } + else + // Somebody else inserted the new symbol so free our copy + newSymb->OSString::free(); + } + + oldSymb->retain(); // Retain the old symbol before releasing the lock. + + pool->openGate(); + return oldSymb; +} + +const OSSymbol *OSSymbol::withCStringNoCopy(const char *cString) +{ + pool->closeGate(); + + OSSymbol *oldSymb = pool->findSymbol(cString); + if (!oldSymb) { + OSSymbol *newSymb = new OSSymbol; + if (!newSymb) { + pool->openGate(); + return newSymb; + } + + if (newSymb->OSString::initWithCStringNoCopy(cString)) + oldSymb = pool->insertSymbol(newSymb); + + if (newSymb == oldSymb) { + pool->openGate(); + return newSymb; // return the newly created & inserted symbol. + } + else + // Somebody else inserted the new symbol so free our copy + newSymb->OSString::free(); + } + + oldSymb->retain(); // Retain the old symbol before releasing the lock. + + pool->openGate(); + return oldSymb; +} + +void OSSymbol::checkForPageUnload(void *startAddr, void *endAddr) +{ + OSSymbol *probeSymbol; + OSSymbolPoolState state; + + pool->closeGate(); + state = pool->initHashState(); + while ( (probeSymbol = pool->nextHashState(&state)) ) { + if (probeSymbol->string >= startAddr && probeSymbol->string < endAddr) { + const char *oldString = probeSymbol->string; + + probeSymbol->string = (char *) kalloc(probeSymbol->length); + ACCUMSIZE(probeSymbol->length); + bcopy(oldString, probeSymbol->string, probeSymbol->length); + probeSymbol->flags &= ~kOSStringNoCopy; + } + } + pool->openGate(); +} + +void OSSymbol::taggedRelease(const void *tag) const +{ + super::taggedRelease(tag); +} + +void OSSymbol::taggedRelease(const void *tag, const int when) const +{ + pool->closeGate(); + super::taggedRelease(tag, when); + pool->openGate(); +} + +void OSSymbol::free() +{ + pool->removeSymbol(this); + super::free(); +} + +bool OSSymbol::isEqualTo(const char *aCString) const +{ + return super::isEqualTo(aCString); +} + +bool OSSymbol::isEqualTo(const OSSymbol *aSymbol) const +{ + return aSymbol == this; +} + +bool OSSymbol::isEqualTo(const OSMetaClassBase *obj) const +{ + OSSymbol * sym; + OSString * str; + + if ((sym = OSDynamicCast(OSSymbol, obj))) + return isEqualTo(sym); + else if ((str = OSDynamicCast(OSString, obj))) + return super::isEqualTo(str); + else + return false; +} diff --git a/OSSymbol.h b/OSSymbol.h new file mode 100755 index 0000000..15d8d4a --- /dev/null +++ b/OSSymbol.h @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* IOSymbol.h created by gvdl on Fri 1998-10-30 */ +/* OSSymbol must be created through the factory methods and thus is not subclassable. */ + +#ifndef _OS_OSSYMBOL_H +#define _OS_OSSYMBOL_H + +#include "OSString.h" + +/*! + * @header + * + * @abstract + * This header declares the OSSymbol container class. + */ + +// xx-review: OSSymbol does not override setChar + +/*! + * @class OSSymbol + * + * @abstract + * OSSymbol wraps a C string in a unique C++ object + * for use as keys in Libkern collections. + * + * @discussion + * OSSymbol is a container class for managing uniqued strings, + * for example, those used as dictionary keys. + * Its static instance-creation functions check + * for an existing instance of OSSymbol + * with the requested C string value before creating a new object. + * If an instance already exists in the pool of unique symbols, + * its reference count is incremented + * and the existing instance is returned. + * + * While OSSymbol provides for uniquing of a given string value, + * it makes no effort to enforce immutability of that value. + * Altering the contents of an OSSymbol should be avoided. + * + * Use Restrictions + * + * With very few exceptions in the I/O Kit, all Libkern-based C++ + * classes, functions, and macros are unsafe + * to use in a primary interrupt context. + * Consult the I/O Kit documentation related to primary interrupts + * for more information. + * + * OSSymbol provides no concurrency protection; + * it's up to the usage context to provide any protection necessary. + * Some portions of the I/O Kit, such as + * @link //apple_ref/doc/class/IORegistryEntry IORegistryEntry@/link, + * handle synchronization via defined member functions for setting + * properties. + */ +class OSSymbol : public OSString +{ + friend class OSSymbolPool; + + OSDeclareAbstractStructors(OSSymbol) + +private: + struct ExpansionData { }; + + /* Reserved for future use. (Internal use only) */ + ExpansionData * reserved; + + static void initialize(); + + // xx-review: not in xnu, delete? + friend void checkModuleForSymbols(void); /* in catalogue? */ + + // xx-review: these should be removed from the symbol set. + + /*! + * @function initWithString + * + * @abstract + * Overridden to prevent creation of duplicate symbols. + * + * @param aString Unused. + * + * @result + * false. + * + * @discussion + * Overrides OSString's implementation to prevent creation + * of distinct OSSymbols with the same string value. + */ + virtual bool initWithString(const OSString * aString); + + + /*! + * @function initWithCString + * + * @abstract + * Overridden to prevent creation of duplicate symbols. + * + * @param cString Unused. + * + * @result + * false. + * + * @discussion + * Overrides OSString's implementation to prevent creation + * of distinct OSSymbols with the same string value. + */ + virtual bool initWithCString(const char * cString); + + + /*! + * @function initWithCStringNoCopy + * + * @abstract + * Overridden to prevent creation of duplicate symbols. + * + * @param cString Unused. + * + * @result + * false. + * + * @discussion + * Overrides OSString's implementation to prevent creation + * of distinct OSSymbols with the same string value. + */ + virtual bool initWithCStringNoCopy(const char *cString); + +protected: + +// xx-review: should we just omit this from headerdoc? + /*! + * @function taggedRelease + * + * @abstract + * Overrides + * @link + * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*,constint) + * OSObject::taggedRelease(const void *, const int)@/link + * to synchronize with the symbol pool. + * + * @param tag Used for tracking collection references. + * @param freeWhen If decrementing the reference count makes it + * >= freeWhen, the object is immediately freed. + * + * @discussion + * Because OSSymbol shares instances, the reference-counting functions + * must synchronize access to the class-internal tables + * used to track those instances. + */ + virtual void taggedRelease( + const void * tag, + const int freeWhen) const; + + +// xx-review: should we just omit this from headerdoc? + /*! + * @function free + * + * @abstract + * Overrides + * @link + * //apple_ref/cpp/instm/OSObject/free/virtualvoid/() + * OSObject::free@/link + * to synchronize with the symbol pool. + * + * @discussion + * Because OSSymbol shares instances, the reference-counting functions + * must synchronize access to the class-internal tables + * used to track those instances. + */ + virtual void free(); + +public: + +// xx-review: should we just omit this from headerdoc? + /*! + * @function taggedRelease + * + * @abstract + * Overrides + * @link + * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*) + * OSObject::taggedRelease(const void *)@/link + * to synchronize with the symbol pool. + * + * @param tag Used for tracking collection references. + * + * @discussion + * Because OSSymbol shares instances, the reference-counting functions + * must synchronize access to the class-internal tables + * used to track those instances. + */ + + /* Original note (not for headerdoc): + * The C++ language has forced me to override this method + * even though I have implemented it as + * { super::taggedRelease(tag) }. + * It seems that C++ is confused about the appearance of the protected + * taggedRelease with 2 parameters and refuses to only inherit one function. + * See + * @link + * //apple_ref/cpp/instm/OSObject/taggedRelease/virtualvoid/(constvoid*,constint) + * OSObject::taggedRelease(const void *, const int)@/link. + */ + virtual void taggedRelease(const void * tag) const; + + + /*! + * @function withString + * + * @abstract + * Returns an OSSymbol created from an OSString, + * or the existing unique instance of the same value. + * + * @param aString The OSString object to look up or copy. + * + * @result + * An instance of OSSymbol + * representing the same characters as aString; + * NULL on failure. + * + * @discussion + * This function creates or returns the unique OSSymbol instance + * representing the string value of aString. + * You can compare it with other OSSymbols using the == operator. + * + * OSSymbols are reference-counted normally. + * This function either returns a + * new OSSymbol with a retain count of 1, + * or increments the retain count of the existing instance. + */ + static const OSSymbol * withString(const OSString * aString); + + + /*! + * @function withCString + * + * @abstract + * Returns an OSSymbol created from a C string, + * or the existing unique instance of the same value. + * + * @param cString The C string to look up or copy. + * + * @result + * An instance of OSSymbol representing + * the same characters as cString; + * NULL on failure. + * + * @discussion + * This function returns the unique OSSymbol instance + * representing the string value of cString. + * You can compare it with other OSSymbols using the == operator. + * + * OSSymbols are reference-counted normally. + * This function either returns a + * new OSSymbol with a retain count of 1, + * or increments the retain count of the existing instance. + */ + static const OSSymbol * withCString(const char * cString); + + + /*! + * @function withCStringNoCopy + * + * @abstract + * Returns an OSSymbol created from a C string, + * without copying that string, + * or the existing unique instance of the same value. + * + * @param cString The C string to look up or use. + * @result + * An instance of OSSymbol representing + * the same characters as cString; + * NULL. + * + * @discussion + * Avoid using this function; + * OSSymbols should own their internal string buffers. + * + * This function returns the unique OSSymbol instance + * representing the string value of cString. + * You can compare it with other OSSymbols using the == operator. + * + * OSSymbols are reference-counted normally. + * This function either returns a + * new OSSymbol with a retain count of 1, + * or increments the retain count of the existing instance. + */ + static const OSSymbol * withCStringNoCopy(const char * cString); + + + /*! + * @function isEqualTo + * + * @abstract + * Tests the equality of two OSSymbol objects. + * + * @param aSymbol The OSSymbol object being compared against the receiver. + * + * @result + * true if the two OSSymbol objects are equivalent, + * false otherwise. + * + * @discussion + * Two OSSymbol objects are considered equal if they have the same address; + * that is, this function is equivalent to the == operator. + */ + virtual bool isEqualTo(const OSSymbol * aSymbol) const; + + + /*! + * @function isEqualTo + * + * @abstract Tests the equality of an OSSymbol object with a C string. + * + * @param cString The C string to compare against the receiver. + * + * @result + * true if the OSSymbol's characters + * are equivalent to the C string's, + * false otherwise. + */ + virtual bool isEqualTo(const char * cString) const; + + + /*! + * @function isEqualTo + * + * @abstract Tests the equality of an OSSymbol object to an arbitrary object. + * + * @param anObject The object to be compared against the receiver. + * @result Returns true if the two objects are equivalent, + * false otherwise. + * + * @discussion + * An OSSymbol is considered equal to another object + * if that object is derived from + * @link //apple_ref/doc/class/OSMetaClassBase OSString@/link + * and contains the equivalent bytes of the same length. + */ + virtual bool isEqualTo(const OSMetaClassBase * anObject) const; + + + /* OSRuntime only INTERNAL API - DO NOT USE */ + /* Not to be included in headerdoc. */ + // xx-review: this should be removed from the symbol set. + static void checkForPageUnload( + void * startAddr, + void * endAddr); + + + OSMetaClassDeclareReservedUnused(OSSymbol, 0); + OSMetaClassDeclareReservedUnused(OSSymbol, 1); + OSMetaClassDeclareReservedUnused(OSSymbol, 2); + OSMetaClassDeclareReservedUnused(OSSymbol, 3); + OSMetaClassDeclareReservedUnused(OSSymbol, 4); + OSMetaClassDeclareReservedUnused(OSSymbol, 5); + OSMetaClassDeclareReservedUnused(OSSymbol, 6); + OSMetaClassDeclareReservedUnused(OSSymbol, 7); +}; + +#endif /* !_OS_OSSYMBOL_H */ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..2490f61 --- /dev/null +++ b/main.cpp @@ -0,0 +1,42 @@ +/* + * libkern_test + * Copyright (c) 2012 Christina Brooks + * + * Testing the libkern functionality. + */ + +#include "main.h" +#include "OSMetaClass.h" +#include "OSArray.h" +#include "OSObject.h" +#include "OSString.h" +#include "OSSerialize.h" + +extern "C" volatile int kmod_start(void); +void libkern_init0(); + +volatile int kmod_start(void) +{ + libkern_init0(); + + OSString* one = OSString::withCString("Anal sex"); + OSString* two = OSString::withCString("Cunnilungus"); + + OSArray* sexthings = OSArray::withCapacity(2); + + sexthings->setObject(one); + sexthings->setObject(two); + + printk("Hello from IOKit!\n"); + + printk("Put: %p %p\n", one, two); + printk("OSArray: %p\n", sexthings); + printk("Get: %p %p\n", sexthings->getObject(0), sexthings->getObject(1)); + + OSSerialize* ser = OSSerialize::withCapacity(1024); + sexthings->serialize(ser); + + printk("Serialized: %s \n", ser->text()); + + return 0; +} \ No newline at end of file diff --git a/main.h b/main.h new file mode 100644 index 0000000..3a02be4 --- /dev/null +++ b/main.h @@ -0,0 +1,13 @@ +/* + * Passenger + * Copyright (c) 2012 Christina Brooks + * + * xxx + */ + +#ifndef __Passenger__main__ +#define __Passenger__main__ + +#include "runtime.h" + +#endif diff --git a/runtime.h b/runtime.h new file mode 100644 index 0000000..713ee32 --- /dev/null +++ b/runtime.h @@ -0,0 +1,47 @@ +/* + * runtime.h + * Copyright (c) 2012 Christina Brooks + * + * xxx + */ + +#ifndef libkern_runtime_h +#define libkern_runtime_h + +#include "mach_types.h" + +typedef __darwin_size_t size_t; + +#define __unused + +#ifdef __cplusplus +extern "C" { +#endif + +/* starndard stuff */ + void panic(const char *fmt, ...); + void printk(const char *fmt, ...); + int snprintf(char *buf, size_t size, const char *fmt, ...); + +/* mem */ + void kfree(void* ptr); + void* kalloc(size_t size); + void bzero(void* base, size_t size); + void bcopy(const void *src, void *dest, size_t n); + +/* string */ + int strcmp(const char *s1, const char *s2); + int strncmp(const char *s1, const char *s2, size_t n); + size_t strlen(const char *s); + +#ifdef __cplusplus +} + +/* now for C++ syms */ +void kfree(void* ptr, size_t size); + +#endif + +#define assert(x) if (!x) { panic("[%s:%d] assertion failed '%s'", __FILE__, __LINE__, #x); } + +#endif