Commit FS#8314. This adds strnat[case]cmp written by Martin Pool, which respects numbers within strings, and gives a more intuitive
sorting. This also adds a setting, so that the sorting can be used in the file browser. The implementation is very generic, and can possibly be used in other places. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20155 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
e6c023cb64
commit
d13f1a485f
10 changed files with 332 additions and 17 deletions
|
@ -45,6 +45,7 @@
|
||||||
#include "cuesheet.h"
|
#include "cuesheet.h"
|
||||||
#include "filetree.h"
|
#include "filetree.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "strnatcmp.h"
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
#include "keyboard.h"
|
#include "keyboard.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -242,12 +243,26 @@ static int compare(const void* p1, const void* p2)
|
||||||
|
|
||||||
case SORT_ALPHA:
|
case SORT_ALPHA:
|
||||||
case SORT_ALPHA_REVERSED:
|
case SORT_ALPHA_REVERSED:
|
||||||
|
{
|
||||||
if (global_settings.sort_case)
|
if (global_settings.sort_case)
|
||||||
return strncmp(e1->name, e2->name, MAX_PATH)
|
{
|
||||||
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER)
|
||||||
|
return strnatcmp(e1->name, e2->name)
|
||||||
|
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
||||||
|
else
|
||||||
|
return strncmp(e1->name, e2->name, MAX_PATH)
|
||||||
|
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return strncasecmp(e1->name, e2->name, MAX_PATH)
|
{
|
||||||
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
if (global_settings.interpret_numbers == SORT_INTERPRET_AS_NUMBER)
|
||||||
|
return strnatcasecmp(e1->name, e2->name)
|
||||||
|
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
||||||
|
else
|
||||||
|
return strncasecmp(e1->name, e2->name, MAX_PATH)
|
||||||
|
* (criteria == SORT_ALPHA_REVERSED ? -1 : 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0; /* never reached */
|
return 0; /* never reached */
|
||||||
|
|
|
@ -12187,3 +12187,45 @@
|
||||||
quickscreen: ""
|
quickscreen: ""
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_NUMBERS
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "Interpret numbers when sorting"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Zahlen beim Sortieren interpretieren"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Zahlen beim Sortieren interpretieren"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_AS_DIGIT
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "As digits"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "als Ziffern"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "als Ziffern"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_AS_NUMBERS
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "As whole numbers"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "als komplette Zahlen"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "als komplette Zahlen"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
@ -12359,3 +12359,45 @@
|
||||||
*: "Credits"
|
*: "Credits"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_NUMBERS
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "Interpret numbers when sorting"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Interpret numbers when sorting"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Interpret numbers when sorting"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_AS_DIGIT
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "As digits"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "As digits"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "As digits"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_SORT_INTERPRET_AS_NUMBERS
|
||||||
|
desc: in Settings -> File view
|
||||||
|
user:
|
||||||
|
<source>
|
||||||
|
*: "As whole numbers"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "As whole numbers"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "As whole numbers"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
|
@ -100,6 +100,7 @@ static int fileview_callback(int action,const struct menu_item_ex *this_item);
|
||||||
MENUITEM_SETTING(sort_case, &global_settings.sort_case, NULL);
|
MENUITEM_SETTING(sort_case, &global_settings.sort_case, NULL);
|
||||||
MENUITEM_SETTING(sort_dir, &global_settings.sort_dir, fileview_callback);
|
MENUITEM_SETTING(sort_dir, &global_settings.sort_dir, fileview_callback);
|
||||||
MENUITEM_SETTING(sort_file, &global_settings.sort_file, fileview_callback);
|
MENUITEM_SETTING(sort_file, &global_settings.sort_file, fileview_callback);
|
||||||
|
MENUITEM_SETTING(interpret_numbers, &global_settings.interpret_numbers, fileview_callback);
|
||||||
MENUITEM_SETTING(dirfilter, &global_settings.dirfilter, NULL);
|
MENUITEM_SETTING(dirfilter, &global_settings.dirfilter, NULL);
|
||||||
MENUITEM_SETTING(show_filename_ext, &global_settings.show_filename_ext, NULL);
|
MENUITEM_SETTING(show_filename_ext, &global_settings.show_filename_ext, NULL);
|
||||||
MENUITEM_SETTING(browse_current, &global_settings.browse_current, NULL);
|
MENUITEM_SETTING(browse_current, &global_settings.browse_current, NULL);
|
||||||
|
@ -124,7 +125,7 @@ static int fileview_callback(int action,const struct menu_item_ex *this_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_MENU(file_menu, ID2P(LANG_FILE), 0, Icon_file_view_menu,
|
MAKE_MENU(file_menu, ID2P(LANG_FILE), 0, Icon_file_view_menu,
|
||||||
&sort_case, &sort_dir, &sort_file,
|
&sort_case, &sort_dir, &sort_file, &interpret_numbers,
|
||||||
&dirfilter, &show_filename_ext, &browse_current,
|
&dirfilter, &show_filename_ext, &browse_current,
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
&show_path_in_browser
|
&show_path_in_browser
|
||||||
|
|
|
@ -147,6 +147,7 @@ enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB,
|
||||||
/* file and dir sort options */
|
/* file and dir sort options */
|
||||||
enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */
|
enum { SORT_ALPHA, SORT_DATE, SORT_DATE_REVERSED, SORT_TYPE, /* available as settings */
|
||||||
SORT_ALPHA_REVERSED, SORT_TYPE_REVERSED }; /* internal use only */
|
SORT_ALPHA_REVERSED, SORT_TYPE_REVERSED }; /* internal use only */
|
||||||
|
enum { SORT_INTERPRET_AS_DIGIT, SORT_INTERPRET_AS_NUMBER };
|
||||||
|
|
||||||
/* recursive dir insert options */
|
/* recursive dir insert options */
|
||||||
enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK };
|
enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK };
|
||||||
|
@ -612,8 +613,9 @@ struct user_settings
|
||||||
|
|
||||||
/* file browser sorting */
|
/* file browser sorting */
|
||||||
bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */
|
bool sort_case; /* dir sort order: 0=case insensitive, 1=sensitive */
|
||||||
int sort_file; /* 0=alpha, 1=date, 2=date (new first), 3=type */
|
|
||||||
int sort_dir; /* 0=alpha, 1=date (old first), 2=date (new first) */
|
int sort_dir; /* 0=alpha, 1=date (old first), 2=date (new first) */
|
||||||
|
int sort_file; /* 0=alpha, 1=date, 2=date (new first), 3=type */
|
||||||
|
int interpret_numbers; /* true=strnatcmp, false=strcmp */
|
||||||
|
|
||||||
/* power settings */
|
/* power settings */
|
||||||
int poweroff; /* idle power off timer */
|
int poweroff; /* idle power off timer */
|
||||||
|
|
|
@ -783,7 +783,20 @@ const struct settings_list settings[] = {
|
||||||
"all,supported,music,playlists", NULL, 4, ID2P(LANG_ALL),
|
"all,supported,music,playlists", NULL, 4, ID2P(LANG_ALL),
|
||||||
ID2P(LANG_FILTER_SUPPORTED), ID2P(LANG_FILTER_MUSIC),
|
ID2P(LANG_FILTER_SUPPORTED), ID2P(LANG_FILTER_MUSIC),
|
||||||
ID2P(LANG_PLAYLISTS)),
|
ID2P(LANG_PLAYLISTS)),
|
||||||
|
/* file sorting */
|
||||||
OFFON_SETTING(0, sort_case, LANG_SORT_CASE, false, "sort case", NULL),
|
OFFON_SETTING(0, sort_case, LANG_SORT_CASE, false, "sort case", NULL),
|
||||||
|
CHOICE_SETTING(0, sort_dir, LANG_SORT_DIR, 0 ,
|
||||||
|
"sort dirs", "alpha,oldest,newest", NULL, 3,
|
||||||
|
ID2P(LANG_SORT_ALPHA), ID2P(LANG_SORT_DATE),
|
||||||
|
ID2P(LANG_SORT_DATE_REVERSE)),
|
||||||
|
CHOICE_SETTING(0, sort_file, LANG_SORT_FILE, 0 ,
|
||||||
|
"sort files", "alpha,oldest,newest,type", NULL, 4,
|
||||||
|
ID2P(LANG_SORT_ALPHA), ID2P(LANG_SORT_DATE),
|
||||||
|
ID2P(LANG_SORT_DATE_REVERSE) , ID2P(LANG_SORT_TYPE)),
|
||||||
|
CHOICE_SETTING(0, interpret_numbers, LANG_SORT_INTERPRET_NUMBERS, 1,
|
||||||
|
"sort interpret number", "digits,numbers",NULL, 2,
|
||||||
|
ID2P(LANG_SORT_INTERPRET_AS_DIGIT),
|
||||||
|
ID2P(LANG_SORT_INTERPRET_AS_NUMBERS)),
|
||||||
CHOICE_SETTING(0, show_filename_ext, LANG_SHOW_FILENAME_EXT, 3,
|
CHOICE_SETTING(0, show_filename_ext, LANG_SHOW_FILENAME_EXT, 3,
|
||||||
"show filename exts", "off,on,unknown,view_all", NULL , 4 ,
|
"show filename exts", "off,on,unknown,view_all", NULL , 4 ,
|
||||||
ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_UNKNOWN_TYPES),
|
ID2P(LANG_OFF), ID2P(LANG_ON), ID2P(LANG_UNKNOWN_TYPES),
|
||||||
|
@ -893,16 +906,6 @@ const struct settings_list settings[] = {
|
||||||
OFFON_SETTING(F_TEMPVAR, talk_battery_level, LANG_TALK_BATTERY_LEVEL, false,
|
OFFON_SETTING(F_TEMPVAR, talk_battery_level, LANG_TALK_BATTERY_LEVEL, false,
|
||||||
"Announce Battery Level", NULL),
|
"Announce Battery Level", NULL),
|
||||||
|
|
||||||
/* file sorting */
|
|
||||||
CHOICE_SETTING(0, sort_file, LANG_SORT_FILE, 0 ,
|
|
||||||
"sort files", "alpha,oldest,newest,type", NULL, 4,
|
|
||||||
ID2P(LANG_SORT_ALPHA), ID2P(LANG_SORT_DATE),
|
|
||||||
ID2P(LANG_SORT_DATE_REVERSE) , ID2P(LANG_SORT_TYPE)),
|
|
||||||
CHOICE_SETTING(0, sort_dir, LANG_SORT_DIR, 0 ,
|
|
||||||
"sort dirs", "alpha,oldest,newest", NULL, 3,
|
|
||||||
ID2P(LANG_SORT_ALPHA), ID2P(LANG_SORT_DATE),
|
|
||||||
ID2P(LANG_SORT_DATE_REVERSE)),
|
|
||||||
|
|
||||||
#ifdef HAVE_RECORDING
|
#ifdef HAVE_RECORDING
|
||||||
/* recording */
|
/* recording */
|
||||||
STRINGCHOICE_SETTING(F_RECSETTING, rec_timesplit, LANG_SPLIT_TIME, 0,
|
STRINGCHOICE_SETTING(F_RECSETTING, rec_timesplit, LANG_SPLIT_TIME, 0,
|
||||||
|
|
|
@ -450,7 +450,7 @@ Kenderes Tamas
|
||||||
Eric Shattow
|
Eric Shattow
|
||||||
Joshua Simmons
|
Joshua Simmons
|
||||||
Sei Aoyumi
|
Sei Aoyumi
|
||||||
|
Martin Pool
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
|
@ -49,6 +49,7 @@ common/strcasestr.c
|
||||||
common/strcat.c
|
common/strcat.c
|
||||||
common/strchr.c
|
common/strchr.c
|
||||||
common/strcmp.c
|
common/strcmp.c
|
||||||
|
common/strnatcmp.c
|
||||||
common/strcpy.c
|
common/strcpy.c
|
||||||
common/strncmp.c
|
common/strncmp.c
|
||||||
common/strncpy.c
|
common/strncpy.c
|
||||||
|
|
179
firmware/common/strnatcmp.c
Normal file
179
firmware/common/strnatcmp.c
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "strnatcmp.h"
|
||||||
|
|
||||||
|
#define assert(x) /* nothing */
|
||||||
|
|
||||||
|
|
||||||
|
/* These are defined as macros to make it easier to adapt this code to
|
||||||
|
* different characters types or comparison functions. */
|
||||||
|
static inline int
|
||||||
|
nat_isdigit(char a)
|
||||||
|
{
|
||||||
|
return isdigit((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
nat_isspace(char a)
|
||||||
|
{
|
||||||
|
return a == '0' || isspace((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline char
|
||||||
|
nat_toupper(char a)
|
||||||
|
{
|
||||||
|
return toupper((unsigned char) a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
|
return bias;
|
||||||
|
else if (!nat_isdigit(*a))
|
||||||
|
return -1;
|
||||||
|
else if (!nat_isdigit(*b))
|
||||||
|
return +1;
|
||||||
|
else 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 (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||||
|
return 0;
|
||||||
|
else if (!nat_isdigit(*a))
|
||||||
|
return -1;
|
||||||
|
else if (!nat_isdigit(*b))
|
||||||
|
return +1;
|
||||||
|
else if (*a < *b)
|
||||||
|
return -1;
|
||||||
|
else 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;
|
||||||
|
|
||||||
|
assert(a && b);
|
||||||
|
ai = bi = 0;
|
||||||
|
while (1) {
|
||||||
|
ca = a[ai]; cb = b[bi];
|
||||||
|
|
||||||
|
/* skip over leading spaces or zeros */
|
||||||
|
while (nat_isspace(ca))
|
||||||
|
ca = a[++ai];
|
||||||
|
|
||||||
|
while (nat_isspace(cb))
|
||||||
|
cb = b[++bi];
|
||||||
|
|
||||||
|
/* process run of digits */
|
||||||
|
if (nat_isdigit(ca) && nat_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 = nat_toupper(ca);
|
||||||
|
cb = nat_toupper(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ca < cb)
|
||||||
|
return -1;
|
||||||
|
else if (ca > cb)
|
||||||
|
return +1;
|
||||||
|
|
||||||
|
++ai; ++bi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int strnatcmp(const char *a, const char *b) {
|
||||||
|
return strnatcmp0(a, b, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Compare, recognizing numeric string and ignoring case. */
|
||||||
|
int strnatcasecmp(const char *a, const char *b) {
|
||||||
|
return strnatcmp0(a, b, 1);
|
||||||
|
}
|
30
firmware/include/strnatcmp.h
Normal file
30
firmware/include/strnatcmp.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* -*- 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* CUSTOMIZATION SECTION
|
||||||
|
*
|
||||||
|
* You can change this typedef, but must then also change the inline
|
||||||
|
* functions in strnatcmp.c */
|
||||||
|
|
||||||
|
int strnatcmp(const char *a, const char *b);
|
||||||
|
int strnatcasecmp(const char *a, const char *b);
|
Loading…
Reference in a new issue