From c424de16b1c8607f2caa7c85d69196f9d8e3a103 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sat, 8 Sep 2012 15:11:20 +0200 Subject: maint: move the last coreutils-specific files from lib/ to gl/ Convert the few remaining coreutils-specific files in lib/ to gnulib-style modules under gl/, removing their corresponding .m4 files, since the information recorded in those files is better stored in module-description file in gl/modules/. * bootstrap.conf (gnulib_modules): Add new modules: fd-reopen, buffer-lcm, xfts, strnumcmp. * gl/lib/buffer-lcm.c: Renamed from the file in lib/. * gl/lib/buffer-lcm.h: Likewise. * gl/lib/fd-reopen.c: Likewise. * gl/lib/fd-reopen.h: Likewise. * gl/lib/strintcmp.c: Likewise. * gl/lib/strnumcmp-in.h: Likewise. * gl/lib/strnumcmp.c: Likewise. * gl/lib/strnumcmp.h: Likewise. * gl/lib/xfts.c: Likewise. * gl/lib/xfts.h: Likewise. * gl/modules/buffer-lcm: New module-description file. * gl/modules/fd-reopen: Likewise. * gl/modules/strnumcmp: Likewise. * gl/modules/xfts: Likewise. * m4/fd-reopen.m4: Remove, no longer needed. * m4/strnumcmp.m4: Likewise. * m4/xfts.m4: Likewise. * m4/prereq.m4: Do not AC_REQUIRE the m4 functions from our just-removed m4/*.m4 files. --- gl/lib/strnumcmp-in.h | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 gl/lib/strnumcmp-in.h (limited to 'gl/lib/strnumcmp-in.h') diff --git a/gl/lib/strnumcmp-in.h b/gl/lib/strnumcmp-in.h new file mode 100644 index 000000000..95ab55fdc --- /dev/null +++ b/gl/lib/strnumcmp-in.h @@ -0,0 +1,244 @@ +/* Compare numeric strings. This is an internal include file. + + Copyright (C) 1988-2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Written by Mike Haertel. */ + +#ifndef STRNUMCMP_IN_H +# define STRNUMCMP_IN_H 1 + +# include "strnumcmp.h" + +# include + +# define NEGATION_SIGN '-' +# define NUMERIC_ZERO '0' + +/* ISDIGIT differs from isdigit, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char + or EOF. + - It's typically faster. + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + isdigit unless it's important to use the locale's definition + of 'digit' even when the host does not conform to POSIX. */ +# define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) + + +/* Compare strings A and B containing decimal fractions < 1. + DECIMAL_POINT is the decimal point. Each string + should begin with a decimal point followed immediately by the digits + of the fraction. Strings not of this form are treated as zero. */ + +/* The goal here, is to take two numbers a and b... compare these + in parallel. Instead of converting each, and then comparing the + outcome. Most likely stopping the comparison before the conversion + is complete. The algorithm used, in the old "sort" utility: + + Algorithm: fraccompare + Action : compare two decimal fractions + accepts : char *a, char *b + returns : -1 if ab. + implement: + + if *a == decimal_point AND *b == decimal_point + find first character different in a and b. + if both are digits, return the difference *a - *b. + if *a is a digit + skip past zeros + if digit return 1, else 0 + if *b is a digit + skip past zeros + if digit return -1, else 0 + if *a is a decimal_point + skip past decimal_point and zeros + if digit return 1, else 0 + if *b is a decimal_point + skip past decimal_point and zeros + if digit return -1, else 0 + return 0 */ + +static inline int _GL_ATTRIBUTE_PURE +fraccompare (char const *a, char const *b, char decimal_point) +{ + if (*a == decimal_point && *b == decimal_point) + { + while (*++a == *++b) + if (! ISDIGIT (*a)) + return 0; + if (ISDIGIT (*a) && ISDIGIT (*b)) + return *a - *b; + if (ISDIGIT (*a)) + goto a_trailing_nonzero; + if (ISDIGIT (*b)) + goto b_trailing_nonzero; + return 0; + } + else if (*a++ == decimal_point) + { + a_trailing_nonzero: + while (*a == NUMERIC_ZERO) + a++; + return ISDIGIT (*a); + } + else if (*b++ == decimal_point) + { + b_trailing_nonzero: + while (*b == NUMERIC_ZERO) + b++; + return - ISDIGIT (*b); + } + return 0; +} + +/* Compare strings A and B as numbers without explicitly converting + them to machine numbers, to avoid overflow problems and perhaps + improve performance. DECIMAL_POINT is the decimal point and + THOUSANDS_SEP the thousands separator. A DECIMAL_POINT of -1 + causes comparisons to act as if there is no decimal point + character, and likewise for THOUSANDS_SEP. */ + +static inline int _GL_ATTRIBUTE_PURE +numcompare (char const *a, char const *b, + int decimal_point, int thousands_sep) +{ + unsigned char tmpa = *a; + unsigned char tmpb = *b; + int tmp; + size_t log_a; + size_t log_b; + + if (tmpa == NEGATION_SIGN) + { + do + tmpa = *++a; + while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep); + if (tmpb != NEGATION_SIGN) + { + if (tmpa == decimal_point) + do + tmpa = *++a; + while (tmpa == NUMERIC_ZERO); + if (ISDIGIT (tmpa)) + return -1; + while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep) + tmpb = *++b; + if (tmpb == decimal_point) + do + tmpb = *++b; + while (tmpb == NUMERIC_ZERO); + return - ISDIGIT (tmpb); + } + do + tmpb = *++b; + while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep); + + while (tmpa == tmpb && ISDIGIT (tmpa)) + { + do + tmpa = *++a; + while (tmpa == thousands_sep); + do + tmpb = *++b; + while (tmpb == thousands_sep); + } + + if ((tmpa == decimal_point && !ISDIGIT (tmpb)) + || (tmpb == decimal_point && !ISDIGIT (tmpa))) + return fraccompare (b, a, decimal_point); + + tmp = tmpb - tmpa; + + for (log_a = 0; ISDIGIT (tmpa); ++log_a) + do + tmpa = *++a; + while (tmpa == thousands_sep); + + for (log_b = 0; ISDIGIT (tmpb); ++log_b) + do + tmpb = *++b; + while (tmpb == thousands_sep); + + if (log_a != log_b) + return log_a < log_b ? 1 : -1; + + if (!log_a) + return 0; + + return tmp; + } + else if (tmpb == NEGATION_SIGN) + { + do + tmpb = *++b; + while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep); + if (tmpb == decimal_point) + do + tmpb = *++b; + while (tmpb == NUMERIC_ZERO); + if (ISDIGIT (tmpb)) + return 1; + while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep) + tmpa = *++a; + if (tmpa == decimal_point) + do + tmpa = *++a; + while (tmpa == NUMERIC_ZERO); + return ISDIGIT (tmpa); + } + else + { + while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep) + tmpa = *++a; + while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep) + tmpb = *++b; + + while (tmpa == tmpb && ISDIGIT (tmpa)) + { + do + tmpa = *++a; + while (tmpa == thousands_sep); + do + tmpb = *++b; + while (tmpb == thousands_sep); + } + + if ((tmpa == decimal_point && !ISDIGIT (tmpb)) + || (tmpb == decimal_point && !ISDIGIT (tmpa))) + return fraccompare (a, b, decimal_point); + + tmp = tmpa - tmpb; + + for (log_a = 0; ISDIGIT (tmpa); ++log_a) + do + tmpa = *++a; + while (tmpa == thousands_sep); + + for (log_b = 0; ISDIGIT (tmpb); ++log_b) + do + tmpb = *++b; + while (tmpb == thousands_sep); + + if (log_a != log_b) + return log_a < log_b ? -1 : 1; + + if (!log_a) + return 0; + + return tmp; + } +} + +#endif -- cgit v1.2.3-54-g00ecf