summaryrefslogtreecommitdiff
path: root/gl/lib/strnumcmp-in.h
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2012-09-08 15:11:20 +0200
committerJim Meyering <meyering@redhat.com>2012-09-10 08:58:03 +0200
commitc424de16b1c8607f2caa7c85d69196f9d8e3a103 (patch)
treefad5d543de0cef43dfa32e60a0e3937562799d15 /gl/lib/strnumcmp-in.h
parent07fcfe36cee091b2dc15543dc406597bf1fffe67 (diff)
downloadcoreutils-c424de16b1c8607f2caa7c85d69196f9d8e3a103.tar.xz
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.
Diffstat (limited to 'gl/lib/strnumcmp-in.h')
-rw-r--r--gl/lib/strnumcmp-in.h244
1 files changed, 244 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>. */
+
+/* Written by Mike Haertel. */
+
+#ifndef STRNUMCMP_IN_H
+# define STRNUMCMP_IN_H 1
+
+# include "strnumcmp.h"
+
+# include <stddef.h>
+
+# 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 a<b, 0 if a=b, 1 if a>b.
+ 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