libsemanage: add semanage_str_replace() utility function

This function will be used in the next commit.

Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
This commit is contained in:
Nicolas Iooss 2016-12-21 19:21:02 +01:00 committed by Stephen Smalley
parent a228bb3736
commit 57a3b1b4b0
3 changed files with 99 additions and 0 deletions

View File

@ -230,6 +230,61 @@ void semanage_rtrim(char *str, char trim_to)
}
}
char *semanage_str_replace(const char *search, const char *replace,
const char *src, size_t lim)
{
size_t count = 0, slen, rlen, newsize;
char *p, *pres, *result;
const char *psrc;
slen = strlen(search);
rlen = strlen(replace);
/* Do not support empty search strings */
if (slen == 0)
return NULL;
/* Count the occurences of search in src and compute the new size */
for (p = strstr(src, search); p != NULL; p = strstr(p + slen, search)) {
count++;
if (lim && count >= lim)
break;
}
if (!count)
return strdup(src);
/* Allocate the result string */
newsize = strlen(src) + 1 + count * (rlen - slen);
result = malloc(newsize);
if (!result)
return NULL;
/* Fill the result */
psrc = src;
pres = result;
for (p = strstr(src, search); p != NULL; p = strstr(psrc, search)) {
/* Copy the part which has not been modified */
if (p != psrc) {
size_t length = (size_t)(p - psrc);
memcpy(pres, psrc, length);
pres += length;
}
/* Copy the replacement part */
if (rlen != 0) {
memcpy(pres, replace, rlen);
pres += rlen;
}
psrc = p + slen;
count--;
if (!count)
break;
}
/* Copy the last part, after doing a sanity check */
assert(pres + strlen(psrc) + 1 == result + newsize);
strcpy(pres, psrc);
return result;
}
/* list_addafter_controlmem does *NOT* duplicate the data argument
* use at your own risk, I am building a list out of malloc'd memory and
* it is only going to get stored into this list, thus when I destroy it

View File

@ -115,6 +115,16 @@ int semanage_str_count(char *data, char what);
*/
void semanage_rtrim(char *str, char trim_to);
/**
* @param value being searched for
* @param replacement value that replaces found search values
* @param string being searched and replaced on
* @param maximum number of value occurences (zero for unlimited)
* @return newly-allocated string with the replaced values
*/
char *semanage_str_replace(const char *search, const char *replace,
const char *src, size_t lim);
/**
* @param data some string
* @return modifies the string such that the first whitespace char becomes

View File

@ -40,6 +40,7 @@ void test_semanage_split(void);
void test_semanage_list(void);
void test_semanage_str_count(void);
void test_semanage_rtrim(void);
void test_semanage_str_replace(void);
void test_semanage_findval(void);
void test_slurp_file_filter(void);
@ -101,6 +102,10 @@ int semanage_utilities_add_tests(CU_pSuite suite)
if (NULL == CU_add_test(suite, "semanage_rtrim", test_semanage_rtrim)) {
goto err;
}
if (NULL == CU_add_test(suite, "semanage_str_replace",
test_semanage_str_replace)) {
goto err;
}
if (NULL == CU_add_test(suite, "semanage_findval",
test_semanage_findval)) {
goto err;
@ -257,6 +262,35 @@ void test_semanage_rtrim(void)
free(str);
}
void test_semanage_str_replace(void)
{
const char *test_str = "Hello, I am %{USERNAME} and my id is %{USERID}";
char *str1, *str2;
str1 = semanage_str_replace("%{USERNAME}", "root", test_str, 0);
CU_ASSERT_STRING_EQUAL(str1, "Hello, I am root and my id is %{USERID}");
str2 = semanage_str_replace("%{USERID}", "0", str1, 1);
CU_ASSERT_STRING_EQUAL(str2, "Hello, I am root and my id is 0");
free(str1);
free(str2);
str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 0);
CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(;)");
free(str1);
str1 = semanage_str_replace(":(", ";)", "Test :( :) ! :(:(:))(:(", 3);
CU_ASSERT_STRING_EQUAL(str1, "Test ;) :) ! ;);):))(:(");
free(str1);
str1 = semanage_str_replace("", "empty search string", "test", 0);
CU_ASSERT_EQUAL(str1, NULL);
str1 = semanage_str_replace("a", "", "abracadabra", 0);
CU_ASSERT_STRING_EQUAL(str1, "brcdbr");
free(str1);
}
void test_semanage_findval(void)
{
char *tok;