Moved Natural String Sort functions into MUtils library.

This commit is contained in:
LoRd_MuldeR 2014-11-30 18:46:56 +01:00
parent 52b230f2db
commit a0707809f5
13 changed files with 572 additions and 43 deletions

View File

@ -15,6 +15,7 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\3rd_party\strnatcmp\src\strnatcmp.cpp" />
<ClCompile Include="src\CPUFeatures_Win32.cpp" /> <ClCompile Include="src\CPUFeatures_Win32.cpp" />
<ClCompile Include="src\DLLMain.cpp" /> <ClCompile Include="src\DLLMain.cpp" />
<ClCompile Include="src\ErrorHandler_Win32.cpp" /> <ClCompile Include="src\ErrorHandler_Win32.cpp" />
@ -38,6 +39,8 @@
<ClInclude Include="include\MUtils\OSSupport.h" /> <ClInclude Include="include\MUtils\OSSupport.h" />
<ClInclude Include="include\MUtils\Startup.h" /> <ClInclude Include="include\MUtils\Startup.h" />
<ClInclude Include="include\MUtils\Terminal.h" /> <ClInclude Include="include\MUtils\Terminal.h" />
<ClInclude Include="src\3rd_party\keccak\include\keccak_impl.h" />
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h" />
<ClInclude Include="src\DirLocker.h" /> <ClInclude Include="src\DirLocker.h" />
<ClInclude Include="src\Utils_Win32.h" /> <ClInclude Include="src\Utils_Win32.h" />
<CustomBuild Include="include\Mutils\UpdateChecker.h"> <CustomBuild Include="include\Mutils\UpdateChecker.h">
@ -118,7 +121,7 @@
<PreprocessorDefinitions>WIN32;MUTILS_DLL_EXPORT;_DEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;MUTILS_DLL_EXPORT;_DEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet> <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
<AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
</ClCompile> </ClCompile>
<Link> <Link>
@ -145,8 +148,9 @@
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<FloatingPointModel>Fast</FloatingPointModel> <FloatingPointModel>Fast</FloatingPointModel>
<CreateHotpatchableImage>false</CreateHotpatchableImage> <CreateHotpatchableImage>false</CreateHotpatchableImage>
<AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<CompileAsManaged>false</CompileAsManaged>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -154,7 +158,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(QTDIR)\lib</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(QTDIR)\lib</AdditionalLibraryDirectories>
<AdditionalDependencies>QtCore4.lib;QtGui4.lib;Psapi.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>QtCore4.lib;QtGui4.lib;Psapi.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>false</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">
@ -174,8 +178,10 @@
<BufferSecurityCheck>false</BufferSecurityCheck> <BufferSecurityCheck>false</BufferSecurityCheck>
<FloatingPointModel>Fast</FloatingPointModel> <FloatingPointModel>Fast</FloatingPointModel>
<CreateHotpatchableImage>false</CreateHotpatchableImage> <CreateHotpatchableImage>false</CreateHotpatchableImage>
<AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(SolutionDir)\..\Prerequisites\VisualLeakDetector\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<TreatWarningAsError>true</TreatWarningAsError> <TreatWarningAsError>true</TreatWarningAsError>
<CompileAsManaged>false</CompileAsManaged>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>

View File

@ -19,6 +19,12 @@
<Filter Include="Source Files\Generated"> <Filter Include="Source Files\Generated">
<UniqueIdentifier>{458f07b7-5414-4e9c-a599-222196e8d2e8}</UniqueIdentifier> <UniqueIdentifier>{458f07b7-5414-4e9c-a599-222196e8d2e8}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Source Files\3rd Party">
<UniqueIdentifier>{d5bcdb46-27a3-4772-86b4-1b30e02a30cc}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\3rd Party">
<UniqueIdentifier>{6261ec8d-8041-495b-bddf-6fe07c11c952}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="src\UpdateChecker.cpp"> <ClCompile Include="src\UpdateChecker.cpp">
@ -57,6 +63,9 @@
<ClCompile Include="src\GUI.cpp"> <ClCompile Include="src\GUI.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\3rd_party\strnatcmp\src\strnatcmp.cpp">
<Filter>Source Files\3rd Party</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="src\CriticalSection_Win32.h"> <ClInclude Include="src\CriticalSection_Win32.h">
@ -98,6 +107,12 @@
<ClInclude Include="src\Utils_Win32.h"> <ClInclude Include="src\Utils_Win32.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="src\3rd_party\strnatcmp\include\strnatcmp.h">
<Filter>Header Files\3rd Party</Filter>
</ClInclude>
<ClInclude Include="src\3rd_party\keccak\include\keccak_impl.h">
<Filter>Header Files\3rd Party</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<CustomBuild Include="include\Mutils\UpdateChecker.h"> <CustomBuild Include="include\Mutils\UpdateChecker.h">

