#include #include #include #include #include #include #include #include "util/mem.h" #include "util/str.h" bool str_ends_with(const char *haystack, const char *needle) { size_t haystack_len; size_t needle_len; haystack_len = strlen(haystack); needle_len = strlen(needle); if (needle_len > haystack_len) { return false; } return !memcmp(&haystack[haystack_len - needle_len], needle, needle_len); } bool wstr_ends_with(const wchar_t *haystack, const wchar_t *needle) { size_t haystack_len; size_t needle_len; haystack_len = wcslen(haystack); needle_len = wcslen(needle); if (needle_len > haystack_len) { return false; } return !memcmp( &haystack[haystack_len - needle_len], needle, needle_len * sizeof(wchar_t)); } size_t str_format(char *buf, size_t nchars, const char *fmt, ...) { va_list ap; size_t result; va_start(ap, fmt); result = str_vformat(buf, nchars, fmt, ap); va_end(ap); return result; } size_t str_vformat(char *buf, size_t nchars, const char *fmt, va_list ap) { int result; result = _vsnprintf(buf, nchars, fmt, ap); if (result >= (int) nchars || result < 0) { abort(); } return (size_t) result; } size_t wstr_format(wchar_t *buf, size_t nchars, const wchar_t *fmt, ...) { va_list ap; size_t result; va_start(ap, fmt); result = wstr_vformat(buf, nchars, fmt, ap); va_end(ap); return result; } size_t wstr_vformat(wchar_t *buf, size_t nchars, const wchar_t *fmt, va_list ap) { int result; result = _vsnwprintf(buf, nchars, fmt, ap); if (result >= (int) nchars || result < 0) { abort(); } return (size_t) result; } void str_cat(char *dest, size_t dnchars, const char *src) { size_t dlen; size_t slen; dlen = strlen(dest); slen = strlen(src); if (dlen + slen >= dnchars) { abort(); } memcpy(dest + dlen, src, (slen + 1) * sizeof(char)); } void str_cpy(char *dest, size_t dnchars, const char *src) { size_t slen; slen = strlen(src); if (slen >= dnchars) { abort(); } memcpy(dest, src, (slen + 1) * sizeof(char)); } void wstr_cat(wchar_t *dest, size_t dnchars, const wchar_t *src) { size_t dlen; size_t slen; dlen = wcslen(dest); slen = wcslen(src); if (dlen + slen >= dnchars) { abort(); } memcpy(dest + dlen, src, (slen + 1) * sizeof(wchar_t)); } void wstr_cpy(wchar_t *dest, size_t dnchars, const wchar_t *src) { size_t slen; slen = wcslen(src); if (slen >= dnchars) { abort(); } memcpy(dest, src, (slen + 1) * sizeof(wchar_t)); } char *str_dup(const char *str) { char *dest; size_t nbytes; nbytes = strlen(str) + 1; dest = xmalloc(nbytes); memcpy(dest, str, nbytes); return dest; } void str_trim(char *str) { char *pos; for (pos = str + strlen(str) - 1; pos > str; pos--) { if (!isspace(*pos)) { return; } *pos = '\0'; } } wchar_t *str_widen(const char *src) { int nchars; wchar_t *result; nchars = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); if (!nchars) { abort(); } result = xmalloc(nchars * sizeof(wchar_t)); if (!MultiByteToWideChar(CP_ACP, 0, src, -1, result, nchars)) { abort(); } return result; } wchar_t *wstr_dup(const wchar_t *wstr) { wchar_t *dest; size_t nchars; nchars = wcslen(wstr) + 1; dest = xmalloc(nchars * sizeof(wchar_t)); memcpy(dest, wstr, nchars * sizeof(wchar_t)); return dest; } bool wstr_narrow(const wchar_t *src, char **dest) { int nbytes; nbytes = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL); if (nbytes <= 0) { goto size_fail; } *dest = xmalloc(nbytes); if (WideCharToMultiByte(CP_ACP, 0, src, -1, *dest, nbytes, NULL, NULL) != nbytes) { goto conv_fail; } return true; conv_fail: free(*dest); *dest = NULL; size_fail: return false; } bool str_eq(const char *lhs, const char *rhs) { if (lhs == NULL || rhs == NULL) { return lhs == rhs; } else { return strcmp(lhs, rhs) == 0; } } bool wstr_eq(const wchar_t *lhs, const wchar_t *rhs) { if (lhs == NULL || rhs == NULL) { return lhs == rhs; } else { return wcscmp(lhs, rhs) == 0; } } bool wstr_insensitive_eq(const wchar_t *lhs, const wchar_t *rhs) { if (lhs == NULL || rhs == NULL) { return lhs == rhs; } else { return _wcsicmp(lhs, rhs) == 0; } }