On Tue, Aug 13, 2013 at 11:15 PM, Glenn Fowler <[email protected]> wrote:
> On Tue, 13 Aug 2013 17:11:04 -0400 Glenn Fowler wrote:
>> On Tue, 13 Aug 2013 22:55:33 +0200 Roland Mainz wrote:
>> > On Tue, Aug 13, 2013 at 10:10 PM, Lionel Cons <[email protected]> 
>> > wrote:
>> > > On 13 August 2013 22:05, Glenn Fowler <[email protected]> wrote:
>> > >> On Tue, 13 Aug 2013 21:51:09 +0200 Lionel Cons wrote:
>> > >>> On 13 August 2013 15:54, Glenn Fowler <[email protected]> wrote:
>> > >>> > I looked at this closer and stpncpy() is different from strncopy()
>> > >>> > so unlike
>> > >>> >         strcopy() => stpcpy()
>> > >>> > we won't be able to do
>> > >>> >         strncopy() => stpncpy()
>> > >>> > ast strncopy() usage is to prevent overflow of the destination string
>> > >>> > so in most cases the size argument is >> strlen(source)
>> > >>> > and in that case stpncpy() will fill the difference with '\0' -- a 
>> > >>> > waste
>> > >>> > unless an app really needs the '\0''s
>> > >>
>> > >>> I think the point of having stpcpy() and stpncpy() in libast is to
>> > >>> provide the new POSIX string functions for old systems. My staff said
>> > >>> there are two advantages in using them:
>> > >>> 1. stpcpy() returns the end of the string, allowing fast
>> > >>> concatenations. Those who think this is no longer necessary should
>> > >>> feel free to benchmark the effects on ARM and ARM64
>> > >> right, that's why we had strcopy()/strncopy() for 20 some years
>> > >>
>> > >>> 2. stpcpy() can be used on all systems with libast, and newer systems
>> > >>> which have libast in libc benefit from hand optimised assembler code
>> > >>> which can be 10 fold faster than the plain C code for longer strings
>> > >>
>> > >>> > without the '\0' fill property the ast usage could be adjusted
>> > >>
>> > >>> Isn't this like the old story of strncpy() adding '\0' at the end of
>> > >>> some platforms and on others don't do it?
>> > >>
>> > >> I don't mind a function adding 1 '\0'
>> > >> but in stpncpy(dst,src,len) if (strlen(src) < len) then it pads with 
>> > >> (len-strlen(src)) '\0's
>> > >
>> > > OK.
>> > > What is the rationale behind this behaviour? Does *POSIX* strncpy() do
>> > > the same? Is there an alternative in *POSIX* which doesn't fill the
>> > > string buffer up to <n> all the time?
>
>> > The POSIX manpage for |strncpy()| says this:
>> > -- snip --
>> >        If  the  array  pointed to by s2 is a string that is shorter
>> > than n bytes, null bytes shall be appended to the copy in the array
>> > pointed to by s1, until n bytes in all
>> >        are written.
>> > -- snip --
>> > ... |stpcpy()| and |stpncpy()| only differ from |strcpy()| and
>> > |strncpy()| that the |stp*()|-functions return a pointer to the '\0'
>> > byte at the end of the C string while the |str*()|-function always
>> > return a pointer to the beginning of the destination buffer. Beyond
>> > that they are AFAIK identical... and that's the only rationale...
>
>> > IMO the standard should provide |strncpy()|/|stpncpy()| variants which
>> > exactly add '\0' at the requested end of the buffer and not fill the
>> > buffer up to the limit...
>
>> > ... NSPR (Netscape Portable Runtime... used bu Mozilla/Firefox/etc.)
>> > has a |*strcpyz()|:
>> > -- snip --
>> > /*
>> >  * PL_strncpyz
>> >  *
>> >  * Copies the source string into the destination buffer, up to and 
>> > including
>> >  * the trailing '\0' or up but not including the max'th character, 
>> > whichever
>> >  * comes first.  It does not (can not) verify that the destination buffer 
>> > is
>> >  * large enough.  The destination string is always terminated with a '\0',
>> >  * unlike the traditional libc implementation.  It returns the "dest" 
>> > argument.
>> >  *
>> >  * NOTE: If you call this with a source "abcdefg" and a max of 5, the
>> >  * destination will end up with "abcd\0" (i.e., its strlen length will be 
>> > 4)!
>> >  *
>> >  * This means you can do this:
>> >  *
>> >  *     char buffer[ SOME_SIZE ];
>> >  *     PL_strncpyz(buffer, src, sizeof(buffer));
>> >  *
>> >  * and the result will be properly terminated.
>> >  */
>
>> > PR_EXTERN(char *)
>> > PL_strncpyz(char *dest, const char *src, PRUint32 max);
>> > -- snip --
>
>> > ... Glenn: Does that help ?
>
>> that's what strcopy()/strncopy() do and that's why strncopy() will stay in 
>> use
>
>> the 0 fill semantic is bizarre
>> maybe useful in crypto code but certainly bad for
>
>>       char    buf[1024];
>>       char*   b = buf;
>
>>       b = stpcpy(b, x, &buf[sizeof(buf)] - b);
>>       b = stpcpy(b, y, &buf[sizeof(buf)] - b);
>>       b = stpcpy(b, z, &buf[sizeof(buf)] - b);
>
> rats -- stpcpy => stpncpy above

