Added implementation of property_getAttributes(). This is a horrible interface, both to implement and to use. We should add some better interfaces.

This commit is contained in:
theraven 2011-04-28 20:36:36 +00:00
parent c6f0651609
commit 8ee4d9c38a
4 changed files with 119 additions and 10 deletions

View File

@ -5,6 +5,7 @@
#include "objc/runtime.h"
#include "method_list.h"
#include "visibility.h"
size_t objc_alignof_type (const char *type);
@ -38,7 +39,7 @@ const char *objc_skip_argspec(const char *type)
return type;
}
static size_t lengthOfTypeEncoding(const char *types)
PRIVATE size_t lengthOfTypeEncoding(const char *types)
{
const char *end = objc_skip_typespec(types);
size_t length = end - types;

View File

@ -573,6 +573,14 @@ const char *object_getClassName(id obj);
*/
const char *property_getName(objc_property_t property);
/**
* Returns the attributes for the specified property. This is similar to an
* Objective-C type encoding, but contains some extra information. A full
* description of the format for this string may be found in Apple's
* Objective-C Runtime Programming Guide.
*/
const char *property_getAttributes(objc_property_t property);
/**
* Testswhether a protocol conforms to another protocol.
*/

View File

@ -60,14 +60,6 @@ struct objc_property
* Flag set if the property is synthesized.
*/
const char isSynthesized;
/**
* Name of the set method for this property.
*/
const char *setter_name;
/**
* Type encoding of the setter for this property.
*/
const char *setter_types;
/**
* Name of the getter for this property.
*/
@ -76,6 +68,14 @@ struct objc_property
* Type encoding for the get method for this property.
*/
const char *getter_types;
/**
* Name of the set method for this property.
*/
const char *setter_name;
/**
* Type encoding of the setter for this property.
*/
const char *setter_types;
};
/**

View File

@ -199,5 +199,105 @@ objc_property_t* class_copyPropertyList(Class cls, unsigned int *outCount)
const char *property_getName(objc_property_t property)
{
return property->name;
if (NULL == property) { return NULL; }
const char *name = property->name;
if (name[0] == 0)
{
name += name[1];
}
return name;
}
PRIVATE size_t lengthOfTypeEncoding(const char *types);
const char *property_getAttributes(objc_property_t property)
{
if (NULL == property) { return NULL; }
char *name = (char*)property->name;
if (name[0] == 0)
{
return name + 2;
}
size_t typeSize = lengthOfTypeEncoding(property->getter_types);
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.
size_t encodingSize = typeSize + nameSize + 6;
char flags[16];
size_t i = 0;
// Flags that are a comma then a character
if ((property->attributes & OBJC_PR_readonly) == OBJC_PR_readonly)
{
flags[i++] = ',';
flags[i++] = 'R';
}
if ((property->attributes & OBJC_PR_copy) == OBJC_PR_copy)
{
flags[i++] = ',';
flags[i++] = 'C';
}
if ((property->attributes & OBJC_PR_retain) == OBJC_PR_retain)
{
flags[i++] = ',';
flags[i++] = '&';
}
if ((property->attributes & OBJC_PR_nonatomic) == OBJC_PR_nonatomic)
{
flags[i++] = ',';
flags[i++] = 'N';
}
encodingSize += i;
flags[i] = '\0';
size_t setterLength = 0;
size_t getterLength = 0;
if ((property->attributes & OBJC_PR_getter) == OBJC_PR_getter)
{
getterLength = strlen(property->getter_name);
encodingSize += 2 + getterLength;
}
if ((property->attributes & OBJC_PR_setter) == OBJC_PR_setter)
{
setterLength = strlen(property->setter_name);
encodingSize += 2 + setterLength;
}
name = malloc(encodingSize);
// Set the leading 0 and the offset of the name
char *insert = name;
*(insert++) = 0;
*(insert++) = 0;
// Set the type encoding
*(insert++) = 'T';
memcpy(insert, property->getter_types, typeSize);
insert += typeSize;
// Set the flags
memcpy(insert, flags, i);
insert += i;
if ((property->attributes & OBJC_PR_getter) == OBJC_PR_getter)
{
*(insert++) = ',';
*(insert++) = 'G';
memcpy(insert, property->getter_name, getterLength);
insert += getterLength;
}
if ((property->attributes & OBJC_PR_setter) == OBJC_PR_setter)
{
*(insert++) = ',';
*(insert++) = 'S';
memcpy(insert, property->setter_name, setterLength);
insert += setterLength;
}
*(insert++) = ',';
*(insert++) = 'V';
name[1] = (char)(uintptr_t)(insert - name);
memcpy(insert, property->name, nameSize);
insert += nameSize;
*insert = '\0';
//FIXME: Don't leak if this is called simultaneously from two threads.
//Should be an atomic CAS
property->name = name;
return name + 2;
}