Re: AW: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-25 Thread Jody Bruchon
I did not see the email you've quoted on the mailing list. Interesting. 
I shall respond to it now.


On 2015-08-25 03:00, dietmar.schind...@manroland-web.com wrote:

Von: Tito
Gesendet: Montag, 24. August 2015 21:29

Hi Jody,
so you pass the buck to the silly caller to guess what is consistent,
but even in the few replies on this thread there were different views
about it.


Yes, I will gladly pass the buck to the silly caller. It is the function 
caller's responsibility to use the function properly and check for error 
conditions the caller actually cares about. There is no way to know what 
exactly will be done with a chunk of published code in ten years or in 
ten hours. Basic C programming rules say to quietly work with as many 
inputs as possible and fail gracefully when something goes wrong. In the 
case of asking "ends with?" you get to choose between returning "int: 
true/false" or "int: more possible outputs than simple true/false" or 
"pointer to a string or NULL on failure." Since increasingly complex 
return values tend to require increasingly complex code to handle those 
possibilities, the question posed is most simply answered as a 
true/false question: "does string X end with Y?" Choosing for Y == 
 to return true or false is linguistically nonsensical but 
*logical from a byte-for-byte analysis perspective* for the reasons I 
discussed in my previous message.



In my opinion it would be better to cover such corner cases with
meaningful responses by analyzing the semantics of this new function
that checks if a _string_ ends with a specific _string_ or as somebody
suggested a specific _suffix_.


More meaningful responses (by which we are really discussing "return 
values" or--in one of the worst cases--structs passed as pointers and 
modified by the called function as the "return value") require more 
complicated code to handle those responses. Keeping responses as simple 
as possible minimizes code size AND complexity. Adding complexity is 
always bad by default unless adding complexity is ultimately the only 
"simple" solution. Passing struct pointers around in network packet 
handling code is unavoidable due to the information density required of 
the task, for example, but it makes no sense to apply such density to 
the straightforward question of "does this string end with this other 
string?"


We could always perform very complex analysis of such a simple question 
and return a series of bit flags for possibilities; for example, "yes, 
but the case of the text differs" or "no, but if you offset left by one 
character, yes" or "yes, and both substrings are in upper case." How 
complex should the answer to the question be? How much time should we 
waste trying to make our response more meaningful?


IMO for such a simple question, the calling code should be able to do 
something like this if it wants and just be done with it:


if (ends_with(a, b) == 1) do_true_work();
else do_false_work();

In this case, if b == '' and that's a problem for the calling code, the 
calling code should be going "if (*b == '\0') handle_empty_case()" and 
dealing with it prior to calling ends_with(). Likewise, it's possible 
that the author of the calling code knows that the data their code is 
working with can safely ignore what happens when empty strings are 
passed to ends_with() and attempting to "help" the author will only 
frustrate them instead and possibly force them to make more obnoxious 
code sort of like this:


x = ends_with(a, b);
switch (x) {
  case 0:
do_false_work();
break;
  case 1:
  case -1:
do_true_work();
break;
  default:
do_unknown_retval_error_message();
}

or a much smarter programmer not interested in a different response 
might instead do one of these to bypass such "helpfulness" in responses:


if (*b != '\0') {
  if (ends_with(a, b) == 0) {
do_false_work();
goto did_false_work;
  }
}
do_true_work();
did_false_work:
...

if (ends_with == 0) do_false_work();
else do_true_work();
...

An exercise for the reader: what happens to the code in all these 
workarounds if we have 0, 1, and 2 as return values for 
{false,true,empty} and then "improve" the function later by changing 
various "corner cases" to return negative values, or if we add return 
value 3 for {ends_with_if_shifted_left_by_one_char} or any other such 
"improvement" of similar type? Unless all *potential* future return 
value sets are clearly documented, we could break things in interesting 
ways!


Or, we just return "true/false" in the simplest possible way and stop 
pretending we know more than the calling programmer does about their code.



This suffix being non-existent is a anomaly that probably the caller
would like to be informed about.


Then let them check for it. The caller knows their input data set. We do 
not and we can never know in advance what will be thrown at any of the 
reusable functions we write.



If a useless answer for empty strings is a problem, the writer of th

Re: AW: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-25 Thread Tito



On 08/25/2015 09:00 AM, dietmar.schind...@manroland-web.com wrote:

Von: Tito
Gesendet: Montag, 24. August 2015 21:29

On 08/24/2015 12:51 AM, Jody Bruchon wrote:

On 2015-08-21 17:26, Tito wrote:

what sense would it make to check if str\0 ends_with \0 if all strings
do end with \0 ?


In this case, I view this as a problem of handling all possible valid
inputs in a robust manner. It can also make the code more efficient
since \0 is just another byte and is guaranteed to be at the end of any
valid string, thus solving the problem of what to do when passed an
empty (but properly zero-terminated) string without having to add code
for a special case and/or add parameters for string lengths.

It does not matter that "ends with " is a comparison that almost
certainly serves no practical purpose in the code calling it; what
matters is that the behavior is consistent if the calling code is silly
enough to pass empty strings and expect a meaningful response.


Hi Jody,
so you pass the buck to the silly caller to guess what is consistent,
but even in the few replies on this thread there were different views
about it.