View File

@ -88,6 +88,9 @@ namespace MUtils
MUTILS_API bool remove_file(const QString &fileName); MUTILS_API bool remove_file(const QString &fileName);
MUTILS_API bool remove_directory(const QString &folderPath); MUTILS_API bool remove_directory(const QString &folderPath);
//String sorting
MUTILS_API void natural_string_sort(QStringList &list, const bool bIgnoreCase);
//Internal //Internal
namespace Internal namespace Internal
{ {

View File

@ -56,39 +56,42 @@
namespace MUtils namespace MUtils
{ {
// Section from KeccakSponge.h namespace Internal
// needed here, since hashState needs to be explicitly 32-byte aligned and therefore can't be
// transformed into a class (in order to forward declarate) like in the other hash wrappers.
namespace KeccakImpl
{ {
#define KeccakPermutationSize 1600 // Section from KeccakSponge.h
#define KeccakPermutationSizeInBytes (KeccakPermutationSize/8) // needed here, since hashState needs to be explicitly 32-byte aligned and therefore can't be
#define KeccakMaximumRate 1536 // transformed into a class (in order to forward declarate) like in the other hash wrappers.
#define KeccakMaximumRateInBytes (KeccakMaximumRate/8) namespace KeccakImpl
#if defined(__GNUC__)
#define ALIGN __attribute__ ((aligned(32)))
#elif defined(_MSC_VER)
#define ALIGN __declspec(align(32))
#else
#define ALIGN
#endif
ALIGN typedef struct spongeStateStruct
{ {
ALIGN unsigned char state[KeccakPermutationSizeInBytes]; #define KeccakPermutationSize 1600
ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes]; #define KeccakPermutationSizeInBytes (KeccakPermutationSize/8)
unsigned int rate; #define KeccakMaximumRate 1536
unsigned int capacity; #define KeccakMaximumRateInBytes (KeccakMaximumRate/8)
unsigned int bitsInQueue;
unsigned int fixedOutputLength; #if defined(__GNUC__)
int squeezing; #define ALIGN __attribute__ ((aligned(32)))
unsigned int bitsAvailableForSqueezing; #elif defined(_MSC_VER)
#define ALIGN __declspec(align(32))
#else
#define ALIGN
#endif
ALIGN typedef struct spongeStateStruct
{
ALIGN unsigned char state[KeccakPermutationSizeInBytes];
ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes];
unsigned int rate;
unsigned int capacity;
unsigned int bitsInQueue;
unsigned int fixedOutputLength;
int squeezing;
unsigned int bitsAvailableForSqueezing;
}
spongeState;
typedef spongeState hashState;
} }
spongeState; // End Section from KeccakSponge.h
typedef spongeState hashState;
} }
// End Section from KeccakSponge.h
class MUTILS_API KeccakHash class MUTILS_API KeccakHash
{ {
@ -107,7 +110,7 @@ namespace MUtils
protected: protected:
bool m_initialized; bool m_initialized;
KeccakImpl::hashState *m_state; Internal::KeccakImpl::hashState *m_state;
QByteArray m_hashResult; QByteArray m_hashResult;
}; };
}; };

27
src/3rd_party/keccak/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,27 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/

View File

