Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
0002 /*
0003  * string function definitions for NOLIBC
0004  * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
0005  */
0006 
0007 #ifndef _NOLIBC_STRING_H
0008 #define _NOLIBC_STRING_H
0009 
0010 #include "std.h"
0011 
0012 static void *malloc(size_t len);
0013 
0014 /*
0015  * As much as possible, please keep functions alphabetically sorted.
0016  */
0017 
0018 static __attribute__((unused))
0019 int memcmp(const void *s1, const void *s2, size_t n)
0020 {
0021     size_t ofs = 0;
0022     char c1 = 0;
0023 
0024     while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
0025         ofs++;
0026     }
0027     return c1;
0028 }
0029 
0030 static __attribute__((unused))
0031 void *_nolibc_memcpy_up(void *dst, const void *src, size_t len)
0032 {
0033     size_t pos = 0;
0034 
0035     while (pos < len) {
0036         ((char *)dst)[pos] = ((const char *)src)[pos];
0037         pos++;
0038     }
0039     return dst;
0040 }
0041 
0042 static __attribute__((unused))
0043 void *_nolibc_memcpy_down(void *dst, const void *src, size_t len)
0044 {
0045     while (len) {
0046         len--;
0047         ((char *)dst)[len] = ((const char *)src)[len];
0048     }
0049     return dst;
0050 }
0051 
0052 /* might be ignored by the compiler without -ffreestanding, then found as
0053  * missing.
0054  */
0055 __attribute__((weak,unused,section(".text.nolibc_memmove")))
0056 void *memmove(void *dst, const void *src, size_t len)
0057 {
0058     size_t dir, pos;
0059 
0060     pos = len;
0061     dir = -1;
0062 
0063     if (dst < src) {
0064         pos = -1;
0065         dir = 1;
0066     }
0067 
0068     while (len) {
0069         pos += dir;
0070         ((char *)dst)[pos] = ((const char *)src)[pos];
0071         len--;
0072     }
0073     return dst;
0074 }
0075 
0076 /* must be exported, as it's used by libgcc on ARM */
0077 __attribute__((weak,unused,section(".text.nolibc_memcpy")))
0078 void *memcpy(void *dst, const void *src, size_t len)
0079 {
0080     return _nolibc_memcpy_up(dst, src, len);
0081 }
0082 
0083 /* might be ignored by the compiler without -ffreestanding, then found as
0084  * missing.
0085  */
0086 __attribute__((weak,unused,section(".text.nolibc_memset")))
0087 void *memset(void *dst, int b, size_t len)
0088 {
0089     char *p = dst;
0090 
0091     while (len--)
0092         *(p++) = b;
0093     return dst;
0094 }
0095 
0096 static __attribute__((unused))
0097 char *strchr(const char *s, int c)
0098 {
0099     while (*s) {
0100         if (*s == (char)c)
0101             return (char *)s;
0102         s++;
0103     }
0104     return NULL;
0105 }
0106 
0107 static __attribute__((unused))
0108 int strcmp(const char *a, const char *b)
0109 {
0110     unsigned int c;
0111     int diff;
0112 
0113     while (!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
0114         ;
0115     return diff;
0116 }
0117 
0118 static __attribute__((unused))
0119 char *strcpy(char *dst, const char *src)
0120 {
0121     char *ret = dst;
0122 
0123     while ((*dst++ = *src++));
0124     return ret;
0125 }
0126 
0127 /* this function is only used with arguments that are not constants or when
0128  * it's not known because optimizations are disabled.
0129  */
0130 static __attribute__((unused))
0131 size_t nolibc_strlen(const char *str)
0132 {
0133     size_t len;
0134 
0135     for (len = 0; str[len]; len++);
0136     return len;
0137 }
0138 
0139 /* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
0140  * the two branches, then will rely on an external definition of strlen().
0141  */
0142 #if defined(__OPTIMIZE__)
0143 #define strlen(str) ({                          \
0144     __builtin_constant_p((str)) ?           \
0145         __builtin_strlen((str)) :       \
0146         nolibc_strlen((str));           \
0147 })
0148 #else
0149 #define strlen(str) nolibc_strlen((str))
0150 #endif
0151 
0152 static __attribute__((unused))
0153 size_t strnlen(const char *str, size_t maxlen)
0154 {
0155     size_t len;
0156 
0157     for (len = 0; (len < maxlen) && str[len]; len++);
0158     return len;
0159 }
0160 
0161 static __attribute__((unused))
0162 char *strdup(const char *str)
0163 {
0164     size_t len;
0165     char *ret;
0166 
0167     len = strlen(str);
0168     ret = malloc(len + 1);
0169     if (__builtin_expect(ret != NULL, 1))
0170         memcpy(ret, str, len + 1);
0171 
0172     return ret;
0173 }
0174 
0175 static __attribute__((unused))
0176 char *strndup(const char *str, size_t maxlen)
0177 {
0178     size_t len;
0179     char *ret;
0180 
0181     len = strnlen(str, maxlen);
0182     ret = malloc(len + 1);
0183     if (__builtin_expect(ret != NULL, 1)) {
0184         memcpy(ret, str, len);
0185         ret[len] = '\0';
0186     }
0187 
0188     return ret;
0189 }
0190 
0191 static __attribute__((unused))
0192 size_t strlcat(char *dst, const char *src, size_t size)
0193 {
0194     size_t len;
0195     char c;
0196 
0197     for (len = 0; dst[len]; len++)
0198         ;
0199 
0200     for (;;) {
0201         c = *src;
0202         if (len < size)
0203             dst[len] = c;
0204         if (!c)
0205             break;
0206         len++;
0207         src++;
0208     }
0209 
0210     return len;
0211 }
0212 
0213 static __attribute__((unused))
0214 size_t strlcpy(char *dst, const char *src, size_t size)
0215 {
0216     size_t len;
0217     char c;
0218 
0219     for (len = 0;;) {
0220         c = src[len];
0221         if (len < size)
0222             dst[len] = c;
0223         if (!c)
0224             break;
0225         len++;
0226     }
0227     return len;
0228 }
0229 
0230 static __attribute__((unused))
0231 char *strncat(char *dst, const char *src, size_t size)
0232 {
0233     char *orig = dst;
0234 
0235     while (*dst)
0236         dst++;
0237 
0238     while (size && (*dst = *src)) {
0239         src++;
0240         dst++;
0241         size--;
0242     }
0243 
0244     *dst = 0;
0245     return orig;
0246 }
0247 
0248 static __attribute__((unused))
0249 int strncmp(const char *a, const char *b, size_t size)
0250 {
0251     unsigned int c;
0252     int diff = 0;
0253 
0254     while (size-- &&
0255            !(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
0256         ;
0257 
0258     return diff;
0259 }
0260 
0261 static __attribute__((unused))
0262 char *strncpy(char *dst, const char *src, size_t size)
0263 {
0264     size_t len;
0265 
0266     for (len = 0; len < size; len++)
0267         if ((dst[len] = *src))
0268             src++;
0269     return dst;
0270 }
0271 
0272 static __attribute__((unused))
0273 char *strrchr(const char *s, int c)
0274 {
0275     const char *ret = NULL;
0276 
0277     while (*s) {
0278         if (*s == (char)c)
0279             ret = s;
0280         s++;
0281     }
0282     return (char *)ret;
0283 }
0284 
0285 #endif /* _NOLIBC_STRING_H */