diff options
author | Michael Jennings <mej@kainx.org> | 2002-07-14 03:31:38 +0000 |
---|---|---|
committer | Michael Jennings <mej@kainx.org> | 2002-07-14 03:31:38 +0000 |
commit | 0b1d8ad509b3e9b353fa96954ba0abf38bb9d843 (patch) | |
tree | ba9d57204a6fe1a26ff8a96f2a490ed36e90d322 | |
parent | a5f7c5eac03b9806627433d8d52563ebedd2d056 (diff) | |
download | libast-0b1d8ad509b3e9b353fa96954ba0abf38bb9d843.tar.gz |
Sat Jul 13 23:26:12 2002 Michael Jennings (mej)
New function, version_compare(), which accurately compares package
version numbers. Take a look at the various test cases to see what
kinds of comparisons it can accurately make, and if you see any that
aren't there, let me know.
SVN revision: 6339
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | include/libast.h | 1 | ||||
-rw-r--r-- | libast.spec | 2 | ||||
-rw-r--r-- | src/conf.c | 6 | ||||
-rw-r--r-- | src/mem.c | 2 | ||||
-rw-r--r-- | src/strings.c | 110 | ||||
-rw-r--r-- | src/tok.c | 5 | ||||
-rw-r--r-- | test/test.c | 18 |
8 files changed, 144 insertions, 7 deletions
@@ -244,3 +244,10 @@ Sun Jun 9 14:16:38 2002 Michael Jennings (mej) Return on failed assert. ---------------------------------------------------------------------- +Sat Jul 13 23:26:12 2002 Michael Jennings (mej) + +New function, version_compare(), which accurately compares package +version numbers. Take a look at the various test cases to see what +kinds of comparisons it can accurately make, and if you see any that +aren't there, let me know. +---------------------------------------------------------------------- diff --git a/include/libast.h b/include/libast.h index df6a34c..f5917f4 100644 --- a/include/libast.h +++ b/include/libast.h @@ -670,6 +670,7 @@ extern char *garbage_collect(char *, size_t); extern char *file_garbage_collect(char *, size_t); extern char *condense_whitespace(char *); extern void hex_dump(void *, size_t); +extern spif_cmp_t version_compare(const char *, const char *); #ifndef HAVE_MEMMEM extern void *memmem(const void *, size_t, const void *, size_t); #endif diff --git a/libast.spec b/libast.spec index 2c2a8d8..5ed3177 100644 --- a/libast.spec +++ b/libast.spec @@ -1,7 +1,7 @@ Summary: Library of Assorted Spiffy Things Name: libast Version: 0.5 -Release: 1 +Release: 0.1 Copyright: BSD Group: System Environment/Libraries Source: %{name}-%{version}.tar.gz @@ -590,7 +590,7 @@ shell_expand(char *s) for (pbuff++; *pbuff && *pbuff != '`' && l < max; pbuff++, l++) { Command[l] = *pbuff; } - ASSERT(l < CONFIG_BUFF); + ASSERT_RVAL(l < CONFIG_BUFF, NULL); Command[l] = 0; Command = shell_expand(Command); Output = builtin_exec(Command); @@ -672,7 +672,7 @@ shell_expand(char *s) newbuff[j] = *pbuff; } } - ASSERT(j < CONFIG_BUFF); + ASSERT_RVAL(j < CONFIG_BUFF, NULL); newbuff[j] = 0; D_PARSE(("shell_expand(%s) returning \"%s\"\n", s, newbuff)); @@ -763,7 +763,7 @@ open_config_file(char *name) int ver; char buff[256], test[30], *begin_ptr, *end_ptr; - ASSERT(name != NULL); + ASSERT_RVAL(name != NULL, NULL); snprintf(test, sizeof(test), "<%s-", libast_program_name); fp = fopen(name, "rt"); @@ -86,7 +86,7 @@ memrec_find_var(memrec_t *memrec, const void *ptr) register ptr_t *p; register unsigned long i; - ASSERT(memrec != NULL); + ASSERT_RVAL(memrec != NULL, NULL); REQUIRE_RVAL(ptr != NULL, NULL); for (i = 0, p = memrec->ptrs; i < memrec->cnt; i++, p++) { diff --git a/src/strings.c b/src/strings.c index d5e81e5..8e59d34 100644 --- a/src/strings.c +++ b/src/strings.c @@ -736,8 +736,8 @@ hex_dump(void *buff, register size_t count) for (ptr = (unsigned char *) buff, j = 0; j < count; j += 8) { print_error(" %8p | %06lu | %07x | ", buff, (unsigned long) count, (unsigned int) j); l = ((count - j < 8) ? (count - j) : (8)); - memset(buffr, 0, 9); memcpy(buffr, ptr + j, l); + memset(buffr + l, 0, 9 - l); for (k = 0; k < l; k++) { print_error("%02x ", buffr[k]); } @@ -747,3 +747,111 @@ hex_dump(void *buff, register size_t count) print_error("| %-8s\n", safe_str((char *) buffr, l)); } } + +#define CHAR_CLASS_MATCH(a, b) ((isalpha(a) && isalpha(b)) \ + || (isdigit(a) && isdigit(b)) \ + || (!isalnum(a) && !isalnum(b))) +spif_cmp_t +version_compare(const char *v1, const char *v2) +{ + char buff1[128], buff2[128]; + + for (; *v1 && *v2; ) { + if (isalpha(*v1) && isalpha(*v2)) { + char *p1 = buff1, *p2 = buff2; + spif_int8_t ival1 = 5, ival2 = 5; + + /* Compare words. First, copy each word into buffers. */ + for (; isalpha(*v1); v1++, p1++) *p1 = *v1; + for (; isalpha(*v2); v2++, p2++) *p2 = *v2; + *p1 = *p2 = 0; + + /* Change the buffered strings to lowercase for easier comparison. */ + downcase_str(buff1); + downcase_str(buff2); + + /* Some strings require special handling. */ + if (!strcmp(buff1, "snap")) { + ival1 = 1; + } else if (!strcmp(buff1, "pre")) { + ival1 = 2; + } else if (!strcmp(buff1, "alpha")) { + ival1 = 3; + } else if (!strcmp(buff1, "beta")) { + ival1 = 4; + } + if (!strcmp(buff2, "snap")) { + ival2 = 1; + } else if (!strcmp(buff2, "pre")) { + ival2 = 2; + } else if (!strcmp(buff2, "alpha")) { + ival2 = 3; + } else if (!strcmp(buff2, "beta")) { + ival2 = 4; + } + if (ival1 != ival2) { + /* If the values are different, compare them. */ + return SPIF_CMP_FROM_INT(ival1 - ival2); + } else if (ival1 == 5) { + int c; + + /* Two arbitrary strings. Compare them too. */ + if ((c = strcmp(buff1, buff2)) != 0) { + return SPIF_CMP_FROM_INT(c); + } + } + } else if (isdigit(*v1) && isdigit(*v2)) { + char *p1 = buff1, *p2 = buff2; + spif_int32_t ival1, ival2; + spif_cmp_t c; + + /* Compare numbers. First, copy each number into buffers. */ + for (; isdigit(*v1); v1++, p1++) *p1 = *v1; + for (; isdigit(*v2); v2++, p2++) *p2 = *v2; + *p1 = *p2 = 0; + + /* Convert the strings into actual integers. */ + ival1 = SPIF_CAST(int32) strtol(buff1, (char **) NULL, 10); + ival2 = SPIF_CAST(int32) strtol(buff2, (char **) NULL, 10); + + /* Compare the integers and return if not equal. */ + c = SPIF_CMP_FROM_INT(ival1 - ival2); + if (!SPIF_CMP_IS_EQUAL(c)) { + return c; + } + } else if (!isalnum(*v1) && !isalnum(*v2)) { + char *p1 = buff1, *p2 = buff2; + spif_cmp_t c; + + /* Compare non-alphanumeric strings. */ + for (; !isalnum(*v1); v1++, p1++) *p1 = *v1; + for (; !isalnum(*v2); v2++, p2++) *p2 = *v2; + *p1 = *p2 = 0; + + c = SPIF_CMP_FROM_INT(strcasecmp(buff1, buff2)); + if (!SPIF_CMP_IS_EQUAL(c)) { + return c; + } + } else { + return SPIF_CMP_FROM_INT(strcasecmp(buff1, buff2)); + } + } + + /* We've reached the end of one of the strings. */ + if (*v1) { + if (!BEG_STRCASECMP(v1, "snap") || !BEG_STRCASECMP(v1, "pre") + || !BEG_STRCASECMP(v1, "alpha") || !BEG_STRCASECMP(v1, "beta")) { + return SPIF_CMP_LESS; + } else { + return SPIF_CMP_GREATER; + } + } else if (*v2) { + if (!BEG_STRCASECMP(v2, "snap") || !BEG_STRCASECMP(v2, "pre") + || !BEG_STRCASECMP(v2, "alpha") || !BEG_STRCASECMP(v2, "beta")) { + return SPIF_CMP_GREATER; + } else { + return SPIF_CMP_LESS; + } + } + return SPIF_CMP_EQUAL; +} @@ -178,11 +178,13 @@ spif_tok_eval(spif_tok_t self) const char *pstr, *delim = NULL; spif_str_t tmp; char quote; + size_t len; if (SPIF_STR_ISNULL(self->src)) { return FALSE; } pstr = SPIF_CAST_C(const char *) SPIF_STR_STR(SPIF_STR(self->src)); + len = spif_str_get_len(SPIF_STR(self->src)); if (!SPIF_STR_ISNULL(self->sep)) { delim = SPIF_CAST_C(const char *) SPIF_STR_STR(SPIF_STR(self->sep)); @@ -199,7 +201,7 @@ spif_tok_eval(spif_tok_t self) /* The outermost for loop is where we traverse the string. Each new word brings us back to the top where we resize our string list. */ for (quote = 0; *pstr; ) { - tmp = spif_str_new_from_buff("", 4096); + tmp = spif_str_new_from_buff("", len); spif_str_clear(tmp, 0); /* This for loop is where we process each character. */ @@ -230,6 +232,7 @@ spif_tok_eval(spif_tok_t self) /* Reallocate the new string to be just the right size. */ spif_str_trim(tmp); + len -= spif_str_get_len(tmp); /* Add it to the list */ SPIF_LIST_APPEND(self->tokens, tmp); diff --git a/test/test.c b/test/test.c index 0e325a3..8d60dd7 100644 --- a/test/test.c +++ b/test/test.c @@ -221,6 +221,24 @@ test_strings(void) free_array(SPIF_CAST(ptr) slist, 5); TEST_PASS(); + TEST_BEGIN("version_compare() function"); + TEST_FAIL_IF(!SPIF_CMP_IS_LESS(version_compare("1.0", "1.0.1"))); + TEST_FAIL_IF(!SPIF_CMP_IS_LESS(version_compare("2.9.99", "3.0"))); + TEST_FAIL_IF(!SPIF_CMP_IS_LESS(version_compare("3.0", "29.9.9"))); + TEST_FAIL_IF(!SPIF_CMP_IS_LESS(version_compare("1.0pre2", "1.0"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("0.5.3", "0.5.3snap4"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("2.2.4", "2.2.4beta3"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("2.2.4beta3", "2.2.4alpha7"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("1.27.3", "1.13.1"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("0.10", "0.9.2"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("2.3.2a", "2.3.2"))); + TEST_FAIL_IF(!SPIF_CMP_IS_GREATER(version_compare("4.0p1", "4.0"))); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(version_compare("3.4.5", "3.4.5"))); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(version_compare("1.2.0b3", "1.2.0b3"))); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(version_compare("2.0alpha", "2.0alpha"))); + TEST_FAIL_IF(!SPIF_CMP_IS_EQUAL(version_compare("5.4pre1", "5.4pre1"))); + TEST_PASS(); + TEST_PASSED("string"); return 0; } |