#ifndef OS_OSMETACLASS_H
#define OS_OSMETACLASS_H

#include <sys/types.h>

#include <libkern/OSReturn.h>
#include <kern/debug.h>
#include <APPLE/libkern/c++/OSMetaClass.h>


//functions



class OSMetaClass;
class OSObject;
class OSString;
class OSSymbol;
class OSDictionary;
class OSSerialize;

class OSMetaClassBase{
public:
#include <APPLE/libkern/c++/OSMetaClass_OSMetaClassBase.h>
/*OSDynamicCast


Roughly analogous to (type *) inst, but check if valid first.
public

#define OSDynamicCast(type, inst) \ 
    ((type *) OSMetaClassBase::safeMetaCast((inst), (type::metaClass))) 
Parameters
type
Name of desired class name. Notice that it is assumed that you desire to cast to a pointer to an object of this type. Also type qualifiers, like const, are not recognized and will cause a (usually obscure) compile error.
inst
Pointer to object that you wish to attempt to type cast. May be 0.
Return Value

If object non-zero and it is of the desired type, otherwise 0. 
Discussion 

OSDynamicCast is an attempt to implement a rudimentary equivalent to RTTI's dynamic_cast operator. Note that the restricted subset of C++ upon which the I/O Kit is based does not support RTTI. OSDynamicCast is build on the OSMetaClass mechanism. Note it is safe to call this with a 0 parameter.*/
#define OSDynamicCast(type, inst) \
    ((type *) OSMetaClassBase::safeMetaCast((inst), (type::metaClass))) 


};

class OSMetaClass : private OSMetaClassBase{

public:

/*OSDeclareDefaultStructors


Declares runtime type information data and interfaces (one of the macros used in the class declaration of all subclasses of OSObject). 
public

#define OSDeclareDefaultStructors(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 (); \ 
    public: \ 
    className (); \ 
    protected: 
Parameters
className
Name of class (NO QUOTES).
Discussion 

By convention this should be 'called' immediately after the opening brace in a class declaration. It leaves the current privacy state as 'protected:'.*/
#define OSDeclareDefaultStructors(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 (); \
    public: \
    className (); \
    protected:

/*OSDefineMetaClassAndStructors


Defines an OSMetaClass subclass and the runtime system routines.
public

#define OSDefineMetaClassAndStructors(className, superClassName) \ 
    // 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)) \ 
    { ; } \ 
    OSObject * className ::MetaClass::alloc() const \ 
    { return new className; } \ 
    className :: className () : superClassName (&gMetaClass) \ 
    { gMetaClass.instanceConstructed(); } 
Parameters
className
Name of class. NO QUOTES and NO MACROS.
superClassName
Name of super class. NO QUOTES and NO MACROS.
Discussion 

Define an OSMetaClass subclass and the primary constructors and destructors for a subclass of OSObject that isn't an abstract class. In general this 'function' is 'called' at the top of the file just before the first function is implemented for a particular class.*/
#define OSDefineMetaClassAndStructors(className, superClassName) \
    /* 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)) \
    { ; } \
    OSObject * className ::MetaClass::alloc() const \
    { return new className; } \
    className :: className () : superClassName (&gMetaClass) \
    { gMetaClass.instanceConstructed(); }

/*OSDeclareAbstractStructors


Declares runtime type information data and interfaces (one of the macros used in the class declaration of all subclasses of OSObject). 
public

#define OSDeclareAbstractStructors(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 (); \ 
    private: \ 
    className (); / Make primary constructor private in abstract *\ 
    protected: 
Parameters
className
Name of class (NO QUOTES).
Discussion 

This macro is used when the class being declared has one or more '= 0' pure virtual methods and thus it is illegal to create an instance of this class. It leaves the current privacy state as 'protected:'.*/
#define OSDeclareAbstractStructors(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 (); \
    private: \
    className (); /* Make primary constructor private in abstract */ \
    protected:

/*OSMetaClass(const char *, const OSMetaClass *, unsigned int)


Constructor for OSMetaClass objects. 
protected

OSMetaClass(
    const char *inClassName, 
    const OSMetaClass *inSuperClass, 
    unsigned int inClassSize); 
Parameters
inClassName
C string of the name of the class this metaclass represents.
inSuperClassName
C string of the name of the super class.
inClassSize
size of the class.
Discussion 

This constructor is protected and cannot be used to instantiate an OSMetaClass object, i.e. OSMetaClass is an abstract class. This function stores the currently constructing OSMetaClass instance away for later processing. See preModLoad and postModLoad.*/
OSMetaClass(
    const char *inClassName, 
    const OSMetaClass *inSuperClass, 
    unsigned int inClassSize); 

/*instanceConstructed


Counts the instances of the class behind this metaclass. 
public

void instanceConstructed() const; 
Discussion 

Every non-abstract class that inherits from OSObject has a default constructor that calls its own metaclass's instanceConstructed function. This constructor is defined by the OSDefineMetaClassAndStructors macro (qv) that all OSObject subclasses must use. Also, if the instance count goes from 0 to 1, i.e. the first instance, then increment the instance count of the super class.*/
void instanceConstructed() const; 

};



#endif