X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbasic%2Fstring-util.c;h=5d4510e1b3bc457103da44e9128cc240588fdc53;hp=6006767daac5b025fdb56e44fd28d82a2443f20b;hb=b3ba37e13ca5fda7de81196b87b12e069d563665;hpb=da2587d5154e11d4e643e326793f3ce2cc48dee6 diff --git a/src/basic/string-util.c b/src/basic/string-util.c index 6006767da..5d4510e1b 100644 --- a/src/basic/string-util.c +++ b/src/basic/string-util.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,8 +17,16 @@ along with systemd; If not, see . ***/ +#include +#include +#include +#include +#include +#include + #include "alloc-util.h" #include "gunicode.h" +#include "macro.h" #include "string-util.h" #include "utf8.h" #include "util.h" @@ -310,18 +316,86 @@ char *truncate_nl(char *s) { return s; } +char ascii_tolower(char x) { + + if (x >= 'A' && x <= 'Z') + return x - 'A' + 'a'; + + return x; +} + +char ascii_toupper(char x) { + + if (x >= 'a' && x <= 'z') + return x - 'a' + 'A'; + + return x; +} + char *ascii_strlower(char *t) { char *p; assert(t); for (p = t; *p; p++) - if (*p >= 'A' && *p <= 'Z') - *p = *p - 'A' + 'a'; + *p = ascii_tolower(*p); + + return t; +} + +char *ascii_strupper(char *t) { + char *p; + + assert(t); + + for (p = t; *p; p++) + *p = ascii_toupper(*p); + + return t; +} + +char *ascii_strlower_n(char *t, size_t n) { + size_t i; + + if (n <= 0) + return t; + + for (i = 0; i < n; i++) + t[i] = ascii_tolower(t[i]); return t; } +int ascii_strcasecmp_n(const char *a, const char *b, size_t n) { + + for (; n > 0; a++, b++, n--) { + int x, y; + + x = (int) (uint8_t) ascii_tolower(*a); + y = (int) (uint8_t) ascii_tolower(*b); + + if (x != y) + return x - y; + } + + return 0; +} + +int ascii_strcasecmp_nn(const char *a, size_t n, const char *b, size_t m) { + int r; + + r = ascii_strcasecmp_n(a, b, MIN(n, m)); + if (r != 0) + return r; + + if (n < m) + return -1; + else if (n > m) + return 1; + else + return 0; +} + bool chars_intersect(const char *a, const char *b) { const char *p; @@ -394,6 +468,7 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne char *e; const char *i, *j; unsigned k, len, len2; + int r; assert(s); assert(percent <= 100); @@ -413,23 +488,23 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne k = 0; for (i = s; k < x && i < s + old_length; i = utf8_next_char(i)) { - int c; + char32_t c; - c = utf8_encoded_to_unichar(i); - if (c < 0) + r = utf8_encoded_to_unichar(i, &c); + if (r < 0) return NULL; k += unichar_iswide(c) ? 2 : 1; } if (k > x) /* last character was wide and went over quota */ - x ++; + x++; for (j = s + old_length; k < new_length && j > i; ) { - int c; + char32_t c; j = utf8_prev_char(j); - c = utf8_encoded_to_unichar(j); - if (c < 0) + r = utf8_encoded_to_unichar(j, &c); + if (r < 0) return NULL; k += unichar_iswide(c) ? 2 : 1; } @@ -748,25 +823,20 @@ int free_and_strdup(char **p, const char *s) { return 1; } -#pragma GCC push_options -#pragma GCC optimize("O0") +/* + * Pointer to memset is volatile so that compiler must de-reference + * the pointer and can't assume that it points to any function in + * particular (such as memset, which it then might further "optimize") + * This approach is inspired by openssl's crypto/mem_clr.c. + */ +typedef void *(*memset_t)(void *,int,size_t); -void* memory_erase(void *p, size_t l) { - volatile uint8_t* x = (volatile uint8_t*) p; - - /* This basically does what memset() does, but hopefully isn't - * optimized away by the compiler. One of those days, when - * glibc learns memset_s() we should replace this call by - * memset_s(), but until then this has to do. */ - - for (; l > 0; l--) - *(x++) = 'x'; +static volatile memset_t memset_func = memset; - return p; +void* memory_erase(void *p, size_t l) { + return memset_func(p, 'x', l); } -#pragma GCC pop_options - char* string_erase(char *x) { if (!x)