diff --git a/include/re_fmt.h b/include/re_fmt.h index 540caa624..91dba08cb 100644 --- a/include/re_fmt.h +++ b/include/re_fmt.h @@ -39,6 +39,7 @@ uint64_t pl_u64(const struct pl *pl); uint64_t pl_x64(const struct pl *pl); double pl_float(const struct pl *pl); int pl_bool(bool *val, const struct pl *pl); +int pl_hex(const struct pl *pl, uint8_t *hex, size_t len); bool pl_isset(const struct pl *pl); int pl_strcpy(const struct pl *pl, char *str, size_t size); int pl_strdup(char **dst, const struct pl *src); @@ -49,6 +50,7 @@ int pl_cmp(const struct pl *pl1, const struct pl *pl2); int pl_casecmp(const struct pl *pl1, const struct pl *pl2); const char *pl_strchr(const struct pl *pl, char c); const char *pl_strrchr(const struct pl *pl, char c); +const char *pl_strstr(const struct pl *pl, const char *str); int pl_trim(struct pl *pl); int pl_ltrim(struct pl *pl); int pl_rtrim(struct pl *pl); diff --git a/src/fmt/pl.c b/src/fmt/pl.c index e1e11a7f1..32edd193b 100644 --- a/src/fmt/pl.c +++ b/src/fmt/pl.c @@ -355,6 +355,29 @@ int pl_bool(bool *val, const struct pl *pl) } +/** + * Convert an ASCII hex string as a pointer-length object to binary format + * + * @param pl Pointer-length object + * @param hex Destination binary buffer + * @param len Length of binary buffer + * + * @return 0 if success, otherwise errorcode + */ +int pl_hex(const struct pl *pl, uint8_t *hex, size_t len) +{ + if (!pl_isset(pl) || !hex || (pl->l != (2 * len))) + return EINVAL; + + for (size_t i = 0; i < pl->l; i += 2) { + hex[i/2] = ch_hex(*(pl->p + i)) << 4; + hex[i/2] += ch_hex(*(pl->p + i +1)); + } + + return 0; +} + + /** * Check if pointer-length object is set * @@ -655,6 +678,39 @@ const char *pl_strrchr(const struct pl *pl, char c) } +/** + * Locate the first substring in a pointer-length string + * + * @param pl Pointer-length string + * @param str Substring to locate + * + * @return Pointer to first char if substring is found, otherwise NULL + */ +const char *pl_strstr(const struct pl *pl, const char *str) +{ + size_t len = str_len(str); + + /*case pl not set & pl is not long enough*/ + if (!pl_isset(pl) || pl->l < len) + return NULL; + + /*case str is empty or just '\0'*/ + if (!len) + return pl->p; + + for (size_t i = 0; i < pl->l; ++i) { + /*case rest of pl is not long enough*/ + if (pl->l - i < len) + return NULL; + + if (!memcmp(pl->p + i, str, len)) + return pl->p + i; + } + + return NULL; +} + + /** * Trim white space characters at start of pointer-length string * diff --git a/test/fmt.c b/test/fmt.c index eea4e9ba7..381f412fe 100644 --- a/test/fmt.c +++ b/test/fmt.c @@ -30,6 +30,8 @@ int test_fmt_pl(void) const struct pl pl4 = PL("rattarei4"); const char str0[] = "rattarei"; const char str1[] = "rattaray"; + const char str2[] = "foo"; + const char str3[] = "bar"; struct pl pl5, pl6; const struct pl pl7 = PL("hei"); const struct pl pl7_ = PL("Hei"); @@ -116,6 +118,20 @@ int test_fmt_pl(void) if (NULL != pl_strrchr(&pl_empty, 'r')) goto out; + /* pl_strstr() */ + if (pl.p != pl_strstr(&pl, str0)) + goto out; + if (pl1.p != pl_strstr(&pl1, str2)) + goto out; + if (pl1.p + 3 != pl_strstr(&pl1, str3)) + goto out; + if (NULL != pl_strstr(&pl, str1)) + goto out; + if (pl.p != pl_strstr(&pl, "")) + goto out; + if (NULL != pl_strstr(&pl1, str0)) + goto out; + return 0; out: return EINVAL;