Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Feb 2006 16:02:37 +0100
From:      Ulrich Spoerlein <q@galgenberg.net>
To:        Peter Jeremy <peterjeremy@optushome.com.au>
Cc:        hackers@freebsd.org
Subject:   Re: Naive implementation of strverscmp(3)
Message-ID:  <20060215150237.GA1123@galgenberg.net>
In-Reply-To: <20060215080532.GB684@turion.vk2pj.dyndns.org>
References:  <20060214212503.GE1107@galgenberg.net> <20060215080532.GB684@turion.vk2pj.dyndns.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--A6N2fC+uXW/VQSAv
Content-Type: multipart/mixed; boundary="r5Pyd7+fXNt84Ff3"
Content-Disposition: inline


--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Peter Jeremy wrote:
> >Is there a chance this might get included into libc? Or is it considered=
=20
> >bloat?
>I don't think it belongs in libc.  Maybe libutil.

This would require patching the gqview configure script, but I can live=20
with that.

>For the first point, consider
>   strverscmp("jan25", "janx25");

This fell victim to a rearranging of the while loop. Thanks for pointing=20
that out!

Attached is an updated version, which now also takes leading zeros into=20
account. It still differs from the GNU version, because
strverscmp("foo.009", "foo.0") > 0
In my book, '009' is just greater than zero, no matter what. If someone=20
could explain to me, why the GNU folks do it the other way round, I=20
could try implementing that too.

Also, what do people think about the commented out while construct? It=20
saves a call to strcspn(s2) if s1 has no digits, but it's rather ugly.


Ulrich Spoerlein
--=20
  PGP Key ID: 20FEE9DD				Encrypted mail welcome!
Fingerprint: AEC9 AF5E 01AC 4EE1 8F70  6CBD E76E 2227 20FE E9DD
Which is worse: ignorance or apathy?
Don't know. Don't care.

--r5Pyd7+fXNt84Ff3
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="strverscmp.c"
Content-Transfer-Encoding: quoted-printable

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#ifdef __FreeBSD__
int
strverscmp(const char *s1, const char *s2);

int
strverscmp(const char *s1, const char *s2)
{
  static const char *digits =3D "0123456789";
  char *t1, *t2;
  int ret;
  long n1, n2;
  size_t p1, p2;

  p1 =3D strcspn(s1, digits);
  p2 =3D strcspn(s2, digits);
  //while ((p1=3Dstrcspn(s1, digits)) !=3D 0 && p1 =3D=3D (p2=3Dstrcspn(s2,=
 digits))) {
  while (p1 =3D=3D p2 && p1 !=3D 0) {
 =20
    /* Different prefix */
    if ((ret =3D strncmp(s1, s2, p1)) !=3D 0)
      return ret;

    s1 +=3D p1;
    s2 +=3D p2;
    n1 =3D strtol(s1, &t1, 10);
    n2 =3D strtol(s2, &t2, 10);
   =20
    if (n1 < n2)
      return -1;
    else if (n1 > n2)
      return 1;

    /* One number is "shorter", e.g., "07" vs "007" */
    if (t1-s1 < t2-s2)
      return 1;
    else if (t1-s1 > t2-s2)
      return -1;

    /* Numbers are equal or not present, try with next ones. */
    s1 =3D t1;
    s2 =3D t2;
    p1 =3D strcspn(s1, digits);
    p2 =3D strcspn(s2, digits);
  }
 =20
  return strcmp(s1, s2);
}
#endif

int
main(int argc, char **argv)
{
  char **array, *temp;
  int i, j, n =3D 10;

  array =3D (char **) calloc(n, sizeof(char *));
  array[0] =3D strdup("jan009");
  array[1] =3D strdup("jan10");
  array[2] =3D strdup("jan09");
  array[3] =3D strdup("jan0a");
  array[4] =3D strdup("jan17b");
  array[5] =3D strdup("jan17a");
  array[6] =3D strdup("janx25");
  array[7] =3D strdup("jan25");
  array[8] =3D strdup("jan17x");
  array[9] =3D strdup("jan9");

  /* Bubble sort */
  for (i=3D0; i<n; ++i) {
    for (j=3Di; j<n; ++j) {
      if (strverscmp(array[i], array[j]) > 0) {
	temp =3D array[j];
	array[j] =3D array[i];
	array[i] =3D temp;
      }
    }
  }

  for (i=3D0; i<n; ++i) {
    printf("%s\n", array[i]);
  }

  printf("%d =3D 0\n", strverscmp("a", "a"));
  printf("%d < 0\n", strverscmp("item#99", "item#100"));
  printf("%d > 0\n", strverscmp("alpha1", "alpha001"));
  printf("%d > 0\n", strverscmp("part1_f012", "part1_f01"));
  printf("%d < 0\n", strverscmp("foo.009", "foo.0"));
  printf("%d\n", strcmp("jan25", "janx25"));
  printf("%d\n", strverscmp("jan25", "janx25"));

  return 0;
}

--r5Pyd7+fXNt84Ff3--

--A6N2fC+uXW/VQSAv
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (FreeBSD)

iD8DBQFD80KN524iJyD+6d0RAtNRAKCE8oRGCVNDlIryk4PQXloTCeKPCACff7mZ
WW7inlp+3GrRoOzGKG7WjIc=
=bGHa
-----END PGP SIGNATURE-----

--A6N2fC+uXW/VQSAv--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060215150237.GA1123>