mailing list of musl libc
 help / color / mirror / code / Atom feed
* [PATCH] conforming strverscmp() implementation
@ 2015-03-03 10:45 Sergey Dmitrouk
  2015-03-03 15:54 ` Rich Felker
  0 siblings, 1 reply; 3+ messages in thread
From: Sergey Dmitrouk @ 2015-03-03 10:45 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 984 bytes --]

Hi,

Attached is strverscmp() that should conform to what is described in
manual pages.  It's not actually a diff as it would be harder to read
in this case.

The idea is just as described in manuals (once you get what they mean):

1. Find point where strings differ as in current code, but keep track
   of locations of last seen numbers.
2. If numbers are both integers (that is they don't start with zero or
   it's a single zero) compare as in current implementation.
3. If only one of numbers is integer, the other one is smaller.
4. Otherwise, number with longer leading sequence of zeroes is smaller.
5. If leading zeroes match, compare characters following last zero in
   both strings.

I didn't see much comments in musl, so there is none in this file, but
can add some if requested.

Implementation is admittedly more sophisticated than current version for
the reason that all simpler approaches I tried fail for at least one of
possible comparison cases.

Regards,
Sergey

[-- Attachment #2: strverscmp.c --]
[-- Type: text/plain, Size: 1030 bytes --]

#define _GNU_SOURCE
#include <ctype.h>
#include <string.h>

int strverscmp(const char *l, const char *r)
{
	const char *ln=(isdigit(*l) ? l : NULL), *rn=(isdigit(*r) ? r : NULL);
	while (*l==*r) {
		if (!*l) return 0;

		if (isdigit(*l)) {
			if (ln == NULL) {
				ln = l; rn = r;
			}
		} else {
			ln = NULL; rn = NULL;
		}

		l++; r++;
	}

	if ((*l != '\0' && !isdigit(*l)) || (*r != '\0' && !isdigit(*r))) {
		ln = NULL; rn = NULL;
	}

	if (ln != NULL) {
		int intl=(*ln != '0' || !isdigit(*(ln + 1)));
		int intr=(*rn != '0' || !isdigit(*(rn + 1)));

		if (intl ^ intr) {
			return intl ? 1 : -1;
		} else if (intl) {
			size_t lenl=0, lenr=0;
			while (isdigit(l[lenl])) lenl++;
			while (isdigit(r[lenr])) lenr++;
			if (lenl==lenr) {
				return (*l - *r);
			} else if (lenl>lenr) {
				return 1;
			} else {
				return -1;
			}
		} else {
			size_t zl=0, zr=0;
			while (ln[zl]=='0') zl++;
			while (rn[zr]=='0') zr++;
			if (zl>zr) {
				return -1;
			} else if (zl<zr) {
				return 1;
			}
		}
	}

	return (*l - *r);
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-03-03 19:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-03 10:45 [PATCH] conforming strverscmp() implementation Sergey Dmitrouk
2015-03-03 15:54 ` Rich Felker
2015-03-03 19:27   ` Sergey Dmitrouk

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).