mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@aerifal.cx>
To: musl@lists.openwall.com
Subject: Re: strverscmp
Date: Sun, 17 Feb 2013 13:39:44 -0500	[thread overview]
Message-ID: <20130217183944.GF20323@brightrain.aerifal.cx> (raw)
In-Reply-To: <20130201200452.26687bed.idunham@lavabit.com>

Hey, sorry it's taken me so long to get to reading and reviewing this
well. Here are some comments, mostly stylistic, but one's about a
corner-case bug. See below. With that said, the algorithm looks right
to me, and I think we can commit soon.

Rich


On Fri, Feb 01, 2013 at 08:04:52PM -0800, Isaac Dunham wrote:
> On Fri, 1 Feb 2013 21:38:33 -0500
> Rich Felker <dalias@aerifal.cx> wrote:
> 
> > > Fix strverscmp (patch same as the last time I sent it)
> > 
> > I'm not sure whether we got it into a fully-working state or not; the
> > conversation kinda died out last time. I'll review it again too. I
> > remember it didn't look quite like the algorithm I described/proposed,
> > but that doesn't mean it's wrong. It looked like it could at least use
> > some streamlining though.
> 
> The last review was just before I got it working. Here's the final version.
> 
> Probably somewhere it could be optimized, though...
> As long as it doesn't end up looking like the GNU one.
> 
> -- 
> Isaac Dunham <idunham@lavabit.com>

> diff --git a/src/string/strverscmp.c b/src/string/strverscmp.c
> index 7054967..8f3f11f 100644
> --- a/src/string/strverscmp.c
> +++ b/src/string/strverscmp.c
> @@ -1,7 +1,41 @@
> +#define _GNU_SOURCE
> +#include <ctype.h>
>  #include <string.h>
>  
>  int strverscmp(const char *l, const char *r)
>  {
> -	/* FIXME */
> -	return strcmp(l, r);
> +	int haszero=1;
> +	while (*l && *r && l[0]==r[0]){

I used to do a lot of while loops like this, but now I feel like it
makes it hard to follow the end-of-string logic -- a lot more code
runs after the null terminator is hit, and it's nontrivial to follow
through it all and make sure the right thing happens, as the
subsequent code after the loop is now handling two very-distinct
loop-exit conditions:

1. Loop exited due to mismatch.
2. Loop exited due to hitting end-of-string with no mismatch.

What about instead doing something like this:

	while (*l==*r) {
		if (!*l) return 0;
		/* ... */

That way, the "equal strings" case is trivially correct. It also might
generate better code.

Note that I also made a couple stylistic changes here; unless you
object, I prefer *p to p[0] when p is just being used as a moving
pointer within a string, always accessed with offset 0. It's just more
concise/less cluttered and avoids suggesting it's used as a string in
itself. Also added a space before the open brace, for consistency with
style elsewhere.


> +		if (l[0]=='0'){
> +			if (haszero==1) {
> +				haszero=0;
> +			}
> +		} else if (isdigit(l[0])) {
> +			if (haszero==1) {
> +				haszero=2;
> +			}
> +		} else {
> +			haszero=1;
> +		}
> +		l++; r++;
> +	}
> +	if (haszero==1 && (l[0]=='0' || r[0]=='0')) {
> +		haszero=0;
> +	}
> +	if ((isdigit(l[0]) && isdigit(r[0]) ) && haszero) {
> +		int lenl=0, lenr=0, firstl=l[0], firstr=r[0];

These variables have the wrong types. int is not sufficient to store a
character count in a string. You need size_t.

> +		while (isdigit(l++[0]) ) {
> +			lenl++;
> +		}
> +		while (isdigit(r++[0]) ) {
> +			lenr++;
> +		}
> +		if (lenl==lenr) {
> +			return (firstl -  firstr);
> +		} else {
> +			return (lenl - lenr);
> +		}

I see what's going on here, but I find saving the first mismatching
characters (btw, you could have just saved the difference) then
continuing to advance the l/r pointers a bit confusing at first. Why
not instead do:

		while (isdigit(l[lenl])) lenl++;


  reply	other threads:[~2013-02-17 18:39 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-02-01  7:10 musl 0.9.9 released Rich Felker
2013-02-02  2:23 ` Isaac Dunham
2013-02-02  2:38   ` Rich Felker
2013-02-02  4:04     ` strverscmp Isaac Dunham
2013-02-17 18:39       ` Rich Felker [this message]
2013-02-19  1:15         ` strverscmp Isaac Dunham
2013-02-26  6:40           ` strverscmp Rich Felker
2013-02-02  5:14     ` fgetgrent Isaac Dunham
2013-02-02  5:32       ` fgetgrent Rich Felker
2013-02-17 18:50       ` fgetgrent Rich Felker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130217183944.GF20323@brightrain.aerifal.cx \
    --to=dalias@aerifal.cx \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).