mirror of
https://github.com/darlinghq/darling-libobjc2.git
synced 2024-11-23 12:19:44 +00:00
Finished implementing the new runtime APIs.
This commit is contained in:
parent
084bbdd877
commit
4796a41e4e
3
ANNOUNCE
3
ANNOUNCE
@ -6,12 +6,13 @@ libobjc2). This runtime was designed to support the features of Objective-C 2
|
||||
for use with GNUstep and other Objective-C programs. Highlights of this
|
||||
release include:
|
||||
|
||||
- Compatibility with the new runtime APIs introduced with Mac OS X 10.7.
|
||||
- Support for small objects (ones hidden inside a pointer). On 32-bit systems,
|
||||
the runtime permits one small object class, on 64-bit systems it permits 4.
|
||||
- Support for prototype-style object orientation. You can now add methods, as
|
||||
well as associated references, to individual objects, as well as cloning
|
||||
them. The runtime now supports everything required for the JavaScript object
|
||||
model.
|
||||
model, including the ability to use blocks as methods.
|
||||
|
||||
You may obtain the code for this release from subversion at the following
|
||||
subversion branch:
|
||||
|
36
Test/PropertyIntrospectionTest.m
Normal file
36
Test/PropertyIntrospectionTest.m
Normal file
@ -0,0 +1,36 @@
|
||||
#import <objc/runtime.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@interface Foo
|
||||
@property (getter=bar, setter=setBar:, nonatomic, copy) id foo;
|
||||
@end
|
||||
@interface Foo(Bar)
|
||||
-(id)bar;
|
||||
-(void)setBar:(id)b;
|
||||
@end
|
||||
@implementation Foo
|
||||
@synthesize foo;
|
||||
@end
|
||||
|
||||
int main(void)
|
||||
{
|
||||
objc_property_t p = class_getProperty(objc_getClass("Foo"), "foo");
|
||||
unsigned int count;
|
||||
objc_property_attribute_t *l = property_copyAttributeList(p, &count);
|
||||
for (unsigned int i=0 ; i<count ; i++)
|
||||
{
|
||||
switch (l[i].name[0])
|
||||
{
|
||||
case 'T': assert(0==strcmp(l[i].value, "@")); break;
|
||||
case 'C': assert(0==strcmp(l[i].value, "")); break;
|
||||
case 'N': assert(0==strcmp(l[i].value, "")); break;
|
||||
case 'G': assert(0==strcmp(l[i].value, "bar")); break;
|
||||
case 'S': assert(0==strcmp(l[i].value, "setBar:")); break;
|
||||
case 'B': assert(0==strcmp(l[i].value, "foo")); break;
|
||||
}
|
||||
}
|
||||
assert(0 == property_copyAttributeList(0, &count));
|
||||
return 0;
|
||||
}
|
28
Test/ProtocolCreation.m
Normal file
28
Test/ProtocolCreation.m
Normal file
@ -0,0 +1,28 @@
|
||||
#import <objc/runtime.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@protocol Test2 @end
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Protocol *p = objc_allocateProtocol("Test");
|
||||
protocol_addMethodDescription(p, @selector(someMethod), "@:", YES, NO);
|
||||
assert(objc_getProtocol("Test2"));
|
||||
protocol_addProtocol(p, objc_getProtocol("Test2"));
|
||||
objc_property_attribute_t attrs[] = { {"T", "@" } };
|
||||
protocol_addProperty(p, "foo", attrs, 1, YES, YES);
|
||||
objc_registerProtocol(p);
|
||||
Protocol *p1 = objc_getProtocol("Test");
|
||||
assert(p == p1);
|
||||
struct objc_method_description d = protocol_getMethodDescription(p1, @selector(someMethod), YES, NO);
|
||||
assert(strcmp(sel_getName(d.name), "someMethod") == 0);
|
||||
assert(strcmp((d.types), "@:") == 0);
|
||||
assert(protocol_conformsToProtocol(p1, objc_getProtocol("Test2")));
|
||||
unsigned int count;
|
||||
objc_property_t *props = protocol_copyPropertyList(p1, &count);
|
||||
assert(count == 1);
|
||||
assert(strcmp("T@,Vfoo", property_getAttributes(*props)) == 0);
|
||||
return 0;
|
||||
}
|
@ -460,6 +460,17 @@ int objc_getClassList(Class *buffer, int bufferLen)
|
||||
}
|
||||
return count;
|
||||
}
|
||||
Class *objc_copyClassList(unsigned int *outCount)
|
||||
{
|
||||
int count = class_table->table_used;
|
||||
Class *buffer = calloc(sizeof(Class), count);
|
||||
if (NULL != outCount)
|
||||
{
|
||||
*outCount = count;
|
||||
}
|
||||
objc_getClassList(buffer, count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Class class_getSuperclass(Class cls)
|
||||
{
|
||||
|
@ -41,6 +41,7 @@ const char *objc_skip_argspec(const char *type)
|
||||
|
||||
PRIVATE size_t lengthOfTypeEncoding(const char *types)
|
||||
{
|
||||
if ((NULL == types) || ('\0' == types[0])) { return 0; }
|
||||
const char *end = objc_skip_typespec(types);
|
||||
size_t length = end - types;
|
||||
return length;
|
||||
|
@ -163,6 +163,26 @@ struct objc_method_description
|
||||
const char *types;
|
||||
};
|
||||
|
||||
/**
|
||||
* The objc_property_attribute_t type is used to store attributes for
|
||||
* properties. This is used to store a decomposed version of the property
|
||||
* encoding, with each flag stored in the name and each value in the value.
|
||||
*
|
||||
* All of the strings that these refer to are internal to the runtime and
|
||||
* should not be freed.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* The flag that this attribute describes. All current flags are single characters,
|
||||
*/
|
||||
const char *name;
|
||||
/**
|
||||
*/
|
||||
const char *value;
|
||||
} objc_property_attribute_t;
|
||||
|
||||
|
||||
|
||||
#ifndef YES
|
||||
# define YES ((BOOL)1)
|
||||
@ -520,6 +540,12 @@ id objc_getClass(const char *name);
|
||||
* Otherwise, it copies classes and returns the number copied.
|
||||
*/
|
||||
int objc_getClassList(Class *buffer, int bufferLen);
|
||||
/**
|
||||
* Returns a copy of the list of all classes in the system. The caller is
|
||||
* responsible for freeing this list. The number of classes is returned in the
|
||||
* parameter.
|
||||
*/
|
||||
Class *objc_copyClassList(unsigned int *outCount);
|
||||
|
||||
/**
|
||||
* Returns the metaclass with the specified name. This is equivalent to
|
||||
@ -544,6 +570,41 @@ id objc_lookUpClass(const char *name);
|
||||
* Returns the protocol with the specified name.
|
||||
*/
|
||||
Protocol *objc_getProtocol(const char *name);
|
||||
/**
|
||||
* Allocates a new protocol. This returns NULL if a protocol with the same
|
||||
* name already exists in the system.
|
||||
*
|
||||
* Protocols are immutable after they have been registered, so may only be
|
||||
* modified between calling this function and calling objc_registerProtocol().
|
||||
*/
|
||||
Protocol *objc_allocateProtocol(const char *name);
|
||||
/**
|
||||
* Registers a protocol with the runtime. After this point, the protocol may
|
||||
* not be modified.
|
||||
*/
|
||||
void objc_registerProtocol(Protocol *proto);
|
||||
/**
|
||||
* Adds a method to the protocol.
|
||||
*/
|
||||
void protocol_addMethodDescription(Protocol *aProtocol,
|
||||
SEL name,
|
||||
const char *types,
|
||||
BOOL isRequiredMethod,
|
||||
BOOL isInstanceMethod);
|
||||
/**
|
||||
* Adds a protocol to the protocol.
|
||||
*/
|
||||
void protocol_addProtocol(Protocol *aProtocol, Protocol *addition);
|
||||
/**
|
||||
* Adds a property to the protocol.
|
||||
*/
|
||||
void protocol_addProperty(Protocol *aProtocol,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount,
|
||||
BOOL isRequiredProperty,
|
||||
BOOL isInstanceProperty);
|
||||
|
||||
|
||||
/**
|
||||
* Registers a new class and its metaclass with the runtime. This function
|
||||
@ -600,6 +661,36 @@ const char *property_getName(objc_property_t property);
|
||||
*/
|
||||
const char *property_getAttributes(objc_property_t property);
|
||||
|
||||
/**
|
||||
* Returns an array of attributes for this property.
|
||||
*/
|
||||
objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
|
||||
unsigned int *outCount);
|
||||
/**
|
||||
* Adds a property to the class, given a specified set of attributes. Note
|
||||
* that this only sets the property metadata. The property accessor methods
|
||||
* must already be created.
|
||||
*/
|
||||
BOOL class_addProperty(Class cls,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount);
|
||||
|
||||
/**
|
||||
* Replaces property metadata. If the property does not exist, then this is
|
||||
* equivalent to calling class_addProperty().
|
||||
*/
|
||||
void class_replaceProperty(Class cls,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount);
|
||||
|
||||
/**
|
||||
* Returns a copy of a single attribute.
|
||||
*/
|
||||
char *property_copyAttributeValue(objc_property_t property,
|
||||
const char *attributeName);
|
||||
|
||||
/**
|
||||
* Testswhether a protocol conforms to another protocol.
|
||||
*/
|
||||
|
11
properties.h
11
properties.h
@ -1,3 +1,4 @@
|
||||
#include "visibility.h"
|
||||
|
||||
enum PropertyAttributeKind
|
||||
{
|
||||
@ -55,7 +56,7 @@ struct objc_property
|
||||
* Attributes for this property. Made by ORing together
|
||||
* PropertyAttributeKinds.
|
||||
*/
|
||||
const char attributes;
|
||||
char attributes;
|
||||
/**
|
||||
* Flag set if the property is synthesized.
|
||||
*/
|
||||
@ -88,8 +89,7 @@ struct objc_property_list
|
||||
*/
|
||||
int count;
|
||||
/*
|
||||
* UNUSED. In future, categories will be allowed to add properties and
|
||||
* then this will be used to link the declarations together.
|
||||
* The next property in a linked list.
|
||||
*/
|
||||
struct objc_property_list *next;
|
||||
/**
|
||||
@ -98,3 +98,8 @@ struct objc_property_list
|
||||
struct objc_property properties[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs a property description from a list of attributes.
|
||||
*/
|
||||
PRIVATE struct objc_property propertyFromAttrs(const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount);
|
||||
|
211
properties.m
211
properties.m
@ -10,6 +10,7 @@
|
||||
#include "visibility.h"
|
||||
#include "nsobject.h"
|
||||
#include "gc_ops.h"
|
||||
#include "lock.h"
|
||||
|
||||
PRIVATE int spinlocks[spinlock_count];
|
||||
|
||||
@ -181,6 +182,7 @@ objc_property_t class_getProperty(Class cls, const char *name)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount)
|
||||
{
|
||||
if (Nil == cls || !objc_test_class_flag(cls, objc_class_flag_new_abi))
|
||||
@ -228,6 +230,32 @@ const char *property_getName(objc_property_t property)
|
||||
|
||||
PRIVATE size_t lengthOfTypeEncoding(const char *types);
|
||||
|
||||
/**
|
||||
* The compiler stores the type encoding of the getter. We replace this with
|
||||
* the type encoding of the property itself. We use a 0 byte at the start to
|
||||
* indicate that the swap has taken place.
|
||||
*/
|
||||
static const char *property_getTypeEncoding(objc_property_t property)
|
||||
{
|
||||
if (NULL == property) { return NULL; }
|
||||
|
||||
const char *name = property->getter_types;
|
||||
if (name[0] == 0)
|
||||
{
|
||||
return &name[1];
|
||||
}
|
||||
size_t typeSize = lengthOfTypeEncoding(name);
|
||||
char *buffer = malloc(typeSize + 2);
|
||||
buffer[0] = 0;
|
||||
memcpy(buffer+1, name, typeSize);
|
||||
buffer[typeSize+1] = 0;
|
||||
if (!__sync_bool_compare_and_swap(&(property->getter_types), name, buffer))
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
return &property->getter_types[1];
|
||||
}
|
||||
|
||||
const char *property_getAttributes(objc_property_t property)
|
||||
{
|
||||
if (NULL == property) { return NULL; }
|
||||
@ -238,7 +266,8 @@ const char *property_getAttributes(objc_property_t property)
|
||||
return name + 2;
|
||||
}
|
||||
|
||||
size_t typeSize = lengthOfTypeEncoding(property->getter_types);
|
||||
const char *typeEncoding = property_getTypeEncoding(property);
|
||||
size_t typeSize = strlen(typeEncoding);
|
||||
size_t nameSize = strlen(property->name);
|
||||
// Encoding is T{type},V{name}, so 4 bytes for the "T,V" that we always
|
||||
// need. We also need two bytes for the leading null and the length.
|
||||
@ -287,7 +316,7 @@ const char *property_getAttributes(objc_property_t property)
|
||||
*(insert++) = 0;
|
||||
// Set the type encoding
|
||||
*(insert++) = 'T';
|
||||
memcpy(insert, property->getter_types, typeSize);
|
||||
memcpy(insert, typeEncoding, typeSize);
|
||||
insert += typeSize;
|
||||
// Set the flags
|
||||
memcpy(insert, flags, i);
|
||||
@ -322,3 +351,181 @@ const char *property_getAttributes(objc_property_t property)
|
||||
return (const char*)(encoding + 2);
|
||||
}
|
||||
|
||||
objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
|
||||
unsigned int *outCount)
|
||||
{
|
||||
if (NULL == property) { return NULL; }
|
||||
objc_property_attribute_t attrs[10];
|
||||
int count = 0;
|
||||
|
||||
attrs[count].name = "T";
|
||||
attrs[count].value = property_getTypeEncoding(property);
|
||||
count++;
|
||||
if ((property->attributes & OBJC_PR_copy) == OBJC_PR_copy)
|
||||
{
|
||||
attrs[count].name = "C";
|
||||
attrs[count].value = "";
|
||||
count++;
|
||||
}
|
||||
if ((property->attributes & OBJC_PR_retain) == OBJC_PR_retain)
|
||||
{
|
||||
attrs[count].name = "&";
|
||||
attrs[count].value = "";
|
||||
count++;
|
||||
}
|
||||
if ((property->attributes & OBJC_PR_nonatomic) == OBJC_PR_nonatomic)
|
||||
{
|
||||
attrs[count].name = "N";
|
||||
attrs[count].value = "";
|
||||
count++;
|
||||
}
|
||||
if ((property->attributes & OBJC_PR_getter) == OBJC_PR_getter)
|
||||
{
|
||||
attrs[count].name = "G";
|
||||
attrs[count].value = property->getter_name;
|
||||
count++;
|
||||
}
|
||||
if ((property->attributes & OBJC_PR_setter) == OBJC_PR_setter)
|
||||
{
|
||||
attrs[count].name = "S";
|
||||
attrs[count].value = property->setter_name;
|
||||
count++;
|
||||
}
|
||||
attrs[count].name = "V";
|
||||
attrs[count].value = property_getName(property);
|
||||
count++;
|
||||
|
||||
objc_property_attribute_t *propAttrs = calloc(sizeof(objc_property_attribute_t), count);
|
||||
memcpy(propAttrs, attrs, count * sizeof(objc_property_attribute_t));
|
||||
if (NULL != outCount)
|
||||
{
|
||||
*outCount = count;
|
||||
}
|
||||
return propAttrs;
|
||||
}
|
||||
|
||||
PRIVATE struct objc_property propertyFromAttrs(const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount)
|
||||
{
|
||||
struct objc_property p = { 0 };
|
||||
for (unsigned int i=0 ; i<attributeCount ; i++)
|
||||
{
|
||||
switch (attributes[i].name[0])
|
||||
{
|
||||
case 'T':
|
||||
{
|
||||
size_t typeSize = strlen(attributes[i].value);
|
||||
char *buffer = malloc(typeSize + 2);
|
||||
buffer[0] = 0;
|
||||
memcpy(buffer+1, attributes[i].value, typeSize);
|
||||
buffer[typeSize+1] = 0;
|
||||
p.getter_types = buffer;
|
||||
break;
|
||||
}
|
||||
case 'S':
|
||||
{
|
||||
p.setter_name = strdup(attributes[i].value);
|
||||
break;
|
||||
}
|
||||
case 'G':
|
||||
{
|
||||
p.getter_name = strdup(attributes[i].value);
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
{
|
||||
p.name = strdup(attributes[i].value);
|
||||
break;
|
||||
}
|
||||
case 'C':
|
||||
{
|
||||
p.attributes |= OBJC_PR_copy;
|
||||
}
|
||||
case '&':
|
||||
{
|
||||
p.attributes |= OBJC_PR_retain;
|
||||
}
|
||||
case 'N':
|
||||
{
|
||||
p.attributes |= OBJC_PR_nonatomic;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
BOOL class_addProperty(Class cls,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount)
|
||||
{
|
||||
if ((Nil == cls) || (NULL == name) || (class_getProperty(cls, name) != 0)) { return NO; }
|
||||
struct objc_property p = propertyFromAttrs(attributes, attributeCount);
|
||||
// If there is a name mismatch, the attributes are invalid.
|
||||
if ((p.name != 0) && (strcmp(name, p.name) != 0)) { return NO; }
|
||||
|
||||
struct objc_property_list *l = calloc(1, sizeof(struct objc_property_list));
|
||||
l->count = 0;
|
||||
memcpy(&l->properties, &p, sizeof(struct objc_property));
|
||||
LOCK_RUNTIME_FOR_SCOPE();
|
||||
l->next = cls->properties;
|
||||
cls->properties = l;
|
||||
return YES;
|
||||
}
|
||||
|
||||
void class_replaceProperty(Class cls,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount)
|
||||
{
|
||||
if ((Nil == cls) || (NULL == name)) { return; }
|
||||
objc_property_t old = class_getProperty(cls, name);
|
||||
if (NULL == old)
|
||||
{
|
||||
class_addProperty(cls, name, attributes, attributeCount);
|
||||
return;
|
||||
}
|
||||
struct objc_property p = propertyFromAttrs(attributes, attributeCount);
|
||||
memcpy(old, &p, sizeof(struct objc_property));
|
||||
if (NULL == old->name)
|
||||
{
|
||||
old->name = name;
|
||||
}
|
||||
}
|
||||
char *property_copyAttributeValue(objc_property_t property,
|
||||
const char *attributeName)
|
||||
{
|
||||
if ((NULL == property) || (NULL == attributeName)) { return NULL; }
|
||||
switch (attributeName[0])
|
||||
{
|
||||
case 'T':
|
||||
{
|
||||
return strdup(property_getTypeEncoding(property));
|
||||
}
|
||||
case 'V':
|
||||
{
|
||||
return strdup(property_getName(property));
|
||||
}
|
||||
case 'S':
|
||||
{
|
||||
return strdup(property->setter_name);
|
||||
}
|
||||
case 'G':
|
||||
{
|
||||
return strdup(property->getter_name);
|
||||
}
|
||||
case 'C':
|
||||
{
|
||||
return ((property->attributes |= OBJC_PR_copy) == OBJC_PR_copy) ? strdup("") : 0;
|
||||
}
|
||||
case '&':
|
||||
{
|
||||
return ((property->attributes |= OBJC_PR_retain) == OBJC_PR_retain) ? strdup("") : 0;
|
||||
}
|
||||
case 'N':
|
||||
{
|
||||
return ((property->attributes |= OBJC_PR_nonatomic) == OBJC_PR_nonatomic) ? strdup("") : 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
121
protocol.c
121
protocol.c
@ -3,7 +3,6 @@
|
||||
#include "properties.h"
|
||||
#include "class.h"
|
||||
#include "lock.h"
|
||||
#include "visibility.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BUFFER_TYPE struct objc_protocol_list
|
||||
@ -494,3 +493,123 @@ Protocol*__unsafe_unretained* objc_copyProtocolList(unsigned int *outCount)
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
Protocol *objc_allocateProtocol(const char *name)
|
||||
{
|
||||
if (objc_getProtocol(name) != NULL) { return NULL; }
|
||||
Protocol *p = calloc(1, sizeof(Protocol2));
|
||||
p->name = strdup(name);
|
||||
return p;
|
||||
}
|
||||
void objc_registerProtocol(Protocol *proto)
|
||||
{
|
||||
if (NULL == proto) { return; }
|
||||
LOCK_RUNTIME_FOR_SCOPE();
|
||||
if (objc_getProtocol(proto->name) != NULL) { return; }
|
||||
if (nil != proto->isa) { return; }
|
||||
proto->isa = ObjC2ProtocolClass;
|
||||
protocol_table_insert((struct objc_protocol2*)proto);
|
||||
}
|
||||
void protocol_addMethodDescription(Protocol *aProtocol,
|
||||
SEL name,
|
||||
const char *types,
|
||||
BOOL isRequiredMethod,
|
||||
BOOL isInstanceMethod)
|
||||
{
|
||||
if ((NULL == aProtocol) || (NULL == name) || (NULL == types)) { return; }
|
||||
if (nil != aProtocol->isa) { return; }
|
||||
Protocol2 *proto = (Protocol2*)aProtocol;
|
||||
struct objc_method_description_list **listPtr;
|
||||
if (isInstanceMethod)
|
||||
{
|
||||
if (isRequiredMethod)
|
||||
{
|
||||
listPtr = &proto->instance_methods;
|
||||
}
|
||||
else
|
||||
{
|
||||
listPtr = &proto->optional_instance_methods;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isRequiredMethod)
|
||||
{
|
||||
listPtr = &proto->class_methods;
|
||||
}
|
||||
else
|
||||
{
|
||||
listPtr = &proto->optional_class_methods;
|
||||
}
|
||||
}
|
||||
if (NULL == *listPtr)
|
||||
{
|
||||
*listPtr = calloc(1, sizeof(struct objc_method_description_list) + sizeof(struct objc_method_description));
|
||||
(*listPtr)->count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*listPtr)->count++;
|
||||
*listPtr = realloc(*listPtr, sizeof(struct objc_method_description_list) +
|
||||
sizeof(struct objc_method_description) * (*listPtr)->count);
|
||||
}
|
||||
struct objc_method_description_list *list = *listPtr;
|
||||
int index = list->count-1;
|
||||
list->methods[index].name = sel_getName(name);
|
||||
list->methods[index].types= types;
|
||||
}
|
||||
void protocol_addProtocol(Protocol *aProtocol, Protocol *addition)
|
||||
{
|
||||
if ((NULL == aProtocol) || (NULL == addition)) { return; }
|
||||
Protocol2 *proto = (Protocol2*)aProtocol;
|
||||
if (NULL == proto->protocol_list)
|
||||
{
|
||||
proto->protocol_list = calloc(1, sizeof(struct objc_property_list) + sizeof(Protocol2*));
|
||||
proto->protocol_list->count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
proto->protocol_list->count++;
|
||||
proto->protocol_list = realloc(proto->protocol_list, sizeof(struct objc_property_list) +
|
||||
proto->protocol_list->count * sizeof(Protocol2*));
|
||||
proto->protocol_list->count = 1;
|
||||
}
|
||||
proto->protocol_list->list[proto->protocol_list->count-1] = (Protocol2*)addition;
|
||||
}
|
||||
void protocol_addProperty(Protocol *aProtocol,
|
||||
const char *name,
|
||||
const objc_property_attribute_t *attributes,
|
||||
unsigned int attributeCount,
|
||||
BOOL isRequiredProperty,
|
||||
BOOL isInstanceProperty)
|
||||
{
|
||||
if ((NULL == aProtocol) || (NULL == name)) { return; }
|
||||
if (nil != aProtocol->isa) { return; }
|
||||
if (!isInstanceProperty) { return; }
|
||||
Protocol2 *proto = (Protocol2*)aProtocol;
|
||||
struct objc_property_list **listPtr;
|
||||
if (isRequiredProperty)
|
||||
{
|
||||
listPtr = &proto->properties;
|
||||
}
|
||||
else
|
||||
{
|
||||
listPtr = &proto->optional_properties;
|
||||
}
|
||||
if (NULL == *listPtr)
|
||||
{
|
||||
*listPtr = calloc(1, sizeof(struct objc_property_list) + sizeof(struct objc_property));
|
||||
(*listPtr)->count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*listPtr)->count++;
|
||||
*listPtr = realloc(*listPtr, sizeof(struct objc_property_list) +
|
||||
sizeof(struct objc_property) * (*listPtr)->count);
|
||||
}
|
||||
struct objc_property_list *list = *listPtr;
|
||||
int index = list->count-1;
|
||||
list->properties[index] = propertyFromAttrs(attributes, attributeCount);
|
||||
list->properties[index].name = strdup(name);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user