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

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

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

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

Attached is an updated version, which now also takes leading zeros into 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 could explain to me, why the GNU folks do it the other way round, I could try implementing that too.

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


Ulrich Spoerlein
--
 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.
#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 = "0123456789";
  char *t1, *t2;
  int ret;
  long n1, n2;
  size_t p1, p2;

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

    s1 += p1;
    s2 += p2;
    n1 = strtol(s1, &t1, 10);
    n2 = strtol(s2, &t2, 10);
    
    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 = t1;
    s2 = t2;
    p1 = strcspn(s1, digits);
    p2 = strcspn(s2, digits);
  }
  
  return strcmp(s1, s2);
}
#endif

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

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

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

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

  printf("%d = 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;
}

Attachment: pgp4Zf3I8k6Sp.pgp
Description: PGP signature

Reply via email to