diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-05-05 15:42:10 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-05-05 15:42:15 +0300 |
commit | 29aa531e5137b9c16b04857a7b66385e78486342 (patch) | |
tree | cdec8833f0f3f96b40dd0e44e970c24ce7f131a2 /source | |
parent | f91e9529dacb21ef709e7fd1ef8f989731a5a2f3 (diff) | |
parent | d3b3df037197d46b608eb38a5dbd6f1d2761ec36 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_idprop.h | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/idprop.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/idprop_utils.c | 251 | ||||
-rw-r--r-- | source/blender/python/generic/idprop_py_api.c | 46 |
5 files changed, 259 insertions, 62 deletions
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index c686fa41e7e..94630eaa7b0 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -152,8 +152,13 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference); # define IDP_Id(prop) ((ID *) (prop)->data.pointer) #endif -/* for printout/logging only */ -char *IDP_reprN(const struct IDProperty *prop); +/* Format IDProperty as strings */ +char *IDP_reprN( + const struct IDProperty *prop, uint *r_len); +void IDP_repr_fn( + const IDProperty *prop, + void (*str_append_fn)(void *user_data, const char *str, uint str_len), + void *user_data); void IDP_print(const struct IDProperty *prop); #ifdef __cplusplus diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index fe79f74ef27..9e241b7fa81 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -119,6 +119,7 @@ set(SRC intern/icons_rasterize.c intern/idcode.c intern/idprop.c + intern/idprop_utils.c intern/image.c intern/image_gen.c intern/ipo.c diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 1e7f6cf284a..0c5078e3e36 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -1107,17 +1107,3 @@ void IDP_Reset(IDProperty *prop, const IDProperty *reference) /** \} */ -/* We could write a C version, see: idprop_py_api.c */ -#ifndef WITH_PYTHON -char *IDP_reprN(IDProperty *UNUSED(prop)) -{ - return BLI_strdup("<unsupported>"); -} - -void IDP_print(IDProperty *prop) -{ - char *repr = IDP_reprN(prop); - printf("IDProperty(%p): %s\n", prop, repr); - MEM_freeN(repr); -} -#endif /* WITH_PYTHON */ diff --git a/source/blender/blenkernel/intern/idprop_utils.c b/source/blender/blenkernel/intern/idprop_utils.c new file mode 100644 index 00000000000..21005da2d97 --- /dev/null +++ b/source/blender/blenkernel/intern/idprop_utils.c @@ -0,0 +1,251 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/idprop_utils.c + * \ingroup bke + */ + +#include <stdio.h> +#include <string.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_dynstr.h" + +#include "BKE_idprop.h" +#include "BKE_idcode.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_strict_flags.h" + + +/* -------------------------------------------------------------------- */ +/** \name IDProp Repr + * + * Convert an IDProperty to a string. + * + * Output should be a valid Python literal + * (with minor exceptions - float nan for eg). + * \{ */ + +struct ReprState { + void (*str_append_fn)(void *user_data, const char *str, uint str_len); + void *user_data; + /* Big enough to format any primitive type. */ + char buf[128]; +}; + +static void idp_str_append_escape(struct ReprState *state, const char *str, const uint str_len, bool quote) +{ + if (quote) { + state->str_append_fn(state->user_data, "\"", 1); + } + uint i_prev = 0, i = 0; + while (i < str_len) { + const char c = str[i]; + if (c == '"') { + if (i_prev != i) { + state->str_append_fn(state->user_data, str + i_prev, i - i_prev); + } + state->str_append_fn(state->user_data, "\\\"", 2); + i_prev = i + 1; + } + else if (c == '\\') { + if (i_prev != i) { + state->str_append_fn(state->user_data, str + i_prev, i - i_prev); + } + state->str_append_fn(state->user_data, "\\\\", 2); + i_prev = i + 1; + } + else if (c < 32) { + if (i_prev != i) { + state->str_append_fn(state->user_data, str + i_prev, i - i_prev); + } + char buf[5]; + uint len = (uint)BLI_snprintf_rlen(buf, sizeof(buf), "\\x%02x", c); + BLI_assert(len == 4); + state->str_append_fn(state->user_data, buf, len); + i_prev = i + 1; + } + i++; + } + state->str_append_fn(state->user_data, str + i_prev, i - i_prev); + if (quote) { + state->str_append_fn(state->user_data, "\"", 1); + } +} + +static void idp_repr_fn_recursive(struct ReprState *state, const IDProperty *prop) +{ + /* Note: 'strlen' will be calculated at compile time for literals. */ +#define STR_APPEND_STR(str) { \ + state->str_append_fn(state->user_data, str, (uint)strlen(str)); \ +} ((void)0) + +#define STR_APPEND_STR_QUOTE(str) { \ + idp_str_append_escape(state, str, (uint)strlen(str), true); \ +} ((void)0) + +#define STR_APPEND_FMT(format, ...) { \ + const uint len = (uint)BLI_snprintf_rlen(state->buf, sizeof(state->buf), format, __VA_ARGS__); \ + state->str_append_fn(state->user_data, state->buf, len); \ +} ((void)0) + + switch (prop->type) { + case IDP_STRING: + { + STR_APPEND_STR_QUOTE(IDP_String(prop)); + break; + } + case IDP_INT: + { + STR_APPEND_FMT("%d", IDP_Int(prop)); + break; + } + case IDP_FLOAT: + { + STR_APPEND_FMT("%g", (double)IDP_Float(prop)); + break; + } + case IDP_DOUBLE: + { + STR_APPEND_FMT("%g", IDP_Double(prop)); + break; + } + case IDP_ARRAY: + { + STR_APPEND_STR("["); + switch (prop->subtype) { + case IDP_INT: + for (const int *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) { + if (v != prop->data.pointer) { + STR_APPEND_STR(", "); + } + STR_APPEND_FMT("%d", *v); + } + break; + case IDP_FLOAT: + for (const float *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) { + if (v != prop->data.pointer) { + STR_APPEND_STR(", "); + } + STR_APPEND_FMT("%g", (double)*v); + } + break; + case IDP_DOUBLE: + for (const double *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) { + if (v != prop->data.pointer) { + STR_APPEND_STR(", "); + } + STR_APPEND_FMT("%g", *v); + } + break; + } + STR_APPEND_STR("]"); + break; + } + case IDP_IDPARRAY: + { + STR_APPEND_STR("["); + for (const IDProperty *v = prop->data.pointer, *v_end = v + prop->len; v != v_end; v++) { + if (v != prop->data.pointer) { + STR_APPEND_STR(", "); + } + idp_repr_fn_recursive(state, v); + } + STR_APPEND_STR("]"); + break; + } + case IDP_GROUP: + { + STR_APPEND_STR("{"); + for (const IDProperty *subprop = prop->data.group.first; subprop; subprop = subprop->next) { + if (subprop != prop->data.group.first) { + STR_APPEND_STR(", "); + } + STR_APPEND_STR_QUOTE(subprop->name); + STR_APPEND_STR(": "); + idp_repr_fn_recursive(state, subprop); + } + STR_APPEND_STR("}"); + break; + } + case IDP_ID: + { + const ID *id = prop->data.pointer; + STR_APPEND_STR("bpy.data."); + STR_APPEND_STR(BKE_idcode_to_name_plural(GS(id->name))); + STR_APPEND_STR("["); + STR_APPEND_STR_QUOTE(id->name + 2); + STR_APPEND_STR("]"); + break; + } + default: + { + BLI_assert(0); + break; + } + } + +#undef STR_APPEND_STR +#undef STR_APPEND_STR_QUOTE +#undef STR_APPEND_FMT + +} + +void IDP_repr_fn( + const IDProperty *prop, + void (*str_append_fn)(void *user_data, const char *str, uint str_len), + void *user_data) +{ + struct ReprState state = { + .str_append_fn = str_append_fn, + .user_data = user_data, + }; + idp_repr_fn_recursive(&state, prop); +} + +static void repr_str(void *user_data, const char *str, uint len) +{ + BLI_dynstr_nappend(user_data, str, (int)len); +} + +char *IDP_reprN(const IDProperty *prop, uint *r_len) +{ + DynStr *ds = BLI_dynstr_new(); + IDP_repr_fn(prop, repr_str, ds); + char *cstring = BLI_dynstr_get_cstring(ds); + if (r_len != NULL) { + *r_len = (uint)BLI_dynstr_get_len(ds); + } + BLI_dynstr_free(ds); + return cstring; +} + +void IDP_print(const IDProperty *prop) +{ + char *repr = IDP_reprN(prop, NULL); + printf("IDProperty(%p): ", prop); + puts(repr); + MEM_freeN(repr); +} + +/** \} */ diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index c35472026fa..4b56d4412e6 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1806,49 +1806,3 @@ PyObject *BPyInit_idprop(void) return mod; } - -/* -------------------------------------------------------------------- */ -/* debug only function */ - -char *IDP_reprN(const IDProperty *prop) -{ - if (prop == NULL) { - return BLI_strdup("None"); - } - - PyGILState_STATE gilstate; - bool use_gil = true; /* !PyC_IsInterpreterActive(); */ - PyObject *ret_dict; - PyObject *ret_str; - - if (use_gil) { - gilstate = PyGILState_Ensure(); - } - - /* Note: non-const cast is safe here since we only repr the result. */ - /* to_dict() */ - ret_dict = BPy_IDGroup_MapDataToPy((IDProperty *)prop); - ret_str = PyObject_Repr(ret_dict); - Py_DECREF(ret_dict); - - Py_ssize_t res_str_len = 0; - char *res_str_bytes = _PyUnicode_AsStringAndSize(ret_str, &res_str_len); - - res_str_bytes = BLI_strdupn(res_str_bytes, res_str_len); - - Py_DECREF(ret_str); - - if (use_gil) { - PyGILState_Release(gilstate); - } - return res_str_bytes; -} - - -void IDP_print(const IDProperty *prop) -{ - char *repr = IDP_reprN(prop); - printf("IDProperty(%p): %s\n", prop, repr); - MEM_freeN(repr); -} - |