common: New function map_static_strings

* common/mapstrings.c (struct intmapping_s): New.
(map_static_strings): New.
* common/stringhelp.c (do_strconcat): Rename to ...
(vstrconcat): this and make global.

* common/t-mapstrings.c (test_map_static_strings): New test.
This commit is contained in:
Werner Koch 2022-03-18 13:47:10 +01:00
parent e081a601f7
commit c145366549
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 86 additions and 5 deletions

View File

@ -68,6 +68,18 @@ struct mapping_s
static struct mapping_s *mappings;
/* Similar to above but using two integers and a domain as key. */
struct intmapping_s
{
struct intmapping_s *next;
int key1;
int key2;
const char *string;
char domain[1];
};
static struct intmapping_s *intmappings;
/* If STRING has already been mapped, return the mapped string. If
not return NULL. */
static const char *
@ -165,3 +177,40 @@ map_static_macro_string (const char *string)
return store_mapping (string, p);
}
/* If a list of strings has already been mapped to a the tuple
* (DOMAIN,KEY1,KEY2) return that string. If not, create a mapping
* made up of the concatenation of the given strings. */
const char *
map_static_strings (const char *domain, int key1, int key2,
const char *string1, ...)
{
va_list arg_ptr;
struct intmapping_s *m;
if (!string1 || !domain)
return "";
for (m = intmappings; m; m = m->next)
if (m->key1 == key1 && m->key2 == key2 && !strcmp (domain, m->domain))
return m->string;
m = xmalloc (sizeof *m + strlen (domain));
strcpy (m->domain, domain);
m->key1 = key1;
m->key2 = key2;
va_start (arg_ptr, string1);
m->string = vstrconcat (string1, arg_ptr);
va_end (arg_ptr);
if (!m->string)
log_fatal ("map_static_strings failed: %s\n", strerror (errno));
gpgrt_annotate_leaked_object (m->string);
gpgrt_annotate_leaked_object (m);
m->next = intmappings;
intmappings = m;
return m->string;
}

View File

@ -1167,9 +1167,10 @@ try_percent_escape (const char *str, const char *extra)
}
static char *
do_strconcat (const char *s1, va_list arg_ptr)
/* Same as strconcat but takes a va_list. Returns EINVAL if the list
* is too long, all other errors are due to an ENOMEM condition. */
char *
vstrconcat (const char *s1, va_list arg_ptr)
{
const char *argv[48];
size_t argc;
@ -1214,7 +1215,7 @@ strconcat (const char *s1, ...)
else
{
va_start (arg_ptr, s1);
result = do_strconcat (s1, arg_ptr);
result = vstrconcat (s1, arg_ptr);
va_end (arg_ptr);
}
return result;
@ -1233,7 +1234,7 @@ xstrconcat (const char *s1, ...)
else
{
va_start (arg_ptr, s1);
result = do_strconcat (s1, arg_ptr);
result = vstrconcat (s1, arg_ptr);
va_end (arg_ptr);
}
if (!result)

View File

@ -141,9 +141,12 @@ char *try_percent_escape (const char *str, const char *extra);
NULL. Returns a malloced buffer with the new string or NULL on a
malloc error or if too many arguments are given. */
char *strconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0);
/* Same but taking a va_list. */
char *vstrconcat (const char *s1, va_list arg_ptr);
/* Ditto, but die on error. */
char *xstrconcat (const char *s1, ...) GPGRT_ATTR_SENTINEL(0);
char **strsplit (char *string, char delim, char replacement, int *count);
/* Tokenize STRING using the set of delimiters in DELIM. */
@ -172,5 +175,7 @@ char *substitute_envvars (const char *string);
/*-- mapstrings.c --*/
const char *map_static_macro_string (const char *string);
const char *map_static_strings (const char *domain, int key1, int key2,
const char *string1, ...);
#endif /*GNUPG_COMMON_STRINGHELP_H*/

View File

@ -88,6 +88,31 @@ test_map_static_macro_string (void)
}
static void
test_map_static_strings (void)
{
const char *s, *s1;
s1 = map_static_strings ("mydomain", 0, 42,
"This", " ", "is", " ", "my"," ","string", NULL);
if (strcmp (s1, "This is my string"))
fail (1);
s = map_static_strings ("mydomain", 0, 42,
"This", " ", "is", " ", "my"," ","string", NULL);
if (strcmp (s1, s))
fail (2);
s = map_static_strings ("mydomain", 0, 42, "foo", NULL);
if (strcmp (s1, s))
fail (3);
s = map_static_strings ("mydomain", 1, 42, "foo 1.42", NULL);
if (!strcmp (s1, s))
fail (4);
s = map_static_strings ("xdomain", 1, 42, "foo 1.42 other domain", NULL);
if (!strcmp (s1, s))
fail (5);
}
int
main (int argc, char **argv)
{
@ -95,6 +120,7 @@ main (int argc, char **argv)
(void)argv;
test_map_static_macro_string ();
test_map_static_strings ();
return 0;
}