1 /* uniqstr.c -- implementation of unique strings used for shortage
2 memory footprint by lot of strings.
4 Copyright (C) 2022 Sergey Sushilin <sergeysushilin@protonmail.com>
6 This file is part of Build.
8 Build is free software: you can redistribute it and/or
9 modify it under the terms of either the GNU General Public License
10 as published by the Free Software Foundation;
11 either version 2 of the License, or version 3 of the License,
12 or both in parallel, as here.
14 Build is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received copies of the GNU General Public License
20 version 2 and 3 along with this program.
21 If not, see http://www.gnu.org/licenses/. */
29 #include "diagnostic.h"
35 /* Use global variable to simplify API. */
36 static Hash uniqstrs_table
;
37 static struct mutex uniqstrs_table_mutex
;
40 uniqstr_new_from_buffer (char const *str
, size_t size
)
46 if (UNLIKELY (size
> UINT32_MAX
))
48 warning (_("string is too long"));
52 size32
= (uint32_t) size
;
53 mutex_acquire (&uniqstrs_table_mutex
);
54 res
= HashFind (&uniqstrs_table
, str
, size32
);
55 mutex_release (&uniqstrs_table_mutex
);
59 /* First insertion in the hash. */
60 r
= malloc (sizeof (uint32_t) + size32
+ 1);
62 if (UNLIKELY (r
== NULL
))
65 *(uint32_t *) r
= size32
;
66 r
+= sizeof (uint32_t);
67 memcpy (r
, str
, size32
);
69 mutex_acquire (&uniqstrs_table_mutex
);
71 if (UNLIKELY (HashInsert (&uniqstrs_table
, r
, size32
, r
) == NULL
))
74 mutex_release (&uniqstrs_table_mutex
);
81 warning (_("memory exhausted"));
86 uniqstr_new (const char *str
)
88 return uniqstr_new_from_buffer (str
, strlen (str
));
92 uniqstr_len (uniqstr str
)
94 return *(const uint32_t *) (str
- sizeof (uint32_t));
98 uniqstr_cmp (uniqstr str1
, uniqstr str2
)
104 uniqstr_chr (uniqstr str
, char c
)
106 return memchr (str
, c
, uniqstr_len (str
));
110 uniqstrs_table_create (void)
112 if (UNLIKELY (!mutex_create (&uniqstrs_table_mutex
)))
115 /* Can not provide uniqstr_hash() since HashFind can be called
116 with non-uniqstr pointer. */
117 HashInit (&uniqstrs_table
);
121 uniqstr_destroy (void *p
)
123 free ((char *) p
- sizeof (uint32_t));
127 uniqstrs_table_destroy (void)
129 HashClearWithDestructor (&uniqstrs_table
, uniqstr_destroy
);
130 mutex_destroy (&uniqstrs_table_mutex
);