2022-02-07 17:23:20 +01:00
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/*
* string function definitions for NOLIBC
* Copyright ( C ) 2017 - 2021 Willy Tarreau < w @ 1 wt . eu >
*/
# ifndef _NOLIBC_STRING_H
# define _NOLIBC_STRING_H
# include "std.h"
2022-03-29 17:17:37 +07:00
static void * malloc ( size_t len ) ;
2022-02-07 17:23:20 +01:00
/*
* As much as possible , please keep functions alphabetically sorted .
*/
static __attribute__ ( ( unused ) )
int memcmp ( const void * s1 , const void * s2 , size_t n )
{
size_t ofs = 0 ;
char c1 = 0 ;
while ( ofs < n & & ! ( c1 = ( ( char * ) s1 ) [ ofs ] - ( ( char * ) s2 ) [ ofs ] ) ) {
ofs + + ;
}
return c1 ;
}
2022-02-07 17:23:40 +01:00
static __attribute__ ( ( unused ) )
void * _nolibc_memcpy_up ( void * dst , const void * src , size_t len )
{
size_t pos = 0 ;
while ( pos < len ) {
( ( char * ) dst ) [ pos ] = ( ( const char * ) src ) [ pos ] ;
pos + + ;
}
return dst ;
}
static __attribute__ ( ( unused ) )
void * _nolibc_memcpy_down ( void * dst , const void * src , size_t len )
{
while ( len ) {
len - - ;
( ( char * ) dst ) [ len ] = ( ( const char * ) src ) [ len ] ;
}
return dst ;
}
2022-02-07 17:23:47 +01:00
/* might be ignored by the compiler without -ffreestanding, then found as
* missing .
*/
__attribute__ ( ( weak , unused , section ( " .text.nolibc_memmove " ) ) )
2022-02-07 17:23:20 +01:00
void * memmove ( void * dst , const void * src , size_t len )
{
2022-02-07 17:23:41 +01:00
size_t dir , pos ;
2022-02-07 17:23:20 +01:00
2022-02-07 17:23:41 +01:00
pos = len ;
dir = - 1 ;
if ( dst < src ) {
pos = - 1 ;
dir = 1 ;
2022-02-07 17:23:20 +01:00
}
2022-02-07 17:23:41 +01:00
while ( len ) {
pos + = dir ;
( ( char * ) dst ) [ pos ] = ( ( const char * ) src ) [ pos ] ;
len - - ;
}
return dst ;
2022-02-07 17:23:20 +01:00
}
/* must be exported, as it's used by libgcc on ARM */
2022-02-07 17:23:44 +01:00
__attribute__ ( ( weak , unused , section ( " .text.nolibc_memcpy " ) ) )
2022-02-07 17:23:20 +01:00
void * memcpy ( void * dst , const void * src , size_t len )
{
2022-02-07 17:23:40 +01:00
return _nolibc_memcpy_up ( dst , src , len ) ;
2022-02-07 17:23:20 +01:00
}
2022-02-07 17:23:47 +01:00
/* might be ignored by the compiler without -ffreestanding, then found as
* missing .
*/
__attribute__ ( ( weak , unused , section ( " .text.nolibc_memset " ) ) )
2022-02-07 17:23:20 +01:00
void * memset ( void * dst , int b , size_t len )
{
char * p = dst ;
while ( len - - )
* ( p + + ) = b ;
return dst ;
}
static __attribute__ ( ( unused ) )
char * strchr ( const char * s , int c )
{
while ( * s ) {
if ( * s = = ( char ) c )
return ( char * ) s ;
s + + ;
}
return NULL ;
}
2022-03-21 18:33:10 +01:00
static __attribute__ ( ( unused ) )
int strcmp ( const char * a , const char * b )
{
unsigned int c ;
int diff ;
while ( ! ( diff = ( unsigned char ) * a + + - ( c = ( unsigned char ) * b + + ) ) & & c )
;
return diff ;
}
2022-02-07 17:23:20 +01:00
static __attribute__ ( ( unused ) )
char * strcpy ( char * dst , const char * src )
{
char * ret = dst ;
while ( ( * dst + + = * src + + ) ) ;
return ret ;
}
2022-03-23 08:18:06 +01:00
/* this function is only used with arguments that are not constants or when
* it ' s not known because optimizations are disabled .
*/
2022-02-07 17:23:20 +01:00
static __attribute__ ( ( unused ) )
size_t nolibc_strlen ( const char * str )
{
size_t len ;
for ( len = 0 ; str [ len ] ; len + + ) ;
return len ;
}
2022-03-23 08:18:06 +01:00
/* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
* the two branches , then will rely on an external definition of strlen ( ) .
*/
# if defined(__OPTIMIZE__)
2022-02-07 17:23:20 +01:00
# define strlen(str) ({ \
__builtin_constant_p ( ( str ) ) ? \
__builtin_strlen ( ( str ) ) : \
nolibc_strlen ( ( str ) ) ; \
} )
2022-03-23 08:18:06 +01:00
# else
# define strlen(str) nolibc_strlen((str))
# endif
2022-02-07 17:23:20 +01:00
2022-03-29 17:17:36 +07:00
static __attribute__ ( ( unused ) )
size_t strnlen ( const char * str , size_t maxlen )
{
size_t len ;
for ( len = 0 ; ( len < maxlen ) & & str [ len ] ; len + + ) ;
return len ;
}
2022-03-29 17:17:37 +07:00
static __attribute__ ( ( unused ) )
char * strdup ( const char * str )
{
size_t len ;
char * ret ;
len = strlen ( str ) ;
ret = malloc ( len + 1 ) ;
if ( __builtin_expect ( ret ! = NULL , 1 ) )
memcpy ( ret , str , len + 1 ) ;
return ret ;
}
static __attribute__ ( ( unused ) )
char * strndup ( const char * str , size_t maxlen )
{
size_t len ;
char * ret ;
len = strnlen ( str , maxlen ) ;
ret = malloc ( len + 1 ) ;
if ( __builtin_expect ( ret ! = NULL , 1 ) ) {
memcpy ( ret , str , len ) ;
ret [ len ] = ' \0 ' ;
}
return ret ;
}
2022-02-07 17:23:43 +01:00
static __attribute__ ( ( unused ) )
size_t strlcat ( char * dst , const char * src , size_t size )
{
size_t len ;
char c ;
for ( len = 0 ; dst [ len ] ; len + + )
;
for ( ; ; ) {
c = * src ;
if ( len < size )
dst [ len ] = c ;
if ( ! c )
break ;
len + + ;
src + + ;
}
return len ;
}
2022-02-07 17:23:42 +01:00
static __attribute__ ( ( unused ) )
size_t strlcpy ( char * dst , const char * src , size_t size )
{
size_t len ;
char c ;
for ( len = 0 ; ; ) {
c = src [ len ] ;
if ( len < size )
dst [ len ] = c ;
if ( ! c )
break ;
len + + ;
}
return len ;
}
2022-02-07 17:23:43 +01:00
static __attribute__ ( ( unused ) )
char * strncat ( char * dst , const char * src , size_t size )
{
char * orig = dst ;
while ( * dst )
dst + + ;
while ( size & & ( * dst = * src ) ) {
src + + ;
dst + + ;
size - - ;
}
* dst = 0 ;
return orig ;
}
2022-03-21 18:33:10 +01:00
static __attribute__ ( ( unused ) )
int strncmp ( const char * a , const char * b , size_t size )
{
unsigned int c ;
int diff = 0 ;
while ( size - - & &
! ( diff = ( unsigned char ) * a + + - ( c = ( unsigned char ) * b + + ) ) & & c )
;
return diff ;
}
2022-02-07 17:23:43 +01:00
2022-02-07 17:23:42 +01:00
static __attribute__ ( ( unused ) )
char * strncpy ( char * dst , const char * src , size_t size )
{
size_t len ;
for ( len = 0 ; len < size ; len + + )
if ( ( dst [ len ] = * src ) )
src + + ;
return dst ;
}
2022-02-07 17:23:20 +01:00
static __attribute__ ( ( unused ) )
char * strrchr ( const char * s , int c )
{
const char * ret = NULL ;
while ( * s ) {
if ( * s = = ( char ) c )
ret = s ;
s + + ;
}
return ( char * ) ret ;
}
# endif /* _NOLIBC_STRING_H */