Mhhh... |strlcpy()| is nearthe thing we may want... except that it
returns a |size_t| and not a pointer to the '\0' string:
-- snip --
STRLCPY(9)          Basic C Library Functions         STRLCPY(9)

NAME
       strlcpy - Copy a NUL terminated string into a sized
       buffer

SYNOPSIS
       size_t strlcpy(char * dest, const char * src,
                      size_t size);

ARGUMENTS
       dest
           Where to copy the string to

       src
           Where to copy the string from

       size
           size of destination buffer

BSD
       the result is always a valid NUL-terminated string that
       fits in the buffer (unless, of course, the buffer size is
       zero). It does not pad out the result like strncpy does.
-- snip --

I'm stunned that the standards people forgot to add a |strncpy()|
version which only adds one '\0' and doens't pad the complete buffer
with '\0' ...

----

Bye,
Roland

-- 
  __ .  . __
 (o.\ \/ /.o) [email protected]
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)

On Tue, Aug 13, 2013 at 11:15 PM, Glenn Fowler <[email protected]> wrote:
>
> On Tue, 13 Aug 2013 17:11:04 -0400 Glenn Fowler wrote:
>> On Tue, 13 Aug 2013 22:55:33 +0200 Roland Mainz wrote:
>> > On Tue, Aug 13, 2013 at 10:10 PM, Lionel Cons <[email protected]> 
>> > wrote:
>> > > On 13 August 2013 22:05, Glenn Fowler <[email protected]> wrote:
>> > >> On Tue, 13 Aug 2013 21:51:09 +0200 Lionel Cons wrote:
>> > >>> On 13 August 2013 15:54, Glenn Fowler <[email protected]> wrote:
>> > >>> > I looked at this closer and stpncpy() is different from strncopy()
>> > >>> > so unlike
>> > >>> >         strcopy() => stpcpy()
>> > >>> > we won't be able to do
>> > >>> >         strncopy() => stpncpy()
>> > >>> > ast strncopy() usage is to prevent overflow of the destination string
>> > >>> > so in most cases the size argument is >> strlen(source)
>> > >>> > and in that case stpncpy() will fill the difference with '\0' -- a 
>> > >>> > waste
>> > >>> > unless an app really needs the '\0''s
>> > >>
>> > >>> I think the point of having stpcpy() and stpncpy() in libast is to
>> > >>> provide the new POSIX string functions for old systems. My staff said
>> > >>> there are two advantages in using them:
>> > >>> 1. stpcpy() returns the end of the string, allowing fast
>> > >>> concatenations. Those who think this is no longer necessary should
>> > >>> feel free to benchmark the effects on ARM and ARM64
>> > >> right, that's why we had strcopy()/strncopy() for 20 some years
>> > >>
>> > >>> 2. stpcpy() can be used on all systems with libast, and newer systems
>> > >>> which have libast in libc benefit from hand optimised assembler code
>> > >>> which can be 10 fold faster than the plain C code for longer strings
>> > >>
>> > >>> > without the '\0' fill property the ast usage could be adjusted
>> > >>
>> > >>> Isn't this like the old story of strncpy() adding '\0' at the end of
>> > >>> some platforms and on others don't do it?
>> > >>
>> > >> I don't mind a function adding 1 '\0'
>> > >> but in stpncpy(dst,src,len) if (strlen(src) < len) then it pads with 
>> > >> (len-strlen(src)) '\0's
>> > >
>> > > OK.
>> > > What is the rationale behind this behaviour? Does *POSIX* strncpy() do
>> > > the same? Is there an alternative in *POSIX* which doesn't fill the
>> > > string buffer up to <n> all the time?
>
>> > The POSIX manpage for |strncpy()| says this:
>> > -- snip --
>> >        If  the  array  pointed to by s2 is a string that is shorter
>> > than n bytes, null bytes shall be appended to the copy in the array
>> > pointed to by s1, until n bytes in all
>> >        are written.
>> > -- snip --
>> > ... |stpcpy()| and |stpncpy()| only differ from |strcpy()| and
>> > |strncpy()| that the |stp*()|-functions return a pointer to the '\0'
>> > byte at the end of the C string while the |str*()|-function always
>> > return a pointer to the beginning of the destination buffer. Beyond
>> > that they are AFAIK identical... and that's the only rationale...
>
>> > IMO the standard should provide |strncpy()|/|stpncpy()| variants which
>> > exactly add '\0' at the requested end of the buffer and not fill the
>> > buffer up to the limit...
>
>> > ... NSPR (Netscape Portable Runtime... used bu Mozilla/Firefox/etc.)
>> > has a |*strcpyz()|:
>> > -- snip --
>> > /*
>> >  * PL_strncpyz
>> >  *
>> >  * Copies the source string into the destination buffer, up to and 
>> > including
>> >  * the trailing '\0' or up but not including the max'th character, 
>> > whichever
>> >  * comes first.  It does not (can not) verify that the destination buffer 
>> > is
>> >  * large enough.  The destination string is always terminated with a '\0',
>> >  * unlike the traditional libc implementation.  It returns the "dest" 
>> > argument.
>> >  *
>> >  * NOTE: If you call this with a source "abcdefg" and a max of 5, the
>> >  * destination will end up with "abcd\0" (i.e., its strlen length will be 
>> > 4)!
>> >  *
>> >  * This means you can do this:
>> >  *
>> >  *     char buffer[ SOME_SIZE ];
>> >  *     PL_strncpyz(buffer, src, sizeof(buffer));
>> >  *
>> >  * and the result will be properly terminated.
>> >  */
>
>> > PR_EXTERN(char *)
>> > PL_strncpyz(char *dest, const char *src, PRUint32 max);
>> > -- snip --
>
>> > ... Glenn: Does that help ?
>
>> that's what strcopy()/strncopy() do and that's why strncopy() will stay in 
>> use
>
>> the 0 fill semantic is bizarre
>> maybe useful in crypto code but certainly bad for
>
>>       char    buf[1024];
>>       char*   b = buf;
>
>>       b = stpcpy(b, x, &buf[sizeof(buf)] - b);
>>       b = stpcpy(b, y, &buf[sizeof(buf)] - b);
>>       b = stpcpy(b, z, &buf[sizeof(buf)] - b);
>
> rats -- stpcpy => stpncpy above
>



-- 
  __ .  . __
 (o.\ \/ /.o) [email protected]
  \__\/\/__/  MPEG specialist, C&&JAVA&&Sun&&Unix programmer
  /O /==\ O\  TEL +49 641 3992797
 (;O/ \/ \O;)
_______________________________________________
ast-developers mailing list
[email protected]
http://lists.research.att.com/mailman/listinfo/ast-developers

Reply via email to