To add a data point: I vote for Jody Bruchon's coherent view.


In my opinion it would be better to cover such corner cases with
meaningful responses by analyzing the semantics of this new function
that checks if a _string_ ends with a specific _string_ or as somebody
suggested a specific _suffix_.


An empty string is a string also; treating it accordingly is meaningful.


This suffix being non-existent is a anomaly that probably the caller
would like to be informed about.


Calling it an anomaly is a personal choice; I'd call it a normal extreme case.


If a useless answer for empty strings is a problem, the writer of the calling
code needs to handle that themselves, and is in a far more flexible
position to do so than the person writing the called function that only
answers "yes" or "no."


Why should a function give a useless answer?
Wouldn't it be better for the caller to give him
always useful answers (return different values, set errno, etc.).


We cannot predict the usefulness of all possible cases, so this question 
implies an unprovable assumption.


I also say that we're all C programmers if we're here fiddling with the
guts of BusyBox and we can all easily understand why returning "yes" for
"ends with \0?" is a technically correct result since all C strings end
with \0.


This is a somewhat dogmatic argument:
"The people of the inner circle know it better."

SusV3 instead for the strstr function of which ends_with() could be
considered a subset of functionality (just looks for s2 at the end of
s1) says:

"#include 

  char *strstr(const char *s1, const char *s2);

DESCRIPTION

  The strstr() function shall locate the first occurrence in the
string pointed to by s1 of the sequence of bytes (excluding the
terminating null byte) in the string pointed to by s2.

RETURN VALUE

  Upon successful completion, strstr() shall return a pointer to the
located string or a null pointer if the string is not found.

  If s2 points to a string with zero length, the function shall
return s1.

ERRORS

  No errors are defined."

So as you can see they explicitly request a specific action for the case
of a zero length key:

  "If s2 points to a string with zero length, the function shall
return s1."

Not that I like their solution but still this is a fact and makes me
think that we should also handle this corner case in better way
rather than return a "useless value".


We see that the strstr() function also does not handle a string with zero 
length in any special way;
the manual just states explicitly what results from normal proceeding according 
to the description.


Hi,

that what results is still the opposite of what results in the 
ends_with() way for basically the same problem.


Ciao,
Tito


--
Best regards,
Dietmar Schindler



___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-25 Thread Tito



On 08/24/2015 10:58 PM, Bartosz Gołaszewski wrote:

2015-08-24 21:29 GMT+02:00 Tito :



On 08/24/2015 12:51 AM, Jody Bruchon wrote:


On 2015-08-21 17:26, Tito wrote:


what sense would it make to check if str\0 ends_with \0 if all strings
do end with \0 ?



In this case, I view this as a problem of handling all possible valid
inputs in a robust manner. It can also make the code more efficient
since \0 is just another byte and is guaranteed to be at the end of any
valid string, thus solving the problem of what to do when passed an
empty (but properly zero-terminated) string without having to add code
for a special case and/or add parameters for string lengths.

It does not matter that "ends with " is a comparison that almost
certainly serves no practical purpose in the code calling it; what
matters is that the behavior is consistent if the calling code is silly
enough to pass empty strings and expect a meaningful response.



Hi Jody,
so you pass the buck to the silly caller to guess what is consistent, but
even in the few replies on this thread there were different views about it.
In my opinion it would be better to cover such corner cases with
meaningful responses by analyzing the semantics of this new function
that checks if a _string_ ends with a specific _string_ or as somebody
suggested a specific _suffix_.
This suffix being non-existent is a anomaly that probably the caller
would like to be informed about.


If a useless answer for empty strings is a problem, the writer of the
calling
code needs to handle that themselves, and is in a far more flexible
position to do so than the person writing the called function that only
answers "yes" or "no."



Why should a function give a useless answer?
Wouldn't it be better for the caller to give him
always useful answers (return different values, set errno, etc.).


I also say that we're all C programmers if we're here fiddling with the
guts of BusyBox and we can all easily understand why returning "yes" for
"ends with \0?" is a technically correct result since all C strings end
with \0.



This is a somewhat dogmatic argument:
"The people of the inner circle know it better."

SusV3 instead for the strstr function of which ends_with() could be
considered a subset of functionality (just looks for s2 at the end of s1)
says:

"#include 

 char *strstr(const char *s1, const char *s2);

DESCRIPTION

 The strstr() function shall locate the first occurrence in the string
pointed to by s1 of the sequence of bytes (excluding the terminating null
byte) in the string pointed to by s2.

RETURN VALUE

 Upon successful completion, strstr() shall return a pointer to the
located string or a null pointer if the string is not found.

 If s2 points to a string with zero length, the function shall return s1.

ERRORS

 No errors are defined."

So as you can see they explicitly request a specific action for the case
of a zero length key:

 "If s2 points to a string with zero length, the function shall return
s1."

Not that I like their solution but still this is a fact and makes me
think that we should also handle this corner case in better way
rather than return a "useless value".


To be honest this is the part of the series I don't really care much
about as opposed to the actual readahead patch that makes use of this
new function. Let's call it is_suffixed_with() to stay consistent with
is_prefixed_with() & make it return true for key="\0". The way it
works (including key="\0") shall be reflected in the comment
describing it. What do you think?


