Commit: d3b3df037197d46b608eb38a5dbd6f1d2761ec36
Author: Campbell Barton
Date:   Sat May 5 14:27:54 2018 +0200
Branches: master
https://developer.blender.org/rBd3b3df037197d46b608eb38a5dbd6f1d2761ec36

IDProp API: add native C repr function

Was using Python which wasn't very efficient (even for logging).

===================================================================

M       source/blender/blenkernel/BKE_idprop.h
M       source/blender/blenkernel/CMakeLists.txt
M       source/blender/blenkernel/intern/idprop.c
A       source/blender/blenkernel/intern/idprop_utils.c
M       source/blender/python/generic/idprop_py_api.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_idprop.h 
b/source/blender/blenkernel/BKE_idprop.h
index 48a5db93504..8a2cdd7b37c 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -145,8 +145,13 @@ void IDP_RelinkProperty(struct IDProperty *prop);
 #  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);
 
 #endif /* __BKE_IDPROP_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt 
b/source/blender/blenkernel/CMakeLists.txt
index d789671ab24..723ba347dfb 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -117,6 +117,7 @@ set(SRC
        intern/icons.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 5fb6dd558e0..fe00d68b4ea 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -1069,17 +1069,3 @@ void IDP_ClearProperty(IDProperty *prop)
 
 /** \} */
 
-/* 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);
-}
-

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to