blob: eaa73608e956aedadc198bd05b51b42a3a4eb400 [file] [log] [blame]
/*
* This file is part of the PulseView project.
*
* 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.
*/
// strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
// This file has been modified for C++ compatibility.
// Original at https://github.com/sourcefrog/natsort/blob/master/strnatcmp.c
#ifndef PULSEVIEW_PV_STRNATCMP_HPP
#define PULSEVIEW_PV_STRNATCMP_HPP
#include <cctype>
#include <cstddef> /* size_t */
#include <string>
using std::string;
static 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(*a) && !isdigit(*b))
return bias;
if (!isdigit(*a))
return -1;
if (!isdigit(*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(*a) && !isdigit(*b))
return 0;
if (!isdigit(*a))
return -1;
if (!isdigit(*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, fractional, result;
char ca, cb;
ai = bi = 0;
while (true) {
ca = a[ai];
cb = b[bi];
// Skip over leading spaces or zeroes
while (isspace(ca))
ca = a[++ai];
while (isspace(cb))
cb = b[++bi];
// Process run of digits
if (isdigit(ca) && isdigit(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(ca);
cb = toupper(cb);
}
if (ca < cb)
return -1;
if (ca > cb)
return +1;
++ai;
++bi;
}
}
// Compare, recognizing numeric strings and being case sensitive
int strnatcmp(char const *a, char const *b)
{
return strnatcmp0(a, b, 0);
}
int strnatcmp(const string a, const string b)
{
return strnatcmp0(a.c_str(), b.c_str(), 0);
}
// Compare, recognizing numeric strings and ignoring case
int strnatcasecmp(char const *a, char const *b)
{
return strnatcmp0(a, b, 1);
}
int strnatcasecmp(const string a, const string b)
{
return strnatcmp0(a.c_str(), b.c_str(), 1);
}
#endif // PULSEVIEW_PV_STRNATCMP_HPP