Hi,
this is a step in the right direction.

Thanks for your time and effort.

Ciao,
Tito
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

AW: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-25 Thread dietmar.schindler
> Von: Tito
> Gesendet: Montag, 24. August 2015 21:29
>
> On 08/24/2015 12:51 AM, Jody Bruchon wrote:
> > On 2015-08-21 17:26, Tito wrote:
> >> what sense would it make to check if str\0 ends_with \0 if all strings
> >> do end with \0 ?
> >
> > In this case, I view this as a problem of handling all possible valid
> > inputs in a robust manner. It can also make the code more efficient
> > since \0 is just another byte and is guaranteed to be at the end of any
> > valid string, thus solving the problem of what to do when passed an
> > empty (but properly zero-terminated) string without having to add code
> > for a special case and/or add parameters for string lengths.
> >
> > It does not matter that "ends with " is a comparison that almost
> > certainly serves no practical purpose in the code calling it; what
> > matters is that the behavior is consistent if the calling code is silly
> > enough to pass empty strings and expect a meaningful response.
>
> Hi Jody,
> so you pass the buck to the silly caller to guess what is consistent,
> but even in the few replies on this thread there were different views
> about it.

To add a data point: I vote for Jody Bruchon's coherent view.

> In my opinion it would be better to cover such corner cases with
> meaningful responses by analyzing the semantics of this new function
> that checks if a _string_ ends with a specific _string_ or as somebody
> suggested a specific _suffix_.

An empty string is a string also; treating it accordingly is meaningful.

> This suffix being non-existent is a anomaly that probably the caller
> would like to be informed about.

Calling it an anomaly is a personal choice; I'd call it a normal extreme case.

> > If a useless answer for empty strings is a problem, the writer of the 
> > calling
> > code needs to handle that themselves, and is in a far more flexible
> > position to do so than the person writing the called function that only
> > answers "yes" or "no."
>
> Why should a function give a useless answer?
> Wouldn't it be better for the caller to give him
> always useful answers (return different values, set errno, etc.).

We cannot predict the usefulness of all possible cases, so this question 
implies an unprovable assumption.

> > I also say that we're all C programmers if we're here fiddling with the
> > guts of BusyBox and we can all easily understand why returning "yes" for
> > "ends with \0?" is a technically correct result since all C strings end
> > with \0.
>
> This is a somewhat dogmatic argument:
> "The people of the inner circle know it better."
>
> SusV3 instead for the strstr function of which ends_with() could be
> considered a subset of functionality (just looks for s2 at the end of
> s1) says:
>
> "#include 
>
>  char *strstr(const char *s1, const char *s2);
>
> DESCRIPTION
>
>  The strstr() function shall locate the first occurrence in the
> string pointed to by s1 of the sequence of bytes (excluding the
> terminating null byte) in the string pointed to by s2.
>
> RETURN VALUE
>
>  Upon successful completion, strstr() shall return a pointer to the
> located string or a null pointer if the string is not found.
>
>  If s2 points to a string with zero length, the function shall
> return s1.
>
> ERRORS
>
>  No errors are defined."
>
> So as you can see they explicitly request a specific action for the case
> of a zero length key:
>
>  "If s2 points to a string with zero length, the function shall
> return s1."
>
> Not that I like their solution but still this is a fact and makes me
> think that we should also handle this corner case in better way
> rather than return a "useless value".

We see that the strstr() function also does not handle a string with zero 
length in any special way; the manual just states explicitly what results from 
normal proceeding according to the description.
--
Best regards,
Dietmar Schindler

manroland web systems GmbH -- Managing Director: Joern Gosse
Registered Office: Augsburg -- Trade Register: AG Augsburg -- HRB-No.: 26816 -- 
VAT: DE281389840

Confidentiality note:
This eMail and any files transmitted with it are confidential and intended 
solely for the use of the individual or entity to whom they are addressed. If 
you are not the intended recipient, you are hereby notified that any use or 
dissemination of this communication is strictly prohibited. If you have 
received this eMail in error, then please delete this eMail.

! Please consider your environmental responsibility before printing this eMail !

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-24 Thread Xabier Oneca -- xOneca
Hello Tito,

2015-08-24 21:29 GMT+02:00 Tito :
> So as you can see they explicitly request a specific action for the case
> of a zero length key:
>
> "If s2 points to a string with zero length, the function shall return
> s1."
>
> Not that I like their solution but still this is a fact and makes me
> think that we should also handle this corner case in better way
> rather than return a "useless value".

uClibc does exactly that, but doesn't treat an empty key in a special
way. It simply returns full string as a 'side effect' of the search
algorithm used.

That said, I have realized now that there's a previous similar
function called is_prefixed_with, which finds if a string starts with
a key and returns the rest of the string if found (i.e. the string
without the prefix).

And, as already has said Bartosz, maybe the correct name for ends_with
may be is_suffixed_with. But for consistency it should also return the
string at the position of the match or something like that. But until
it's return value is not consistent with is_prefixed_with, I would
*leave* it as ends_with to prevent confusion.

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-24 Thread Xabier Oneca -- xOneca
Hello Bartosz,

