[gexiv2/wip/fix-raw-for-iptc: 8/8] iptc: Fix return value of get_raw_ for multi-value




commit 1dd330bfe39feb8a3ac3c213101edfe8572e6728
Author: Jens Georg <mail jensge org>
Date:   Sun Jun 20 13:06:46 2021 +0200

    iptc: Fix return value of get_raw_ for multi-value
    
    This was returning a static wrapper for stack-allocated data which will
    just crash.
    
    Also, do not use ", " as a separator, but consider it to be binary data
    and use 4 times INFORMATION SEPARATOR FOUR (ASCII 0x1c) to separate
    records

 gexiv2/gexiv2-metadata-iptc.cpp | 32 ++++++++++++++++----------------
 gexiv2/gexiv2-metadata.h        |  6 ++++--
 test/gexiv2-regression.c        |  4 ++--
 3 files changed, 22 insertions(+), 20 deletions(-)
---
diff --git a/gexiv2/gexiv2-metadata-iptc.cpp b/gexiv2/gexiv2-metadata-iptc.cpp
index f2a20a0..4442c96 100644
--- a/gexiv2/gexiv2-metadata-iptc.cpp
+++ b/gexiv2/gexiv2-metadata-iptc.cpp
@@ -436,29 +436,29 @@ GBytes* gexiv2_metadata_get_iptc_tag_raw (GExiv2Metadata *self, const gchar* tag
 
                // Create return string by extracting raw value from Exiv2 and
                // adding separators (if needed).
-               std::ostringstream os;
-            long size = 0;
-            gpointer temp_str = nullptr;
-            gboolean add_separator = FALSE;
-            const gchar* SEPARATOR = ", ";
-            const int seperator_length = strlen(SEPARATOR);
+            bool add_separator = false;
+
+            // Define record separarator as 4x INFORMATION SEPARATOR FOUR
+            constexpr guint8 SEPARATOR[] = {28, 28, 28, 28};
+            constexpr int seperator_length = sizeof(SEPARATOR);
+
+            GByteArray* concatenated_raw_arrays = g_byte_array_new();
 
             for (; it != iptc_data.end(); ++it) {
-               size = it->size();
+                auto size = it->size();
                if (it->key() == tag && size > 0) {
-                       if (add_separator == TRUE) {
-                               os.write(SEPARATOR, seperator_length);
+                    if (add_separator) {
+                        g_byte_array_append(concatenated_raw_arrays, SEPARATOR, seperator_length);
                        }
-                       temp_str = g_malloc(size);
-                       it->copy(static_cast<Exiv2::byte*>(temp_str), Exiv2::invalidByteOrder);
-                               os.write(static_cast<const char*>(temp_str), size);
-                    g_free(temp_str);
-
-                    add_separator = TRUE;
+                    auto old_size = concatenated_raw_arrays->len;
+                    g_byte_array_set_size(concatenated_raw_arrays, old_size + size);
+                    it->copy(static_cast<Exiv2::byte*>(concatenated_raw_arrays->data + old_size),
+                             Exiv2::invalidByteOrder);
+                    add_separator = true;
                 }
             }
 
-            return g_bytes_new_static((os.str().c_str() ), os.str().length());
+            return g_byte_array_free_to_bytes(concatenated_raw_arrays);
         }
     } catch (Exiv2::Error& e) {
         g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
diff --git a/gexiv2/gexiv2-metadata.h b/gexiv2/gexiv2-metadata.h
index 97b943f..6ca16f0 100644
--- a/gexiv2/gexiv2-metadata.h
+++ b/gexiv2/gexiv2-metadata.h
@@ -951,7 +951,8 @@ gboolean            gexiv2_metadata_set_tag_multiple        (GExiv2Metadata *self, const 
gchar* t
  *
  * The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html";></ulink>
  *
- * Tags that support multiple values are returned as a single string, with elements separated by ", ".
+ * Tags that support multiple values may be returned as a single byte array, with records separated
+ * by 4x INFORMATION SEPARATOR FOUR (ASCII 0x1c)
  *
  * Returns: (transfer full) (allow-none): The tag's raw value as a byte array
  *
@@ -966,7 +967,8 @@ GBytes*                     gexiv2_metadata_try_get_tag_raw         (GExiv2Metadata 
*self, const gchar* t
  *
  * The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html";></ulink>
  *
- * Tags that support multiple values are returned as a single string, with elements separated by ", ".
+ * Tags that support multiple values may bereturned as a single byte array, with records separated
+ * by 4x INFORMATION SEPARATOR FOUR (ASCII 0x1c)
  *
  * Returns: (transfer full) (allow-none): The tag's raw value as a byte array
  *
diff --git a/test/gexiv2-regression.c b/test/gexiv2-regression.c
index b7d48ea..23de131 100644
--- a/test/gexiv2-regression.c
+++ b/test/gexiv2-regression.c
@@ -376,8 +376,8 @@ static void test_ggo_62(void){
 
     // == "R 1a, R 1b, R 2"
     const gchar R_OUTPUT_RAW[] = {
-        0x52, 0x20, 0x31, 0x61, 0x2c, 0x20,
-        0x52, 0x20, 0x31, 0x62, 0x2c, 0x20,
+        0x52, 0x20, 0x31, 0x61, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x52, 0x20, 0x31, 0x62, 0x1c, 0x1c, 0x1c, 0x1c,
         0x52, 0x20, 0x32
     };
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]