[klibc] strverscmp, scandir, alphasort and versionsort
Luciano Miguel Ferreira Rocha
strange at nsk.no-ip.org
Tue Oct 3 13:54:58 PDT 2006
Hello,
These are implementations of strverscmp, scandir, alphasort and
versionsort, and some test cases for them.
I know these aren't in POSIX, but they're useful, nonetheless, and
someone else might be interested in them.
Regards,
Luciano Rocha
--
lfr
0/0
-------------- next part --------------
/* ----------------------------------------------------------------------- *
*
* Copyright 2006 Luciano Rocha - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* ----------------------------------------------------------------------- */
#include <string.h>
#include <ctype.h>
/* strverscmp
from the manual:
What this function does is the following. If both strings are equal,
return 0. Otherwise find the position between two bytes with the prop-
erty that before it both strings are equal, while directly after it
there is a difference. Find the largest consecutive digit strings con-
taining (or starting at, or ending at) this position. If one or both of
these is empty, then return what strcmp() would have returned (numeri-
cal ordering of byte values). Otherwise, compare both digit strings
numerically, where digit strings with one or more leading zeroes are
interpreted as if they have a decimal point in front (so that in par-
ticular digit strings with more leading zeroes come before digit
strings with fewer leading zeroes). Thus, the ordering is 000, 00, 01,
010, 09, 0, 1, 9, 10.
*/
/* shift by ten, to the left */
static unsigned long shift10(unsigned long v, int n)
{
while (n--)
v *= 10;
return v;
}
/* strverscmp */
int strverscmp(const char *s1, const char *s2)
{
int i;
unsigned long v1, v2; /* numerical value */
int l1, l2, /* length of digit strings */
z1, z2, /* length of leading zeroes string */
j1, j2, /* pointers to the beginning of the digit strings */
k1, k2; /* pointers to after the digit strings */
for (i = 0; s1[i] && s1[i] == s2[i]; i++);
if (s1[i] == s2[i])
return 0;
/* s1[i] != s2[i] */
/* s1[i] or s2[i] not in a digit string, normal cmp */
if ((!isdigit(s1[i]) && (i == 0 || !isdigit(s1[i-1])))
|| (!isdigit(s2[i]) && (i == 0 || !isdigit(s2[i-1]))))
return (s1[i] - s2[i]);
/* find v1 */
for (j1 = i - 1; j1 >= 0 && isdigit(s1[j1]); j1--);
j1++; /* j1 now points to first digit */
/* find leading zeros */
for (z1 = j1; s1[z1] == '0'; z1++);
z1 -= j1;
/* find v2 */
for (j2 = i - 1; j2 >= 0 && isdigit(s2[j2]); j2--);
j2++; /* j2 now points to first digit */
/* find leading zeros */
for (z2 = j2; s2[z2] == '0'; z2++);
z2 -= j2;
/* "digit strings with more leading zeroes come before digit strings
* with fewer leading zeroes" */
/* but a "0" has no leading zeroes, get length first */
for (l1 = j1 + z1; isdigit(s1[l1]); l1++);
for (l2 = j2 + z2; isdigit(s2[l2]); l2++);
l1 -= j1 + z1;
l2 -= j2 + z2;
if (z1 == 1 && !l1) {
z1 = 0;
l1 = 1;
}
if (z2 == 1 && !l2) {
z2 = 0;
l2 = 1;
}
if (z1 > z2)
return -1;
if (z1 < z2)
return 1;
v1 = v2 = 0;
/* get v1 */
for (k1 = j1 + z1; isdigit(s1[k1]); k1++)
v1 = v1 * 10 + (s1[k1] - '0');
/* get v2 */
for (k2 = j2 + z2; isdigit(s2[k2]); k2++)
v2 = v2 * 10 + (s2[k2] - '0');
/* leading '0's? shift the difference of length */
if (z1) {
if (l1 > l2)
v2 = shift10(v2, l1 - l2);
else if (l2 > l1)
v1 = shift10(v1, l2 - l1);
}
/* check numerical value */
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
/* equal. check length, and then check the rest of the
* string */
if (l1 != l2)
return l1 - l2;
return strverscmp(s1 + k1, s2 + k2);
}
-------------- next part --------------
/* ----------------------------------------------------------------------- *
*
* Copyright 2006 Luciano Rocha - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* ----------------------------------------------------------------------- */
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
/* from the manual:
* The scandir() function scans the directory dir, calling
* filter() on each directory entry. Entries for which filter()
* returns non-zero are stored in strings allocated via malloc(),
* sorted using qsort() with the comparison function compar(), and
* collected in array namelist which is allocated via malloc(). If
* filter is NULL, all entries are selected.
*/
int scandir(const char *dir,
struct dirent ***namelist,
int(*filter)(const struct dirent *),
int(*compar)(const void *, const void *))
{
DIR *d;
struct dirent *de, **list;
int nl;
if (!(d = opendir(dir)))
return -1;
list = NULL;
nl = 0;
while ((de = readdir(d))) {
if (filter && !filter(de)) continue;
if (!(list = realloc(list, sizeof(struct dirent *) * (nl+1)))
|| !(list[nl] = malloc(de->d_reclen)))
break;
memcpy(list[nl], de, de->d_reclen);
nl++;
}
closedir(d);
/* error allocating memory? */
if (de) {
while (nl > 0) {
free(list[--nl]);
}
free(list);
nl = -1;
} else {
qsort(list, nl, sizeof(struct dirent *), compar);
*namelist = list;
}
return nl;
}
-------------- next part --------------
/* ----------------------------------------------------------------------- *
*
* Copyright 2006 Luciano Rocha - All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* ----------------------------------------------------------------------- */
#include <string.h>
#include <dirent.h>
/* sort using strcmp on *d->d_name */
int alphasort(const void *a, const void *b)
{
const struct dirent *const*_a = a, *const*_b = b;
return strcmp((*_a)->d_name, (*_b)->d_name);
}
/* sort using strverscmp on *d->d_name */
int versionsort(const void *a, const void *b)
{
struct dirent *const*_a = a, *const*_b = b;
return strverscmp((*_a)->d_name, (*_b)->d_name);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: tests.tar.gz
Type: application/x-tar-gz
Size: 2404 bytes
Desc: not available
Url : http://www.zytor.com/pipermail/klibc/attachments/20061003/377dca47/attachment.bin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
Url : http://www.zytor.com/pipermail/klibc/attachments/20061003/377dca47/attachment-0001.bin
More information about the klibc
mailing list