2015-08-24 22:58 GMT+02:00 Bartosz Gołaszewski :
> To be honest this is the part of the series I don't really care much
> about as opposed to the actual readahead patch that makes use of this
> new function.

Then you should have made ends_with patch part of the same patch as
readahead implementation, so it would have gone unnoticed! ;)

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-24 Thread Bartosz Gołaszewski
2015-08-24 21:29 GMT+02:00 Tito :
>
>
> On 08/24/2015 12:51 AM, Jody Bruchon wrote:
>>
>> On 2015-08-21 17:26, Tito wrote:
>>>
>>> what sense would it make to check if str\0 ends_with \0 if all strings
>>> do end with \0 ?
>>
>>
>> In this case, I view this as a problem of handling all possible valid
>> inputs in a robust manner. It can also make the code more efficient
>> since \0 is just another byte and is guaranteed to be at the end of any
>> valid string, thus solving the problem of what to do when passed an
>> empty (but properly zero-terminated) string without having to add code
>> for a special case and/or add parameters for string lengths.
>>
>> It does not matter that "ends with " is a comparison that almost
>> certainly serves no practical purpose in the code calling it; what
>> matters is that the behavior is consistent if the calling code is silly
>> enough to pass empty strings and expect a meaningful response.
>
>
> Hi Jody,
> so you pass the buck to the silly caller to guess what is consistent, but
> even in the few replies on this thread there were different views about it.
> In my opinion it would be better to cover such corner cases with
> meaningful responses by analyzing the semantics of this new function
> that checks if a _string_ ends with a specific _string_ or as somebody
> suggested a specific _suffix_.
> This suffix being non-existent is a anomaly that probably the caller
> would like to be informed about.
>
>> If a useless answer for empty strings is a problem, the writer of the
>> calling
>> code needs to handle that themselves, and is in a far more flexible
>> position to do so than the person writing the called function that only
>> answers "yes" or "no."
>
>
> Why should a function give a useless answer?
> Wouldn't it be better for the caller to give him
> always useful answers (return different values, set errno, etc.).
>
>> I also say that we're all C programmers if we're here fiddling with the
>> guts of BusyBox and we can all easily understand why returning "yes" for
>> "ends with \0?" is a technically correct result since all C strings end
>> with \0.
>
>
> This is a somewhat dogmatic argument:
> "The people of the inner circle know it better."
>
> SusV3 instead for the strstr function of which ends_with() could be
> considered a subset of functionality (just looks for s2 at the end of s1)
> says:
>
> "#include 
>
> char *strstr(const char *s1, const char *s2);
>
> DESCRIPTION
>
> The strstr() function shall locate the first occurrence in the string
> pointed to by s1 of the sequence of bytes (excluding the terminating null
> byte) in the string pointed to by s2.
>
> RETURN VALUE
>
> Upon successful completion, strstr() shall return a pointer to the
> located string or a null pointer if the string is not found.
>
> If s2 points to a string with zero length, the function shall return s1.
>
> ERRORS
>
> No errors are defined."
>
> So as you can see they explicitly request a specific action for the case
> of a zero length key:
>
> "If s2 points to a string with zero length, the function shall return
> s1."
>
> Not that I like their solution but still this is a fact and makes me
> think that we should also handle this corner case in better way
> rather than return a "useless value".

To be honest this is the part of the series I don't really care much
about as opposed to the actual readahead patch that makes use of this
new function. Let's call it is_suffixed_with() to stay consistent with
is_prefixed_with() & make it return true for key="\0". The way it
works (including key="\0") shall be reflected in the comment
describing it. What do you think?

-- 
Best regards,
Bartosz Golaszewski
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-24 Thread Tito



On 08/24/2015 12:51 AM, Jody Bruchon wrote:

On 2015-08-21 17:26, Tito wrote:

what sense would it make to check if str\0 ends_with \0 if all strings
do end with \0 ?


In this case, I view this as a problem of handling all possible valid
inputs in a robust manner. It can also make the code more efficient
since \0 is just another byte and is guaranteed to be at the end of any
valid string, thus solving the problem of what to do when passed an
empty (but properly zero-terminated) string without having to add code
for a special case and/or add parameters for string lengths.

It does not matter that "ends with " is a comparison that almost
certainly serves no practical purpose in the code calling it; what
matters is that the behavior is consistent if the calling code is silly
enough to pass empty strings and expect a meaningful response.


Hi Jody,
so you pass the buck to the silly caller to guess what is consistent, 
but even in the few replies on this thread there were different views 
about it.

In my opinion it would be better to cover such corner cases with
meaningful responses by analyzing the semantics of this new function
that checks if a _string_ ends with a specific _string_ or as somebody
suggested a specific _suffix_.
This suffix being non-existent is a anomaly that probably the caller
would like to be informed about.


If a useless answer for empty strings is a problem, the writer of the calling
code needs to handle that themselves, and is in a far more flexible
position to do so than the person writing the called function that only
answers "yes" or "no."


Why should a function give a useless answer?
Wouldn't it be better for the caller to give him
always useful answers (return different values, set errno, etc.).


