You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2022/06/08 20:36:43 UTC

[qpid-proton] 02/08: PROTON-2557: Introduce pn_tostring in place of pn_inspect

This is an automated email from the ASF dual-hosted git repository.

astitcher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit d9ccd2923be628ac85e8a8da45090d981f0585cd
Author: Andrew Stitcher <as...@apache.org>
AuthorDate: Wed Jun 1 19:25:58 2022 -0400

    PROTON-2557: Introduce pn_tostring in place of pn_inspect
    
    Introduce and use a new API pn_tostring which produces a string
    representation of a Proton object in a char* string. It allocates this
    string with malloc and the application must free it.
    
    This replaces pn_inspect which requires the application to use the
    pn_string_t type purely to receive the string output. But we really
    don't want or need to expose this type outside the library itself.
---
 c/benchmarks/connection-driver.cpp     | 18 +++++++++---------
 c/benchmarks/message-encoding_list.cpp | 24 ++++++++++++------------
 c/benchmarks/message-encoding_map.cpp  | 31 +++++++++++++++----------------
 c/examples/direct.c                    |  7 +++----
 c/examples/receive.c                   |  7 +++----
 c/include/proton/object.h              |  1 +
 c/src/core/object/object.c             | 16 +++++++++++++++-
 c/tests/fuzz/fuzz-connection-driver.c  |  7 +++----
 c/tests/fuzz/fuzz-proactor-receive.c   |  8 ++++----
 c/tests/object_test.cpp                | 11 +++++------
 c/tests/pn_test.cpp                    |  7 ++++---
 c/tests/pn_test.hpp                    |  4 ----
 cpp/src/object.cpp                     |  7 +++----
 cpp/src/proton_bits.cpp                |  7 +++----
 14 files changed, 80 insertions(+), 75 deletions(-)

diff --git a/c/benchmarks/connection-driver.cpp b/c/benchmarks/connection-driver.cpp
index e2fdad16e..f3bef928a 100644
--- a/c/benchmarks/connection-driver.cpp
+++ b/c/benchmarks/connection-driver.cpp
@@ -19,24 +19,25 @@
  *
  */
 
-#include <unistd.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <wait.h>
 
 #include <benchmark/benchmark.h>
 
 #include "proton/connection_driver.h"
 #include "proton/engine.h"
+#include "proton/listener.h"
 #include "proton/log.h"
 #include "proton/message.h"
+#include "proton/netaddr.h"
+#include "proton/object.h"
+#include "proton/proactor.h"
+#include "proton/sasl.h"
 #include "proton/transport.h"
-#include <proton/listener.h>
-#include <proton/netaddr.h>
-#include <proton/proactor.h>
-#include <proton/sasl.h>
 
 
 // variant of the receive.c proactor example
@@ -475,11 +476,10 @@ static void decode_message(pn_delivery_t *dlv) {
       // decode it into a proton message
       pn_message_t *m = pn_message();
       if (PN_OK == pn_message_decode(m, buffer, len)) {
-        pn_string_t *s = pn_string(NULL);
-        pn_inspect(pn_message_body(m), s);
+        char *s = pn_tostring(pn_message_body(m));
         if (VERBOSE)
-          printf("%s\n", pn_string_get(s));
-        pn_free(s);
+          printf("%s\n", s);
+        free(s);
       }
       pn_message_free(m);
     }
diff --git a/c/benchmarks/message-encoding_list.cpp b/c/benchmarks/message-encoding_list.cpp
index 51e8cebd0..1b4954fa1 100644
--- a/c/benchmarks/message-encoding_list.cpp
+++ b/c/benchmarks/message-encoding_list.cpp
@@ -18,24 +18,25 @@
  * under the License.
  *
  */
-#include <unistd.h>
 
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <wait.h>
+
+#include <benchmark/benchmark.h>
 
 #include "proton/connection_driver.h"
 #include "proton/engine.h"
+#include "proton/listener.h"
 #include "proton/log.h"
 #include "proton/message.h"
