[gexiv2] Fix get/set Iptc Repeatable tags
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gexiv2] Fix get/set Iptc Repeatable tags
- Date: Sun, 20 Jun 2021 10:08:22 +0000 (UTC)
commit 8398396cf42bbcce44f0ca4bd08306e1353808c8
Author: postscript-dev <43813-postscript-dev users noreply gitlab gnome org>
Date: Sat Mar 20 23:28:43 2021 +0000
Fix get/set Iptc Repeatable tags
Iptc allows repeatable (multiple value) and non-repeatable (single
value) tags. Repeatable tags are not stored as a single group but as
separate elements, each with the same tag name. This arrangement
caused the problems found in issue #62.
Fix closes #62, changes the public interface to provide get/set access in a
similar way to Xmp array tags.
Changes:
+ Fix the get/set string/multiple/raw versions of the functions
+ Modernize code (e.g. nullptr for NULL)
+ Add Regression test
+ Update the public documentation
gexiv2/gexiv2-metadata-iptc.cpp | 250 +++++++++++++++++++++++++++++++---------
gexiv2/gexiv2-metadata.h | 34 +++++-
test/gexiv2-regression.c | 136 ++++++++++++++++++++++
3 files changed, 359 insertions(+), 61 deletions(-)
---
diff --git a/gexiv2/gexiv2-metadata-iptc.cpp b/gexiv2/gexiv2-metadata-iptc.cpp
index afeec29..356fd7c 100644
--- a/gexiv2/gexiv2-metadata-iptc.cpp
+++ b/gexiv2/gexiv2-metadata-iptc.cpp
@@ -101,64 +101,136 @@ gchar** gexiv2_metadata_get_iptc_tags(GExiv2Metadata* self) {
}
gchar* gexiv2_metadata_get_iptc_tag_string (GExiv2Metadata *self, const gchar* tag, GError **error) {
- g_return_val_if_fail(GEXIV2_IS_METADATA (self), NULL);
- g_return_val_if_fail(tag != NULL, NULL);
- g_return_val_if_fail(self->priv->image.get() != NULL, NULL);
+ g_return_val_if_fail(GEXIV2_IS_METADATA (self), nullptr);
+ g_return_val_if_fail(tag != nullptr, nullptr);
+ g_return_val_if_fail(self->priv != nullptr, nullptr);
+ g_return_val_if_fail(self->priv->image.get() != nullptr, nullptr);
g_return_val_if_fail(error == nullptr || *error == nullptr, FALSE);
- Exiv2::IptcData& iptc_data = self->priv->image->iptcData();
-
try {
- Exiv2::IptcData::iterator it = iptc_data.findKey(Exiv2::IptcKey(tag));
+ const auto& iptc_data = self->priv->image->iptcData();
+ const Exiv2::IptcKey key(tag);
+ auto it = iptc_data.findKey(key);
+
while (it != iptc_data.end() && it->count() == 0)
it++;
-
- if (it != iptc_data.end())
- return g_strdup (it->toString ().c_str ());
+
+ if (it != iptc_data.end()) {
+ std::ostringstream os;
+
+ // Iptc allows Repeatable tags (multi-value) and Non-Repeatable tags
+ // (single value). Repeatable tags are not grouped together, but exist as
+ // separate entries with the same tag name.
+ if (!Exiv2::IptcDataSets::dataSetRepeatable(key.tag(), key.record())) {
+ return g_strdup (it->toString ().c_str ());
+ }
+ const gchar* SEPARATOR = ", ";
+ gboolean add_separator = FALSE;
+
+ for (; it != iptc_data.end(); ++it) {
+ if (it->key() == tag) {
+ if (add_separator == TRUE) {
+ os << SEPARATOR;
+ }
+ os << it->toString();
+ add_separator = TRUE;
+ }
+ }
+ return g_strdup (os.str().c_str());
+ }
} catch (Exiv2::Error& e) {
g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
}
- return NULL;
+ return nullptr;
}
gchar* gexiv2_metadata_get_iptc_tag_interpreted_string (GExiv2Metadata *self, const gchar* tag, GError
**error) {
- g_return_val_if_fail(GEXIV2_IS_METADATA (self), NULL);
- g_return_val_if_fail(tag != NULL, NULL);
- g_return_val_if_fail(self->priv->image.get() != NULL, NULL);
+ g_return_val_if_fail(GEXIV2_IS_METADATA (self), nullptr);
+ g_return_val_if_fail(tag != nullptr, nullptr);
+ g_return_val_if_fail(self->priv != nullptr, nullptr);
+ g_return_val_if_fail(self->priv->image.get() != nullptr, nullptr);
g_return_val_if_fail(error == nullptr || *error == nullptr, FALSE);
- Exiv2::IptcData& iptc_data = self->priv->image->iptcData();
-
try {
- Exiv2::IptcData::iterator it = iptc_data.findKey(Exiv2::IptcKey(tag));
+ const auto& iptc_data = self->priv->image->iptcData();
+ const Exiv2::IptcKey key(tag);
+ auto it = iptc_data.findKey(key);
+
while (it != iptc_data.end() && it->count() == 0)
it++;
-
+
if (it != iptc_data.end()) {
- std::ostringstream os;
- it->write (os);
-
- return g_strdup (os.str ().c_str ());
+ std::ostringstream os;
+
+ // Iptc allows Repeatable tags (multi-value) and Non-Repeatable tags
+ // (single value). Repeatable tags are not grouped together, but exist as
+ // separate entries with the same tag name.
+ if (!Exiv2::IptcDataSets::dataSetRepeatable(key.tag(), key.record())) {
+ it->write (os);
+ return g_strdup (os.str().c_str());
+ }
+ const gchar* SEPARATOR = ", ";
+ gboolean add_separator = FALSE;
+
+ for (; it != iptc_data.end(); ++it) {
+ if (it->key() == tag) {
+ if (add_separator == TRUE) {
+ os << SEPARATOR;
+ }
+ it->write(os);
+ add_separator = TRUE;
+ }
+ }
+ return g_strdup (os.str().c_str());
}
} catch (Exiv2::Error& e) {
g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
}
- return NULL;
+ return nullptr;
}
gboolean gexiv2_metadata_set_iptc_tag_string (GExiv2Metadata *self, const gchar* tag,
const gchar* value, GError **error) {
g_return_val_if_fail (GEXIV2_IS_METADATA (self), FALSE);
- g_return_val_if_fail(tag != NULL, FALSE);
- g_return_val_if_fail(value != NULL, FALSE);
- g_return_val_if_fail(self->priv->image.get() != NULL, FALSE);
+ g_return_val_if_fail(tag != nullptr, FALSE);
+ g_return_val_if_fail(value != nullptr, FALSE);
+ g_return_val_if_fail(self->priv != nullptr, FALSE);
+ g_return_val_if_fail(self->priv->image.get() != nullptr, FALSE);
g_return_val_if_fail(error == nullptr || *error == nullptr, FALSE);
try {
- self->priv->image->iptcData()[tag] = value;
-
+ const Exiv2::IptcKey key(tag);
+ auto& iptc_data = self->priv->image->iptcData();
+
+ // Iptc allows Repeatable tags (multi-value) and Non-Repeatable tags
+ // (single value). Repeatable tags are not grouped together, but exist as
+ // separate entries with the same tag name.
+ if (!Exiv2::IptcDataSets::dataSetRepeatable(key.tag(), key.record())) {
+ iptc_data[tag] = value;
+ return TRUE;
+ }
+
+ // Repeatable values can be any type
+ GError** error = nullptr;
+ const gchar* type = gexiv2_metadata_get_iptc_tag_type(tag, error);
+
+ if (error != nullptr && *error != nullptr) {
+ g_set_error_literal (error, g_quark_from_string ("GExiv2"), (*error)->code, (*error)->message);
+ return FALSE;
+ }
+
+ if (type == nullptr)
+ throw Exiv2::Error(Exiv2::ErrorCode::kerInvalidKey, tag);
+
+ auto v = Exiv2::Value::create(Exiv2::TypeInfo::typeId(static_cast<const std::string>(type)));
+
+
+
+ if (v->read(static_cast<const std::string>(value)) != 0 || iptc_data.add(key,v.get()) != 0)
+ return FALSE;
+
return TRUE;
} catch (Exiv2::Error& e) {
g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
@@ -209,17 +281,22 @@ gchar** gexiv2_metadata_get_iptc_tag_multiple (GExiv2Metadata *self, const gchar
gboolean gexiv2_metadata_set_iptc_tag_multiple (GExiv2Metadata *self, const gchar* tag,
const gchar** values, GError **error) {
g_return_val_if_fail (GEXIV2_IS_METADATA (self), FALSE);
- g_return_val_if_fail(tag != NULL, FALSE);
- g_return_val_if_fail(values != NULL, FALSE);
- g_return_val_if_fail(self->priv->image.get() != NULL, FALSE);
+ g_return_val_if_fail(tag != nullptr, FALSE);
+ g_return_val_if_fail(values != nullptr, FALSE);
+ g_return_val_if_fail(self->priv != nullptr, FALSE);
+ g_return_val_if_fail(self->priv->image.get() != nullptr, FALSE);
g_return_val_if_fail(error == nullptr || *error == nullptr, FALSE);
-
- Exiv2::IptcData& iptc_data = self->priv->image->iptcData();
-
+
try {
+ auto& iptc_data = self->priv->image->iptcData();
+
+ // Iptc allows Repeatable tags (multi-value) and Non-Repeatable tags
+ // (single value). Repeatable tags are not grouped together, but exist as
+ // separate entries with the same tag name.
+
/* first clear all existing ... */
- Exiv2::IptcKey iptc_key(tag);
- Exiv2::IptcData::iterator iptc_it = iptc_data.begin();
+ const Exiv2::IptcKey iptc_key(tag);
+ auto iptc_it = iptc_data.begin();
while (iptc_it != iptc_data.end()) {
if (iptc_it->count() > 0 && iptc_key.key () == iptc_it->key ())
iptc_it = iptc_data.erase (iptc_it);
@@ -227,17 +304,43 @@ gboolean gexiv2_metadata_set_iptc_tag_multiple (GExiv2Metadata *self, const gcha
++iptc_it;
}
- /* ... and then set the others */
- auto iptc_value = Exiv2::Value::create(Exiv2::string);
-
- const gchar **it = values;
- while (*it != NULL) {
- iptc_value->read (static_cast<const std::string>(*it));
- iptc_data.add (iptc_key, iptc_value.get());
-
- ++it;
+ if (!Exiv2::IptcDataSets::dataSetRepeatable(iptc_key.tag(), iptc_key.record())) {
+ // Skip to last value and assign
+ const gchar** val_it = values;
+ while (*val_it != nullptr) {
+ val_it++;
+ }
+
+ --val_it;
+ iptc_data[tag] = static_cast<const std::string>(*val_it);
+
+ return TRUE;
}
-
+
+ // Repeatable values can be any type
+ GError** error = nullptr;
+ const gchar* type = gexiv2_metadata_get_iptc_tag_type(tag, error);
+
+ if (error != nullptr && *error != nullptr) {
+ g_set_error_literal (error, g_quark_from_string ("GExiv2"), (*error)->code, (*error)->message);
+ return FALSE;
+ }
+
+ if (type == nullptr)
+ throw Exiv2::Error(Exiv2::ErrorCode::kerInvalidKey, tag);
+
+ auto v = Exiv2::Value::create(Exiv2::TypeInfo::typeId(static_cast<const std::string>(type)));
+
+ // Add each value separately
+ const gchar** val_it = values;
+ while (*val_it != nullptr) {
+
+ if (v->read(static_cast<const std::string>(*val_it)) != 0 || iptc_data.add(iptc_key,v.get()) !=
0) {
+ return FALSE;
+ }
+ val_it++;
+ }
+
return TRUE;
} catch (Exiv2::Error& e) {
g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
@@ -303,31 +406,64 @@ gboolean gexiv2_metadata_iptc_tag_supports_multiple_values(const gchar* tag, GEr
}
GBytes* gexiv2_metadata_get_iptc_tag_raw (GExiv2Metadata *self, const gchar* tag, GError **error) {
- g_return_val_if_fail(GEXIV2_IS_METADATA (self), NULL);
- g_return_val_if_fail(tag != NULL, NULL);
- g_return_val_if_fail(self->priv->image.get() != NULL, NULL);
+ g_return_val_if_fail(GEXIV2_IS_METADATA (self), nullptr);
+ g_return_val_if_fail(tag != nullptr, nullptr);
+ g_return_val_if_fail(self->priv != nullptr, nullptr);
+ g_return_val_if_fail(self->priv->image.get() != nullptr, nullptr);
g_return_val_if_fail(error == nullptr || *error == nullptr, FALSE);
- Exiv2::IptcData& iptc_data = self->priv->image->iptcData();
-
try {
- Exiv2::IptcData::iterator it = iptc_data.findKey(Exiv2::IptcKey(tag));
+ const auto& iptc_data = self->priv->image->iptcData();
+ const Exiv2::IptcKey key(tag);
+ auto it = iptc_data.findKey(key);
+
while (it != iptc_data.end() && it->count() == 0)
it++;
if (it != iptc_data.end()) {
- long size = it->size();
- if( size > 0 ) {
- gpointer data = g_malloc(size);
- it->copy((Exiv2::byte*)data, Exiv2::invalidByteOrder);
- return g_bytes_new_take(data, size);
+ // Iptc allows Repeatable tags (multi-value) and Non-Repeatable tags
+ // (single value). Repeatable tags are not grouped together, but exist as
+ // separate entries with the same tag name.
+ if (!Exiv2::IptcDataSets::dataSetRepeatable(key.tag(), key.record())) {
+ long size = it->size();
+ if( size > 0 ) {
+ gpointer data = g_malloc(size);
+ it->copy(static_cast<Exiv2::byte*>(data), Exiv2::invalidByteOrder);
+ return g_bytes_new_take(data, size);
+ }
+ }
+
+ // 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);
+
+ for (; it != iptc_data.end(); ++it) {
+ size = it->size();
+ if (it->key() == tag && size > 0) {
+ if (add_separator == TRUE) {
+ os.write(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;
+ }
}
+
+ return g_bytes_new_static((os.str().c_str() ), os.str().length());
}
} catch (Exiv2::Error& e) {
g_set_error_literal (error, g_quark_from_string ("GExiv2"), e.code (), e.what ());
}
- return NULL;
+ return nullptr;
}
G_END_DECLS
diff --git a/gexiv2/gexiv2-metadata.h b/gexiv2/gexiv2-metadata.h
index 47e56f4..c8b225e 100644
--- a/gexiv2/gexiv2-metadata.h
+++ b/gexiv2/gexiv2-metadata.h
@@ -625,6 +625,8 @@ gint gexiv2_metadata_get_pixel_height (GExiv2Metadata
*self);
*
* 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 ", ".
+ *
* Returns: (transfer full) (allow-none): The tag's value as a string
*
* Since: 0.12.2
@@ -638,6 +640,9 @@ gchar* gexiv2_metadata_try_get_tag_string (GExiv2Metadata
*self, const gchar*
* @value: The value to set or replace the existing value
* @error: (allow-none): A return location for a #GError or %NULL
*
+ * If a tag supports multiple values, then @value is added to any existing values. For single
+ * tags, @value replaces the value.
+ *
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
* Returns: TRUE on success
@@ -653,6 +658,8 @@ gboolean gexiv2_metadata_try_set_tag_string (GExiv2Metadata *self, const
gchar*
*
* 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 ", ".
+ *
* In case of error, a GLib warning will be logged. Use instead
* gexiv2_metadata_try_get_tag_string() if you want to avoid this and
* control if and how the error is outputted.
@@ -672,6 +679,9 @@ gchar* gexiv2_metadata_get_tag_string (GExiv2Metadata
*self, const gchar* tag
*
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
+ * If a tag supports multiple values, then @value is added to any existing values. For single
+ * value tags, @value replaces the value.
+ *
* In case of error, a GLib warning will be logged. Use instead
* gexiv2_metadata_try_set_tag_string() if you want to avoid this and
* control if and how the error is outputted.
@@ -722,6 +732,8 @@ gboolean gexiv2_metadata_set_xmp_tag_struct (GExiv2Metadata *self, const gchar*
* An interpreted string is one fit for user display. It may display units or use formatting
* appropriate to the type of data the tag holds.
*
+ * Tags that support multiple values are returned as a single string, with elements separated by ", ".
+ *
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
* Returns: (transfer full) (allow-none): The tag's interpreted value as a string
@@ -738,6 +750,8 @@ gchar* gexiv2_metadata_try_get_tag_interpreted_string
(GExiv2Metadata *self, c
* An interpreted string is one fit for user display. It may display units or use formatting
* appropriate to the type of data the tag holds.
*
+ * Tags that support multiple values are returned as a single string, with elements separated by ", ".
+ *
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
* Returns: (transfer full) (allow-none): The tag's interpreted value as a string
@@ -814,8 +828,8 @@ gboolean gexiv2_metadata_set_tag_long (GExiv2Metadata *self, const
gchar* tag,
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
* Returns: (transfer full) (allow-none) (array zero-terminated=1): The multiple string values of
- * the tag. Returns NULL if parameters are NULL or @tag does not begin with recognised type of
- * metadata ("Exif.", "Xmp." or "Iptc."). For a well formed @tag, returns array[0] = NULL if @tag
+ * @tag. Returns %NULL if parameters are %NULL or @tag does not begin with recognised type of
+ * metadata ("Exif.", "Xmp." or "Iptc."). For a well formed @tag, returns array[0] = %NULL if @tag
* is undefined or is not set in the current metadata.
*
* Since: 0.12.2
@@ -831,6 +845,10 @@ gchar** gexiv2_metadata_try_get_tag_multiple (GExiv2Metadata
*self, const gcha
*
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
+ * All previous @tag values are erased. For multiple value tags, each of the non %NULL
+ * entries in @values is stored. For single value tags, only the last non %NULL value
+ * is assigned.
+ *
* Returns: Boolean success value
*
* Since: 0.12.2
@@ -849,8 +867,8 @@ gboolean gexiv2_metadata_try_set_tag_multiple (GExiv2Metadata *self, const
gcha
* control if and how the error is outputted.
*
* Returns: (transfer full) (allow-none) (array zero-terminated=1): The multiple string values of
- * the tag. Returns NULL if parameters are NULL or @tag does not begin with recognised type of
- * metadata ("Exif.", "Xmp." or "Iptc."). For a well formed @tag, returns array[0] = NULL if @tag
+ * the tag. Returns %NULL if parameters are %NULL or @tag does not begin with recognised type of
+ * metadata ("Exif.", "Xmp." or "Iptc."). For a well formed @tag, returns array[0] = %NULL if @tag
* is undefined or is not set in the current metadata.
* (Note: <ulink url="https://gitlab.gnome.org/GNOME/gexiv2/-/issues/61">xmpText/langAlt bug</ulink>
* is fixed in gexiv2_metadata_try_get_tag_multiple())
@@ -868,6 +886,10 @@ gchar** gexiv2_metadata_get_tag_multiple (GExiv2Metadata
*self, const gchar* t
*
* The Exiv2 Tag Reference can be found at <ulink url="http://exiv2.org/metadata.html"></ulink>
*
+ * All previous @tag values are erased. For multiple value tags, each of the non %NULL
+ * entries in @values is stored. For single value tags, only the last non %NULL value
+ * is assigned.
+ *
* In case of error, a GLib warning will be logged. Use instead
* gexiv2_metadata_try_set_tag_multiple() if you want to avoid this and
* control if and how the error is outputted.
@@ -887,6 +909,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 ", ".
+ *
* Returns: (transfer full) (allow-none): The tag's raw value as a byte array
*
* Since: 0.12.2
@@ -900,6 +924,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 ", ".
+ *
* Returns: (transfer full) (allow-none): The tag's raw value as a byte array
*
* Deprecated: 0.12.2: Use gexiv2_metadata_try_get_tag_raw() instead.
diff --git a/test/gexiv2-regression.c b/test/gexiv2-regression.c
index 2cd0599..c9d779f 100644
--- a/test/gexiv2-regression.c
+++ b/test/gexiv2-regression.c
@@ -327,6 +327,141 @@ static void test_ggo_58(void) {
g_clear_object(&meta);
}
+/* Regression test for https://gitlab.gnome.org/GNOME/gexiv2/issues/62 */
+static void test_ggo_62(void){
+ GExiv2Metadata* meta = NULL;
+ gboolean result = FALSE;
+ gchar* value = NULL;
+ gchar** values = NULL;
+ GBytes *raw_value = NULL;
+ GError* error = NULL;
+ const gchar* IPTC_REPEATABLE_TAG = "Iptc.Application2.Keywords";
+ const gchar* IPTC_NON_REPEATABLE_TAG = "Iptc.Application2.Category";
+
+ // Output tags
+ const gchar* NR_OUTPUT_SINGLE = "NR 2";
+ const gchar* NR_OUTPUT_MULTIPLE[] = {
+ "NR 2",
+ NULL
+ };
+
+ // == "NR 2"
+ const gchar NR_OUTPUT_RAW[] = {
+ 0x4e, 0x52, 0x20, 0x32
+ };
+
+ const gchar* R_OUTPUT_SINGLE = "R 1a, R 1b, R 2";
+ const gchar* R_OUTPUT_MULTIPLE[] = {
+ "R 1a",
+ "R 1b",
+ "R 2",
+ NULL
+ };
+
+ // == "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, 0x32
+ };
+
+
+ //// Setup
+ meta = gexiv2_metadata_new();
+ g_assert_nonnull(meta);
+
+ result = gexiv2_metadata_open_path(meta, SAMPLE_PATH "/no-metadata.jpg", &error);
+ g_assert_no_error(error);
+ g_assert_true(result);
+
+
+ //// Test setting/getting Non-Repeatable Iptc tag
+ // Setting
+ values = g_new(gchar*, 3);
+ values[0] = g_strdup("NR 1a");
+ values[1] = g_strdup("NR 1b");
+ values[2] = NULL;
+ result = gexiv2_metadata_try_set_tag_multiple(meta, IPTC_NON_REPEATABLE_TAG, (const gchar**)values,
&error);
+ g_assert_no_error(error);
+ g_assert_true(result);
+ g_strfreev (values);
+
+ result = gexiv2_metadata_try_set_tag_string(meta, IPTC_NON_REPEATABLE_TAG, "NR 2", &error);
+ g_assert_no_error(error);
+ g_assert_true(result);
+
+ // Getting
+ value = gexiv2_metadata_try_get_tag_string(meta, IPTC_NON_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(value);
+ g_assert_cmpstr(value, ==, NR_OUTPUT_SINGLE);
+ g_free (value);
+
+ value = gexiv2_metadata_try_get_tag_interpreted_string(meta, IPTC_NON_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(value);
+ g_assert_cmpstr(value, ==, NR_OUTPUT_SINGLE);
+ g_free (value);
+
+ values = gexiv2_metadata_try_get_tag_multiple(meta, IPTC_NON_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(values);
+ g_assert_true (g_strv_equal ((const gchar**)values, NR_OUTPUT_MULTIPLE));
+ g_assert_null(values[1]);
+ g_strfreev (values);
+
+ raw_value = gexiv2_metadata_try_get_tag_raw(meta, IPTC_NON_REPEATABLE_TAG, &error);
+ g_assert_nonnull (raw_value);
+ g_assert_cmpmem (g_bytes_get_data(raw_value, NULL), g_bytes_get_size(raw_value),
+ NR_OUTPUT_RAW, sizeof(NR_OUTPUT_RAW));
+ g_clear_pointer (&raw_value, g_bytes_unref);
+
+
+ //// Test setting/getting Repeatable Iptc tag
+ // Setting
+ values = g_new(gchar*, 3);
+ values[0] = g_strdup("R 1a");
+ values[1] = g_strdup("R 1b");
+ values[2] = NULL;
+ result = gexiv2_metadata_try_set_tag_multiple(meta, IPTC_REPEATABLE_TAG, (const gchar**)values, &error);
+ g_assert_no_error(error);
+ g_assert_true(result);
+ g_strfreev (values);
+
+ result = gexiv2_metadata_try_set_tag_string(meta, IPTC_REPEATABLE_TAG, "R 2", &error);
+ g_assert_no_error(error);
+ g_assert_true(result);
+
+ // Getting
+ value = gexiv2_metadata_try_get_tag_string(meta, IPTC_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(value);
+ g_assert_cmpstr(value, ==, R_OUTPUT_SINGLE);
+ g_free (value);
+
+ value = gexiv2_metadata_try_get_tag_interpreted_string(meta, IPTC_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(value);
+ g_assert_cmpstr(value, ==, R_OUTPUT_SINGLE);
+ g_free (value);
+
+ values = gexiv2_metadata_try_get_tag_multiple(meta, IPTC_REPEATABLE_TAG, &error);
+ g_assert_no_error(error);
+ g_assert_nonnull(values);
+ g_assert_true (g_strv_equal ((const gchar**)values, R_OUTPUT_MULTIPLE));
+ g_strfreev (values);
+
+ raw_value = gexiv2_metadata_try_get_tag_raw(meta, IPTC_REPEATABLE_TAG, &error);
+ g_assert_nonnull (raw_value);
+ g_assert_cmpmem (g_bytes_get_data(raw_value, NULL), g_bytes_get_size(raw_value),
+ R_OUTPUT_RAW, sizeof(R_OUTPUT_RAW));
+ g_clear_pointer (&raw_value, g_bytes_unref);
+
+
+ //// Cleanup
+ g_clear_object(&meta);
+}
+
int main(int argc, char *argv[static argc + 1])
{
g_test_init(&argc, &argv, NULL);
@@ -341,6 +476,7 @@ int main(int argc, char *argv[static argc + 1])
g_test_add_func("/bugs/gnome/gitlab/xx", test_ggo_xx);
g_test_add_func("/bugs/gnome/gitlab/45", test_ggo_45);
g_test_add_func("/bugs/gnome/gitlab/58", test_ggo_58);
+ g_test_add_func("/bugs/gnome/gitlab/62", test_ggo_62);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]