summaryrefslogtreecommitdiff
path: root/src/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/string.c')
-rw-r--r--src/string.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/src/string.c b/src/string.c
index c14f1b5..ae19271 100644
--- a/src/string.c
+++ b/src/string.c
@@ -27,6 +27,7 @@
* all others pass through
*/
enum HX_quote_selector {
+ HXQUOTE_ALWAYS,
HXQUOTE_ACCEPT,
HXQUOTE_REJECT,
};
@@ -211,6 +212,8 @@ EXPORT_SYMBOL char **HX_split(const char *str, const char *delim,
*cp = max;
ret = malloc(sizeof(char *) * (*cp + 1));
+ if (ret == nullptr)
+ return nullptr;
ret[*cp] = NULL;
{
@@ -378,20 +381,48 @@ EXPORT_SYMBOL char *HX_stpltrim(const char *p)
return const_cast1(char *, p);
}
+/**
+ * Helper for substr() function for dealing with negative off/len values
+ * @z: total length of string
+ * @offset: n>=0 specifies offset from the start,
+ * n<0 specifies offset from the end
+ * @len: "length"; n>=0 specifies length to copy (from @offset),
+ * n<0 specifies the byte relative to the end at which to stop
+ *
+ * @abstart: (result) absolute start
+ * @retval: (result) absolute length to copy (from *@abstart)
+ */
+size_t HX_substr_helper(size_t z, long offset, long len, size_t *start)
+{
+ if (offset >= 0)
+ *start = offset;
+ else if (offset == LONG_MIN)
+ *start = z + -static_cast(size_t, LONG_MIN);
+ else
+ *start = z >= static_cast(unsigned long, -offset) ? z + offset : z;
+
+ size_t end;
+ if (len >= 0)
+ end = *start < SIZE_MAX - len ? *start + len : SIZE_MAX;
+ else if (len == LONG_MIN)
+ end = z + -static_cast(unsigned long, LONG_MIN);
+ else
+ end = z >= static_cast(unsigned long, -len) ? z + len : 0;
+ if (end > z)
+ end = z;
+ return end > *start ? end - *start : 0;
+}
+
/* supports negative offsets like scripting languages */
EXPORT_SYMBOL char *HX_strmid(const char *expr, long offset, long length)
{
- char *buffer;
-
- if (offset < 0)
- offset = strlen(expr) + offset;
- if (length < 0)
- length = strlen(expr) - offset + length;
- if ((buffer = malloc(length + 1)) == NULL)
+ size_t start = 0, tocopy = HX_substr_helper(strlen(expr), offset, length, &start);
+ char *buffer = malloc(tocopy + 1);
+ if (buffer == nullptr)
return NULL;
-
- expr += offset;
- return HX_strlcpy(buffer, expr, length + 1);
+ memcpy(buffer, &expr[start], tocopy);
+ buffer[tocopy] = '\0';
+ return buffer;
}
EXPORT_SYMBOL char *HX_strndup(const char *src, size_t size)
@@ -773,7 +804,7 @@ static size_t HX_quoted_size(const char *s, unsigned int type)
EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type,
char **free_me)
{
- const struct HX_quote_rule *rule;
+ const struct HX_quote_rule *rule = nullptr;
bool do_quote;
char *tmp;
@@ -782,15 +813,19 @@ EXPORT_SYMBOL char *HX_strquote(const char *src, unsigned int type,
return NULL;
}
/* If quote_chars is NULL, it is clear all chars are to be encoded. */
- rule = &HX_quote_rules[type];
- if (type >= ARRAY_SIZE(HX_quote_rules) || rule->chars == NULL)
+ if (type >= ARRAY_SIZE(HX_quote_rules)) {
do_quote = true;
- else if (rule->selector == HXQUOTE_REJECT)
- do_quote = strpbrk(src, rule->chars) != NULL;
- else if (rule->selector == HXQUOTE_ACCEPT)
- do_quote = HX_strchr2(src, rule->chars) != NULL;
- else
- do_quote = false;
+ } else {
+ rule = &HX_quote_rules[type];
+ if (rule->selector == HXQUOTE_ALWAYS)
+ do_quote = true;
+ else if (rule->selector == HXQUOTE_REJECT)
+ do_quote = strpbrk(src, rule->chars) != NULL;
+ else if (rule->selector == HXQUOTE_ACCEPT)
+ do_quote = HX_strchr2(src, rule->chars) != NULL;
+ else
+ do_quote = false;
+ }
/*
* free_me == NULL implies that we always allocate, even if
* there is nothing to quote.