Treat the property encoding string as canonical.

This is more reliable than the bitfields (and is constructed from them if the compiler doesn’t fill in the string).
main
David Chisnall 10 years ago
parent 8c35e72655
commit 2493137996

@ -1,6 +1,7 @@
#include "objc/runtime.h"
#include "objc/objc-arc.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -513,64 +514,62 @@ objc_property_attribute_t *property_copyAttributeList(objc_property_t property,
attrs[count].value = types;
count++;
}
if (checkAttribute(property->attributes, OBJC_PR_readonly))
{
attrs[count].name = "R";
attrs[count].value = "";
count++;
}
if (checkAttribute(property->attributes, OBJC_PR_copy))
{
attrs[count].name = "C";
attrs[count].value = "";
count++;
}
if (checkAttribute(property->attributes, OBJC_PR_retain) ||
checkAttribute(property->attributes2, OBJC_PR_strong))
// If the compiler provides a type encoding string, then it's more
// informative than the bitfields and should be treated as canonical. If
// the compiler didn't provide a type encoding string, then this will
// create a best-effort one.
const char *attributes = property_getAttributes(property);
for (int i=strlen(types)+1 ; attributes[i] != 0 ; i++)
{
attrs[count].name = "&";
attrs[count].value = "";
count++;
}
if (checkAttribute(property->attributes2, OBJC_PR_dynamic) &&
!checkAttribute(property->attributes2, OBJC_PR_synthesized))
{
attrs[count].name = "D";
attrs[count].value = "";
count++;
}
if (checkAttribute(property->attributes2, OBJC_PR_weak))
{
attrs[count].name = "W";
attrs[count].value = "";
count++;
}
if ((property->attributes & OBJC_PR_nonatomic) == OBJC_PR_nonatomic)
{
attrs[count].name = "N";
assert(count<12);
if (attributes[i] == ',')
{
// Comma is never the last character in the string, so this should
// never push us past the end.
i++;
}
attrs[count].value = "";
switch (attributes[i])
{
case 'R':
attrs[count].name = "R";
break;
case 'C':
attrs[count].name = "C";
break;
case '&':
attrs[count].name = "&";
break;
case 'D':
attrs[count].name = "D";
break;
case 'W':
attrs[count].name = "W";
break;
case 'N':
attrs[count].name = "N";
break;
case 'G':
attrs[count].name = "G";
attrs[count].value = property->getter_name;
i += strlen(attrs[count].value);
break;
case 'S':
attrs[count].name = "S";
attrs[count].value = property->setter_name;
i += strlen(attrs[count].value);
break;
case 'V':
attrs[count].name = "V";
attrs[count].value = attributes+i+1;
i += strlen(attributes+i)-1;
break;
default:
i++;
continue;
}
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++;
}
const char *name = property_getIVar(property);
if (name != NULL)
{
attrs[count].name = "V";
attrs[count].value = name;
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)
@ -695,6 +694,7 @@ char *property_copyAttributeValue(objc_property_t property,
const char *attributeName)
{
if ((NULL == property) || (NULL == attributeName)) { return NULL; }
const char *attributes = property_getAttributes(property);
switch (attributeName[0])
{
case 'T':
@ -703,9 +703,13 @@ char *property_copyAttributeValue(objc_property_t property,
return (NULL == types) ? NULL : strdup(types);
}
case 'D':
case 'R':
case 'W':
case 'C':
case '&':
case 'N':
{
return checkAttribute(property->attributes2, OBJC_PR_dynamic) &&
!checkAttribute(property->attributes2, OBJC_PR_synthesized) ? strdup("") : 0;
return strchr(attributes, attributeName[0]) ? strdup("") : 0;
}
case 'V':
{
@ -719,27 +723,6 @@ char *property_copyAttributeValue(objc_property_t property,
{
return strdup(property->getter_name);
}
case 'R':
{
return checkAttribute(property->attributes, OBJC_PR_readonly) ? strdup("") : 0;
}
case 'W':
{
return checkAttribute(property->attributes2, OBJC_PR_weak) ? strdup("") : 0;
}
case 'C':
{
return checkAttribute(property->attributes, OBJC_PR_copy) ? strdup("") : 0;
}
case '&':
{
return checkAttribute(property->attributes, OBJC_PR_retain) ||
checkAttribute(property->attributes2, OBJC_PR_strong) ? strdup("") : 0;
}
case 'N':
{
return checkAttribute(property->attributes, OBJC_PR_nonatomic) ? strdup("") : 0;
}
}
return 0;
}

Loading…
Cancel
Save