@ -19,6 +19,7 @@
***************************************************************************/ ***************************************************************************/
namespace MUtils { namespace MUtils {
namespace Internal {
namespace KeccakImpl { namespace KeccakImpl {
typedef unsigned char UINT8; typedef unsigned char UINT8;
@ -1997,5 +1998,6 @@ HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen,
} // end of namespace KeccakImpl } // end of namespace KeccakImpl
} // end of namespace Internal
} // end of namespace MUtils } // end of namespace MUtils

View File

@ -0,0 +1,40 @@
/* -*- 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.
*/
namespace MUtils
{
namespace Internal
{
namespace NaturalSort
{
/* CUSTOMIZATION SECTION
*
* You can change this typedef, but must then also change the inline
* functions in strnatcmp.c */
typedef wchar_t nat_char;
int strnatcmp(nat_char const *a, nat_char const *b);
int strnatcasecmp(nat_char const *a, nat_char const *b);
}
}
}

196
src/3rd_party/strnatcmp/readme.htm vendored Normal file
View File

@ -0,0 +1,196 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<title>Natural Order String Comparison</title>
</head>
<body>
<h1>Natural Order String Comparison</h1>
<p>by <a href="http://sourcefrog.net/">Martin Pool</a>
</p><p>Computer string sorting algorithms generally don't order strings
containing numbers in the same way that a human would do. Consider:
</p><blockquote><pre>rfc1.txt
rfc2086.txt
rfc822.txt
</pre></blockquote>
<p>It would be more friendly if the program listed the files as
</p><blockquote><pre>rfc1.txt
rfc822.txt
rfc2086.txt
</pre></blockquote>
<p>Filenames sort properly if people insert leading zeros, but they
don't always do that.
</p><p>I've written a subroutine that compares strings according to this
natural ordering. You can use this routine in your own software, or
download a patch to add it to your favourite Unix program.
</p><h2>Sorting</h2>
<p>Strings are sorted as usual, except that decimal integer substrings
are compared on their numeric value. For example,
</p><blockquote>
a &lt; a0 &lt; a1 &lt; a1a &lt; a1b &lt; a2 &lt; a10 &lt; a20
</blockquote>
<p>Strings can contain several number parts:
</p><blockquote>
x2-g8 &lt; x2-y7 &lt; x2-y08 &lt; x8-y8
</blockquote>
in which case numeric fields are separated by nonnumeric characters.
Leading spaces are ignored. This works very well for IP addresses
from log files, for example.
<p>
Leading zeros are <u>not</u> ignored, which tends to give more
reasonable results on decimal fractions.
</p>
<blockquote>
1.001 &lt; 1.002 &lt; 1.010 &lt; 1.02 &lt; 1.1 &lt; 1.3
</blockquote>
<p>Some applications may wish to change this by modifying the test
that calls <code>isspace</code>.
</p><p>
Performance is linear: each character of the string is scanned
at most once, and only as many characters as necessary to decide
are considered.
</p>
<p><a href="http://sourcefrog.net/projects/natsort/example-out.txt">Longer example of the results</a>
</p><h2>Licensing</h2>
<p>This software is copyright by Martin Pool, and made available under
the same licence as zlib:
</p><blockquote>
<p> 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.
</p><p> 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:
</p><p> 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.
</p><p> 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
</p><p> 3. This notice may not be removed or altered from any source distribution.
</p></blockquote>
<p>This licence applies only to the C implementation. You are free to
reimplement the idea fom scratch in any language.
</p><h2>Related Work</h2>
<p>
POSIX sort(1) has the -n option to sort numbers, but this doesn't
work if there is a non-numeric prefix.
</p>
<p>
GNU ls(1) has the <tt>--sort=version</tt> option, which works
the same way.
</p>
<p>
The PHP scripting language now has a
<a href="http://us3.php.net/manual/en/function.strnatcmp.php">strnatcmp</a>
function based on this code.
The PHP wrapper was done by Andrei Zimievsky.
</p>
<p>
<a href="http://www.naturalordersort.org/">Stuart
Cheshire</a> has a Macintosh <q>system extension</q> to do natural ordering.
I indepdendently reinvented the algorithm, but Stuart had it
first. I borrowed the term <q>natural sort</q> from him.
</p>
<p>
<a href="http://search.cpan.org/src/EDAVIS/Sort-Versions-1.4/README"><tt>Sort::Versions</tt></a>
in Perl. "The code has some special magic to deal with common
conventions in program version numbers, like the difference between
'decimal' versions (eg perl 5.005) and the Unix kind (eg perl 5.6.1)."
</p><p><a href="http://www.cpan.org/modules/by-module/Sort/Sort-Naturally-1.01.readme"><tt>Sort::Naturally</tt></a>
is also in Perl, by Sean M. Burke. It uses locale-sensitive character classes to sort words and numeric substrings
in a way similar to natsort.
</p><p>
Ed Avis wrote <a href="http://membled.com/work/apps/todo/numsort">something similar in Haskell</a>.
</p><p>
Pierre-Luc Paour wrote a <a href="http://pierre-luc.paour.9online.fr/NaturalOrderComparator.java"><tt>NaturalOrderComparator</tt>
in Java</a>
</p><p>Kristof Coomans wrote a <a href="http://sourcefrog.net/projects/natsort/natcompare.js">natural sort comparison in Javascript</a></p>
<p>Alan Davies wrote
<a href="http://sourcefrog.net/projects/natsort/natcmp.rb"><tt>natcmp.rb</tt></a>,
an implementation in <a href="http://www.ruby-lang.org/">Ruby</a>.
</p><p><a href="http://sourceforge.net/projects/numacomp">Numacomp</a>
- similar thing in Python.
</p><p><a href="http://code.google.com/p/as3natcompare/">as3natcompare</a>
implementation in Flash ActionScript 3.
</p><h2>Get It!</h2>
<ul>
<li><a href="http://sourcefrog.net/projects/natsort/strnatcmp.c">strnatcmp.c</a>,
<a href="http://sourcefrog.net/projects/natsort/strnatcmp.h">strnatcmp.h</a> - the algorithm itself
</li><li><a href="http://sourcefrog.net/projects/natsort/natsort.c">natsort.c</a> - example driver program.
(Try <tt>ls -F /proc | natsort</tt>)
</li><li><a href="http://sourcefrog.net/projects/natsort/textutils.diff">textutils.diff</a> - patch to add
natural sort to sort(1) from GNU textutils-2.0; use the new
<tt>-N</tt> option.</li>
<li>Natural ordering is now in PHP4rc2, through the <a href="http://php.net/manual/html/function.strnatcasecmp.html">strnatcasecmp</a>
and <a href="http://php.net/manual/html/function.strnatcmp.html">strnatcmp</a>
functions.</li>
</ul>
<h2>To Do</h2>
<p>
Comparison of characters is purely numeric, without taking
character set or locale into account. So it is only correct for
ASCII. This should probably be a separate function because doing
the comparisons will probably introduce a dependency on the OS
mechanism for finding the locale and comparing characters.
</p><p>
It might be good to support multibyte character sets too.
</p><p>
If you fix either of these, please mail me. They should not be
very hard.
</p></body></html>

View File

@ -0,0 +1,214 @@
/* -*- 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.
*/
/*
* 2013-08-23: Skip leading zero's for any run of digits, except
* when a decimal point was seen immediatley before.
* Patch by LoRd_MuldeR <mulder2@gmx.de>
*/
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "../include/strnatcmp.h"
/* 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(MUtils::Internal::NaturalSort::nat_char a)
{
return iswdigit(a);
}
static inline int nat_isspace(MUtils::Internal::NaturalSort::nat_char a)
{
return iswspace(a);
}
static inline MUtils::Internal::NaturalSort::nat_char nat_isdecpoint(MUtils::Internal::NaturalSort::nat_char a)
{
return (a == L'.') || (a == L',');
}
static inline MUtils::Internal::NaturalSort::nat_char nat_toupper(MUtils::Internal::NaturalSort::nat_char a)
{
return towupper(a);
}
static int compare_right(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_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(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_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(MUtils::Internal::NaturalSort::nat_char const *a, MUtils::Internal::NaturalSort::nat_char const *b, const bool fold_case)
{
int ai, bi;
MUtils::Internal::NaturalSort::nat_char ca, cb;
int result;
bool fractional;
int sa, sb;
assert(a && b);
ai = bi = 0;
fractional = false;
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))
{
sa = sb = 0;
if(!fractional)
{
while (ca == L'0')
{
ca = a[++ai]; sa++;
}
while (cb == L'0')
{
cb = b[++bi]; sb++;
}
}
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;
}
/* on tie, the string with the longer leading zero's sequence wins */
if(sa < sb)
return -1;
else if(sa > sb)
return +1;
}
if (!ca && !cb)
{
/* The strings compare the same. Perhaps the caller
will want to call strcmp to break the tie. */
return (fold_case) ? _wcsicmp(a, b) : wcscmp(a, b);
}
if (fold_case)
{
ca = nat_toupper(ca);
cb = nat_toupper(cb);
}
if (ca < cb)
return -1;
else if (ca > cb)
return +1;
/* skipp leading zero's, unless previously seen char was a decimal point */
fractional = nat_isdecpoint(ca) && nat_isdecpoint(cb);
++ai; ++bi;
}
}
int MUtils::Internal::NaturalSort::strnatcmp(nat_char const *a, nat_char const *b)
{
return strnatcmp0(a, b, false);
}
/* Compare, recognizing numeric string and ignoring case. */
int MUtils::Internal::NaturalSort::strnatcasecmp(nat_char const *a, nat_char const *b)
{
return strnatcmp0(a, b, true);
}

