[tepl] FileMetadata: start to create class



commit 8c0cd8d3be9d88b05b7383941c0ad1117abb9558
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Fri Apr 17 13:11:06 2020 +0200

    FileMetadata: start to create class

 po/POTFILES.in            |   1 +
 tepl/meson.build          |   2 +
 tepl/tepl-file-metadata.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++
 tepl/tepl-file-metadata.h |  91 +++++++++++++++++
 tepl/tepl.h               |   1 +
 5 files changed, 338 insertions(+)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 964a37d..6747813 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ tepl/tepl-file.c
 tepl/tepl-file-content.c
 tepl/tepl-file-content-loader.c
 tepl/tepl-file-loader.c
+tepl/tepl-file-metadata.c
 tepl/tepl-file-saver.c
 tepl/tepl-info-bar.c
 tepl/tepl-init.c
diff --git a/tepl/meson.build b/tepl/meson.build
index a9226e9..da9d786 100644
--- a/tepl/meson.build
+++ b/tepl/meson.build
@@ -8,6 +8,7 @@ tepl_public_headers = [
   'tepl-encoding.h',
   'tepl-file.h',
   'tepl-file-loader.h',
+  'tepl-file-metadata.h',
   'tepl-file-saver.h',
   'tepl-fold-region.h',
   'tepl-gutter-renderer-folds.h',
@@ -33,6 +34,7 @@ tepl_public_c_files = [
   'tepl-encoding.c',
   'tepl-file.c',
   'tepl-file-loader.c',
+  'tepl-file-metadata.c',
   'tepl-file-saver.c',
   'tepl-fold-region.c',
   'tepl-gutter-renderer-folds.c',
diff --git a/tepl/tepl-file-metadata.c b/tepl/tepl-file-metadata.c
new file mode 100644
index 0000000..ebf7ca0
--- /dev/null
+++ b/tepl/tepl-file-metadata.c
@@ -0,0 +1,243 @@
+/*
+ * This file is part of Tepl, a text editor library.
+ *
+ * Copyright 2020 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Tepl is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * Tepl 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tepl-file-metadata.h"
+#include "tepl-utils.h"
+
+struct _TeplFileMetadataPrivate
+{
+       /* Keys: gchar *
+        * Values: gchar *
+        * Never NULL.
+        */
+       GHashTable *hash_table;
+
+       /* Time of last access in milliseconds since January 1, 1970 UTC.
+        * Permits to remove the oldest TeplFileMetadata's from the XML file, so
+        * that the XML file doesn't grow indefinitely.
+        */
+       gint64 atime;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (TeplFileMetadata, tepl_file_metadata, G_TYPE_OBJECT)
+
+static void
+set_current_atime (TeplFileMetadata *metadata)
+{
+       metadata->priv->atime = g_get_real_time () / 1000;
+}
+
+static void
+tepl_file_metadata_finalize (GObject *object)
+{
+       TeplFileMetadata *metadata = TEPL_FILE_METADATA (object);
+
+       g_hash_table_unref (metadata->priv->hash_table);
+
+       G_OBJECT_CLASS (tepl_file_metadata_parent_class)->finalize (object);
+}
+
+static void
+tepl_file_metadata_class_init (TeplFileMetadataClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = tepl_file_metadata_finalize;
+}
+
+static void
+tepl_file_metadata_init (TeplFileMetadata *metadata)
+{
+       metadata->priv = tepl_file_metadata_get_instance_private (metadata);
+
+       metadata->priv->hash_table = g_hash_table_new_full (g_str_hash,
+                                                           g_str_equal,
+                                                           g_free,
+                                                           g_free);
+}
+
+TeplFileMetadata *
+tepl_file_metadata_new (void)
+{
+       return g_object_new (TEPL_TYPE_FILE_METADATA, NULL);
+}
+
+gchar *
+tepl_file_metadata_get (TeplFileMetadata *metadata,
+                       const gchar      *key)
+{
+       g_return_val_if_fail (TEPL_IS_FILE_METADATA (metadata), NULL);
+       g_return_val_if_fail (tepl_utils_metadata_key_is_valid (key), NULL);
+
+       set_current_atime (metadata);
+
+       return g_strdup (g_hash_table_lookup (metadata->priv->hash_table, key));
+}
+
+void
+tepl_file_metadata_set (TeplFileMetadata *metadata,
+                       const gchar      *key,
+                       const gchar      *value)
+{
+       g_return_if_fail (TEPL_IS_FILE_METADATA (metadata));
+       g_return_if_fail (tepl_utils_metadata_key_is_valid (key));
+       g_return_if_fail (value == NULL || g_utf8_validate (value, -1, NULL));
+
+       set_current_atime (metadata);
+
+       if (value == NULL)
+       {
+               g_hash_table_remove (metadata->priv->hash_table, key);
+       }
+       else
+       {
+               _tepl_file_metadata_insert_entry (metadata, key, value);
+       }
+}
+
+/* Returns: TRUE on success. */
+gboolean
+_tepl_file_metadata_set_atime_str (TeplFileMetadata *metadata,
+                                  const gchar      *atime_str)
+{
+       g_return_val_if_fail (TEPL_IS_FILE_METADATA (metadata), FALSE);
+       g_return_val_if_fail (atime_str != NULL, FALSE);
+
+       return g_ascii_string_to_signed (atime_str,
+                                        10,
+                                        0, G_MAXINT64,
+                                        &metadata->priv->atime,
+                                        NULL);
+}
+
+/* See GCompareFunc. */
+gint
+_tepl_file_metadata_compare_atime (TeplFileMetadata *metadata1,
+                                  TeplFileMetadata *metadata2)
+{
+       g_return_val_if_fail (TEPL_IS_FILE_METADATA (metadata1), 0);
+       g_return_val_if_fail (TEPL_IS_FILE_METADATA (metadata2), 0);
+
+       if (metadata1->priv->atime < metadata2->priv->atime)
+       {
+               return -1;
+       }
+       else if (metadata1->priv->atime > metadata2->priv->atime)
+       {
+               return 1;
+       }
+
+       return 0;
+}
+
+void
+_tepl_file_metadata_insert_entry (TeplFileMetadata *metadata,
+                                 const gchar      *key,
+                                 const gchar      *value)
+{
+       g_return_if_fail (TEPL_IS_FILE_METADATA (metadata));
+       g_return_if_fail (tepl_utils_metadata_key_is_valid (key));
+       g_return_if_fail (g_utf8_validate (value, -1, NULL));
+
+       g_hash_table_replace (metadata->priv->hash_table,
+                             g_strdup (key),
+                             g_strdup (value));
+}
+
+void
+_tepl_file_metadata_copy_into (TeplFileMetadata *src_metadata,
+                              TeplFileMetadata *dest_metadata)
+{
+       GHashTableIter iter;
+       gpointer key_p;
+       gpointer value_p;
+
+       g_return_if_fail (TEPL_IS_FILE_METADATA (src_metadata));
+       g_return_if_fail (TEPL_IS_FILE_METADATA (dest_metadata));
+
+       g_hash_table_iter_init (&iter, src_metadata->priv->hash_table);
+       while (g_hash_table_iter_next (&iter, &key_p, &value_p))
+       {
+               const gchar *key = key_p;
+               const gchar *value = value_p;
+
+               _tepl_file_metadata_insert_entry (dest_metadata, key, value);
+       }
+}
+
+static void
+append_entries_to_string (TeplFileMetadata *metadata,
+                         GString          *string)
+{
+       GHashTableIter iter;
+       gpointer key_p;
+       gpointer value_p;
+
+       g_hash_table_iter_init (&iter, metadata->priv->hash_table);
+       while (g_hash_table_iter_next (&iter, &key_p, &value_p))
+       {
+               const gchar *key = key_p;
+               const gchar *value = value_p;
+               gchar *value_escaped;
+
+               /* No need to escape the key. */
+
+               value_escaped = g_markup_escape_text (value, -1);
+
+               g_string_append_printf (string,
+                                       "  <entry key=\"%s\" value=\"%s\"/>\n",
+                                       key,
+                                       value_escaped);
+
+               g_free (value_escaped);
+       }
+}
+
+void
+_tepl_file_metadata_append_xml_to_string (TeplFileMetadata *metadata,
+                                         GFile            *location,
+                                         GString          *string)
+{
+       gchar *uri;
+       gchar *uri_escaped;
+
+       g_return_if_fail (TEPL_IS_FILE_METADATA (metadata));
+       g_return_if_fail (G_IS_FILE (location));
+       g_return_if_fail (string != NULL);
+
+       if (g_hash_table_size (metadata->priv->hash_table) == 0)
+       {
+               return;
+       }
+
+       uri = g_file_get_uri (location);
+       uri_escaped = g_markup_escape_text (uri, -1);
+
+       g_string_append_printf (string,
+                               " <document uri=\"%s\" atime=\"%" G_GINT64_FORMAT "\">\n",
+                               uri_escaped,
+                               metadata->priv->atime);
+
+       append_entries_to_string (metadata, string);
+
+       g_string_append (string, " </document>\n");
+
+       g_free (uri);
+       g_free (uri_escaped);
+}
diff --git a/tepl/tepl-file-metadata.h b/tepl/tepl-file-metadata.h
new file mode 100644
index 0000000..2896a91
--- /dev/null
+++ b/tepl/tepl-file-metadata.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of Tepl, a text editor library.
+ *
+ * Copyright 2020 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * Tepl is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * Tepl 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TEPL_FILE_METADATA_H
+#define TEPL_FILE_METADATA_H
+
+#if !defined (TEPL_H_INSIDE) && !defined (TEPL_COMPILATION)
+#error "Only <tepl/tepl.h> can be included directly."
+#endif
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define TEPL_TYPE_FILE_METADATA             (tepl_file_metadata_get_type ())
+#define TEPL_FILE_METADATA(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEPL_TYPE_FILE_METADATA, 
TeplFileMetadata))
+#define TEPL_FILE_METADATA_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), TEPL_TYPE_FILE_METADATA, 
TeplFileMetadataClass))
+#define TEPL_IS_FILE_METADATA(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEPL_TYPE_FILE_METADATA))
+#define TEPL_IS_FILE_METADATA_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), TEPL_TYPE_FILE_METADATA))
+#define TEPL_FILE_METADATA_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), TEPL_TYPE_FILE_METADATA, 
TeplFileMetadataClass))
+
+typedef struct _TeplFileMetadata         TeplFileMetadata;
+typedef struct _TeplFileMetadataClass    TeplFileMetadataClass;
+typedef struct _TeplFileMetadataPrivate  TeplFileMetadataPrivate;
+
+struct _TeplFileMetadata
+{
+       GObject parent;
+
+       TeplFileMetadataPrivate *priv;
+};
+
+struct _TeplFileMetadataClass
+{
+       GObjectClass parent_class;
+
+       gpointer padding[12];
+};
+
+GType                  tepl_file_metadata_get_type                     (void);
+
+TeplFileMetadata *     tepl_file_metadata_new                          (void);
+
+gchar *                        tepl_file_metadata_get                          (TeplFileMetadata *metadata,
+                                                                        const gchar      *key);
+
+void                   tepl_file_metadata_set                          (TeplFileMetadata *metadata,
+                                                                        const gchar      *key,
+                                                                        const gchar      *value);
+
+G_GNUC_INTERNAL
+gboolean               _tepl_file_metadata_set_atime_str               (TeplFileMetadata *metadata,
+                                                                        const gchar      *atime_str);
+
+G_GNUC_INTERNAL
+gint                   _tepl_file_metadata_compare_atime               (TeplFileMetadata *metadata1,
+                                                                        TeplFileMetadata *metadata2);
+
+G_GNUC_INTERNAL
+void                   _tepl_file_metadata_insert_entry                (TeplFileMetadata *metadata,
+                                                                        const gchar      *key,
+                                                                        const gchar      *value);
+
+G_GNUC_INTERNAL
+void                   _tepl_file_metadata_copy_into                   (TeplFileMetadata *src_metadata,
+                                                                        TeplFileMetadata *dest_metadata);
+
+G_GNUC_INTERNAL
+void                   _tepl_file_metadata_append_xml_to_string        (TeplFileMetadata *metadata,
+                                                                        GFile            *location,
+                                                                        GString          *string);
+
+G_END_DECLS
+
+#endif /* TEPL_FILE_METADATA_H */
diff --git a/tepl/tepl.h b/tepl/tepl.h
index 1c15fbd..2ccad32 100644
--- a/tepl/tepl.h
+++ b/tepl/tepl.h
@@ -34,6 +34,7 @@
 #include <tepl/tepl-encoding.h>
 #include <tepl/tepl-file.h>
 #include <tepl/tepl-file-loader.h>
+#include <tepl/tepl-file-metadata.h>
 #include <tepl/tepl-file-saver.h>
 #include <tepl/tepl-fold-region.h>
 #include <tepl/tepl-gutter-renderer-folds.h>


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