[sysprof: 50/63] libsysprof-capture: Rewrite list_files() to avoid GHashTable/GPtrArray
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof: 50/63] libsysprof-capture: Rewrite list_files() to avoid GHashTable/GPtrArray
- Date: Sat, 4 Jul 2020 18:33:33 +0000 (UTC)
commit 75b69d0a896bfd75da33681a7061e03563518c1e
Author: Philip Withnall <withnall endlessm com>
Date: Thu Jul 2 12:38:32 2020 +0100
libsysprof-capture: Rewrite list_files() to avoid GHashTable/GPtrArray
This changes its API and ABI: it now returns an allocated array of const
strings, rather than an allocated array of allocated strings.
The call sites in the source tree have been adjusted accordingly.
Signed-off-by: Philip Withnall <withnall endlessm com>
Helps: #40
src/libsysprof-capture/sysprof-capture-reader.c | 82 ++++++++++++++++++++-----
src/libsysprof-capture/sysprof-capture-reader.h | 2 +-
src/tests/test-capture.c | 2 +-
src/tools/sysprof-dump.c | 4 +-
4 files changed, 71 insertions(+), 19 deletions(-)
---
diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c
index 12b3f87..1166ae5 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.c
+++ b/src/libsysprof-capture/sysprof-capture-reader.c
@@ -62,6 +62,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -1273,20 +1274,60 @@ sysprof_capture_reader_read_file (SysprofCaptureReader *self)
return file_chunk;
}
-char **
+static bool
+array_append (const char ***files,
+ size_t *n_files,
+ size_t *n_files_allocated,
+ const char *new_element)
+{
+ if (*n_files == *n_files_allocated)
+ {
+ const char **new_files;
+
+ *n_files_allocated = (*n_files_allocated > 0) ? 2 * *n_files_allocated : 4;
+ new_files = reallocarray (*files, *n_files_allocated, sizeof (**files));
+ if (new_files == NULL)
+ return false;
+ *files = new_files;
+ }
+
+ (*files)[*n_files] = new_element;
+ *n_files = *n_files + 1;
+ assert (*n_files <= *n_files_allocated);
+
+ return true;
+}
+
+static void
+array_deduplicate (const char **files,
+ size_t *n_files)
+{
+ size_t last_written, next_to_read;
+
+ if (*n_files == 0)
+ return;
+
+ for (last_written = 0, next_to_read = 1; last_written <= next_to_read && next_to_read < *n_files;)
+ {
+ if (strcmp (files[next_to_read], files[last_written]) == 0)
+ next_to_read++;
+ else
+ files[++last_written] = files[next_to_read++];
+ }
+
+ assert (last_written + 1 <= *n_files);
+ *n_files = last_written + 1;
+}
+
+const char **
sysprof_capture_reader_list_files (SysprofCaptureReader *self)
{
- g_autoptr(GHashTable) files = NULL;
- g_autoptr(GPtrArray) ar = NULL;
+ const char **files = NULL;
+ size_t n_files = 0, n_files_allocated = 0;
SysprofCaptureFrameType type;
- GHashTableIter iter;
- const gchar *key;
assert (self != NULL);
- ar = g_ptr_array_new_with_free_func (g_free);
- files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
while (sysprof_capture_reader_peek_type (self, &type))
{
const SysprofCaptureFileChunk *file;
@@ -1300,16 +1341,27 @@ sysprof_capture_reader_list_files (SysprofCaptureReader *self)
if (!(file = sysprof_capture_reader_read_file (self)))
break;
- if (!g_hash_table_contains (files, file->path))
- g_hash_table_insert (files, g_strdup (file->path), NULL);
+ if (!array_append (&files, &n_files, &n_files_allocated, file->path))
+ {
+ free (files);
+ errno = ENOMEM;
+ return NULL;
+ }
}
- g_hash_table_iter_init (&iter, files);
- while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
- g_ptr_array_add (ar, g_strdup (key));
- g_ptr_array_add (ar, NULL);
+ /* Sort and deduplicate the files array. */
+ qsort (files, n_files, sizeof (*files), (int (*)(const void *, const void *)) strcmp);
+ array_deduplicate (files, &n_files);
+
+ /* Add a null terminator */
+ if (!array_append (&files, &n_files, &n_files_allocated, NULL))
+ {
+ free (files);
+ errno = ENOMEM;
+ return NULL;
+ }
- return (char **)g_ptr_array_free (sysprof_steal_pointer (&ar), FALSE);
+ return sysprof_steal_pointer (&files);
}
bool
diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h
index c417f9b..0fffa6a 100644
--- a/src/libsysprof-capture/sysprof-capture-reader.h
+++ b/src/libsysprof-capture/sysprof-capture-reader.h
@@ -144,7 +144,7 @@ SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureFileChunk *sysprof_capture_reader_find_file (SysprofCaptureReader
*self,
const char
*path);
SYSPROF_AVAILABLE_IN_ALL
-char **sysprof_capture_reader_list_files (SysprofCaptureReader
*self);
+const char **sysprof_capture_reader_list_files (SysprofCaptureReader
*self);
SYSPROF_AVAILABLE_IN_ALL
bool sysprof_capture_reader_read_file_fd (SysprofCaptureReader
*self,
const char
*path,
diff --git a/src/tests/test-capture.c b/src/tests/test-capture.c
index 895fdfc..dda2ab1 100644
--- a/src/tests/test-capture.c
+++ b/src/tests/test-capture.c
@@ -747,7 +747,7 @@ test_reader_writer_file (void)
{
g_autofree gchar *data = NULL;
GByteArray *buf = g_byte_array_new ();
- g_auto(GStrv) files = NULL;
+ g_autofree const gchar **files = NULL;
SysprofCaptureWriter *writer;
SysprofCaptureReader *reader;
SysprofCaptureFrameType type;
diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c
index 2439490..17bd3a9 100644
--- a/src/tools/sysprof-dump.c
+++ b/src/tools/sysprof-dump.c
@@ -64,9 +64,9 @@ main (gint argc,
if (list_files)
{
- g_auto(GStrv) files = sysprof_capture_reader_list_files (reader);
+ g_autofree const gchar **files = sysprof_capture_reader_list_files (reader);
- for (guint i = 0; files[i]; i++)
+ for (gsize i = 0; files[i]; i++)
g_print ("%s\n", files[i]);
return EXIT_SUCCESS;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]