View File

@ -26,7 +26,10 @@
//MUtils //MUtils
#include <MUtils/Global.h> #include <MUtils/Global.h>
#include <MUtils/OSSupport.h> #include <MUtils/OSSupport.h>
//Internal
#include "DirLocker.h" #include "DirLocker.h"
#include "3rd_party/strnatcmp/include/strnatcmp.h"
//Qt //Qt
#include <QDir> #include <QDir>
@ -301,6 +304,25 @@ void MUtils::init_process(QProcess &process, const QString &wokringDir, const bo
process.setProcessEnvironment(env); process.setProcessEnvironment(env);
} }
///////////////////////////////////////////////////////////////////////////////
// NATURAL ORDER STRING COMPARISON
///////////////////////////////////////////////////////////////////////////////
static bool natural_string_sort_helper(const QString &str1, const QString &str2)
{
return (MUtils::Internal::NaturalSort::strnatcmp(MUTILS_WCHR(str1), MUTILS_WCHR(str2)) < 0);
}
static bool natural_string_sort_helper_fold_case(const QString &str1, const QString &str2)
{
return (MUtils::Internal::NaturalSort::strnatcasecmp(MUTILS_WCHR(str1), MUTILS_WCHR(str2)) < 0);
}
void MUtils::natural_string_sort(QStringList &list, const bool bIgnoreCase)
{
qSort(list.begin(), list.end(), bIgnoreCase ? natural_string_sort_helper_fold_case : natural_string_sort_helper);
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// SELF-TEST // SELF-TEST
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

@ -21,7 +21,7 @@
/*************************************************************************** /***************************************************************************
** ** ** **
** MUtils::KeccakHash, an API wrapper bringing the optimized implementation of ** ** QKeccakHash, an API wrapper bringing the optimized implementation of **
** Keccak (http://keccak.noekeon.org/) to Qt. ** ** Keccak (http://keccak.noekeon.org/) to Qt. **
** Copyright (C) 2013 Emanuel Eichhammer ** ** Copyright (C) 2013 Emanuel Eichhammer **
** ** ** **
@ -47,17 +47,17 @@
#include <MUtils/KeccakHash.h> #include <MUtils/KeccakHash.h>
#include <QDebug> #include <QDebug>
#include "3rd_party/keccak_impl.h" #include "3rd_party/keccak/include/keccak_impl.h"
MUtils::KeccakHash::KeccakHash() MUtils::KeccakHash::KeccakHash()
{ {
m_initialized = false; m_initialized = false;
m_state = (MUtils::KeccakImpl::hashState*) _aligned_malloc(sizeof(MUtils::KeccakImpl::hashState), 32); m_state = (MUtils::Internal::KeccakImpl::hashState*) _aligned_malloc(sizeof(MUtils::Internal::KeccakImpl::hashState), 32);
if(!m_state) if(!m_state)
{ {
throw "[MUtils::KeccakHash] Error: _aligned_malloc() has failed, probably out of heap space!"; throw "[MUtils::KeccakHash] Error: _aligned_malloc() has failed, probably out of heap space!";
} }
memset(m_state, 0, sizeof(MUtils::KeccakImpl::hashState)); memset(m_state, 0, sizeof(MUtils::Internal::KeccakImpl::hashState));
m_hashResult.clear(); m_hashResult.clear();
} }
@ -81,7 +81,7 @@ bool MUtils::KeccakHash::init(HashBits hashBits)
} }
m_hashResult.clear(); m_hashResult.clear();
memset(m_state, 0, sizeof(MUtils::KeccakImpl::hashState)); memset(m_state, 0, sizeof(MUtils::Internal::KeccakImpl::hashState));
int hashBitLength = 0; int hashBitLength = 0;
switch (hashBits) switch (hashBits)
@ -93,7 +93,7 @@ bool MUtils::KeccakHash::init(HashBits hashBits)
default: throw "Invalid hash length!!"; default: throw "Invalid hash length!!";
} }
if(MUtils::KeccakImpl::Init(m_state, hashBitLength) != MUtils::KeccakImpl::SUCCESS) if(MUtils::Internal::KeccakImpl::Init(m_state, hashBitLength) != MUtils::Internal::KeccakImpl::SUCCESS)
{ {
qWarning("KeccakImpl::Init() has failed unexpectedly!"); qWarning("KeccakImpl::Init() has failed unexpectedly!");
return false; return false;
@ -118,7 +118,7 @@ bool MUtils::KeccakHash::addData(const char *data, int size)
return false; return false;
} }
if(MUtils::KeccakImpl::Update(m_state, (MUtils::KeccakImpl::BitSequence*)data, size*8) != MUtils::KeccakImpl::SUCCESS) if(MUtils::Internal::KeccakImpl::Update(m_state, (MUtils::Internal::KeccakImpl::BitSequence*)data, size*8) != MUtils::Internal::KeccakImpl::SUCCESS)
{ {
qWarning("KeccakImpl::Update() has failed unexpectedly!"); qWarning("KeccakImpl::Update() has failed unexpectedly!");
m_hashResult.clear(); m_hashResult.clear();
@ -138,7 +138,7 @@ const QByteArray &MUtils::KeccakHash::finalize()
return m_hashResult; return m_hashResult;
} }
if(MUtils::KeccakImpl::Final(m_state, (MUtils::KeccakImpl::BitSequence*)m_hashResult.data()) != MUtils::KeccakImpl::SUCCESS) if(MUtils::Internal::KeccakImpl::Final(m_state, (MUtils::Internal::KeccakImpl::BitSequence*)m_hashResult.data()) != MUtils::Internal::KeccakImpl::SUCCESS)
{ {
qWarning("KeccakImpl::Final() has failed unexpectedly!"); qWarning("KeccakImpl::Final() has failed unexpectedly!");
m_hashResult.clear(); m_hashResult.clear();

View File

@ -94,7 +94,7 @@ static int startup_helper(int &argc, char **argv, MUtils::Startup::main_function
int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entry_point) int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entry_point)
{ {
int iResult = -1; int iResult = -1;
#if(MUTILS_DEBUG) #if 1||(MUTILS_DEBUG)
iResult = startup_main(argc, argv, entry_point); iResult = startup_main(argc, argv, entry_point);
#else //MUTILS_DEBUG #else //MUTILS_DEBUG
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -26,6 +26,7 @@
//Internal //Internal
#include <MUtils/Global.h> #include <MUtils/Global.h>
#include <MUtils/Exception.h> #include <MUtils/Exception.h>
#include <MUtils/OSSupport.h>
#include "Config.h" #include "Config.h"
#ifdef _MSC_VER #ifdef _MSC_VER