From: Peter Hutterer Date: Wed, 27 Mar 2013 23:38:48 +0000 (+1000) Subject: Add a set of simple version comparison helpers X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=a0fd39057c739f1c0f5d5ee9ade90381df0ca839;hp=81f2204ceaec3bc99442344c87e2872747c2100a Add a set of simple version comparison helpers These version helpers help to compare major.minor style version numbers, without the need for open-coded and error-prone bitshifting, multiplication, and similar. Signed-off-by: Peter Hutterer Signed-off-by: Rusty Russell --- diff --git a/Makefile-ccan b/Makefile-ccan index 157f5d73..4bc297f7 100644 --- a/Makefile-ccan +++ b/Makefile-ccan @@ -22,7 +22,8 @@ MODS_NORMAL_NO_SRC := alignof \ short_types \ tcon \ tlist \ - typesafe_cb + typesafe_cb \ + version # No external dependencies, with C code: MODS_NORMAL_WITH_SRC := antithread \ diff --git a/ccan/version/LICENSE b/ccan/version/LICENSE new file mode 120000 index 00000000..2354d129 --- /dev/null +++ b/ccan/version/LICENSE @@ -0,0 +1 @@ +../../licenses/BSD-MIT \ No newline at end of file diff --git a/ccan/version/_info b/ccan/version/_info new file mode 100644 index 00000000..3aad1e8a --- /dev/null +++ b/ccan/version/_info @@ -0,0 +1,37 @@ +#include +#include "config.h" + +/** + * version - helper functions for major.minor-style version numbers + * + * This code provides some helper functions to deal with version numbers in + * the form major.minor. + * + * Author: Peter Hutterer + * Maintainer: Peter Hutterer + * License: BSD-MIT + * + * Example: + * struct version a = version(1, 0); + * struct version b = version(2, 2); + * + * if (version_cmp(a, b) < 0) + * printf("Feature supported in version 2.2 but we have %d.%d\n", + * version_major(a), version_minor(a)); + * + * if (version_cmp(a, version(3, 4)) < 0) + * printf("Feature only supported in version 3.4\n"); + * + */ +int main(int argc, char *argv[]) +{ + /* Expect exactly one argument */ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + return 0; + } + + return 1; +} diff --git a/ccan/version/test/compile_fail.c b/ccan/version/test/compile_fail.c new file mode 100644 index 00000000..8cf64b10 --- /dev/null +++ b/ccan/version/test/compile_fail.c @@ -0,0 +1,11 @@ +#include +#include + +int main(void) +{ +#ifdef FAIL + struct version a; + a = 0; /* no direct assignment */ +#endif + return 0; +} diff --git a/ccan/version/test/run.c b/ccan/version/test/run.c new file mode 100644 index 00000000..f7b0782a --- /dev/null +++ b/ccan/version/test/run.c @@ -0,0 +1,69 @@ +#include +#include + +int main(void) +{ + struct version a, b; + + plan_tests(26); + + /* cmp with normal versions */ + a = version(1, 0); + b = version(2, 0); + ok1(version_cmp(a, b) < 0); + + a = version(1, 1); + ok1(version_cmp(a, b) < 0); + + a = version(2, 0); + ok1(version_cmp(a, b) == 0); + + a = version(2, 1); + ok1(version_cmp(a, b) > 0); + + b = version(2, 1); + ok1(version_cmp(a, b) == 0); + + a = version(3, 0); + ok1(version_cmp(a, b) > 0); + + a = version(3, 1); + ok1(version_cmp(a, b) > 0); + + /* inline cmp */ + ok1(version_cmp(a, version(1, 0)) > 0); + ok1(version_cmp(a, version(1, 1)) > 0); + ok1(version_cmp(a, version(3, 0)) > 0); + ok1(version_cmp(a, version(3, 1)) == 0); + ok1(version_cmp(a, version(3, 2)) < 0); + ok1(version_cmp(a, version(4, 0)) < 0); + ok1(version_cmp(a, version(4, 1)) < 0); + + /* limits */ + a = version(0xFFFF, 0xFFFF); + b = version(0xFFFE, 0xFFFF); + ok1(version_cmp(a, b) > 0); + ok1(version_cmp(b, a) < 0); + + b = version(0xFFFF, 0xFFFE); + ok1(version_cmp(a, b) > 0); + ok1(version_cmp(b, a) < 0); + + b = version(0xFFFF, 0xFFFF); + ok1(version_cmp(a, b) == 0); + ok1(version_cmp(b, a) == 0); + + b = version(0, 1); + ok1(version_cmp(a, b) > 0); + ok1(version_cmp(b, a) < 0); + + b = version(1, 0); + ok1(version_cmp(a, b) > 0); + ok1(version_cmp(b, a) < 0); + + b = version(0, 0); + ok1(version_cmp(a, b) > 0); + ok1(version_cmp(b, a) < 0); + + return exit_status(); +} diff --git a/ccan/version/version.h b/ccan/version/version.h new file mode 100644 index 00000000..8820f174 --- /dev/null +++ b/ccan/version/version.h @@ -0,0 +1,80 @@ +/***************************************************************************** + * + * version - simple version handling functions for major.minor version + * types + * + * 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. + * + ****************************************************************************/ + +#ifndef CCAN_VERSION_H +#define CCAN_VERSION_H + +#include + +struct version { + uint32_t _v; /* major << 16 | minor */ +}; + +/** + * version_major - return the major version of the given struct + * @v: the version number to obtain the major number from + */ +static inline uint16_t version_major(struct version v) { + return (v._v & 0xFFFF0000) >> 16; +} + +/** + * version_minor - return the minor version of the given struct + * @v: the version number to obtain the minor number from + */ +static inline uint16_t version_minor(const struct version v) { + return v._v & 0xFFFF; +} + +/** + * version - create a new version number + * @major: major version number + * @minor: minor version number + */ +static inline struct version version(uint16_t major, uint16_t minor) +{ + struct version v = { ._v = major << 16 | minor }; + return v; +} + +/** + * version_cmp - compare two versions + * @a: the first version number + * @b: the second version number + * @return a number greater, equal, or less than 0 if a is greater, equal or + * less than b, respectively + * + * Example: + * struct version a = version(1, 0); + * struct version b = version(1, 3); + * if (version_cmp(a, b) < 0) + * printf("b is smaller than b\n"); + */ +static inline int version_cmp(struct version a, struct version b) +{ + return (a._v == b._v) ? 0 : (a._v > b._v) ? 1 : - 1; +} + +#endif /* CCAN_VERSION_H */