I also say that we're all C programmers if we're here fiddling with the
guts of BusyBox and we can all easily understand why returning "yes" for
"ends with \0?" is a technically correct result since all C strings end
with \0.


This is a somewhat dogmatic argument:
"The people of the inner circle know it better."

SusV3 instead for the strstr function of which ends_with() could be
considered a subset of functionality (just looks for s2 at the end of 
s1) says:


"#include 

char *strstr(const char *s1, const char *s2);

DESCRIPTION

The strstr() function shall locate the first occurrence in the 
string pointed to by s1 of the sequence of bytes (excluding the 
terminating null byte) in the string pointed to by s2.


RETURN VALUE

Upon successful completion, strstr() shall return a pointer to the 
located string or a null pointer if the string is not found.


If s2 points to a string with zero length, the function shall 
return s1.


ERRORS

No errors are defined."

So as you can see they explicitly request a specific action for the case
of a zero length key:

"If s2 points to a string with zero length, the function shall 
return s1."


Not that I like their solution but still this is a fact and makes me
think that we should also handle this corner case in better way
rather than return a "useless value".

Ciao,
Tito


Since there is no correct answer from a layman's perspective
(or even a linguistic interpretation), the technically correct result is
the only valid way I can see to resolve the stalemate and avoid making
an arbitrary choice.

-Jody


___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-23 Thread Jody Bruchon

On 2015-08-21 17:26, Tito wrote:

what sense would it make to check if str\0 ends_with \0 if all strings
do end with \0 ?


In this case, I view this as a problem of handling all possible valid 
inputs in a robust manner. It can also make the code more efficient 
since \0 is just another byte and is guaranteed to be at the end of any 
valid string, thus solving the problem of what to do when passed an 
empty (but properly zero-terminated) string without having to add code 
for a special case and/or add parameters for string lengths.


It does not matter that "ends with " is a comparison that almost 
certainly serves no practical purpose in the code calling it; what 
matters is that the behavior is consistent if the calling code is silly 
enough to pass empty strings and expect a meaningful response. If a 
useless answer for empty strings is a problem, the writer of the calling 
code needs to handle that themselves, and is in a far more flexible 
position to do so than the person writing the called function that only 
answers "yes" or "no."


I also say that we're all C programmers if we're here fiddling with the 
guts of BusyBox and we can all easily understand why returning "yes" for 
"ends with \0?" is a technically correct result since all C strings end 
with \0. Since there is no correct answer from a layman's perspective 
(or even a linguistic interpretation), the technically correct result is 
the only valid way I can see to resolve the stalemate and avoid making 
an arbitrary choice.


-Jody
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-22 Thread walter harms


Am 21.08.2015 22:34, schrieb Xabier Oneca -- xOneca:
> Hello Walter,
> 
> 2015-08-21 18:26 GMT+02:00 walter harms :
>>
>> maybe its a bit late but ...
>>
>> the function name is a bit unfortunate whats about has_suffix() ?
>>
>> you can improve readability by returning strcmp directly and calculating
>> the len immediately.
>>
>> int has_suffix(const char *str, const char *key)
>> {
>> size_t len = strlen(str)-strlen(key);
>>
>> if (len < 0 )
>> return -1;
>>
>> return strcmp(str + len, key);
>> }
>>
>> re,
>>  wh
> 
> strcmp returns 0 when they match. I think it makes more sense if
> has_suffix returns 1 if match, 0 otherwise:
> 
> return !strcmp(str + str_len - key_len, key);
> 
> Also, can len be < 0? Isn't size_t unsigned?


yep, you are right to much c&p, i should have stayed with int.
my idea was make something compatible to strcmp().

my original also had tests for !key etc. the question is: Is that needed ?

