Home | History | Annotate | Line # | Download | only in libobjc
ivars.c revision 1.1
      1  1.1  mrg /* GNU Objective C Runtime ivar related functions.
      2  1.1  mrg    Copyright (C) 2010-2013 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Nicola Pero
      4  1.1  mrg 
      5  1.1  mrg This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg GCC is free software; you can redistribute it and/or modify it under the
      8  1.1  mrg terms of the GNU General Public License as published by the Free Software
      9  1.1  mrg Foundation; either version 3, or (at your option) any later version.
     10  1.1  mrg 
     11  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
     13  1.1  mrg FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
     14  1.1  mrg details.
     15  1.1  mrg 
     16  1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     17  1.1  mrg permissions described in the GCC Runtime Library Exception, version
     18  1.1  mrg 3.1, as published by the Free Software Foundation.
     19  1.1  mrg 
     20  1.1  mrg You should have received a copy of the GNU General Public License and
     21  1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     22  1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23  1.1  mrg <http://www.gnu.org/licenses/>.  */
     24  1.1  mrg 
     25  1.1  mrg #include "objc-private/common.h"
     26  1.1  mrg #include "objc/runtime.h"
     27  1.1  mrg #include "objc-private/module-abi-8.h" /* For runtime structures  */
     28  1.1  mrg #include "objc/thr.h"
     29  1.1  mrg #include "objc-private/runtime.h"      /* the kitchen sink */
     30  1.1  mrg #include <string.h>                    /* For strcmp.  */
     31  1.1  mrg #include <stdlib.h>                    /* For malloc.  */
     32  1.1  mrg 
     33  1.1  mrg struct objc_ivar *
     34  1.1  mrg class_getInstanceVariable (Class class_, const char *name)
     35  1.1  mrg {
     36  1.1  mrg   if (class_ != Nil  &&  name != NULL  &&  ! CLS_IS_IN_CONSTRUCTION (class_))
     37  1.1  mrg     {
     38  1.1  mrg       while (class_ != Nil)
     39  1.1  mrg 	{
     40  1.1  mrg 	  struct objc_ivar_list *ivars = class_->ivars;
     41  1.1  mrg 	  if (ivars != NULL)
     42  1.1  mrg 	    {
     43  1.1  mrg 	      int i;
     44  1.1  mrg 
     45  1.1  mrg 	      for (i = 0; i < ivars->ivar_count; i++)
     46  1.1  mrg 		{
     47  1.1  mrg 		  struct objc_ivar *ivar = &(ivars->ivar_list[i]);
     48  1.1  mrg 
     49  1.1  mrg 		  if (!strcmp (ivar->ivar_name, name))
     50  1.1  mrg 		    return ivar;
     51  1.1  mrg 		}
     52  1.1  mrg 	    }
     53  1.1  mrg 	  class_ = class_getSuperclass (class_);
     54  1.1  mrg 	}
     55  1.1  mrg     }
     56  1.1  mrg   return NULL;
     57  1.1  mrg }
     58  1.1  mrg 
     59  1.1  mrg struct objc_ivar *
     60  1.1  mrg class_getClassVariable (Class class_, const char *name)
     61  1.1  mrg {
     62  1.1  mrg   if (class_ == Nil)
     63  1.1  mrg     return NULL;
     64  1.1  mrg 
     65  1.1  mrg   /* Logically, since a class is an instance of its meta-class, and
     66  1.1  mrg      since its class methods are the instance methods of the
     67  1.1  mrg      meta-class, class variables should be instance variables of the
     68  1.1  mrg      meta-class.  That is different from the normal use of having
     69  1.1  mrg      'static' variables in the class implementation file, because
     70  1.1  mrg      every class would have its own variables.
     71  1.1  mrg 
     72  1.1  mrg      Anyway, it is all speculative at this stage, but if we get class
     73  1.1  mrg      variables in Objective-C, it is conceivable that this
     74  1.1  mrg      implementation should work.  */
     75  1.1  mrg   return class_getInstanceVariable (class_->class_pointer, name);
     76  1.1  mrg }
     77  1.1  mrg 
     78  1.1  mrg void *
     79  1.1  mrg object_getIndexedIvars (id object)
     80  1.1  mrg {
     81  1.1  mrg   if (object == nil)
     82  1.1  mrg     return NULL;
     83  1.1  mrg   else
     84  1.1  mrg     return (void *)(((char *)object)
     85  1.1  mrg 		    + object->class_pointer->instance_size);
     86  1.1  mrg }
     87  1.1  mrg 
     88  1.1  mrg struct objc_ivar *
     89  1.1  mrg object_getInstanceVariable (id object, const char *name, void **returnValue)
     90  1.1  mrg {
     91  1.1  mrg   if (object == nil  ||  name == NULL)
     92  1.1  mrg     return NULL;
     93  1.1  mrg   else
     94  1.1  mrg     {
     95  1.1  mrg       struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
     96  1.1  mrg 
     97  1.1  mrg       if (variable != NULL  &&  returnValue != NULL)
     98  1.1  mrg 	{
     99  1.1  mrg 	  char *location = (char *)object + variable->ivar_offset;
    100  1.1  mrg 
    101  1.1  mrg 	  *returnValue = *((id *)location);
    102  1.1  mrg 	}
    103  1.1  mrg 
    104  1.1  mrg       return variable;
    105  1.1  mrg     }
    106  1.1  mrg }
    107  1.1  mrg 
    108  1.1  mrg struct objc_ivar *
    109  1.1  mrg object_setInstanceVariable (id object, const char *name, void *newValue)
    110  1.1  mrg {
    111  1.1  mrg   if (object == nil  ||  name == NULL)
    112  1.1  mrg     return NULL;
    113  1.1  mrg   else
    114  1.1  mrg     {
    115  1.1  mrg       struct objc_ivar * variable = class_getInstanceVariable (object->class_pointer, name);
    116  1.1  mrg 
    117  1.1  mrg       if (variable != NULL)
    118  1.1  mrg 	{
    119  1.1  mrg 	  char *location = (char *)object + variable->ivar_offset;
    120  1.1  mrg 
    121  1.1  mrg 	  *((id *)location) = (id)newValue;
    122  1.1  mrg 	}
    123  1.1  mrg 
    124  1.1  mrg       return variable;
    125  1.1  mrg     }
    126  1.1  mrg }
    127  1.1  mrg 
    128  1.1  mrg id object_getIvar (id object, struct objc_ivar * variable)
    129  1.1  mrg {
    130  1.1  mrg   if (object == nil  ||  variable == NULL)
    131  1.1  mrg     return nil;
    132  1.1  mrg   else
    133  1.1  mrg     {
    134  1.1  mrg       char *location = (char *)object + variable->ivar_offset;
    135  1.1  mrg 
    136  1.1  mrg       return *((id *)location);
    137  1.1  mrg     }
    138  1.1  mrg }
    139  1.1  mrg 
    140  1.1  mrg void object_setIvar (id object, struct objc_ivar * variable, id value)
    141  1.1  mrg {
    142  1.1  mrg   if (object == nil  ||  variable == NULL)
    143  1.1  mrg     return;
    144  1.1  mrg   else
    145  1.1  mrg     {
    146  1.1  mrg       char *location = (char *)object + variable->ivar_offset;
    147  1.1  mrg 
    148  1.1  mrg       *((id *)location) = value;
    149  1.1  mrg     }
    150  1.1  mrg }
    151  1.1  mrg 
    152  1.1  mrg const char * ivar_getName (struct objc_ivar * variable)
    153  1.1  mrg {
    154  1.1  mrg   if (variable == NULL)
    155  1.1  mrg     return NULL;
    156  1.1  mrg 
    157  1.1  mrg   return variable->ivar_name;
    158  1.1  mrg }
    159  1.1  mrg 
    160  1.1  mrg ptrdiff_t ivar_getOffset (struct objc_ivar * variable)
    161  1.1  mrg {
    162  1.1  mrg   if (variable == NULL)
    163  1.1  mrg     return 0;
    164  1.1  mrg 
    165  1.1  mrg   return (ptrdiff_t)(variable->ivar_offset);
    166  1.1  mrg }
    167  1.1  mrg 
    168  1.1  mrg const char * ivar_getTypeEncoding (struct objc_ivar * variable)
    169  1.1  mrg {
    170  1.1  mrg   if (variable == NULL)
    171  1.1  mrg     return NULL;
    172  1.1  mrg 
    173  1.1  mrg   return variable->ivar_type;
    174  1.1  mrg }
    175  1.1  mrg 
    176  1.1  mrg struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars)
    177  1.1  mrg {
    178  1.1  mrg   unsigned int count = 0;
    179  1.1  mrg   struct objc_ivar **returnValue = NULL;
    180  1.1  mrg   struct objc_ivar_list* ivar_list;
    181  1.1  mrg 
    182  1.1  mrg   if (class_ == Nil  ||  CLS_IS_IN_CONSTRUCTION (class_))
    183  1.1  mrg     {
    184  1.1  mrg       if (numberOfReturnedIvars)
    185  1.1  mrg 	*numberOfReturnedIvars = 0;
    186  1.1  mrg       return NULL;
    187  1.1  mrg     }
    188  1.1  mrg 
    189  1.1  mrg   /* Count how many ivars we have.  */
    190  1.1  mrg   ivar_list = class_->ivars;
    191  1.1  mrg   count = ivar_list->ivar_count;
    192  1.1  mrg 
    193  1.1  mrg   if (count != 0)
    194  1.1  mrg     {
    195  1.1  mrg       unsigned int i = 0;
    196  1.1  mrg 
    197  1.1  mrg       /* Allocate enough memory to hold them.  */
    198  1.1  mrg       returnValue = (struct objc_ivar **)(malloc (sizeof (struct objc_ivar *) * (count + 1)));
    199  1.1  mrg 
    200  1.1  mrg       /* Copy the ivars.  */
    201  1.1  mrg       for (i = 0; i < count; i++)
    202  1.1  mrg 	returnValue[i] = &(ivar_list->ivar_list[i]);
    203  1.1  mrg 
    204  1.1  mrg       returnValue[i] = NULL;
    205  1.1  mrg     }
    206  1.1  mrg 
    207  1.1  mrg   if (numberOfReturnedIvars)
    208  1.1  mrg     *numberOfReturnedIvars = count;
    209  1.1  mrg 
    210  1.1  mrg   return returnValue;
    211  1.1  mrg }
    212  1.1  mrg 
    213  1.1  mrg BOOL
    214  1.1  mrg class_addIvar (Class class_, const char * ivar_name, size_t size,
    215  1.1  mrg 	       unsigned char log_2_of_alignment, const char *type)
    216  1.1  mrg {
    217  1.1  mrg   struct objc_ivar_list *ivars;
    218  1.1  mrg 
    219  1.1  mrg   if (class_ == Nil
    220  1.1  mrg       || (! CLS_IS_IN_CONSTRUCTION (class_))
    221  1.1  mrg       || ivar_name == NULL
    222  1.1  mrg       || (strcmp (ivar_name, "") == 0)
    223  1.1  mrg       || size == 0
    224  1.1  mrg       || type == NULL)
    225  1.1  mrg     return NO;
    226  1.1  mrg 
    227  1.1  mrg   /* Check if the class has an instance variable with that name
    228  1.1  mrg      already.  */
    229  1.1  mrg   ivars = class_->ivars;
    230  1.1  mrg 
    231  1.1  mrg   if (ivars != NULL)
    232  1.1  mrg     {
    233  1.1  mrg       int i;
    234  1.1  mrg 
    235  1.1  mrg       for (i = 0; i < ivars->ivar_count; i++)
    236  1.1  mrg 	{
    237  1.1  mrg 	  struct objc_ivar *ivar = &(ivars->ivar_list[i]);
    238  1.1  mrg 
    239  1.1  mrg 	  if (strcmp (ivar->ivar_name, ivar_name) == 0)
    240  1.1  mrg 	    return NO;
    241  1.1  mrg 	}
    242  1.1  mrg     }
    243  1.1  mrg 
    244  1.1  mrg   /* Ok, no direct ivars.  Check superclasses.  */
    245  1.1  mrg   if (class_getInstanceVariable (objc_getClass ((char *)(class_->super_class)),
    246  1.1  mrg 				 ivar_name))
    247  1.1  mrg     return NO;
    248  1.1  mrg 
    249  1.1  mrg   /* Good.  Create space for the new instance variable.  */
    250  1.1  mrg   if (ivars)
    251  1.1  mrg     {
    252  1.1  mrg       int ivar_count = ivars->ivar_count + 1;
    253  1.1  mrg       int new_size = sizeof (struct objc_ivar_list)
    254  1.1  mrg 	+ (ivar_count - 1) * sizeof (struct objc_ivar);
    255  1.1  mrg 
    256  1.1  mrg       ivars = (struct objc_ivar_list*) objc_realloc (ivars, new_size);
    257  1.1  mrg       ivars->ivar_count = ivar_count;
    258  1.1  mrg       class_->ivars = ivars;
    259  1.1  mrg     }
    260  1.1  mrg   else
    261  1.1  mrg     {
    262  1.1  mrg       int new_size = sizeof (struct objc_ivar_list);
    263  1.1  mrg 
    264  1.1  mrg       ivars = (struct objc_ivar_list*) objc_malloc (new_size);
    265  1.1  mrg       ivars->ivar_count = 1;
    266  1.1  mrg       class_->ivars = ivars;
    267  1.1  mrg     }
    268  1.1  mrg 
    269  1.1  mrg   /* Now ivars is set to a list of instance variables of the right
    270  1.1  mrg      size. */
    271  1.1  mrg   {
    272  1.1  mrg     struct objc_ivar *ivar = &(ivars->ivar_list[ivars->ivar_count - 1]);
    273  1.1  mrg     unsigned int alignment = 1 << log_2_of_alignment;
    274  1.1  mrg     int misalignment;
    275  1.1  mrg 
    276  1.1  mrg     ivar->ivar_name = objc_malloc (strlen (ivar_name) + 1);
    277  1.1  mrg     strcpy ((char *)ivar->ivar_name, ivar_name);
    278  1.1  mrg 
    279  1.1  mrg     ivar->ivar_type = objc_malloc (strlen (type) + 1);
    280  1.1  mrg     strcpy ((char *)ivar->ivar_type, type);
    281  1.1  mrg 
    282  1.1  mrg     /* The new instance variable is placed at the end of the existing
    283  1.1  mrg        instance_size, at the first byte that is aligned with
    284  1.1  mrg        alignment.  */
    285  1.1  mrg     misalignment = class_->instance_size % alignment;
    286  1.1  mrg 
    287  1.1  mrg     if (misalignment == 0)
    288  1.1  mrg       ivar->ivar_offset = class_->instance_size;
    289  1.1  mrg     else
    290  1.1  mrg       ivar->ivar_offset = class_->instance_size - misalignment + alignment;
    291  1.1  mrg 
    292  1.1  mrg     class_->instance_size = ivar->ivar_offset + size;
    293  1.1  mrg   }
    294  1.1  mrg 
    295  1.1  mrg   return YES;
    296  1.1  mrg }
    297  1.1  mrg 
    298  1.1  mrg 
    299  1.1  mrg const char *
    300  1.1  mrg property_getName (struct objc_property * property __attribute__ ((__unused__)))
    301  1.1  mrg {
    302  1.1  mrg   if (property == NULL)
    303  1.1  mrg     return NULL;
    304  1.1  mrg 
    305  1.1  mrg   /* TODO: New ABI.  */
    306  1.1  mrg   /* The current ABI does not have any information on properties.  */
    307  1.1  mrg   return NULL;
    308  1.1  mrg }
    309  1.1  mrg 
    310  1.1  mrg const char *
    311  1.1  mrg property_getAttributes (struct objc_property * property __attribute__ ((__unused__)))
    312  1.1  mrg {
    313  1.1  mrg   if (property == NULL)
    314  1.1  mrg     return NULL;
    315  1.1  mrg 
    316  1.1  mrg   /* TODO: New ABI.  */
    317  1.1  mrg   /* The current ABI does not have any information on properties.  */
    318  1.1  mrg   return NULL;
    319  1.1  mrg }
    320  1.1  mrg 
    321  1.1  mrg struct objc_property *
    322  1.1  mrg class_getProperty (Class class_ __attribute__ ((__unused__)),
    323  1.1  mrg 		   const char *propertyName __attribute__ ((__unused__)))
    324  1.1  mrg {
    325  1.1  mrg   if (class_ == NULL  ||  propertyName == NULL)
    326  1.1  mrg     return NULL;
    327  1.1  mrg 
    328  1.1  mrg   /* TODO: New ABI.  */
    329  1.1  mrg   /* The current ABI does not have any information on class properties.  */
    330  1.1  mrg   return NULL;
    331  1.1  mrg }
    332  1.1  mrg 
    333  1.1  mrg struct objc_property **
    334  1.1  mrg class_copyPropertyList (Class class_ __attribute__ ((__unused__)),
    335  1.1  mrg 			unsigned int *numberOfReturnedProperties __attribute__ ((__unused__)))
    336  1.1  mrg {
    337  1.1  mrg   if (class_ == Nil)
    338  1.1  mrg     {
    339  1.1  mrg       if (numberOfReturnedProperties)
    340  1.1  mrg 	*numberOfReturnedProperties = 0;
    341  1.1  mrg       return NULL;
    342  1.1  mrg     }
    343  1.1  mrg 
    344  1.1  mrg   /* TODO: New ABI.  */
    345  1.1  mrg   /* The current ABI does not have any information on class properties.  */
    346  1.1  mrg   if (numberOfReturnedProperties)
    347  1.1  mrg     *numberOfReturnedProperties = 0;
    348  1.1  mrg 
    349  1.1  mrg   return NULL;
    350  1.1  mrg }
    351  1.1  mrg 
    352  1.1  mrg const char *
    353  1.1  mrg class_getIvarLayout (Class class_ __attribute__ ((__unused__)))
    354  1.1  mrg {
    355  1.1  mrg   return NULL;
    356  1.1  mrg }
    357  1.1  mrg 
    358  1.1  mrg const char *
    359  1.1  mrg class_getWeakIvarLayout (Class class_ __attribute__ ((__unused__)))
    360  1.1  mrg {
    361  1.1  mrg   return NULL;
    362  1.1  mrg }
    363  1.1  mrg 
    364  1.1  mrg void
    365  1.1  mrg class_setIvarLayout (Class class_ __attribute__ ((__unused__)),
    366  1.1  mrg 		     const char *layout __attribute__ ((__unused__)))
    367  1.1  mrg {
    368  1.1  mrg   return;
    369  1.1  mrg }
    370  1.1  mrg 
    371  1.1  mrg void
    372  1.1  mrg class_setWeakIvarLayout (Class class_ __attribute__ ((__unused__)),
    373  1.1  mrg 			 const char *layout __attribute__ ((__unused__)))
    374  1.1  mrg {
    375  1.1  mrg   return;
    376  1.1  mrg }
    377