+
+void
+exif_content_foreach_entry (ExifContent *content,
+ ExifContentForeachEntryFunc func, void *data)
+{
+ unsigned int i;
+
+ if (!content || !func)
+ return;
+
+ for (i = 0; i < content->count; i++)
+ func (content->entries[i], data);
+}
+
+void
+exif_content_log (ExifContent *content, ExifLog *log)
+{
+ if (!content || !content->priv || !log || content->priv->log == log)
+ return;
+
+ if (content->priv->log) exif_log_unref (content->priv->log);
+ content->priv->log = log;
+ exif_log_ref (log);
+}
+
+ExifIfd
+exif_content_get_ifd (ExifContent *c)
+{
+ if (!c || !c->parent) return EXIF_IFD_COUNT;
+
+ return
+ ((c)->parent->ifd[EXIF_IFD_EXIF] == (c)) ? EXIF_IFD_EXIF :
+ ((c)->parent->ifd[EXIF_IFD_0] == (c)) ? EXIF_IFD_0 :
+ ((c)->parent->ifd[EXIF_IFD_1] == (c)) ? EXIF_IFD_1 :
+ ((c)->parent->ifd[EXIF_IFD_GPS] == (c)) ? EXIF_IFD_GPS :
+ ((c)->parent->ifd[EXIF_IFD_INTEROPERABILITY] == (c)) ? EXIF_IFD_INTEROPERABILITY :
+ EXIF_IFD_COUNT;
+}
+
+static void
+fix_func (ExifEntry *e, void *UNUSED(data))
+{
+ exif_entry_fix (e);
+}
+
+/*!
+ * Check if this entry is unknown and if so, delete it.
+ * \note Be careful calling this function in a loop. Deleting an entry from
+ * an ExifContent changes the index of subsequent entries, as well as the
+ * total size of the entries array.
+ */
+static void
+remove_not_recorded (ExifEntry *e, void *UNUSED(data))
+{
+ ExifIfd ifd = exif_entry_get_ifd(e) ;
+ ExifContent *c = e->parent;
+ ExifDataType dt = exif_data_get_data_type (c->parent);
+ ExifTag t = e->tag;
+
+ if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
+ EXIF_SUPPORT_LEVEL_NOT_RECORDED) {
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag 0x%04x is not recorded in IFD '%s' and has therefore been "
+ "removed.", t, exif_ifd_get_name (ifd));
+ exif_content_remove_entry (c, e);
+ }
+
+}
+
+void
+exif_content_fix (ExifContent *c)
+{
+ ExifIfd ifd = exif_content_get_ifd (c);
+ ExifDataType dt;
+ ExifEntry *e;
+ unsigned int i, num;
+
+ if (!c)
+ return;
+
+ dt = exif_data_get_data_type (c->parent);
+
+ /*
+ * First of all, fix all existing entries.
+ */
+ exif_content_foreach_entry (c, fix_func, NULL);
+
+ /*
+ * Go through each tag and if it's not recorded, remove it. If one
+ * is removed, exif_content_foreach_entry() will skip the next entry,
+ * so if this happens do the loop again from the beginning to ensure
+ * they're all checked. This could be avoided if we stop relying on
+ * exif_content_foreach_entry but loop intelligently here.
+ */
+ do {
+ num = c->count;
+ exif_content_foreach_entry (c, remove_not_recorded, NULL);
+ } while (num != c->count);
+
+ /*
+ * Then check for non-existing mandatory tags and create them if needed
+ */
+ num = exif_tag_table_count();
+ for (i = 0; i < num; ++i) {
+ const ExifTag t = exif_tag_table_get_tag (i);
+ if (exif_tag_get_support_level_in_ifd (t, ifd, dt) ==
+ EXIF_SUPPORT_LEVEL_MANDATORY) {
+ if (exif_content_get_entry (c, t))
+ /* This tag already exists */
+ continue;
+ exif_log (c->priv->log, EXIF_LOG_CODE_DEBUG, "exif-content",
+ "Tag '%s' is mandatory in IFD '%s' and has therefore been added.",
+ exif_tag_get_name_in_ifd (t, ifd), exif_ifd_get_name (ifd));
+ e = exif_entry_new ();
+ exif_content_add_entry (c, e);
+ exif_entry_initialize (e, t);
+ exif_entry_unref (e);
+ }
+ }
+}