output: cache the mapped file names

Don't repeatedly call malloc/free for each call to map_file_name.

* bootstrap.conf: We need hash-map.
* src/files.h, src/files.c (map_file_name): The caller must not free
the result.
Adjust callers.
(mapped_dir_prefix, spec_mapped_header_file): Remove.
* src/files.c
(map_file_name): Rename as...
(map_file_name_alloc): this.
(mapped_files, map_file_name, string_equals, string_hash, string_free):
New.
This commit is contained in:
Akim Demaille
2021-02-25 08:31:50 +01:00
parent b96528b48c
commit f6eb1ac87b
7 changed files with 94 additions and 48 deletions

View File

@@ -26,7 +26,9 @@
#include <error.h>
#include <get-errno.h>
#include <gl_array_list.h>
#include <gl_hash_map.h>
#include <gl_xlist.h>
#include <gl_xmap.h>
#include <quote.h>
#include <quotearg.h>
#include <relocatable.h> /* relocate2 */
@@ -58,7 +60,6 @@ char *spec_graph_file = NULL; /* for -g. */
char *spec_html_file = NULL; /* for --html. */
char *spec_xml_file = NULL; /* for -x. */
char *spec_header_file = NULL; /* for --header. */
char *spec_mapped_header_file = NULL;
char *parser_file_name;
/* All computed output file names. */
@@ -95,7 +96,6 @@ uniqstr grammar_file = NULL;
char *all_but_ext;
static char *all_but_tab_ext;
char *dir_prefix;
char *mapped_dir_prefix;
/* C source file extension (the parser source). */
static char *src_extension = NULL;
@@ -109,6 +109,10 @@ struct prefix_map
};
static gl_list_t prefix_maps = NULL;
/* Map file names to prefix-mapped file names. */
static gl_map_t mapped_files = NULL;
/*-----------------------------------------------------------------.
| Return a newly allocated string composed of the concatenation of |
@@ -172,29 +176,25 @@ xfdopen (int fd, char const *mode)
return res;
}
/* Given an input file path, returns a dynamically allocated string that
contains the path with the file prefix mapping rules applied, or NULL if
the input was NULL. */
char *
map_file_name (char const *filename)
/* The mapped name of FILENAME, allocated, if there are prefix maps.
Otherwise NULL. */
static char *
map_file_name_alloc (char const *filename)
{
if (!filename)
return NULL;
struct prefix_map const *p = NULL;
if (prefix_maps)
{
void const *ptr;
gl_list_iterator_t iter = gl_list_iterator (prefix_maps);
while (gl_list_iterator_next (&iter, &ptr, NULL))
{
p = ptr;
if (strncmp (p->oldprefix, filename, strlen (p->oldprefix)) == 0)
break;
p = NULL;
}
gl_list_iterator_free (&iter);
}
assert (prefix_maps);
{
void const *ptr;
gl_list_iterator_t iter = gl_list_iterator (prefix_maps);
while (gl_list_iterator_next (&iter, &ptr, NULL))
{
p = ptr;
if (strncmp (p->oldprefix, filename, strlen (p->oldprefix)) == 0)
break;
p = NULL;
}
gl_list_iterator_free (&iter);
}
if (!p)
return xstrdup (filename);
@@ -209,6 +209,56 @@ map_file_name (char const *filename)
return res;
}
static bool
string_equals (const void *x1, const void *x2)
{
const char *s1 = x1;
const char *s2 = x2;
return STREQ (s1, s2);
}
/* A hash function for NUL-terminated char* strings using
the method described by Bruno Haible.
See https://www.haible.de/bruno/hashfunc.html. */
static size_t
string_hash (const void *x)
{
#define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
const char *s = x;
size_t h = 0;
for (; *s; s++)
h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
return h;
}
static void
string_free (const void *p)
{
free ((void*) p);
}
const char *
map_file_name (char const *filename)
{
if (!filename || !prefix_maps)
return filename;
if (!mapped_files)
mapped_files
= gl_map_nx_create_empty (GL_HASH_MAP,
string_equals, string_hash,
string_free, string_free);
const void *res = gl_map_get (mapped_files, filename);
if (!res)
{
res = map_file_name_alloc (filename);
gl_map_put (mapped_files, xstrdup (filename), res);
}
return res;
}
static void
prefix_map_free (struct prefix_map *p)
{
@@ -445,9 +495,6 @@ compute_output_file_names (void)
output_file_name_check (&spec_verbose_file, false);
}
spec_mapped_header_file = map_file_name (spec_header_file);
mapped_dir_prefix = map_file_name (dir_prefix);
free (all_but_tab_ext);
free (src_extension);
free (header_extension);
@@ -535,10 +582,8 @@ output_file_names_free (void)
free (spec_html_file);
free (spec_xml_file);
free (spec_header_file);
free (spec_mapped_header_file);
free (parser_file_name);
free (dir_prefix);
free (mapped_dir_prefix);
for (int i = 0; i < generated_files_size; i++)
free (generated_files[i].name);
free (generated_files);
@@ -546,4 +591,6 @@ output_file_names_free (void)
if (prefix_maps)
gl_list_free (prefix_maps);
if (mapped_files)
gl_map_free (mapped_files);
}