-
-#include <benchmark/benchmark.h>
-#include <proton/listener.h>
-#include <proton/netaddr.h>
-#include <proton/proactor.h>
-#include <proton/sasl.h>
-#include <wait.h>
+#include "proton/netaddr.h"
+#include "proton/object.h"
+#include "proton/proactor.h"
+#include "proton/sasl.h"
 
 const bool VERBOSE = false;
 const bool ERRORS = true;
@@ -45,13 +46,12 @@ static void decode_message_buffer(pn_rwbytes_t data) {
   int err = pn_message_decode(m, data.start, data.size);
   if (!err) {
     /* Print the decoded message */
-    pn_string_t *s = pn_string(NULL);
-    pn_inspect(pn_message_body(m), s);
+    char *s = pn_tostring(pn_message_body(m));
     if (VERBOSE) {
-      printf("%s\n", pn_string_get(s));
+      printf("%s\n", s);
       fflush(stdout);
     }
-    pn_free(s);
+    free(s);
     pn_message_free(m);
     free(data.start);
   } else {
diff --git a/c/benchmarks/message-encoding_map.cpp b/c/benchmarks/message-encoding_map.cpp
index 86f8e1deb..d58746c73 100644
--- a/c/benchmarks/message-encoding_map.cpp
+++ b/c/benchmarks/message-encoding_map.cpp
@@ -18,24 +18,25 @@
  * under the License.
  *
  */
-#include <unistd.h>
 
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <wait.h>
+
+#include <benchmark/benchmark.h>
 
 #include "proton/connection_driver.h"
 #include "proton/engine.h"
+#include "proton/listener.h"
 #include "proton/log.h"
 #include "proton/message.h"
-
-#include <benchmark/benchmark.h>
-#include <proton/listener.h>
-#include <proton/netaddr.h>
-#include <proton/proactor.h>
-#include <proton/sasl.h>
-#include <wait.h>
+#include "proton/netaddr.h"
+#include "proton/object.h"
+#include "proton/proactor.h"
+#include "proton/sasl.h"
 
 #define MAX_SIZE 1024
 
@@ -49,13 +50,12 @@ static void decode_message_buffer(pn_rwbytes_t data) {
   int err = pn_message_decode(m, data.start, data.size);
   if (!err) {
     /* Print the decoded message */
-    pn_string_t *s = pn_string(NULL);
-    pn_inspect(pn_message_body(m), s);
+    char *s = pn_tostring(pn_message_body(m));
     if (VERBOSE) {
-      printf("%s\n", pn_string_get(s));
+      printf("%s\n", s);
       fflush(stdout);
     }
-    pn_free(s);
+    free(s);
     pn_message_free(m);
     free(data.start);
   } else {
@@ -152,11 +152,10 @@ static void decode_message(pn_delivery_t *dlv) {
       // decode it into a proton message
       pn_message_t *m = pn_message();
       if (PN_OK == pn_message_decode(m, buffer, len)) {
-        pn_string_t *s = pn_string(NULL);
-        pn_inspect(pn_message_body(m), s);
+        char *s = pn_tostring(pn_message_body(m));
         if (VERBOSE)
-          printf("%s\n", pn_string_get(s));
-        pn_free(s);
+          printf("%s\n", s);
+        free(s);
       }
       pn_message_free(m);
     }
diff --git a/c/examples/direct.c b/c/examples/direct.c
index ceaaf2379..977b85c8d 100644
--- a/c/examples/direct.c
+++ b/c/examples/direct.c
@@ -98,11 +98,10 @@ static void decode_message(pn_rwbytes_t data) {
   int err = pn_message_decode(m, data.start, data.size);
   if (!err) {
     /* Print the decoded message */
-    pn_string_t *s = pn_string(NULL);
-    pn_inspect(pn_message_body(m), s);
-    printf("%s\n", pn_string_get(s));
+    char *s = pn_tostring(pn_message_body(m));
+    printf("%s\n", s);
     fflush(stdout);
-    pn_free(s);
+    free(s);
     pn_message_free(m);
     free(data.start);
   } else {
diff --git a/c/examples/receive.c b/c/examples/receive.c
index c70e0d8e3..c6f31f433 100644
--- a/c/examples/receive.c
+++ b/c/examples/receive.c
@@ -61,10 +61,9 @@ static void decode_message(pn_rwbytes_t data) {
   int err = pn_message_decode(m, data.start, data.size);
   if (!err) {
     /* Print the decoded message */
-    pn_string_t *s = pn_string(NULL);
-    pn_inspect(pn_message_body(m), s);
-    printf("%s\n", pn_string_get(s));
-    pn_free(s);
+    char *s = pn_tostring(pn_message_body(m));
+    printf("%s\n", s);
+    free(s);
     pn_message_free(m);
     free(data.start);
   } else {
diff --git a/c/include/proton/object.h b/c/include/proton/object.h
index 3db656406..ce76c6941 100644
--- a/c/include/proton/object.h
+++ b/c/include/proton/object.h
@@ -156,6 +156,7 @@ PN_EXTERN uintptr_t pn_hashcode(void *object);
 PN_EXTERN intptr_t pn_compare(void *a, void *b);
 PN_EXTERN bool pn_equals(void *a, void *b);
 PN_EXTERN int pn_inspect(void *object, pn_string_t *dst);
+PN_EXTERN char *pn_tostring(void *object);
 
 PN_EXTERN pn_list_t *pn_list(const pn_class_t *clazz, size_t capacity);
 PN_EXTERN size_t pn_list_size(pn_list_t *list);
diff --git a/c/src/core/object/object.c b/c/src/core/object/object.c
index 318b3d95f..a3ee2cbfd 100644
--- a/c/src/core/object/object.c
+++ b/c/src/core/object/object.c
@@ -23,8 +23,9 @@
 
 #include "core/memory.h"
 
-#include <stdlib.h>
 #include <assert.h>
+#include <stdlib.h>
+#include <string.h>
 
 #define CID_pn_default CID_pn_object
 #define pn_default_initialize NULL
@@ -369,6 +370,19 @@ int pn_inspect(void *object, pn_string_t *dst)
   return pn_string_addf(dst, "%s<%p>", name, object);
 }
 
+char *pn_tostring(void *object)
+{
+  pn_string_t *s = pn_string(NULL);
+  pn_inspect(object, s);
+
+  const char *sc = pn_string_get(s);
+  int l = pn_string_size(s)+1; // include final null
+  char *r = malloc(l);
+  strncpy(r, sc, l);
+  pn_decref(s);
+  return r;
+}
+
 #define pn_weakref_new NULL
 #define pn_weakref_initialize NULL
 #define pn_weakref_finalize NULL
diff --git a/c/tests/fuzz/fuzz-connection-driver.c b/c/tests/fuzz/fuzz-connection-driver.c
index ba0650896..8f8459fac 100644
--- a/c/tests/fuzz/fuzz-connection-driver.c
+++ b/c/tests/fuzz/fuzz-connection-driver.c
@@ -181,11 +181,10 @@ static void decode_message(pn_delivery_t *dlv) {
       // decode it into a proton message
       pn_message_t *m = pn_message();
       if (PN_OK == pn_message_decode(m, buffer, len)) {
-        pn_string_t *s = pn_string(NULL);
-        pn_inspect(pn_message_body(m), s);
+        char *s = pn_tostring(pn_message_body(m));
         if (ERRORS)
-          printf("%s\n", pn_string_get(s));
-        pn_free(s);
+          printf("%s\n", s);
+        free(s);
       }
       pn_message_free(m);
     }
diff --git a/c/tests/fuzz/fuzz-proactor-receive.c b/c/tests/fuzz/fuzz-proactor-receive.c
index 499c439c2..b81160424 100644
--- a/c/tests/fuzz/fuzz-proactor-receive.c
+++ b/c/tests/fuzz/fuzz-proactor-receive.c
@@ -26,6 +26,7 @@
 #include <proton/delivery.h>
 #include <proton/link.h>
 #include <proton/message.h>
+#include <proton/object.h>
 #include <proton/proactor.h>
 #include <proton/session.h>
 #include <proton/transport.h>
@@ -91,10 +92,9 @@ static void decode_message(pn_delivery_t *dlv) {
       // decode it into a proton message
       pn_message_t *m = pn_message();
       if (PN_OK == pn_message_decode(m, buffer, len)) {
-        pn_string_t *s = pn_string(NULL);
-        pn_inspect(pn_message_body(m), s);
-        printf("%s\n", pn_string_get(s));
-        pn_free(s);
+        char *s = pn_tostring(pn_message_body(m));
+        printf("%s\n", s);
+        free(s);
       }
       pn_message_free(m);
     }
diff --git a/c/tests/object_test.cpp b/c/tests/object_test.cpp
index c5a30237e..bd9d27eeb 100644
--- a/c/tests/object_test.cpp
+++ b/c/tests/object_test.cpp
@@ -714,12 +714,11 @@ TEST_CASE("map_iteration") {
   pn_decref(pairs);
 }
 
-#define test_inspect(o, expected)                                              \
-  do {                                                                         \
-    pn_string_t *dst = pn_string(NULL);                                        \
-    pn_inspect(o, dst);                                                        \
-    CHECK_THAT(expected, Equals(pn_string_get(dst)));                          \
-    pn_free(dst);                                                              \
+#define test_inspect(o, expected)                               \
+  do {                                                          \
+    char  *dst = pn_tostring(o);                                \
+    CHECK_THAT(expected, Equals(dst));                          \
+    free(dst);                                                  \
   } while (0)
 
 TEST_CASE("list_inspect") {
diff --git a/c/tests/pn_test.cpp b/c/tests/pn_test.cpp
index 37e5199dc..03a2526d5 100644
--- a/c/tests/pn_test.cpp
+++ b/c/tests/pn_test.cpp
@@ -60,9 +60,10 @@ std::ostream &operator<<(std::ostream &o, const pn_error_t &const_err) {
 namespace pn_test {
 
 std::string inspect(void *obj) {
-  auto_free<pn_string_t, pn_string_free> s(pn_string(NULL));
-  pn_inspect(obj, s);
-  return pn_string_get(s);
+  char* s = pn_tostring(obj);
+  std::string r(s);
+  free(s);
+  return r;
 }
 
 etypes make_etypes_(int first, ...) {
diff --git a/c/tests/pn_test.hpp b/c/tests/pn_test.hpp
index 249451ba7..c3dcf0176 100644
--- a/c/tests/pn_test.hpp
+++ b/c/tests/pn_test.hpp
@@ -56,10 +56,6 @@ public:
   operator T *() const { return ptr_; } // not marking explicit for convenience
 };
 
-// pn_free() works for some, but not all pn_xxx_t* types.
-// Add typed pn_string_free() so we can be consistent and safe.
-inline void pn_string_free(pn_string_t *s) { pn_free(s); }
-
 // Call pn_inspect(), return std::string
 std::string inspect(void *);
 
diff --git a/cpp/src/object.cpp b/cpp/src/object.cpp
index 2732d5d0e..b3c82cc31 100644
--- a/cpp/src/object.cpp
+++ b/cpp/src/object.cpp
@@ -33,10 +33,9 @@ void pn_ptr_base::decref(void *p) {
 
 std::string pn_ptr_base::inspect(void* p) {
     if (!p) return std::string();
-    ::pn_string_t* s = ::pn_string(NULL);
-    (void) ::pn_inspect(p, s);
-    std::string tmp = std::string(pn_string_get(s));
-    pn_free(s);
+    char* s =  ::pn_tostring(p);
+    std::string tmp(s);
+    free(s);
     return tmp;
 }
 }}
diff --git a/cpp/src/proton_bits.cpp b/cpp/src/proton_bits.cpp
index 3e1b27f7e..517f7456d 100644
--- a/cpp/src/proton_bits.cpp
+++ b/cpp/src/proton_bits.cpp
@@ -54,10 +54,9 @@ std::string error_str(pn_error_t* err, long code) {
 }
 
 std::ostream& operator<<(std::ostream& o, const inspectable& object) {
-    pn_string_t* str = pn_string("");
-    pn_inspect(object.value, str);
-    o << pn_string_get(str);
-    pn_free(str);
+    char* str = pn_tostring(object.value);
+    o << str;
+    free(str);
     return o;
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org