In libobjc/: 2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>
In libobjc/: 2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com> * Makefile.in (C_SOURCE_FILES): Added ivars.c. * ivars.c: New. * objc/objc.h: Updated comments. * objc/runtime.h (object_getClass): New. (object_getClassName): New. (object_setClass): New. (class_getInstanceVariable): New. (object_getIndexedIvars): New. (object_getInstanceVariable): New. (object_setInstanceVariable): New. (object_getIvar): New. (object_setIvar): New. (ivar_getName): New. (ivar_getOffset): New. (ivar_getTypeEncoding): New. * objc-private/module-abi-8.h (struct objc_class): Added. * objects.c (object_getClassName): New. (object_setClass): New. From-SVN: r165269
This commit is contained in:
parent
f3660703cb
commit
fdcbbfe70c
@ -1,3 +1,24 @@
|
||||
2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* Makefile.in (C_SOURCE_FILES): Added ivars.c.
|
||||
* ivars.c: New.
|
||||
* objc/objc.h: Updated comments.
|
||||
* objc/runtime.h (object_getClass): New.
|
||||
(object_getClassName): New.
|
||||
(object_setClass): New.
|
||||
(class_getInstanceVariable): New.
|
||||
(object_getIndexedIvars): New.
|
||||
(object_getInstanceVariable): New.
|
||||
(object_setInstanceVariable): New.
|
||||
(object_getIvar): New.
|
||||
(object_setIvar): New.
|
||||
(ivar_getName): New.
|
||||
(ivar_getOffset): New.
|
||||
(ivar_getTypeEncoding): New.
|
||||
* objc-private/module-abi-8.h (struct objc_class): Added.
|
||||
* objects.c (object_getClassName): New.
|
||||
(object_setClass): New.
|
||||
|
||||
2010-10-11 Nicola Pero <nicola.pero@meta-innovation.com>
|
||||
|
||||
* objc/objc.h: Updated comments.
|
||||
|
@ -171,6 +171,7 @@ C_SOURCE_FILES = \
|
||||
gc.c \
|
||||
hash.c \
|
||||
init.c \
|
||||
ivars.c \
|
||||
memory.c \
|
||||
nil_method.c \
|
||||
objc-foreach.c \
|
||||
|
151
libobjc/ivars.c
Normal file
151
libobjc/ivars.c
Normal file
@ -0,0 +1,151 @@
|
||||
/* GNU Objective C Runtime ivar related functions.
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
Contributed by Nicola Pero
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "objc-private/common.h"
|
||||
#include "objc/objc.h"
|
||||
#include "objc/objc-api.h"
|
||||
#include "objc-private/runtime.h" /* the kitchen sink */
|
||||
#include <string.h> /* For strcmp */
|
||||
|
||||
struct objc_ivar *
|
||||
class_getInstanceVariable (Class class_, const char *name)
|
||||
{
|
||||
if (class_ != Nil && name != NULL)
|
||||
{
|
||||
objc_mutex_lock (__objc_runtime_mutex);
|
||||
while (class_ != Nil)
|
||||
{
|
||||
struct objc_ivar_list *ivars = class_->ivars;
|
||||
if (ivars != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ivars->ivar_count; i++)
|
||||
{
|
||||
struct objc_ivar *ivar = &(ivars->ivar_list[i]);
|
||||
|
||||
if (!strcmp (ivar->ivar_name, name))
|
||||
{
|
||||
objc_mutex_unlock (__objc_runtime_mutex);
|
||||
return ivar;
|
||||
}
|
||||
}
|
||||
}
|
||||
class_ = class_->super_class;
|
||||
}
|
||||
objc_mutex_unlock (__objc_runtime_mutex);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
object_getIndexedIvars (id object)
|
||||
{
|
||||
if (object == nil)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
return (void *)(((char *)object)
|
||||
+ object->class_pointer->instance_size);
|
||||
}
|
||||
}
|
||||
|
||||
struct objc_ivar *
|
||||
object_getInstanceVariable (id object, const char *name, void **returnValue)
|
||||
{
|
||||
if (object == nil || name == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
|
||||
|
||||
if (variable != NULL && returnValue != NULL)
|
||||
{
|
||||
char *location = (char *)object + variable->ivar_offset;
|
||||
|
||||
*returnValue = *((id *)location);
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
struct objc_ivar *
|
||||
object_setInstanceVariable (id object, const char *name, void *newValue)
|
||||
{
|
||||
if (object == nil || name == NULL)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
|
||||
|
||||
if (variable != NULL)
|
||||
{
|
||||
char *location = (char *)object + variable->ivar_offset;
|
||||
|
||||
*((id *)location) = (id)newValue;
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
id object_getIvar (id object, struct objc_ivar * variable)
|
||||
{
|
||||
if (object == nil || variable == NULL)
|
||||
return nil;
|
||||
else
|
||||
{
|
||||
char *location = (char *)object + variable->ivar_offset;
|
||||
|
||||
return *((id *)location);
|
||||
}
|
||||
}
|
||||
|
||||
void object_setIvar (id object, struct objc_ivar * variable, id value)
|
||||
{
|
||||
if (object == nil || variable == NULL)
|
||||
return;
|
||||
else
|
||||
{
|
||||
char *location = (char *)object + variable->ivar_offset;
|
||||
|
||||
*((id *)location) = value;
|
||||
}
|
||||
}
|
||||
|
||||
const char * ivar_getName (struct objc_ivar * variable)
|
||||
{
|
||||
return variable->ivar_name;
|
||||
}
|
||||
|
||||
ptrdiff_t ivar_getOffset (struct objc_ivar * variable)
|
||||
{
|
||||
return (ptrdiff_t)(variable->ivar_offset);
|
||||
}
|
||||
|
||||
const char * ivar_getTypeEncoding (struct objc_ivar * variable)
|
||||
{
|
||||
return variable->ivar_type;
|
||||
}
|
@ -145,6 +145,59 @@ struct objc_protocol_list
|
||||
Protocol *list[1];
|
||||
};
|
||||
|
||||
/*
|
||||
The compiler generates one of these structures for each class.
|
||||
|
||||
This structure is the definition for classes.
|
||||
|
||||
This structure is generated by the compiler in the executable and
|
||||
used by the run-time during normal messaging operations. Therefore
|
||||
some members change type. The compiler generates "char* const" and
|
||||
places a string in the following member variables: super_class.
|
||||
*/
|
||||
struct objc_class {
|
||||
struct objc_class* class_pointer; /* Pointer to the class's meta
|
||||
class. */
|
||||
struct objc_class* super_class; /* Pointer to the super
|
||||
class. NULL for class
|
||||
Object. */
|
||||
const char* name; /* Name of the class. */
|
||||
long version; /* Unknown. */
|
||||
unsigned long info; /* Bit mask. See class masks
|
||||
defined above. */
|
||||
long instance_size; /* Size in bytes of the class.
|
||||
The sum of the class
|
||||
definition and all super
|
||||
class definitions. */
|
||||
#ifdef _WIN64
|
||||
/* We pad the structure manually to prevent warning when -Wpadded is
|
||||
used. The compiler automatically pads the structures that it
|
||||
generates, so this manually padded structure still matches the
|
||||
one generated by the compiler, but if we don't pad manually,
|
||||
-Wpadded detects that padding is being added and generates
|
||||
annoying warnings. This hack is necessary as on LLP64 targets
|
||||
sizeof (long) isn't equal to sizeof (void *). */
|
||||
long pad;
|
||||
#endif
|
||||
struct objc_ivar_list* ivars; /* Pointer to a structure that
|
||||
describes the instance
|
||||
variables in the class
|
||||
definition. NULL indicates
|
||||
no instance variables.
|
||||
Does not include super
|
||||
class variables. */
|
||||
struct objc_method_list* methods; /* Linked list of instance
|
||||
methods defined for the
|
||||
class. */
|
||||
struct sarray * dtable; /* Pointer to instance method
|
||||
dispatch table. */
|
||||
struct objc_class* subclass_list; /* Subclasses */
|
||||
struct objc_class* sibling_class;
|
||||
|
||||
struct objc_protocol_list *protocols; /* Protocols conformed to */
|
||||
void* gc_object_type;
|
||||
};
|
||||
|
||||
/* The compiler generates one of these structures for each category.
|
||||
A class may have many categories and contain both instance and
|
||||
factory methods. */
|
||||
|
@ -91,9 +91,7 @@ typedef struct objc_class *Class;
|
||||
/* An 'id' is an object of an unknown class. The way the object data
|
||||
is stored inside the object is private and what you see here is
|
||||
only the beginning of the actual struct. The first field is always
|
||||
a pointer to the Class that the object belongs to. If performance
|
||||
is paramount, you can use this knowledge to get the class of an
|
||||
object by doing '((id)object)->class_pointer'.
|
||||
a pointer to the Class that the object belongs to.
|
||||
*/
|
||||
typedef struct objc_object
|
||||
{
|
||||
@ -101,7 +99,9 @@ typedef struct objc_object
|
||||
of a Class object, this pointer points to the meta class.
|
||||
|
||||
Compatibility Note: The Apple/NeXT runtime calls this field
|
||||
'isa'. */
|
||||
'isa'. To access this field in a portable way, use
|
||||
object_getClass() from runtime.h, which is an inline function so
|
||||
does not add any overhead. */
|
||||
Class class_pointer;
|
||||
} *id;
|
||||
|
||||
|
@ -146,6 +146,24 @@ struct objc_method_description
|
||||
#define _F_GCINVISIBLE 0x20
|
||||
|
||||
|
||||
/** Internals: defined inline. */
|
||||
|
||||
/* Return the class of 'object', or Nil if the object is nil. If
|
||||
'object' is a class, the meta class is returned; if 'object' is a
|
||||
meta class, the root meta class is returned (note that this is
|
||||
different from the traditional GNU Objective-C Runtime API function
|
||||
object_get_class(), which for a meta class would return the meta
|
||||
class itself). */
|
||||
static inline Class
|
||||
object_getClass (id object)
|
||||
{
|
||||
if (object != nil)
|
||||
return object->class_pointer;
|
||||
else
|
||||
return Nil;
|
||||
}
|
||||
|
||||
|
||||
/** Internals: the following functions are in selector.c. */
|
||||
|
||||
/* Return the name of a given selector. */
|
||||
@ -182,13 +200,13 @@ objc_EXPORT BOOL sel_isEqual (SEL first_selector, SEL second_selector);
|
||||
|
||||
/** Internals: the following functions are in objects.c. */
|
||||
|
||||
/* Create an instance of class 'class', adding extraBytes to the size
|
||||
/* Create an instance of class 'class_', adding extraBytes to the size
|
||||
of the returned object. This method allocates the appropriate
|
||||
amount of memory for the instance, initializes it to zero, then
|
||||
calls all the C++ constructors on appropriate C++ instance
|
||||
variables of the instance (if any) (TODO: This is not implemented
|
||||
yet). */
|
||||
objc_EXPORT id class_createInstance (Class class, size_t extraBytes);
|
||||
variables of the instance (if any) (TODO: The C++ constructors bit
|
||||
is not implemented yet). */
|
||||
objc_EXPORT id class_createInstance (Class class_, size_t extraBytes);
|
||||
|
||||
/* Copy an object and return the copy. extraBytes should be identical
|
||||
to the extraBytes parameter that was passed when creating the
|
||||
@ -201,6 +219,69 @@ objc_EXPORT id object_copy (id object, size_t extraBytes);
|
||||
for the instance. */
|
||||
objc_EXPORT id object_dispose (id object);
|
||||
|
||||
/* Return the name of the class of 'object'. If 'object' is 'nil',
|
||||
returns "Nil". */
|
||||
objc_EXPORT const char * object_getClassName (id object);
|
||||
|
||||
/* Change the class of object to be class_. Return the previous class
|
||||
of object. This is currently not really thread-safe. */
|
||||
objc_EXPORT Class object_setClass (id object, Class class_);
|
||||
|
||||
|
||||
/** Internals: the following functions are in ivars.c. */
|
||||
|
||||
/* Return an instance variable given the class and the instance
|
||||
variable name. This is an expensive function to call, so try to
|
||||
reuse the returned Ivar if you can. */
|
||||
objc_EXPORT Ivar class_getInstanceVariable (Class class_, const char *name);
|
||||
|
||||
/* If the object was created in class_createInstance() with some
|
||||
extraBytes, returns a pointer to them. If it was not, then the
|
||||
returned pointer may make no sense. */
|
||||
objc_EXPORT void * object_getIndexedIvars (id object);
|
||||
|
||||
/* Get the value of an instance variable of type 'id'. The function
|
||||
returns the instance variable. To get the value of the instance
|
||||
variable, you should pass as 'returnValue' a pointer to an 'id';
|
||||
the value will be copied there. Note that 'returnValue' is really
|
||||
a 'void *', not a 'void **'. This function really works only with
|
||||
instance variables of type 'id'; for other types of instance
|
||||
variables, access directly the data at (char *)object +
|
||||
ivar_getOffset (ivar). */
|
||||
objc_EXPORT Ivar object_getInstanceVariable (id object, const char *name, void **returnValue);
|
||||
|
||||
/* Set the value of an instance variable. The value to set is passed
|
||||
in 'newValue' (which really is an 'id', not a 'void *'). The
|
||||
function returns the instance variable. This function really works
|
||||
only with instance variables of type 'id'; for other types of
|
||||
instance variables, access directly the data at (char *)object +
|
||||
ivar_getOffset (ivar). */
|
||||
objc_EXPORT Ivar object_setInstanceVariable (id object, const char *name, void *newValue);
|
||||
|
||||
/* Get the value of an instance variable of type 'id' of the object
|
||||
'object'. This is faster than object_getInstanceVariable if you
|
||||
already have the instance variable because it avoids the expensive
|
||||
call to class_getInstanceVariable that is done by
|
||||
object_getInstanceVariable. */
|
||||
objc_EXPORT id object_getIvar (id object, Ivar variable);
|
||||
|
||||
/* Set the value of an instance variable of type 'id' of the object
|
||||
'object'. This is faster than object_setInstanceVariable if you
|
||||
already have the instance variable because it avoids the expensive
|
||||
call to class_getInstanceVariable that is done by
|
||||
object_setInstanceVariable. */
|
||||
objc_EXPORT void object_setIvar (id object, Ivar variable, id value);
|
||||
|
||||
/* Return the name of the instance variable. */
|
||||
objc_EXPORT const char * ivar_getName (Ivar variable);
|
||||
|
||||
/* Return the offset of the instance variable from the start of the
|
||||
object data. */
|
||||
objc_EXPORT ptrdiff_t ivar_getOffset (Ivar variable);
|
||||
|
||||
/* Return the type encoding of the variable. */
|
||||
objc_EXPORT const char * ivar_getTypeEncoding (Ivar variable);
|
||||
|
||||
|
||||
/* TODO: Add all the other functions in the API. */
|
||||
|
||||
@ -216,8 +297,7 @@ objc_EXPORT id object_dispose (id object);
|
||||
is set. Then, it will abort the program.
|
||||
|
||||
Compatibility note: the Apple runtime will not abort the program
|
||||
after calling the mutation handler.
|
||||
*/
|
||||
after calling the mutation handler. */
|
||||
objc_EXPORT void objc_enumerationMutation (id collection);
|
||||
|
||||
/* 'objc_set_enumeration_mutation_handler' can be used to set a
|
||||
@ -236,8 +316,7 @@ objc_EXPORT void objc_enumerationMutation (id collection);
|
||||
libraries; in the case of GNUstep, GNUstep Base may be using this
|
||||
function to improve the standard enumeration mutation handling.
|
||||
You probably shouldn't use this function unless you are writing
|
||||
your own Foundation library.
|
||||
*/
|
||||
your own Foundation library. */
|
||||
objc_EXPORT void objc_setEnumerationMutationHandler (void (*handler)(id));
|
||||
|
||||
/* This structure (used during fast enumeration) is automatically
|
||||
@ -246,8 +325,7 @@ objc_EXPORT void objc_setEnumerationMutationHandler (void (*handler)(id));
|
||||
defined again with the name of NSFastEnumeration by "Foundation"
|
||||
libraries such as GNUstep Base. And if NSFastEnumeration is
|
||||
defined, the compiler will use it instead of
|
||||
__objcFastEnumerationState when doing fast enumeration.
|
||||
*/
|
||||
__objcFastEnumerationState when doing fast enumeration. */
|
||||
/*
|
||||
struct __objcFastEnumerationState
|
||||
{
|
||||
|
@ -102,6 +102,29 @@ object_dispose (id object)
|
||||
return nil;
|
||||
}
|
||||
|
||||
const char *
|
||||
object_getClassName (id object)
|
||||
{
|
||||
if (object != nil)
|
||||
return object->class_pointer->name;
|
||||
else
|
||||
return "Nil";
|
||||
}
|
||||
|
||||
Class
|
||||
object_setClass (id object, Class class_)
|
||||
{
|
||||
if (object == nil)
|
||||
return Nil;
|
||||
else
|
||||
{
|
||||
Class old_class = object->class_pointer;
|
||||
|
||||
object->class_pointer = class_;
|
||||
return old_class;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Hook functions for memory allocation and disposal. Deprecated
|
||||
and currently unused.
|
||||
|
Loading…
Reference in New Issue
Block a user