mirror of
https://github.com/darlinghq/darling-libobjc2.git
synced 2025-03-03 06:06:05 +00:00
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:
parent
c6f0651609
commit
8ee4d9c38a
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
16
properties.h
16
properties.h
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
102
properties.m
102
properties.m
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user