Improve string util API
Use prefixed names and improve documentation.
This commit is contained in:
parent
9a0bd545d5
commit
979ce64dc0
12 changed files with 169 additions and 134 deletions
|
@ -190,11 +190,11 @@ adb_push(const char *serial, const char *local, const char *remote) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the paths must be quoted
|
// Windows will parse the string, so the paths must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
local = strquote(local);
|
local = sc_str_quote(local);
|
||||||
if (!local) {
|
if (!local) {
|
||||||
return SC_PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
remote = strquote(remote);
|
remote = sc_str_quote(remote);
|
||||||
if (!remote) {
|
if (!remote) {
|
||||||
free((void *) local);
|
free((void *) local);
|
||||||
return SC_PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
|
@ -217,7 +217,7 @@ adb_install(const char *serial, const char *local) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
// Windows will parse the string, so the local name must be quoted
|
// Windows will parse the string, so the local name must be quoted
|
||||||
// (see sys/win/command.c)
|
// (see sys/win/command.c)
|
||||||
local = strquote(local);
|
local = sc_str_quote(local);
|
||||||
if (!local) {
|
if (!local) {
|
||||||
return SC_PROCESS_NONE;
|
return SC_PROCESS_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -779,9 +779,9 @@ parse_integer_arg(const char *s, long *out, bool accept_suffix, long min,
|
||||||
long value;
|
long value;
|
||||||
bool ok;
|
bool ok;
|
||||||
if (accept_suffix) {
|
if (accept_suffix) {
|
||||||
ok = parse_integer_with_suffix(s, &value);
|
ok = sc_str_parse_integer_with_suffix(s, &value);
|
||||||
} else {
|
} else {
|
||||||
ok = parse_integer(s, &value);
|
ok = sc_str_parse_integer(s, &value);
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOGE("Could not parse %s: %s", name, s);
|
LOGE("Could not parse %s: %s", name, s);
|
||||||
|
@ -801,7 +801,7 @@ parse_integer_arg(const char *s, long *out, bool accept_suffix, long min,
|
||||||
static size_t
|
static size_t
|
||||||
parse_integers_arg(const char *s, size_t max_items, long *out, long min,
|
parse_integers_arg(const char *s, size_t max_items, long *out, long min,
|
||||||
long max, const char *name) {
|
long max, const char *name) {
|
||||||
size_t count = parse_integers(s, ':', max_items, out);
|
size_t count = sc_str_parse_integers(s, ':', max_items, out);
|
||||||
if (!count) {
|
if (!count) {
|
||||||
LOGE("Could not parse %s: %s", name, s);
|
LOGE("Could not parse %s: %s", name, s);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -66,7 +66,7 @@ write_position(uint8_t *buf, const struct sc_position *position) {
|
||||||
// write length (2 bytes) + string (non nul-terminated)
|
// write length (2 bytes) + string (non nul-terminated)
|
||||||
static size_t
|
static size_t
|
||||||
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
write_string(const char *utf8, size_t max_len, unsigned char *buf) {
|
||||||
size_t len = utf8_truncation_index(utf8, max_len);
|
size_t len = sc_str_utf8_truncation_index(utf8, max_len);
|
||||||
buffer_write32be(buf, len);
|
buffer_write32be(buf, len);
|
||||||
memcpy(&buf[4], utf8, len);
|
memcpy(&buf[4], utf8, len);
|
||||||
return 4 + len;
|
return 4 + len;
|
||||||
|
|
|
@ -26,7 +26,7 @@ get_icon_path(void) {
|
||||||
if (icon_path_env) {
|
if (icon_path_env) {
|
||||||
// if the envvar is set, use it
|
// if the envvar is set, use it
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
char *icon_path = utf8_from_wide_char(icon_path_env);
|
char *icon_path = sc_str_from_wchars(icon_path_env);
|
||||||
#else
|
#else
|
||||||
char *icon_path = strdup(icon_path_env);
|
char *icon_path = strdup(icon_path_env);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,7 @@ find_muxer(const char *name) {
|
||||||
oformat = av_oformat_next(oformat);
|
oformat = av_oformat_next(oformat);
|
||||||
#endif
|
#endif
|
||||||
// until null or containing the requested name
|
// until null or containing the requested name
|
||||||
} while (oformat && !strlist_contains(oformat->name, ',', name));
|
} while (oformat && !sc_str_list_contains(oformat->name, ',', name));
|
||||||
return oformat;
|
return oformat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ get_server_path(void) {
|
||||||
if (server_path_env) {
|
if (server_path_env) {
|
||||||
// if the envvar is set, use it
|
// if the envvar is set, use it
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
char *server_path = utf8_from_wide_char(server_path_env);
|
char *server_path = sc_str_from_wchars(server_path_env);
|
||||||
#else
|
#else
|
||||||
char *server_path = strdup(server_path_env);
|
char *server_path = strdup(server_path_env);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,12 +19,12 @@ sc_file_get_executable_path(void) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
return utf8_from_wide_char(buf);
|
return sc_str_from_wchars(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sc_file_is_regular(const char *path) {
|
sc_file_is_regular(const char *path) {
|
||||||
wchar_t *wide_path = utf8_to_wide_char(path);
|
wchar_t *wide_path = sc_str_to_wchars(path);
|
||||||
if (!wide_path) {
|
if (!wide_path) {
|
||||||
LOGC("Could not allocate wide char string");
|
LOGC("Could not allocate wide char string");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,7 +13,7 @@ build_cmd(char *cmd, size_t len, const char *const argv[]) {
|
||||||
// <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
|
// <http://daviddeley.com/autohotkey/parameters/parameters.htm#WINPASS>
|
||||||
// only make it work for this very specific program
|
// only make it work for this very specific program
|
||||||
// (don't handle escaping nor quotes)
|
// (don't handle escaping nor quotes)
|
||||||
size_t ret = xstrjoin(cmd, argv, ' ', len);
|
size_t ret = sc_str_join(cmd, argv, ' ', len);
|
||||||
if (ret >= len) {
|
if (ret >= len) {
|
||||||
LOGE("Command too long (%" SC_PRIsizet " chars)", len - 1);
|
LOGE("Command too long (%" SC_PRIsizet " chars)", len - 1);
|
||||||
return false;
|
return false;
|
||||||
|
@ -88,7 +88,7 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle,
|
||||||
goto error_close_stderr;
|
goto error_close_stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *wide = utf8_to_wide_char(cmd);
|
wchar_t *wide = sc_str_to_wchars(cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
if (!wide) {
|
if (!wide) {
|
||||||
LOGC("Could not allocate wide char string");
|
LOGC("Could not allocate wide char string");
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
xstrncpy(char *dest, const char *src, size_t n) {
|
sc_strncpy(char *dest, const char *src, size_t n) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < n - 1 && src[i] != '\0'; ++i)
|
for (i = 0; i < n - 1 && src[i] != '\0'; ++i)
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
|
@ -23,7 +23,7 @@ xstrncpy(char *dest, const char *src, size_t n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
xstrjoin(char *dst, const char *const tokens[], char sep, size_t n) {
|
sc_str_join(char *dst, const char *const tokens[], char sep, size_t n) {
|
||||||
const char *const *remaining = tokens;
|
const char *const *remaining = tokens;
|
||||||
const char *token = *remaining++;
|
const char *token = *remaining++;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -33,7 +33,7 @@ xstrjoin(char *dst, const char *const tokens[], char sep, size_t n) {
|
||||||
if (i == n)
|
if (i == n)
|
||||||
goto truncated;
|
goto truncated;
|
||||||
}
|
}
|
||||||
size_t w = xstrncpy(dst + i, token, n - i);
|
size_t w = sc_strncpy(dst + i, token, n - i);
|
||||||
if (w >= n - i)
|
if (w >= n - i)
|
||||||
goto truncated;
|
goto truncated;
|
||||||
i += w;
|
i += w;
|
||||||
|
@ -47,7 +47,7 @@ truncated:
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
strquote(const char *src) {
|
sc_str_quote(const char *src) {
|
||||||
size_t len = strlen(src);
|
size_t len = strlen(src);
|
||||||
char *quoted = malloc(len + 3);
|
char *quoted = malloc(len + 3);
|
||||||
if (!quoted) {
|
if (!quoted) {
|
||||||
|
@ -61,7 +61,7 @@ strquote(const char *src) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_integer(const char *s, long *out) {
|
sc_str_parse_integer(const char *s, long *out) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
if (*s == '\0') {
|
if (*s == '\0') {
|
||||||
return false;
|
return false;
|
||||||
|
@ -80,7 +80,8 @@ parse_integer(const char *s, long *out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
parse_integers(const char *s, const char sep, size_t max_items, long *out) {
|
sc_str_parse_integers(const char *s, const char sep, size_t max_items,
|
||||||
|
long *out) {
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
do {
|
do {
|
||||||
|
@ -109,7 +110,7 @@ parse_integers(const char *s, const char sep, size_t max_items, long *out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_integer_with_suffix(const char *s, long *out) {
|
sc_str_parse_integer_with_suffix(const char *s, long *out) {
|
||||||
char *endptr;
|
char *endptr;
|
||||||
if (*s == '\0') {
|
if (*s == '\0') {
|
||||||
return false;
|
return false;
|
||||||
|
@ -143,7 +144,7 @@ parse_integer_with_suffix(const char *s, long *out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
strlist_contains(const char *list, char sep, const char *s) {
|
sc_str_list_contains(const char *list, char sep, const char *s) {
|
||||||
char *p;
|
char *p;
|
||||||
do {
|
do {
|
||||||
p = strchr(list, sep);
|
p = strchr(list, sep);
|
||||||
|
@ -161,7 +162,7 @@ strlist_contains(const char *list, char sep, const char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
utf8_truncation_index(const char *utf8, size_t max_len) {
|
sc_str_utf8_truncation_index(const char *utf8, size_t max_len) {
|
||||||
size_t len = strlen(utf8);
|
size_t len = strlen(utf8);
|
||||||
if (len <= max_len) {
|
if (len <= max_len) {
|
||||||
return len;
|
return len;
|
||||||
|
@ -179,7 +180,7 @@ utf8_truncation_index(const char *utf8, size_t max_len) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
wchar_t *
|
wchar_t *
|
||||||
utf8_to_wide_char(const char *utf8) {
|
sc_str_to_wchars(const char *utf8) {
|
||||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||||
if (!len) {
|
if (!len) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -195,7 +196,7 @@ utf8_to_wide_char(const char *utf8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
utf8_from_wide_char(const wchar_t *ws) {
|
sc_str_from_wchars(const wchar_t *ws) {
|
||||||
int len = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
|
int len = WideCharToMultiByte(CP_UTF8, 0, ws, -1, NULL, 0, NULL, NULL);
|
||||||
if (!len) {
|
if (!len) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -212,7 +213,8 @@ utf8_from_wide_char(const wchar_t *ws) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *sc_str_wrap_lines(const char *input, unsigned columns, unsigned indent) {
|
char *
|
||||||
|
sc_str_wrap_lines(const char *input, unsigned columns, unsigned indent) {
|
||||||
assert(indent < columns);
|
assert(indent < columns);
|
||||||
|
|
||||||
struct sc_strbuf buf;
|
struct sc_strbuf buf;
|
||||||
|
|
|
@ -1,65 +1,97 @@
|
||||||
#ifndef STRUTIL_H
|
#ifndef SC_STRUTIL_H
|
||||||
#define STRUTIL_H
|
#define SC_STRUTIL_H
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
// like strncpy, except:
|
/**
|
||||||
// - it copies at most n-1 chars
|
* Like strncpy(), except:
|
||||||
// - the dest string is nul-terminated
|
* - it copies at most n-1 chars
|
||||||
// - it does not write useless bytes if strlen(src) < n
|
* - the dest string is nul-terminated
|
||||||
// - it returns the number of chars actually written (max n-1) if src has
|
* - it does not write useless bytes if strlen(src) < n
|
||||||
// been copied completely, or n if src has been truncated
|
* - it returns the number of chars actually written (max n-1) if src has
|
||||||
|
* been copied completely, or n if src has been truncated
|
||||||
|
*/
|
||||||
size_t
|
size_t
|
||||||
xstrncpy(char *dest, const char *src, size_t n);
|
sc_strncpy(char *dest, const char *src, size_t n);
|
||||||
|
|
||||||
// join tokens by sep into dst
|
/**
|
||||||
// returns the number of chars actually written (max n-1) if no truncation
|
* Join tokens by separator `sep` into `dst`
|
||||||
// occurred, or n if truncated
|
*
|
||||||
|
* Return the number of chars actually written (max n-1) if no truncation
|
||||||
|
* occurred, or n if truncated.
|
||||||
|
*/
|
||||||
size_t
|
size_t
|
||||||
xstrjoin(char *dst, const char *const tokens[], char sep, size_t n);
|
sc_str_join(char *dst, const char *const tokens[], char sep, size_t n);
|
||||||
|
|
||||||
// quote a string
|
/**
|
||||||
// returns the new allocated string, to be freed by the caller
|
* Quote a string
|
||||||
|
*
|
||||||
|
* Return a new allocated string, surrounded with quotes (`"`).
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
strquote(const char *src);
|
sc_str_quote(const char *src);
|
||||||
|
|
||||||
// parse s as an integer into value
|
/**
|
||||||
// returns true if the conversion succeeded, false otherwise
|
* Parse `s` as an integer into `out`
|
||||||
|
*
|
||||||
|
* Return true if the conversion succeeded, false otherwise.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
parse_integer(const char *s, long *out);
|
sc_str_parse_integer(const char *s, long *out);
|
||||||
|
|
||||||
// parse s as integers separated by sep (for example '1234:2000')
|
/**
|
||||||
// returns the number of integers on success, 0 on failure
|
* Parse `s` as integers separated by `sep` (for example `1234:2000`) into `out`
|
||||||
|
*
|
||||||
|
* Returns the number of integers on success, 0 on failure.
|
||||||
|
*/
|
||||||
size_t
|
size_t
|
||||||
parse_integers(const char *s, const char sep, size_t max_items, long *out);
|
sc_str_parse_integers(const char *s, const char sep, size_t max_items,
|
||||||
|
long *out);
|
||||||
|
|
||||||
// parse s as an integer into value
|
/**
|
||||||
// like parse_integer(), but accept 'k'/'K' (x1000) and 'm'/'M' (x1000000) as
|
* Parse `s` as an integer into `out`
|
||||||
// suffix
|
*
|
||||||
// returns true if the conversion succeeded, false otherwise
|
* Like `sc_str_parse_integer()`, but accept 'k'/'K' (x1000) and 'm'/'M'
|
||||||
|
* (x1000000) as suffixes.
|
||||||
|
*
|
||||||
|
* Return true if the conversion succeeded, false otherwise.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
parse_integer_with_suffix(const char *s, long *out);
|
sc_str_parse_integer_with_suffix(const char *s, long *out);
|
||||||
|
|
||||||
// search s in the list separated by sep
|
/**
|
||||||
// for example, strlist_contains("a,bc,def", ',', "bc") returns true
|
* Search `s` in the list separated by `sep`
|
||||||
|
*
|
||||||
|
* For example, sc_str_list_contains("a,bc,def", ',', "bc") returns true.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
strlist_contains(const char *list, char sep, const char *s);
|
sc_str_list_contains(const char *list, char sep, const char *s);
|
||||||
|
|
||||||
// return the index to truncate a UTF-8 string at a valid position
|
/**
|
||||||
|
* Return the index to truncate a UTF-8 string at a valid position
|
||||||
|
*/
|
||||||
size_t
|
size_t
|
||||||
utf8_truncation_index(const char *utf8, size_t max_len);
|
sc_str_utf8_truncation_index(const char *utf8, size_t max_len);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// convert a UTF-8 string to a wchar_t string
|
/**
|
||||||
// returns the new allocated string, to be freed by the caller
|
* Convert a UTF-8 string to a wchar_t string
|
||||||
|
*
|
||||||
|
* Return the new allocated string, to be freed by the caller.
|
||||||
|
*/
|
||||||
wchar_t *
|
wchar_t *
|
||||||
utf8_to_wide_char(const char *utf8);
|
sc_str_to_wchars(const char *utf8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a wchar_t string to a UTF-8 string
|
||||||
|
*
|
||||||
|
* Return the new allocated string, to be freed by the caller.
|
||||||
|
*/
|
||||||
char *
|
char *
|
||||||
utf8_from_wide_char(const wchar_t *s);
|
sc_str_from_wchars(const wchar_t *s);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,6 +100,7 @@ utf8_from_wide_char(const wchar_t *s);
|
||||||
* Break input lines at word boundaries (spaces) so that they fit in `columns`
|
* Break input lines at word boundaries (spaces) so that they fit in `columns`
|
||||||
* columns, left-indented by `indent` spaces.
|
* columns, left-indented by `indent` spaces.
|
||||||
*/
|
*/
|
||||||
char *sc_str_wrap_lines(const char *input, unsigned columns, unsigned indent);
|
char *
|
||||||
|
sc_str_wrap_lines(const char *input, unsigned columns, unsigned indent);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,7 @@ find_muxer(const char *name) {
|
||||||
oformat = av_oformat_next(oformat);
|
oformat = av_oformat_next(oformat);
|
||||||
#endif
|
#endif
|
||||||
// until null or containing the requested name
|
// until null or containing the requested name
|
||||||
} while (oformat && !strlist_contains(oformat->name, ',', name));
|
} while (oformat && !sc_str_list_contains(oformat->name, ',', name));
|
||||||
return oformat;
|
return oformat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
#include "util/str_util.h"
|
#include "util/str_util.h"
|
||||||
|
|
||||||
static void test_xstrncpy_simple(void) {
|
static void test_strncpy_simple(void) {
|
||||||
char s[] = "xxxxxxxxxx";
|
char s[] = "xxxxxxxxxx";
|
||||||
size_t w = xstrncpy(s, "abcdef", sizeof(s));
|
size_t w = sc_strncpy(s, "abcdef", sizeof(s));
|
||||||
|
|
||||||
// returns strlen of copied string
|
// returns strlen of copied string
|
||||||
assert(w == 6);
|
assert(w == 6);
|
||||||
|
@ -24,9 +24,9 @@ static void test_xstrncpy_simple(void) {
|
||||||
assert(!strcmp("abcdef", s));
|
assert(!strcmp("abcdef", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrncpy_just_fit(void) {
|
static void test_strncpy_just_fit(void) {
|
||||||
char s[] = "xxxxxx";
|
char s[] = "xxxxxx";
|
||||||
size_t w = xstrncpy(s, "abcdef", sizeof(s));
|
size_t w = sc_strncpy(s, "abcdef", sizeof(s));
|
||||||
|
|
||||||
// returns strlen of copied string
|
// returns strlen of copied string
|
||||||
assert(w == 6);
|
assert(w == 6);
|
||||||
|
@ -38,9 +38,9 @@ static void test_xstrncpy_just_fit(void) {
|
||||||
assert(!strcmp("abcdef", s));
|
assert(!strcmp("abcdef", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrncpy_truncated(void) {
|
static void test_strncpy_truncated(void) {
|
||||||
char s[] = "xxx";
|
char s[] = "xxx";
|
||||||
size_t w = xstrncpy(s, "abcdef", sizeof(s));
|
size_t w = sc_strncpy(s, "abcdef", sizeof(s));
|
||||||
|
|
||||||
// returns 'n' (sizeof(s))
|
// returns 'n' (sizeof(s))
|
||||||
assert(w == 4);
|
assert(w == 4);
|
||||||
|
@ -52,10 +52,10 @@ static void test_xstrncpy_truncated(void) {
|
||||||
assert(!strncmp("abcdef", s, 3));
|
assert(!strncmp("abcdef", s, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrjoin_simple(void) {
|
static void test_join_simple(void) {
|
||||||
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
||||||
char s[] = "xxxxxxxxxxxxxx";
|
char s[] = "xxxxxxxxxxxxxx";
|
||||||
size_t w = xstrjoin(s, tokens, ' ', sizeof(s));
|
size_t w = sc_str_join(s, tokens, ' ', sizeof(s));
|
||||||
|
|
||||||
// returns strlen of concatenation
|
// returns strlen of concatenation
|
||||||
assert(w == 11);
|
assert(w == 11);
|
||||||
|
@ -70,10 +70,10 @@ static void test_xstrjoin_simple(void) {
|
||||||
assert(!strcmp("abc de fghi", s));
|
assert(!strcmp("abc de fghi", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrjoin_just_fit(void) {
|
static void test_join_just_fit(void) {
|
||||||
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
||||||
char s[] = "xxxxxxxxxxx";
|
char s[] = "xxxxxxxxxxx";
|
||||||
size_t w = xstrjoin(s, tokens, ' ', sizeof(s));
|
size_t w = sc_str_join(s, tokens, ' ', sizeof(s));
|
||||||
|
|
||||||
// returns strlen of concatenation
|
// returns strlen of concatenation
|
||||||
assert(w == 11);
|
assert(w == 11);
|
||||||
|
@ -85,10 +85,10 @@ static void test_xstrjoin_just_fit(void) {
|
||||||
assert(!strcmp("abc de fghi", s));
|
assert(!strcmp("abc de fghi", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrjoin_truncated_in_token(void) {
|
static void test_join_truncated_in_token(void) {
|
||||||
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
||||||
char s[] = "xxxxx";
|
char s[] = "xxxxx";
|
||||||
size_t w = xstrjoin(s, tokens, ' ', sizeof(s));
|
size_t w = sc_str_join(s, tokens, ' ', sizeof(s));
|
||||||
|
|
||||||
// returns 'n' (sizeof(s))
|
// returns 'n' (sizeof(s))
|
||||||
assert(w == 6);
|
assert(w == 6);
|
||||||
|
@ -100,10 +100,10 @@ static void test_xstrjoin_truncated_in_token(void) {
|
||||||
assert(!strcmp("abc d", s));
|
assert(!strcmp("abc d", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrjoin_truncated_before_sep(void) {
|
static void test_join_truncated_before_sep(void) {
|
||||||
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
||||||
char s[] = "xxxxxx";
|
char s[] = "xxxxxx";
|
||||||
size_t w = xstrjoin(s, tokens, ' ', sizeof(s));
|
size_t w = sc_str_join(s, tokens, ' ', sizeof(s));
|
||||||
|
|
||||||
// returns 'n' (sizeof(s))
|
// returns 'n' (sizeof(s))
|
||||||
assert(w == 7);
|
assert(w == 7);
|
||||||
|
@ -115,10 +115,10 @@ static void test_xstrjoin_truncated_before_sep(void) {
|
||||||
assert(!strcmp("abc de", s));
|
assert(!strcmp("abc de", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_xstrjoin_truncated_after_sep(void) {
|
static void test_join_truncated_after_sep(void) {
|
||||||
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
const char *const tokens[] = { "abc", "de", "fghi", NULL };
|
||||||
char s[] = "xxxxxxx";
|
char s[] = "xxxxxxx";
|
||||||
size_t w = xstrjoin(s, tokens, ' ', sizeof(s));
|
size_t w = sc_str_join(s, tokens, ' ', sizeof(s));
|
||||||
|
|
||||||
// returns 'n' (sizeof(s))
|
// returns 'n' (sizeof(s))
|
||||||
assert(w == 8);
|
assert(w == 8);
|
||||||
|
@ -130,9 +130,9 @@ static void test_xstrjoin_truncated_after_sep(void) {
|
||||||
assert(!strcmp("abc de ", s));
|
assert(!strcmp("abc de ", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_strquote(void) {
|
static void test_quote(void) {
|
||||||
const char *s = "abcde";
|
const char *s = "abcde";
|
||||||
char *out = strquote(s);
|
char *out = sc_str_quote(s);
|
||||||
|
|
||||||
// add '"' at the beginning and the end
|
// add '"' at the beginning and the end
|
||||||
assert(!strcmp("\"abcde\"", out));
|
assert(!strcmp("\"abcde\"", out));
|
||||||
|
@ -146,71 +146,71 @@ static void test_utf8_truncate(void) {
|
||||||
|
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 1);
|
count = sc_str_utf8_truncation_index(s, 1);
|
||||||
assert(count == 1);
|
assert(count == 1);
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 2);
|
count = sc_str_utf8_truncation_index(s, 2);
|
||||||
assert(count == 1); // É is 2 bytes-wide
|
assert(count == 1); // É is 2 bytes-wide
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 3);
|
count = sc_str_utf8_truncation_index(s, 3);
|
||||||
assert(count == 3);
|
assert(count == 3);
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 4);
|
count = sc_str_utf8_truncation_index(s, 4);
|
||||||
assert(count == 4);
|
assert(count == 4);
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 5);
|
count = sc_str_utf8_truncation_index(s, 5);
|
||||||
assert(count == 4); // Ô is 2 bytes-wide
|
assert(count == 4); // Ô is 2 bytes-wide
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 6);
|
count = sc_str_utf8_truncation_index(s, 6);
|
||||||
assert(count == 6);
|
assert(count == 6);
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 7);
|
count = sc_str_utf8_truncation_index(s, 7);
|
||||||
assert(count == 7);
|
assert(count == 7);
|
||||||
|
|
||||||
count = utf8_truncation_index(s, 8);
|
count = sc_str_utf8_truncation_index(s, 8);
|
||||||
assert(count == 7); // no more chars
|
assert(count == 7); // no more chars
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_parse_integer(void) {
|
static void test_parse_integer(void) {
|
||||||
long value;
|
long value;
|
||||||
bool ok = parse_integer("1234", &value);
|
bool ok = sc_str_parse_integer("1234", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == 1234);
|
assert(value == 1234);
|
||||||
|
|
||||||
ok = parse_integer("-1234", &value);
|
ok = sc_str_parse_integer("-1234", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == -1234);
|
assert(value == -1234);
|
||||||
|
|
||||||
ok = parse_integer("1234k", &value);
|
ok = sc_str_parse_integer("1234k", &value);
|
||||||
assert(!ok);
|
assert(!ok);
|
||||||
|
|
||||||
ok = parse_integer("123456789876543212345678987654321", &value);
|
ok = sc_str_parse_integer("123456789876543212345678987654321", &value);
|
||||||
assert(!ok); // out-of-range
|
assert(!ok); // out-of-range
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_parse_integers(void) {
|
static void test_parse_integers(void) {
|
||||||
long values[5];
|
long values[5];
|
||||||
|
|
||||||
size_t count = parse_integers("1234", ':', 5, values);
|
size_t count = sc_str_parse_integers("1234", ':', 5, values);
|
||||||
assert(count == 1);
|
assert(count == 1);
|
||||||
assert(values[0] == 1234);
|
assert(values[0] == 1234);
|
||||||
|
|
||||||
count = parse_integers("1234:5678", ':', 5, values);
|
count = sc_str_parse_integers("1234:5678", ':', 5, values);
|
||||||
assert(count == 2);
|
assert(count == 2);
|
||||||
assert(values[0] == 1234);
|
assert(values[0] == 1234);
|
||||||
assert(values[1] == 5678);
|
assert(values[1] == 5678);
|
||||||
|
|
||||||
count = parse_integers("1234:5678", ':', 2, values);
|
count = sc_str_parse_integers("1234:5678", ':', 2, values);
|
||||||
assert(count == 2);
|
assert(count == 2);
|
||||||
assert(values[0] == 1234);
|
assert(values[0] == 1234);
|
||||||
assert(values[1] == 5678);
|
assert(values[1] == 5678);
|
||||||
|
|
||||||
count = parse_integers("1234:-5678", ':', 2, values);
|
count = sc_str_parse_integers("1234:-5678", ':', 2, values);
|
||||||
assert(count == 2);
|
assert(count == 2);
|
||||||
assert(values[0] == 1234);
|
assert(values[0] == 1234);
|
||||||
assert(values[1] == -5678);
|
assert(values[1] == -5678);
|
||||||
|
|
||||||
count = parse_integers("1:2:3:4:5", ':', 5, values);
|
count = sc_str_parse_integers("1:2:3:4:5", ':', 5, values);
|
||||||
assert(count == 5);
|
assert(count == 5);
|
||||||
assert(values[0] == 1);
|
assert(values[0] == 1);
|
||||||
assert(values[1] == 2);
|
assert(values[1] == 2);
|
||||||
|
@ -218,85 +218,85 @@ static void test_parse_integers(void) {
|
||||||
assert(values[3] == 4);
|
assert(values[3] == 4);
|
||||||
assert(values[4] == 5);
|
assert(values[4] == 5);
|
||||||
|
|
||||||
count = parse_integers("1234:5678", ':', 1, values);
|
count = sc_str_parse_integers("1234:5678", ':', 1, values);
|
||||||
assert(count == 0); // max_items == 1
|
assert(count == 0); // max_items == 1
|
||||||
|
|
||||||
count = parse_integers("1:2:3:4:5", ':', 3, values);
|
count = sc_str_parse_integers("1:2:3:4:5", ':', 3, values);
|
||||||
assert(count == 0); // max_items == 3
|
assert(count == 0); // max_items == 3
|
||||||
|
|
||||||
count = parse_integers(":1234", ':', 5, values);
|
count = sc_str_parse_integers(":1234", ':', 5, values);
|
||||||
assert(count == 0); // invalid
|
assert(count == 0); // invalid
|
||||||
|
|
||||||
count = parse_integers("1234:", ':', 5, values);
|
count = sc_str_parse_integers("1234:", ':', 5, values);
|
||||||
assert(count == 0); // invalid
|
assert(count == 0); // invalid
|
||||||
|
|
||||||
count = parse_integers("1234:", ':', 1, values);
|
count = sc_str_parse_integers("1234:", ':', 1, values);
|
||||||
assert(count == 0); // invalid, even when max_items == 1
|
assert(count == 0); // invalid, even when max_items == 1
|
||||||
|
|
||||||
count = parse_integers("1234::5678", ':', 5, values);
|
count = sc_str_parse_integers("1234::5678", ':', 5, values);
|
||||||
assert(count == 0); // invalid
|
assert(count == 0); // invalid
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_parse_integer_with_suffix(void) {
|
static void test_parse_integer_with_suffix(void) {
|
||||||
long value;
|
long value;
|
||||||
bool ok = parse_integer_with_suffix("1234", &value);
|
bool ok = sc_str_parse_integer_with_suffix("1234", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == 1234);
|
assert(value == 1234);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("-1234", &value);
|
ok = sc_str_parse_integer_with_suffix("-1234", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == -1234);
|
assert(value == -1234);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("1234k", &value);
|
ok = sc_str_parse_integer_with_suffix("1234k", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == 1234000);
|
assert(value == 1234000);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("1234m", &value);
|
ok = sc_str_parse_integer_with_suffix("1234m", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == 1234000000);
|
assert(value == 1234000000);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("-1234k", &value);
|
ok = sc_str_parse_integer_with_suffix("-1234k", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == -1234000);
|
assert(value == -1234000);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("-1234m", &value);
|
ok = sc_str_parse_integer_with_suffix("-1234m", &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == -1234000000);
|
assert(value == -1234000000);
|
||||||
|
|
||||||
ok = parse_integer_with_suffix("123456789876543212345678987654321", &value);
|
ok = sc_str_parse_integer_with_suffix("123456789876543212345678987654321", &value);
|
||||||
assert(!ok); // out-of-range
|
assert(!ok); // out-of-range
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
sprintf(buf, "%ldk", LONG_MAX / 2000);
|
sprintf(buf, "%ldk", LONG_MAX / 2000);
|
||||||
ok = parse_integer_with_suffix(buf, &value);
|
ok = sc_str_parse_integer_with_suffix(buf, &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == LONG_MAX / 2000 * 1000);
|
assert(value == LONG_MAX / 2000 * 1000);
|
||||||
|
|
||||||
sprintf(buf, "%ldm", LONG_MAX / 2000);
|
sprintf(buf, "%ldm", LONG_MAX / 2000);
|
||||||
ok = parse_integer_with_suffix(buf, &value);
|
ok = sc_str_parse_integer_with_suffix(buf, &value);
|
||||||
assert(!ok);
|
assert(!ok);
|
||||||
|
|
||||||
sprintf(buf, "%ldk", LONG_MIN / 2000);
|
sprintf(buf, "%ldk", LONG_MIN / 2000);
|
||||||
ok = parse_integer_with_suffix(buf, &value);
|
ok = sc_str_parse_integer_with_suffix(buf, &value);
|
||||||
assert(ok);
|
assert(ok);
|
||||||
assert(value == LONG_MIN / 2000 * 1000);
|
assert(value == LONG_MIN / 2000 * 1000);
|
||||||
|
|
||||||
sprintf(buf, "%ldm", LONG_MIN / 2000);
|
sprintf(buf, "%ldm", LONG_MIN / 2000);
|
||||||
ok = parse_integer_with_suffix(buf, &value);
|
ok = sc_str_parse_integer_with_suffix(buf, &value);
|
||||||
assert(!ok);
|
assert(!ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_strlist_contains(void) {
|
static void test_strlist_contains(void) {
|
||||||
assert(strlist_contains("a,bc,def", ',', "bc"));
|
assert(sc_str_list_contains("a,bc,def", ',', "bc"));
|
||||||
assert(!strlist_contains("a,bc,def", ',', "b"));
|
assert(!sc_str_list_contains("a,bc,def", ',', "b"));
|
||||||
assert(strlist_contains("", ',', ""));
|
assert(sc_str_list_contains("", ',', ""));
|
||||||
assert(strlist_contains("abc,", ',', ""));
|
assert(sc_str_list_contains("abc,", ',', ""));
|
||||||
assert(strlist_contains(",abc", ',', ""));
|
assert(sc_str_list_contains(",abc", ',', ""));
|
||||||
assert(strlist_contains("abc,,def", ',', ""));
|
assert(sc_str_list_contains("abc,,def", ',', ""));
|
||||||
assert(!strlist_contains("abc", ',', ""));
|
assert(!sc_str_list_contains("abc", ',', ""));
|
||||||
assert(strlist_contains(",,|x", '|', ",,"));
|
assert(sc_str_list_contains(",,|x", '|', ",,"));
|
||||||
assert(strlist_contains("xyz", '\0', "xyz"));
|
assert(sc_str_list_contains("xyz", '\0', "xyz"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_wrap_lines(void) {
|
static void test_wrap_lines(void) {
|
||||||
|
@ -341,15 +341,15 @@ int main(int argc, char *argv[]) {
|
||||||
(void) argc;
|
(void) argc;
|
||||||
(void) argv;
|
(void) argv;
|
||||||
|
|
||||||
test_xstrncpy_simple();
|
test_strncpy_simple();
|
||||||
test_xstrncpy_just_fit();
|
test_strncpy_just_fit();
|
||||||
test_xstrncpy_truncated();
|
test_strncpy_truncated();
|
||||||
test_xstrjoin_simple();
|
test_join_simple();
|
||||||
test_xstrjoin_just_fit();
|
test_join_just_fit();
|
||||||
test_xstrjoin_truncated_in_token();
|
test_join_truncated_in_token();
|
||||||
test_xstrjoin_truncated_before_sep();
|
test_join_truncated_before_sep();
|
||||||
test_xstrjoin_truncated_after_sep();
|
test_join_truncated_after_sep();
|
||||||
test_strquote();
|
test_quote();
|
||||||
test_utf8_truncate();
|
test_utf8_truncate();
|
||||||
test_parse_integer();
|
test_parse_integer();
|
||||||
test_parse_integers();
|
test_parse_integers();
|
||||||
|
|
Loading…
Reference in a new issue