jcs
/wallops
/amendments
/32
strnatcmp: Add local copy
jcs made amendment 32 over 3 years ago
--- strnatcmp.c	Wed Aug 31 22:04:17 2022
+++ strnatcmp.c	Wed Aug 31 22:04:17 2022
@@ -0,0 +1,157 @@
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/* partial change history:
+ *
+ * 2004-10-10 mbp: Lift out character type dependencies into macros.
+ *
+ * Eric Sosman pointed out that ctype functions take a parameter whose
+ * value must be that of an unsigned int, even on platforms that have
+ * negative chars in their default char type.
+ *
+ * 2021-10-13 jcs: Modified to compile in THINK C 5
+ */
+
+#include <stddef.h>	/* size_t */
+#include <ctype.h>
+
+#include "strnatcmp.h"
+
+int compare_right(char const *a, char const *b);
+
+int
+compare_right(char const *a, char const *b)
+{
+     int bias = 0;
+     
+     /* The longest run of digits wins.  That aside, the greatest
+	value wins, but we can't know that it will until we've scanned
+	both numbers to know that they have the same magnitude, so we
+	remember it in BIAS. */
+     for (;; a++, b++) {
+	  if (!isdigit((unsigned char)*a)  &&  !isdigit((unsigned char)*b))
+	       return bias;
+	  if (!isdigit((unsigned char)*a))
+	       return -1;
+	  if (!isdigit((unsigned char)*b))
+	       return +1;
+	  if (*a < *b) {
+	       if (!bias)
+		    bias = -1;
+	  } else if (*a > *b) {
+	       if (!bias)
+		    bias = +1;
+	  } else if (!*a  &&  !*b)
+	       return bias;
+     }
+
+     return 0;
+}
+
+
+static int
+compare_left(char const *a, char const *b)
+{
+     /* Compare two left-aligned numbers: the first to have a
+        different value wins. */
+     for (;; a++, b++) {
+	  if (!isdigit((unsigned char)*a)  &&  !isdigit((unsigned char)*b))
+	       return 0;
+	  if (!isdigit((unsigned char)*a))
+	       return -1;
+	  if (!isdigit((unsigned char)*b))
+	       return +1;
+	  if (*a < *b)
+	       return -1;
+	  if (*a > *b)
+	       return +1;
+     }
+
+     return 0;
+}
+
+
+static int
+strnatcmp0(char const *a, char const *b, int fold_case)
+{
+     int ai, bi;
+     char ca, cb;
+     int fractional, result;
+
+     ai = bi = 0;
+     while (1) {
+	  ca = a[ai]; cb = b[bi];
+
+	  /* skip over leading spaces or zeros */
+	  while (isspace((unsigned char)ca))
+	       ca = a[++ai];
+
+	  while (isspace((unsigned char)cb))
+	       cb = b[++bi];
+
+	  /* process run of digits */
+	  if (isdigit((unsigned char)ca)  && isdigit((unsigned char)cb)) {
+	       fractional = (ca == '0' || cb == '0');
+
+	       if (fractional) {
+		    if ((result = compare_left(a+ai, b+bi)) != 0)
+			 return result;
+	       } else {
+		    if ((result = compare_right(a+ai, b+bi)) != 0)
+			 return result;
+	       }
+	  }
+
+	  if (!ca && !cb) {
+	       /* The strings compare the same.  Perhaps the caller
+                  will want to call strcmp to break the tie. */
+	       return 0;
+	  }
+
+	  if (fold_case) {
+	       ca = toupper((unsigned char)ca);
+	       cb = toupper((unsigned char)cb);
+	  }
+
+	  if (ca < cb)
+	       return -1;
+
+	  if (ca > cb)
+	       return +1;
+
+	  ++ai; ++bi;
+     }
+}
+
+
+int
+strnatcmp(char const *a, char const *b) {
+     return strnatcmp0(a, b, 0);
+}
+
+
+/* Compare, recognizing numeric string and ignoring case. */
+int
+strnatcasecmp(char const *a, char const *b) {
+     return strnatcmp0(a, b, 1);
+}
--- strnatcmp.h	Wed Aug 31 22:04:05 2022
+++ strnatcmp.h	Wed Aug 31 22:04:05 2022
@@ -0,0 +1,7 @@
+#ifndef __STRNATCMP_H__
+#define __STRNATCMP_H__
+
+int strnatcmp(char const *a, char const *b);
+int strnatcasecmp(char const *a, char const *b);
+
+#endif