/*
Copyright (C) 2010 ABRT Team
Copyright (C) 2010 RedHat inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "internal_libreport.h"
map_string_t *new_map_string(void)
{
return g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
}
void free_map_string(map_string_t *ms)
{
if (ms)
g_hash_table_destroy(ms);
}
map_string_t *clone_map_string(map_string_t *ms)
{
if (ms == NULL)
return NULL;
map_string_t *clone = new_map_string();
const char *key;
const char *value;
map_string_iter_t iter;
init_map_string_iter(&iter, ms);
while(next_map_string_iter(&iter, &key, &value))
insert_map_string(clone, xstrdup(key), xstrdup(value));
return clone;
}
const char *get_map_string_item_or_empty(map_string_t *ms, const char *key)
{
const char *v = (const char*)g_hash_table_lookup(ms, key);
if (!v) v = "";
return v;
}
string_vector_ptr_t string_vector_new_from_string(const char *value)
{
return g_strsplit(value == NULL ? "" : value, ", ", /*all tokens*/0);
}
void string_vector_free(string_vector_ptr_t vector)
{
g_strfreev(vector);
}
void set_map_string_item_from_bool(map_string_t *ms, const char *key, int value)
{
const char *const raw_value = value ? "yes" : "no";
set_map_string_item_from_string(ms, key, raw_value);
}
#define GET_ITEM_OR_RETURN(val_name, conf, item_name)\
const char *const val_name = get_map_string_item_or_NULL(conf, item_name); \
if (val_name == NULL) \
{ \
log_warning("Option '%s' is not configured", item_name); \
return 0; \
}
int try_get_map_string_item_as_bool(map_string_t *ms, const char *key, int *value)
{
GET_ITEM_OR_RETURN(option, ms, key);
*value = string_to_bool(option);
return true;
}
void set_map_string_item_from_int(map_string_t *ms, const char *key, int value)
{
char raw_value[sizeof(int)*3 + 1];
snprintf(raw_value, sizeof(raw_value), "%d", value);
set_map_string_item_from_string(ms, key, raw_value);
}
int try_get_map_string_item_as_int(map_string_t *ms, const char *key, int *value)
{
GET_ITEM_OR_RETURN(option, ms, key);
char *endptr = NULL;
errno = 0;
long raw_value = strtol(option, &endptr, 10);
/* Check for various possible errors */
if (raw_value > INT_MAX || raw_value < INT_MIN || errno == ERANGE)
{
log_warning("Value of option '%s' is out of integer range", key);
return 0;
}
if ((errno != 0 && raw_value == 0)
|| (endptr == option) /* empty */
|| (endptr[0] != '\0') /* trailing non-digits */)
{
log_warning("Value of option '%s' is not an integer", key);
return 0;
}
*value = (int)raw_value;
return 1;
}
void set_map_string_item_from_uint(map_string_t *ms, const char *key, unsigned int value)
{
char raw_value[sizeof(int)*3 + 1];
snprintf(raw_value, sizeof(raw_value), "%u", value);
set_map_string_item_from_string(ms, key, raw_value);
}
int try_get_map_string_item_as_uint(map_string_t *ms, const char *key, unsigned int *value)
{
GET_ITEM_OR_RETURN(option, ms, key);
char *endptr = NULL;
/* Check just negative number, positive ranges will be tested later */
errno = 0;
long raw_signed_value = strtol(option, &endptr, 10);
if (raw_signed_value < 0)
{
log_warning("Value of option '%s' is out of unsigned integer range (bellow zero)", key);
return 0;
}
unsigned long raw_value;
if (raw_signed_value < INT_MAX)
{ // no need to convert it again, this is already between 0 and maximal value of strtol()
raw_value = raw_signed_value;
}
else
{
errno = 0;
raw_value = strtoul(option, &endptr, 10);
/* Check range */
if (raw_value > UINT_MAX || errno == ERANGE)
{
log_warning("Value of option '%s' is out of unsigned integer range", key);
return 0;
}
}
/* Check for other possible errors */
if ((errno != 0 && raw_value == 0)
|| (endptr == option) /* empty */
|| (endptr[0] != '\0') /* trailing non-digits */)
{
log_warning("Value of option '%s' is not an unsigned integer", key);
return 0;
}
*value = (unsigned int)raw_value;
return 1;
}
void set_map_string_item_from_string(map_string_t *ms, const char *key, const char *value)
{
replace_map_string_item(ms, xstrdup(key), xstrdup(value));
}
int try_get_map_string_item_as_string(map_string_t *ms, const char *key, char **value)
{
GET_ITEM_OR_RETURN(option, ms, key);
char *dup = strdup(option);
if (dup == NULL)
{
log_warning("Insufficient memory for value of option '%s'", key);
return 0;
}
*value = dup;
return 1;
}
void set_map_string_item_from_string_vector(map_string_t *ms, const char *key, string_vector_ptr_t value)
{
if (value == NULL)
{
set_map_string_item_from_string(ms, key, "");
return;
}
gchar *opt_val = g_strjoinv(", ", (gchar **)value);
set_map_string_item_from_string(ms, key, opt_val);
g_free(opt_val);
}
int try_get_map_string_item_as_string_vector(map_string_t *ms, const char *key, string_vector_ptr_t *value)
{
GET_ITEM_OR_RETURN(option, ms, key);
*value = string_vector_new_from_string(option);
return 1;
}