support for non-null terminated byte strings in id properties (as a subtype of IDP_STRING types)
This commit is contained in:
@@ -40,7 +40,11 @@ typedef union IDPropertyTemplate {
|
||||
int i;
|
||||
float f;
|
||||
double d;
|
||||
char *str;
|
||||
struct {
|
||||
char *str;
|
||||
short len;
|
||||
char subtype;
|
||||
} string;
|
||||
struct ID *id;
|
||||
struct {
|
||||
short type;
|
||||
|
||||
@@ -349,17 +349,20 @@ static IDProperty *IDP_CopyString(IDProperty *prop)
|
||||
|
||||
void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
|
||||
{
|
||||
int stlen;
|
||||
|
||||
stlen = strlen(st);
|
||||
int stlen = strlen(st);
|
||||
|
||||
if(maxlen > 0 && maxlen < stlen)
|
||||
stlen= maxlen;
|
||||
|
||||
stlen++; /* make room for null byte */
|
||||
|
||||
IDP_ResizeArray(prop, stlen);
|
||||
BLI_strncpy(prop->data.pointer, st, stlen);
|
||||
if (prop->subtype == IDP_STRING_SUB_BYTE) {
|
||||
IDP_ResizeArray(prop, stlen);
|
||||
memcpy(prop->data.pointer, st, stlen);
|
||||
}
|
||||
else {
|
||||
stlen++; /* make room for null byte */
|
||||
IDP_ResizeArray(prop, stlen);
|
||||
BLI_strncpy(prop->data.pointer, st, stlen);
|
||||
}
|
||||
}
|
||||
|
||||
void IDP_ConcatStringC(IDProperty *prop, const char *st)
|
||||
@@ -703,18 +706,36 @@ IDProperty *IDP_New(int type, IDPropertyTemplate val, const char *name)
|
||||
}
|
||||
case IDP_STRING:
|
||||
{
|
||||
char *st = val.str;
|
||||
const char *st = val.string.str;
|
||||
|
||||
prop = MEM_callocN(sizeof(IDProperty), "IDProperty string");
|
||||
if (st == NULL) {
|
||||
prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
||||
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
||||
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
|
||||
} else {
|
||||
int stlen = strlen(st) + 1;
|
||||
prop->data.pointer = MEM_mallocN(stlen, "id property string 2");
|
||||
prop->len = prop->totallen = stlen;
|
||||
memcpy(prop->data.pointer, st, stlen);
|
||||
if (val.string.subtype == IDP_STRING_SUB_BYTE) {
|
||||
/* note, intentionally not null terminated */
|
||||
if (st == NULL) {
|
||||
prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
||||
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
||||
prop->len = 0;
|
||||
}
|
||||
else {
|
||||
prop->data.pointer = MEM_mallocN(val.string.len, "id property string 2");
|
||||
prop->len = prop->totallen = val.string.len;
|
||||
memcpy(prop->data.pointer, st, val.string.len);
|
||||
}
|
||||
prop->subtype= IDP_STRING_SUB_BYTE;
|
||||
}
|
||||
else {
|
||||
if (st == NULL) {
|
||||
prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1");
|
||||
prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS;
|
||||
prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/
|
||||
}
|
||||
else {
|
||||
int stlen = strlen(st) + 1;
|
||||
prop->data.pointer = MEM_mallocN(stlen, "id property string 3");
|
||||
prop->len = prop->totallen = stlen;
|
||||
memcpy(prop->data.pointer, st, stlen);
|
||||
}
|
||||
prop->subtype= IDP_STRING_SUB_UTF8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -80,6 +80,13 @@ typedef struct IDProperty {
|
||||
#define IDP_IDPARRAY 9
|
||||
#define IDP_NUMTYPES 10
|
||||
|
||||
/*->subtype */
|
||||
|
||||
/* IDP_STRING */
|
||||
#define IDP_STRING_SUB_UTF8 0 /* default */
|
||||
#define IDP_STRING_SUB_BYTE 1 /* arbitrary byte array, _not_ null terminated */
|
||||
|
||||
|
||||
/* add any future new id property types here.*/
|
||||
|
||||
/* watch it: Sequence has identical beginning. */
|
||||
|
||||
@@ -2271,12 +2271,23 @@ void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
|
||||
|
||||
BLI_assert(RNA_property_type(prop) == PROP_STRING);
|
||||
|
||||
if((idprop=rna_idproperty_check(&prop, ptr)))
|
||||
strcpy(value, IDP_String(idprop));
|
||||
else if(sprop->get)
|
||||
if((idprop=rna_idproperty_check(&prop, ptr))) {
|
||||
/* editing bytes is not 100% supported
|
||||
* since they can contain NIL chars */
|
||||
if (idprop->subtype == IDP_STRING_SUB_BYTE) {
|
||||
memcpy(value, IDP_String(idprop), idprop->len + 1);
|
||||
value[idprop->len]= '\0';
|
||||
}
|
||||
else {
|
||||
strcpy(value, IDP_String(idprop));
|
||||
}
|
||||
}
|
||||
else if(sprop->get) {
|
||||
sprop->get(ptr, value);
|
||||
else
|
||||
}
|
||||
else {
|
||||
strcpy(value, sprop->defaultvalue);
|
||||
}
|
||||
}
|
||||
|
||||
char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
|
||||
@@ -2320,8 +2331,14 @@ int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
|
||||
|
||||
BLI_assert(RNA_property_type(prop) == PROP_STRING);
|
||||
|
||||
if((idprop=rna_idproperty_check(&prop, ptr)))
|
||||
return strlen(IDP_String(idprop));
|
||||
if((idprop=rna_idproperty_check(&prop, ptr))) {
|
||||
if (idprop->subtype == IDP_STRING_SUB_BYTE) {
|
||||
return idprop->len;
|
||||
}
|
||||
else {
|
||||
return strlen(IDP_String(idprop));
|
||||
}
|
||||
}
|
||||
else if(sprop->length)
|
||||
return sprop->length(ptr);
|
||||
else
|
||||
@@ -2336,6 +2353,7 @@ void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *val
|
||||
BLI_assert(RNA_property_type(prop) == PROP_STRING);
|
||||
|
||||
if((idprop=rna_idproperty_check(&prop, ptr)))
|
||||
/* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
|
||||
IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
|
||||
else if(sprop->set)
|
||||
sprop->set(ptr, value); /* set function needs to clamp its self */
|
||||
|
||||
@@ -64,11 +64,18 @@ PyObject *BPy_IDGroup_WrapData( ID *id, IDProperty *prop )
|
||||
{
|
||||
switch ( prop->type ) {
|
||||
case IDP_STRING:
|
||||
|
||||
if (prop->subtype == IDP_STRING_SUB_BYTE) {
|
||||
return PyBytes_FromStringAndSize(IDP_Array(prop), prop->len);
|
||||
}
|
||||
else {
|
||||
#ifdef USE_STRING_COERCE
|
||||
return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1);
|
||||
return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1);
|
||||
#else
|
||||
return PyUnicode_FromStringAndSize(IDP_Array(prop), prop->len - 1);
|
||||
return PyUnicode_FromStringAndSize(IDP_Array(prop), prop->len - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
case IDP_INT:
|
||||
return PyLong_FromLong( (long)prop->data.val );
|
||||
case IDP_FLOAT:
|
||||
@@ -332,7 +339,8 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty
|
||||
else if (PyUnicode_Check(ob)) {
|
||||
#ifdef USE_STRING_COERCE
|
||||
PyObject *value_coerce= NULL;
|
||||
val.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
|
||||
val.string.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
|
||||
val.string.subtype = IDP_STRING_SUB_UTF8;
|
||||
prop = IDP_New(IDP_STRING, val, name);
|
||||
Py_XDECREF(value_coerce);
|
||||
#else
|
||||
@@ -340,6 +348,15 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty
|
||||
prop = IDP_New(IDP_STRING, val, name);
|
||||
#endif
|
||||
}
|
||||
else if (PyBytes_Check(ob)) {
|
||||
val.string.str= PyBytes_AS_STRING(ob);
|
||||
val.string.len= PyBytes_GET_SIZE(ob);
|
||||
val.string.subtype= IDP_STRING_SUB_BYTE;
|
||||
|
||||
prop = IDP_New(IDP_STRING, val, name);
|
||||
//prop = IDP_NewString(PyBytes_AS_STRING(ob), name, PyBytes_GET_SIZE(ob));
|
||||
//prop->subtype= IDP_STRING_SUB_BYTE;
|
||||
}
|
||||
else if (PySequence_Check(ob)) {
|
||||
PyObject *item;
|
||||
int i;
|
||||
@@ -493,11 +510,16 @@ static PyObject *BPy_IDGroup_MapDataToPy(IDProperty *prop)
|
||||
{
|
||||
switch (prop->type) {
|
||||
case IDP_STRING:
|
||||
if (prop->subtype == IDP_STRING_SUB_BYTE) {
|
||||
return PyBytes_FromStringAndSize(IDP_Array(prop), prop->len);
|
||||
}
|
||||
else {
|
||||
#ifdef USE_STRING_COERCE
|
||||
return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1);
|
||||
return PyC_UnicodeFromByteAndSize(IDP_Array(prop), prop->len - 1);
|
||||
#else
|
||||
return PyUnicode_FromStringAndSize(IDP_Array(prop), prop->len - 1);
|
||||
return PyUnicode_FromStringAndSize(IDP_Array(prop), prop->len - 1);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case IDP_FLOAT:
|
||||
return PyFloat_FromDouble(*((float*)&prop->data.val));
|
||||
|
||||
Reference in New Issue
Block a user