mirror of
https://github.com/yshui/picom.git
synced 2024-11-11 13:51:02 -05:00
7e833744b7
trim_both removes whitespaces from both side of a string. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
157 lines
3.2 KiB
C
157 lines
3.2 KiB
C
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
|
|
|
#include <string.h>
|
|
|
|
#include <test.h>
|
|
|
|
#include "compiler.h"
|
|
#include "string_utils.h"
|
|
#include "utils.h"
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
// gcc warns about legitimate strncpy in mstrjoin and mstrextend
|
|
// strncpy(str, src1, len1) intentional truncates the null byte from src1.
|
|
// strncpy(str+len1, src2, len2) uses bound depends on the source argument,
|
|
// but str is allocated with len1+len2+1, so this strncpy can't overflow
|
|
#pragma GCC diagnostic ignored "-Wpragmas"
|
|
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
|
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
|
|
|
/**
|
|
* Allocate the space and join two strings.
|
|
*/
|
|
char *mstrjoin(const char *src1, const char *src2) {
|
|
auto len1 = strlen(src1);
|
|
auto len2 = strlen(src2);
|
|
auto len = len1 + len2 + 1;
|
|
auto str = ccalloc(len, char);
|
|
|
|
strncpy(str, src1, len1);
|
|
strncpy(str + len1, src2, len2);
|
|
str[len - 1] = '\0';
|
|
|
|
return str;
|
|
}
|
|
|
|
TEST_CASE(mstrjoin) {
|
|
char *str = mstrjoin("asdf", "qwer");
|
|
TEST_STREQUAL(str, "asdfqwer");
|
|
free(str);
|
|
|
|
str = mstrjoin("", "qwer");
|
|
TEST_STREQUAL(str, "qwer");
|
|
free(str);
|
|
|
|
str = mstrjoin("asdf", "");
|
|
TEST_STREQUAL(str, "asdf");
|
|
free(str);
|
|
}
|
|
|
|
/**
|
|
* Concatenate a string on heap with another string.
|
|
*/
|
|
void mstrextend(char **psrc1, const char *src2) {
|
|
if (!*psrc1) {
|
|
*psrc1 = strdup(src2);
|
|
return;
|
|
}
|
|
|
|
auto len1 = strlen(*psrc1);
|
|
auto len2 = strlen(src2);
|
|
auto len = len1 + len2 + 1;
|
|
*psrc1 = crealloc(*psrc1, len);
|
|
|
|
strncpy(*psrc1 + len1, src2, len2);
|
|
(*psrc1)[len - 1] = '\0';
|
|
}
|
|
|
|
TEST_CASE(mstrextend) {
|
|
char *str1 = NULL;
|
|
mstrextend(&str1, "asdf");
|
|
TEST_STREQUAL(str1, "asdf");
|
|
|
|
mstrextend(&str1, "asd");
|
|
TEST_STREQUAL(str1, "asdfasd");
|
|
|
|
mstrextend(&str1, "");
|
|
TEST_STREQUAL(str1, "asdfasd");
|
|
free(str1);
|
|
}
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
/// Parse a floating point number of form (+|-)?[0-9]*(\.[0-9]*)
|
|
double strtod_simple(const char *src, const char **end) {
|
|
double neg = 1;
|
|
if (*src == '-') {
|
|
neg = -1;
|
|
src++;
|
|
} else if (*src == '+') {
|
|
src++;
|
|
}
|
|
|
|
double ret = 0;
|
|
while (*src >= '0' && *src <= '9') {
|
|
ret = ret * 10 + (*src - '0');
|
|
src++;
|
|
}
|
|
|
|
if (*src == '.') {
|
|
double frac = 0, mult = 0.1;
|
|
src++;
|
|
while (*src >= '0' && *src <= '9') {
|
|
frac += mult * (*src - '0');
|
|
mult *= 0.1;
|
|
src++;
|
|
}
|
|
ret += frac;
|
|
}
|
|
|
|
*end = src;
|
|
return ret * neg;
|
|
}
|
|
|
|
TEST_CASE(strtod_simple) {
|
|
const char *end;
|
|
double result = strtod_simple("1.0", &end);
|
|
TEST_EQUAL(result, 1);
|
|
TEST_EQUAL(*end, '\0');
|
|
|
|
result = strtod_simple("-1.0", &end);
|
|
TEST_EQUAL(result, -1);
|
|
TEST_EQUAL(*end, '\0');
|
|
|
|
result = strtod_simple("+.5", &end);
|
|
TEST_EQUAL(result, 0.5);
|
|
TEST_EQUAL(*end, '\0');
|
|
}
|
|
|
|
const char *trim_both(const char *src, size_t *length) {
|
|
size_t i = 0;
|
|
while (isspace(src[i])) {
|
|
i++;
|
|
}
|
|
size_t j = strlen(src) - 1;
|
|
while (j > i && isspace(src[j])) {
|
|
j--;
|
|
}
|
|
*length = j - i + 1;
|
|
return src + i;
|
|
}
|
|
|
|
TEST_CASE(trim_both) {
|
|
size_t length;
|
|
const char *str = trim_both(" \t\n\r\f", &length);
|
|
TEST_EQUAL(length, 0);
|
|
TEST_EQUAL(*str, '\0');
|
|
|
|
str = trim_both(" asdfas ", &length);
|
|
TEST_EQUAL(length, 6);
|
|
TEST_STRNEQUAL(str, "asdfas", length);
|
|
|
|
str = trim_both(" asdf asdf ", &length);
|
|
TEST_EQUAL(length, 9);
|
|
TEST_STRNEQUAL(str, "asdf asdf", length);
|
|
}
|