Your proposal isn't an improvement over the current situation with strl*
functions, and I don't think this is helpful.

Alejandro Colomar (man-pages) <[email protected]> wrote:

> Hi, Todd and Theo!
> 
> I wrote this function this week, based on strlcpy(3) and strecopy()[1],
> which are the best string copy functions I've seen so far.  But I came
> to improvements that bring one function that I think is better than both
> of those.
> 
> I posted the function for review on codidact.com[2].
> I also discussed it a bit on the groff@ mailing list[3].
> 
> See this manual page I wrote for it.  Since you designed strlcpy(3BSD)
> and strlcat(3BSD), I'm interested in knowing your opinion on it.  If you
> like it, feel free to add it to OpenBSD. ;-)
> 
> Cheers,
> 
> Alex
> 
> 
> [1]: <https://www.symas.com/post/the-sad-state-of-c-strings>
> [2]: <https://software.codidact.com/posts/285946/285952#answer-285952>
> [3]: <https://lists.gnu.org/archive/html/groff/2022-02/msg00050.html>
> 
> 
> ---
> stpecpy(3)          Linux Programmer’s Manual         stpecpy(3)
> 
> NAME
>        stpecpy - bounded string copy and concatenation
> 
> SYNOPSIS
>        #include <string.h>
> 
>        char *_Nonnull stpecpy(char *_Nonnull dest,
>                               const char *_Nonnull restrict src,
>                               char *_Nonnull end);
> 
> DESCRIPTION
>        stpecpy()  copies the string pointed to by src (including
>        the terminating null byte ('\0')) to the array pointed to
>        by dest.  The strings may  not  overlap.   This  function
>        doesn’t  overflow  the destination buffer, and requires a
>        pointer to the end of it for that purpose.
> 
>        end is a pointer to the last element in the dest  buffer.
>        It should be calculated in the following way:
> 
>            char dest[SIZE];
>            char *end;
> 
>            end = &dest[SIZE - 1];
>            stpecpy(dest, "Hello world", end);
> 
>        This  function  only  operates on true "C" strings, which
>        means that src must be terminated by  a  null  byte,  and
>        dest  is guaranteed to be terminated with a null byte af‐
>        ter the call (as long as the buffer  has  a  size  larger
>        than 0).
> 
>        This function is designed to be a safer, more consistent,
>        less  error  prone,  and  simpler  replacement  for other
>        string copy and concatenation functions.
> 
>    Compared to other string copy and concatenation functions
>        strlcat(3BSD)
>               *cat()  functions  have  an  inherent  performance
>               problem:  each  *cat()  call has to find again the
>               teminating null byte in  the  dest  string.   Read
>               about    Shlemiel    the    painter’s    algorithm
>               ⟨https://www.joelonsoftware.com/2001/12/11/back-
>               to-basics/⟩.
> 
>        strlcpy(3BSD)
>        strscpy(9)
>        memccpy(3)
>               One  can   use   strlcpy(3BSD),   strscpy(9),   or
>               memccpy(3)  to concatenate, without strlcat(3BSD),
>               but it’s error prone.  They require  the  user  to
>               recalculate  the  remaining  buffer size for every
>               call.
> 
>        stpcpy(3)
>               It can’t detect overflow.  However,  in  case  the
>               programmer  knows  overflow can’t occur, then it’s
>               simpler to use it.
> 
>        stpncpy(3)
>        strncpy(3)
>        strncat(3)
>               They don’t work with "C" strings.   The  resulting
>               string  is  not guaranteed to be terminated with a
>               null byte.  They also write unnecessary zeros  af‐
>               ter the terminating byte.
> 
>        strcpy(3)
>               It  doesn’t detect overflow, as stpcpy(3), plus it
>               can’t be chained; requires strcat(3).
> 
>        strcat(3)
>               It can’t detect overflow, as  strcpy(3),  plus  it
>               has performance problems, as strlcat(3BSD).
> 
>        snprintf(3)
>               It  has considerable overhead, which can be orders
>               of magnitude slower.
> 
> RETURN VALUE
>        stpecpy() returns a pointer to the terminating null  byte
>        in  dest,  except  if  the  string has been truncated, in
>        which case it returns end + 1.
> 
> EXAMPLES
>    Trivial (not optimized) implementation:
>        char *_Nonnull
>        stpecpy(char *_Nonnull dst, char *_Nonnull restrict src,
>                char *_Nonnull end)
>        {
>            for (/* void */; dst <= end; dst++, src++) {
>                *dst = *src;
>                if (*dst == '\0')
>                    return dst;
>            }
>            /* truncation detected */
>            *end = '\0';
>            return dst;
>        }
> 
>    Example of usage
>        The following program produces this output:
> 
>            $ ./a.out
>            Trunc: 9: Hello wor
>            9: Hello foo
>            Trunc: 9: Hello baa
>            2: HW
> 
>        Source code:
> 
>            int
>            main(void)
>            {
>                ptrdiff_t size = 10;
>                char      buf[size];
>                char     *end;
>                ptrdiff_t len;
> 
>                end = &buf[size - 1];
> 
>                len = stpecpy(stpecpy(buf, "Hello", end), " world", end)
> - buf;
>                if (len == size) {
>                    len--;
>                    printf("Trunc: ");
>                }
>                printf("%ti: %s\n", len, buf);
> 
>                len = stpecpy(stpecpy(stpecpy(buf, "Hello", end), " foo",
> end),
>                              "", end) - buf;
>                if (len == size) {
>                    len--;
>                    printf("Trunc: ");
>                }
>                printf("%ti: %s\n", len, buf);
> 
>                len = stpecpy(stpecpy(stpecpy(buf, "Hello", end), "
> baar", end),
>                              "", end) - buf;
>                if (len == size) {
>                    len--;
>                    printf("Trunc: ");
>                }
>                printf("%ti: %s\n", len, buf);
> 
>                len = stpecpy(stpecpy(buf, "H", end), "W", end) - buf;
>                if (len == size) {
>                    len--;
>                    printf("Trunc: ");
>                }
>                printf("%ti: %s\n", len, buf);
>            }
> 
> SEE ALSO
>        snprintf(3), strncat(3), strncpy(3), stpsecpy(3)
> 
> alx                        2022-02-13                 stpecpy(3)
> 
> 
> -- 
> Alejandro Colomar
> Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
> http://www.alejandro-colomar.es/

Reply via email to