re,
 wh

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Rich Felker
On Fri, Aug 21, 2015 at 06:26:27PM +0200, walter harms wrote:
> 
> 
> Am 21.08.2015 16:23, schrieb Bartosz Golaszewski:
> > This function checks if given key can be found at the end of the string.
> > 
> > Signed-off-by: Bartosz Golaszewski 
> > ---
> >  include/libbb.h  |  1 +
> >  libbb/compare_string_array.c | 30 ++
> >  2 files changed, 31 insertions(+)
> > 
> > diff --git a/include/libbb.h b/include/libbb.h
> > index a56b684..7b41c9b 100644
> > --- a/include/libbb.h
> > +++ b/include/libbb.h
> > @@ -422,6 +422,7 @@ const char *bb_basename(const char *name) FAST_FUNC;
> >  char *last_char_is(const char *s, int c) FAST_FUNC;
> >  const char* endofname(const char *name) FAST_FUNC;
> >  char *is_prefixed_with(const char *string, const char *key) FAST_FUNC;
> > +int ends_with(const char *str, const char *key) FAST_FUNC;
> >  
> >  int ndelay_on(int fd) FAST_FUNC;
> >  int ndelay_off(int fd) FAST_FUNC;
> > diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
> > index e24815a..a2d77c7 100644
> > --- a/libbb/compare_string_array.c
> > +++ b/libbb/compare_string_array.c
> > @@ -23,6 +23,19 @@ char* FAST_FUNC is_prefixed_with(const char *string, 
> > const char *key)
> >  #endif
> >  }
> >  
> > +int FAST_FUNC ends_with(const char *str, const char *key)
> > +{
> > +   size_t str_len = strlen(str), key_len = strlen(key);
> > +
> > +   if (str_len >= key_len) {
> > +   if (strcmp(str + str_len - key_len, key) == 0) {
> > +   return 1;
> > +   }
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> 
> maybe its a bit late but ...
> 
> the function name is a bit unfortunate whats about has_suffix() ?
> 
> you can improve readability by returning strcmp directly and calculating
> the len immediately.
> 
> int has_suffix(const char *str, const char *key)
> {
> size_t len = strlen(str)-strlen(key);
> 
> if (len < 0 )
>   return -1;

No you can't. len<0 is always false because len is unsigned. The
original code in the patch was correct; your version is buggy.

Rich
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Xabier Oneca -- xOneca
Hello,

2015-08-21 23:26 GMT+02:00 Tito :
> what sense would it make to check if str\0 ends_with \0 if all strings do
> end with \0 ?

It can be helpful when key is dynamically created (e.g. extracted from
a string) and it comes as an empty string.

But it also depends on context: If it is too often checked that (*key
== 0) before calling ends_with, it makes sense to embed that check in
ends_with. If it doesn't matter, then why make the code (and binary)
bigger?

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Tito



On 08/21/2015 10:46 PM, Xabier Oneca -- xOneca wrote:

Hello tito,


[...]

  ./test
'testprova' ends_with 'test' = no
'testprova' ends_with 'prova' = yes
'test' ends_with 'prova' = no
'test' ends_with 'testprova' = no
'' ends_with 'testprova' = no
'test' ends_with '' = yes

and I wonder if the last test result is correct:

'test' ends_with '' = yes

Just for fun I've also added a different implementation that
seems to do the right thing (at least for me):

'testprova' ends_with 'test' = no
'testprova' ends_with 'prova' = yes
'test' ends_with 'prova' = no
'test' ends_with 'testprova' = no
'' ends_with 'testprova' = no
'test' ends_with '' = no


Well, The Right Thing(tm) depends on the use case of ends_with()...

To me that last line is correct, because "test\0" *ends* wtih "\0".
But in a context where key should not be empty your exception may make
sense.

Cheers,

Xabier Oneca_,,_



Hi,

what sense would it make to check if str\0 ends_with \0 if all strings 
do end with \0 ?


Ciao,
Tito
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Xabier Oneca -- xOneca
Hello tito,

> [...]
>
>  ./test
> 'testprova' ends_with 'test' = no
> 'testprova' ends_with 'prova' = yes
> 'test' ends_with 'prova' = no
> 'test' ends_with 'testprova' = no
> '' ends_with 'testprova' = no
> 'test' ends_with '' = yes
>
> and I wonder if the last test result is correct:
>
> 'test' ends_with '' = yes
>
> Just for fun I've also added a different implementation that
> seems to do the right thing (at least for me):
>
> 'testprova' ends_with 'test' = no
> 'testprova' ends_with 'prova' = yes
> 'test' ends_with 'prova' = no
> 'test' ends_with 'testprova' = no
> '' ends_with 'testprova' = no
> 'test' ends_with '' = no

Well, The Right Thing(tm) depends on the use case of ends_with()...

To me that last line is correct, because "test\0" *ends* wtih "\0".
But in a context where key should not be empty your exception may make
sense.

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Xabier Oneca -- xOneca
2015-08-21 22:34 GMT+02:00 Xabier Oneca  --  xOneca :
> Hello Walter,
>
> 2015-08-21 18:26 GMT+02:00 walter harms :
>>
>> maybe its a bit late but ...
>>
>> the function name is a bit unfortunate whats about has_suffix() ?
>>
>> you can improve readability by returning strcmp directly and calculating
>> the len immediately.
>>
>> int has_suffix(const char *str, const char *key)
>> {
>> size_t len = strlen(str)-strlen(key);
>>
>> if (len < 0 )
>> return -1;
>>
>> return strcmp(str + len, key);
>> }
>>
>> re,
>>  wh
>
> strcmp returns 0 when they match. I think it makes more sense if
> has_suffix returns 1 if match, 0 otherwise:
>
> return !strcmp(str + str_len - key_len, key);

Should have been:

return !strcmp(str + len, key);

Sorry, I copied Bartosz's strcmp line, but you get it.. ;)

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Xabier Oneca -- xOneca
Hello Walter,

2015-08-21 18:26 GMT+02:00 walter harms :
>
> maybe its a bit late but ...
>
> the function name is a bit unfortunate whats about has_suffix() ?
>
> you can improve readability by returning strcmp directly and calculating
> the len immediately.
>
> int has_suffix(const char *str, const char *key)
> {
> size_t len = strlen(str)-strlen(key);
>
> if (len < 0 )
> return -1;
>
> return strcmp(str + len, key);
> }
>
> re,
>  wh

strcmp returns 0 when they match. I think it makes more sense if
has_suffix returns 1 if match, 0 otherwise:

return !strcmp(str + str_len - key_len, key);

Also, can len be < 0? Isn't size_t unsigned?

Cheers,

Xabier Oneca_,,_
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread tito
Hi,

I've written a little test program to look at some corner cases for this new 
ends_with function:

#include 
#include 

int ends_with(const char *str, const char *key)
{
size_t str_len = strlen(str), key_len = strlen(key);

if (str_len >= key_len) {
if (strcmp(str + str_len - key_len, key) == 0) {
return 1;
}
}

return 0;
}

int my_ends_with(const char *str, const char *key)
{
char *p;
const char *s = str;

while((p = strstr(s, key)) != NULL && *key != 0) {
//  printf("p = %s s = %s\n", p, s);
if (strcmp(p, key) == 0)
return 1;
s++;
}
return 0;
}

int main(int argc, char **argv)
{
printf("'%s' ends_with '%s' = %s\n", "testprova", "test", 
(ends_with("testprova", "test")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "testprova", "prova", 
(ends_with("testprova", "prova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "prova", 
(ends_with("test", "prova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "testprova", 
(ends_with("test", "testprova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "", "testprova", (ends_with("", 
"testprova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "", (ends_with("test", 
"")) ? "yes" : "no");

puts("==");
printf("'%s' ends_with '%s' = %s\n", "testprova", "test", 
(my_ends_with("testprova", "test")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "testprova", "prova", 
(my_ends_with("testprova", "prova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "prova", 
(my_ends_with("test", "prova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "testprova", 
(my_ends_with("test", "testprova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "", "testprova", (my_ends_with("", 
"testprova")) ? "yes" : "no");
printf("'%s' ends_with '%s' = %s\n", "test", "", (my_ends_with("test", 
"")) ? "yes" : "no");

return 0;
}

The output is:

 ./test
'testprova' ends_with 'test' = no
'testprova' ends_with 'prova' = yes
'test' ends_with 'prova' = no
'test' ends_with 'testprova' = no
'' ends_with 'testprova' = no
'test' ends_with '' = yes

and I wonder if the last test result is correct:

'test' ends_with '' = yes

Just for fun I've also added a different implementation that
seems to do the right thing (at least for me):

'testprova' ends_with 'test' = no
'testprova' ends_with 'prova' = yes
'test' ends_with 'prova' = no
'test' ends_with 'testprova' = no
'' ends_with 'testprova' = no
'test' ends_with '' = no

Ciao,
Tito
 


 

On 08/21/2015 06:26 PM, walter harms wrote:
>
>
> Am 21.08.2015 16:23, schrieb Bartosz Golaszewski:
>> This function checks if given key can be found at the end of the string.
>>
>> Signed-off-by: Bartosz Golaszewski 
>> ---
>>   include/libbb.h  |  1 +
>>   libbb/compare_string_array.c | 30 ++
>>   2 files changed, 31 insertions(+)
>>
>> diff --git a/include/libbb.h b/include/libbb.h
>> index a56b684..7b41c9b 100644
>> --- a/include/libbb.h
>> +++ b/include/libbb.h
>> @@ -422,6 +422,7 @@ const char *bb_basename(const char *name) FAST_FUNC;
>>   char *last_char_is(const char *s, int c) FAST_FUNC;
>>   const char* endofname(const char *name) FAST_FUNC;
>>   char *is_prefixed_with(const char *string, const char *key) FAST_FUNC;
>> +int ends_with(const char *str, const char *key) FAST_FUNC;
>>
>>   int ndelay_on(int fd) FAST_FUNC;
>>   int ndelay_off(int fd) FAST_FUNC;
>> diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
>> index e24815a..a2d77c7 100644
>> --- a/libbb/compare_string_array.c
>> +++ b/libbb/compare_string_array.c
>> @@ -23,6 +23,19 @@ char* FAST_FUNC is_prefixed_with(const char *string, 
>> const char *key)
>>   #endif
>>   }
>>
>> +int FAST_FUNC ends_with(const char *str, const char *key)
>> +{
>> +size_t str_len = strlen(str), key_len = strlen(key);
>> +
>> +if (str_len >= key_len) {
>> +if (strcmp(str + str_len - key_len, key) == 0) {
>> +return 1;
>> +}
>> +}
>> +
>> +return 0;
>> +}
>> +
>
> maybe its a bit late but ...
>
> the function name is a bit unfortunate whats about has_suffix() ?
>
> you can improve readability by returning strcmp directly and calculating
> the len immediately.
>
> int has_suffix(const char *str, const char *key)
> {
>  size_t len = strlen(str)-strlen(key);
>
>  if (len < 0 )
>   return -1;
>
>  return strcmp(str + len, key);
> }
>
> re,
>   wh
>
>
>>   /* returns the array index of the string */
>>   /* (index of first match is returned, or -1) */
>>   int 

Re: [RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread walter harms


Am 21.08.2015 16:23, schrieb Bartosz Golaszewski:
> This function checks if given key can be found at the end of the string.
> 
> Signed-off-by: Bartosz Golaszewski 
> ---
>  include/libbb.h  |  1 +
>  libbb/compare_string_array.c | 30 ++
>  2 files changed, 31 insertions(+)
> 
> diff --git a/include/libbb.h b/include/libbb.h
> index a56b684..7b41c9b 100644
> --- a/include/libbb.h
> +++ b/include/libbb.h
> @@ -422,6 +422,7 @@ const char *bb_basename(const char *name) FAST_FUNC;
>  char *last_char_is(const char *s, int c) FAST_FUNC;
>  const char* endofname(const char *name) FAST_FUNC;
>  char *is_prefixed_with(const char *string, const char *key) FAST_FUNC;
> +int ends_with(const char *str, const char *key) FAST_FUNC;
>  
>  int ndelay_on(int fd) FAST_FUNC;
>  int ndelay_off(int fd) FAST_FUNC;
> diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
> index e24815a..a2d77c7 100644
> --- a/libbb/compare_string_array.c
> +++ b/libbb/compare_string_array.c
> @@ -23,6 +23,19 @@ char* FAST_FUNC is_prefixed_with(const char *string, const 
> char *key)
>  #endif
>  }
>  
> +int FAST_FUNC ends_with(const char *str, const char *key)
> +{
> + size_t str_len = strlen(str), key_len = strlen(key);
> +
> + if (str_len >= key_len) {
> + if (strcmp(str + str_len - key_len, key) == 0) {
> + return 1;
> + }
> + }
> +
> + return 0;
> +}
> +

maybe its a bit late but ...

the function name is a bit unfortunate whats about has_suffix() ?

you can improve readability by returning strcmp directly and calculating
the len immediately.

int has_suffix(const char *str, const char *key)
{
size_t len = strlen(str)-strlen(key);

if (len < 0 )
return -1;

return strcmp(str + len, key);
}

re,
 wh


>  /* returns the array index of the string */
>  /* (index of first match is returned, or -1) */
>  int FAST_FUNC index_in_str_array(const char *const string_array[], const 
> char *key)
> @@ -110,3 +123,20 @@ smallint FAST_FUNC yesno(const char *str)
>   return ret / 3;
>  }
>  #endif
> +
> +#if ENABLE_UNIT_TEST
> +
> +BBUNIT_DEFINE_TEST(ends_with)
> +{
> + BBUNIT_ASSERT_TRUE(ends_with("foo bar", "bar"));
> + BBUNIT_ASSERT_TRUE(ends_with("foo", "foo"));
> + BBUNIT_ASSERT_TRUE(ends_with("foo", ""));
> + BBUNIT_ASSERT_TRUE(ends_with("", ""));
> +
> + BBUNIT_ASSERT_FALSE(ends_with("foo", "bar foo"));
> + BBUNIT_ASSERT_FALSE(ends_with("foo foo", "bar"));
> +
> + BBUNIT_ENDTEST;
> +}
> +
> +#endif /* ENABLE_UNIT_TEST */
___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox


[RFC/PATCH v2 3/5] libbb: add ends_with() function

2015-08-21 Thread Bartosz Golaszewski
This function checks if given key can be found at the end of the string.

Signed-off-by: Bartosz Golaszewski 
---
 include/libbb.h  |  1 +
 libbb/compare_string_array.c | 30 ++
 2 files changed, 31 insertions(+)

diff --git a/include/libbb.h b/include/libbb.h
index a56b684..7b41c9b 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -422,6 +422,7 @@ const char *bb_basename(const char *name) FAST_FUNC;
 char *last_char_is(const char *s, int c) FAST_FUNC;
 const char* endofname(const char *name) FAST_FUNC;
 char *is_prefixed_with(const char *string, const char *key) FAST_FUNC;
+int ends_with(const char *str, const char *key) FAST_FUNC;
 
 int ndelay_on(int fd) FAST_FUNC;
 int ndelay_off(int fd) FAST_FUNC;
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
index e24815a..a2d77c7 100644
--- a/libbb/compare_string_array.c
+++ b/libbb/compare_string_array.c
@@ -23,6 +23,19 @@ char* FAST_FUNC is_prefixed_with(const char *string, const 
char *key)
 #endif
 }
 
+int FAST_FUNC ends_with(const char *str, const char *key)
+{
+   size_t str_len = strlen(str), key_len = strlen(key);
+
+   if (str_len >= key_len) {
+   if (strcmp(str + str_len - key_len, key) == 0) {
+   return 1;
+   }
+   }
+
+   return 0;
+}
+
 /* returns the array index of the string */
 /* (index of first match is returned, or -1) */
 int FAST_FUNC index_in_str_array(const char *const string_array[], const char 
*key)
@@ -110,3 +123,20 @@ smallint FAST_FUNC yesno(const char *str)
return ret / 3;
 }
 #endif
+
+#if ENABLE_UNIT_TEST
+
+BBUNIT_DEFINE_TEST(ends_with)
+{
+   BBUNIT_ASSERT_TRUE(ends_with("foo bar", "bar"));
+   BBUNIT_ASSERT_TRUE(ends_with("foo", "foo"));
+   BBUNIT_ASSERT_TRUE(ends_with("foo", ""));
+   BBUNIT_ASSERT_TRUE(ends_with("", ""));
+
+   BBUNIT_ASSERT_FALSE(ends_with("foo", "bar foo"));
+   BBUNIT_ASSERT_FALSE(ends_with("foo foo", "bar"));
+
+   BBUNIT_ENDTEST;
+}
+
+#endif /* ENABLE_UNIT_TEST */
-- 
2.1.4

___
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox