Пример #1
0
/* note: group can be a pointer array or a group */
const char *BPy_IDProperty_Map_ValidateAndCreate(const char *name, IDProperty *group, PyObject *ob)
{
    IDProperty *prop = NULL;
    IDPropertyTemplate val = {0};

    if(strlen(name) >= sizeof(group->name))
        return "the length of IDProperty names is limited to 31 characters";

    if (PyFloat_Check(ob)) {
        val.d = PyFloat_AsDouble(ob);
        prop = IDP_New(IDP_DOUBLE, val, name);
    } else if (PyLong_Check(ob)) {
        val.i = (int) PyLong_AsSsize_t(ob);
        prop = IDP_New(IDP_INT, val, name);
    } else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
        PyObject *value_coerce= NULL;
        val.str = (char *)PyC_UnicodeAsByte(ob, &value_coerce);
        prop = IDP_New(IDP_STRING, val, name);
        Py_XDECREF(value_coerce);
#else
        val.str = _PyUnicode_AsString(ob);
        prop = IDP_New(IDP_STRING, val, name);
#endif
    } else if (PySequence_Check(ob)) {
        PyObject *item;
        int i;

        if((val.array.type= idp_sequence_type(ob)) == -1)
            return "only floats, ints and dicts are allowed in ID property arrays";

        /*validate sequence and derive type.
        we assume IDP_INT unless we hit a float
        number; then we assume it's */

        val.array.len = PySequence_Size(ob);

        switch(val.array.type) {
        case IDP_DOUBLE:
            prop = IDP_New(IDP_ARRAY, val, name);
            for (i=0; i<val.array.len; i++) {
                item = PySequence_GetItem(ob, i);
                ((double*)prop->data.pointer)[i] = (float)PyFloat_AsDouble(item);
                Py_DECREF(item);
            }
            break;
        case IDP_INT:
            prop = IDP_New(IDP_ARRAY, val, name);
            for (i=0; i<val.array.len; i++) {
                item = PySequence_GetItem(ob, i);
                ((int*)prop->data.pointer)[i] = (int)PyLong_AsSsize_t(item);
                Py_DECREF(item);
            }
            break;
        case IDP_IDPARRAY:
            prop= IDP_NewIDPArray(name);
            for (i=0; i<val.array.len; i++) {
                const char *error;
                item = PySequence_GetItem(ob, i);
                error= BPy_IDProperty_Map_ValidateAndCreate("", prop, item);
                Py_DECREF(item);

                if(error)
                    return error;
            }
            break;
        }
    } else if (PyMapping_Check(ob)) {
        PyObject *keys, *vals, *key, *pval;
        int i, len;
        /*yay! we get into recursive stuff now!*/
        keys = PyMapping_Keys(ob);
        vals = PyMapping_Values(ob);

        /*we allocate the group first; if we hit any invalid data,
          we can delete it easily enough.*/
        prop = IDP_New(IDP_GROUP, val, name);
        len = PyMapping_Length(ob);
        for (i=0; i<len; i++) {
            key = PySequence_GetItem(keys, i);
            pval = PySequence_GetItem(vals, i);
            if (!PyUnicode_Check(key)) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                return "invalid element in subgroup dict template!";
            }
            if (BPy_IDProperty_Map_ValidateAndCreate(_PyUnicode_AsString(key), prop, pval)) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                return "invalid element in subgroup dict template!";
            }
            Py_XDECREF(key);
            Py_XDECREF(pval);
        }
        Py_XDECREF(keys);
        Py_XDECREF(vals);
    } else return "invalid property value";

    if(group->type==IDP_IDPARRAY) {
        IDP_AppendArray(group, prop);
        // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
        MEM_freeN(prop);
    } else {
        IDP_ReplaceInGroup(group, prop);
    }

    return NULL;
}
Пример #2
0
/**
 * \note group can be a pointer array or a group.
 * assume we already checked key is a string.
 *
 * \return success.
 */
bool BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty *group, PyObject *ob)
{
    IDProperty *prop = NULL;
    IDPropertyTemplate val = {0};

    const char *name;

    if (name_obj) {
        Py_ssize_t name_size;
        name = _PyUnicode_AsStringAndSize(name_obj, &name_size);

        if (name == NULL) {
            PyErr_Format(PyExc_KeyError,
                         "invalid id-property key, expected a string, not a %.200s",
                         Py_TYPE(name_obj)->tp_name);
            return false;
        }

        if (name_size > MAX_IDPROP_NAME) {
            PyErr_SetString(PyExc_KeyError, "the length of IDProperty names is limited to 63 characters");
            return false;
        }
    }
    else {
        name = "";
    }

    if (PyFloat_Check(ob)) {
        val.d = PyFloat_AsDouble(ob);
        prop = IDP_New(IDP_DOUBLE, &val, name);
    }
    else if (PyLong_Check(ob)) {
        val.i = _PyLong_AsInt(ob);
        if (val.i == -1 && PyErr_Occurred()) {
            return false;
        }
        prop = IDP_New(IDP_INT, &val, name);
    }
    else if (PyUnicode_Check(ob)) {
#ifdef USE_STRING_COERCE
        PyObject *value_coerce = NULL;
        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
        val.str = _PyUnicode_AsString(ob);
        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 *ob_seq_fast = PySequence_Fast(ob, "py -> idprop");
        PyObject *item;
        int i;

        if (ob_seq_fast == NULL) {
            return false;
        }

        if ((val.array.type = idp_sequence_type(ob_seq_fast)) == -1) {
            Py_DECREF(ob_seq_fast);
            PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
            return false;
        }

        /* validate sequence and derive type.
         * we assume IDP_INT unless we hit a float
         * number; then we assume it's */

        val.array.len = PySequence_Fast_GET_SIZE(ob_seq_fast);

        switch (val.array.type) {
        case IDP_DOUBLE:
        {
            double *prop_data;

            prop = IDP_New(IDP_ARRAY, &val, name);
            prop_data = IDP_Array(prop);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
                if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        case IDP_INT:
        {
            int *prop_data;
            prop = IDP_New(IDP_ARRAY, &val, name);
            prop_data = IDP_Array(prop);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);
                if (((prop_data[i] = _PyLong_AsInt(item)) == -1) && PyErr_Occurred()) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        case IDP_IDPARRAY:
        {
            prop = IDP_NewIDPArray(name);
            for (i = 0; i < val.array.len; i++) {
                item = PySequence_Fast_GET_ITEM(ob_seq_fast, i);

                if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
                    Py_DECREF(ob_seq_fast);
                    return false;
                }
            }
            break;
        }
        default:
            /* should never happen */
            Py_DECREF(ob_seq_fast);
            PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
            return false;
        }

        Py_DECREF(ob_seq_fast);
    }
    else if (PyMapping_Check(ob)) {
        PyObject *keys, *vals, *key, *pval;
        int i, len;
        /*yay! we get into recursive stuff now!*/
        keys = PyMapping_Keys(ob);
        vals = PyMapping_Values(ob);

        /* we allocate the group first; if we hit any invalid data,
         * we can delete it easily enough.*/
        prop = IDP_New(IDP_GROUP, &val, name);
        len = PyMapping_Length(ob);
        for (i = 0; i < len; i++) {
            key = PySequence_GetItem(keys, i);
            pval = PySequence_GetItem(vals, i);
            if (BPy_IDProperty_Map_ValidateAndCreate(key, prop, pval) == false) {
                IDP_FreeProperty(prop);
                MEM_freeN(prop);
                Py_XDECREF(keys);
                Py_XDECREF(vals);
                Py_XDECREF(key);
                Py_XDECREF(pval);
                /* error is already set */
                return false;
            }
            Py_XDECREF(key);
            Py_XDECREF(pval);
        }
        Py_XDECREF(keys);
        Py_XDECREF(vals);
    }
    else {
        PyErr_Format(PyExc_TypeError,
                     "invalid id-property type %.200s not supported",
                     Py_TYPE(ob)->tp_name);
        return false;
    }

    if (group->type == IDP_IDPARRAY) {
        IDP_AppendArray(group, prop);
        // IDP_FreeProperty(item);  /* IDP_AppendArray does a shallow copy (memcpy), only free memory */
        MEM_freeN(prop);
    }
    else {
        IDP_ReplaceInGroup(group, prop);
    }

    return true;
}
Пример #3
0
static IDProperty *idp_from_PySequence_Fast(const char *name, PyObject *ob)
{
	IDProperty *prop;
	IDPropertyTemplate val = {0};

	PyObject **ob_seq_fast_items;
	PyObject *item;
	int i;

	ob_seq_fast_items = PySequence_Fast_ITEMS(ob);

	if ((val.array.type = idp_sequence_type(ob)) == (char)-1) {
		PyErr_SetString(PyExc_TypeError, "only floats, ints and dicts are allowed in ID property arrays");
		return NULL;
	}

	/* validate sequence and derive type.
	 * we assume IDP_INT unless we hit a float
	 * number; then we assume it's */

	val.array.len = PySequence_Fast_GET_SIZE(ob);

	switch (val.array.type) {
		case IDP_DOUBLE:
		{
			double *prop_data;
			prop = IDP_New(IDP_ARRAY, &val, name);
			prop_data = IDP_Array(prop);
			for (i = 0; i < val.array.len; i++) {
				item = ob_seq_fast_items[i];
				if (((prop_data[i] = PyFloat_AsDouble(item)) == -1.0) && PyErr_Occurred()) {
					return NULL;
				}
			}
			break;
		}
		case IDP_INT:
		{
			int *prop_data;
			prop = IDP_New(IDP_ARRAY, &val, name);
			prop_data = IDP_Array(prop);
			for (i = 0; i < val.array.len; i++) {
				item = ob_seq_fast_items[i];
				if (((prop_data[i] = PyC_Long_AsI32(item)) == -1) && PyErr_Occurred()) {
					return NULL;
				}
			}
			break;
		}
		case IDP_IDPARRAY:
		{
			prop = IDP_NewIDPArray(name);
			for (i = 0; i < val.array.len; i++) {
				item = ob_seq_fast_items[i];
				if (BPy_IDProperty_Map_ValidateAndCreate(NULL, prop, item) == false) {
					return NULL;
				}
			}
			break;
		}
		default:
			/* should never happen */
			PyErr_SetString(PyExc_RuntimeError, "internal error with idp array.type");
			return NULL;
	}
	return prop;
}