Add string functions used by security plugins to ddsrt (#334)

* String functions required by DDS Security Access Control plugin

The implementation for the DDS Security Access Control plugin
requires two additional string functions. This commit adds the
ddsrt_str_replace function (including tests) and exports the
existing function ddsrt_todigit.

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* Suppress strcpy warnings in Windows builds for ddsrt_str_replace

Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>

* Minor nitpicks on ddsrt_str_replace

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Dennis Potman 2019-12-04 10:22:40 +01:00 committed by eboasson
parent e2afccf4a0
commit 37c64e0965
5 changed files with 97 additions and 1 deletions

View file

@ -176,6 +176,25 @@ ddsrt_strerror_r(
char *buf, char *buf,
size_t buflen); size_t buflen);
/**
* @brief Replace substring of null terminated string
*
* @param[in] str pointer to string
* @param[in] srch non-empty string to replace
* @param[in] subst string to substitute character "srch" with
* @param[in] max maximum number of times to replace search, or 0 for unlimited
*
* @returns Pointer to newly allocated string with max occurrences of srch replaced, or
* NULL on allocation failure or if srch is an empty string.
*/
DDS_EXPORT char *
ddsrt_str_replace(
const char *str,
const char *srch,
const char *subst,
size_t max)
ddsrt_nonnull_all;
#if defined (__cplusplus) #if defined (__cplusplus)
} }
#endif #endif

View file

@ -21,6 +21,19 @@
extern "C" { extern "C" {
#endif #endif
/**
* @brief Convert a character to an integer value
*
* Translates the numeric value of the provided character. For characters in range
* '0' to '9' the returned integer value is 0-9. For the range 'a' to 'z' and 'A'
* to 'Z', the numeric return value is 10-36.
*
* @param[in] chr The character
*
* @returns The integer value for the character, or -1 in case @chr cannot be translated to a numeric value
*/
DDS_EXPORT int32_t ddsrt_todigit(const int chr);
/** /**
* @brief Convert a string to a long long integer. * @brief Convert a string to a long long integer.
* *

View file

@ -15,7 +15,9 @@
#include <string.h> #include <string.h>
#include "dds/ddsrt/heap.h" #include "dds/ddsrt/heap.h"
#include "dds/ddsrt/misc.h"
#include "dds/ddsrt/string.h" #include "dds/ddsrt/string.h"
#include "dds/ddsrt/types.h"
int int
ddsrt_strcasecmp( ddsrt_strcasecmp(
@ -162,3 +164,41 @@ ddsrt_strdup(
return ddsrt_memdup(str, strlen(str) + 1); return ddsrt_memdup(str, strlen(str) + 1);
} }
char *
ddsrt_str_replace(
const char *str,
const char *srch,
const char *subst,
size_t max)
{
const size_t lsrch = strlen(srch);
if (lsrch == 0) /* empty search string is treated as failure */
return NULL;
const size_t lsubst = strlen(subst);
const size_t lstr = strlen(str);
const char *cur = str;
char *res;
size_t cnt;
if (max == 0)
max = SIZE_MAX;
for (cnt = 0; (cur = strstr(cur, srch)) != NULL && cnt < max; cnt++)
cur += lsrch;
if ((res = ddsrt_malloc(lstr + cnt * (lsubst - lsrch) + 1)) == NULL)
return NULL;
char *tmp = res;
cur = str;
while (cnt--)
{
const char *found = strstr(cur, srch);
const size_t skip = (size_t)(found - cur);
memcpy(tmp, cur, skip);
memcpy(tmp + skip, subst, lsubst);
tmp += skip + lsubst;
cur += skip + lsrch;
}
memcpy(tmp, cur, lstr - (size_t) (cur - str) + 1);
return res;
}

View file

@ -16,7 +16,7 @@
#include "dds/ddsrt/strtol.h" #include "dds/ddsrt/strtol.h"
static int ddsrt_todigit(const int chr) int32_t ddsrt_todigit(const int chr)
{ {
if (chr >= '0' && chr <= '9') { if (chr >= '0' && chr <= '9') {
return chr - '0'; return chr - '0';

View file

@ -12,6 +12,7 @@
#include <string.h> #include <string.h>
#include "CUnit/Theory.h" #include "CUnit/Theory.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/string.h" #include "dds/ddsrt/string.h"
typedef enum { eq, lt, gt } eq_t; typedef enum { eq, lt, gt } eq_t;
@ -67,3 +68,26 @@ CU_Theory((const char *s1, const char *s2, size_t n, eq_t e), ddsrt_strncasecmp,
CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0)); CU_ASSERT((e == eq && r == 0) || (e == lt && r < 0) || (e == gt && r > 0));
} }
CU_TheoryDataPoints(ddsrt_str_replace, basic) = {
CU_DataPoints(const char *, "", "a", "aaa", "aaa", "aaa", "aaa", "a", "aa", "acaca", "aacaacaa", "aaa"),
CU_DataPoints(const char *, "a", "", "a", "a", "a", "aa", "aaa", "a", "a", "aa", "a"),
CU_DataPoints(const char *, "b", "b", "b", "bb", "bb", "b", "b", "b", "bb", "b", ""),
CU_DataPoints(size_t, 0, 0, 0, 1, 2, 0, 0, 10, 0, 2, 0),
CU_DataPoints(const char *, "", NULL, "bbb", "bbaa", "bbbba", "ba", "a", "bb", "bbcbbcbb", "bcbcaa", ""),
};
CU_Theory((const char *str, const char *srch, const char *subst, size_t max, const char * exp), ddsrt_str_replace, basic)
{
char * r = ddsrt_str_replace(str, srch, subst, max);
if (exp != NULL)
{
CU_ASSERT_FATAL(r != NULL);
CU_ASSERT(strcmp(r, exp) == 0);
ddsrt_free(r);
}
else
{
CU_ASSERT_FATAL(r == NULL);
}
}