OSDN Git Service

Moved Natural String Sort functions into MUtils library.
authorLoRd_MuldeR <mulder2@gmx.de>
Sun, 30 Nov 2014 17:46:56 +0000 (18:46 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Sun, 30 Nov 2014 17:46:56 +0000 (18:46 +0100)
13 files changed:
MUtilities_VS2013.vcxproj
MUtilities_VS2013.vcxproj.filters
include/MUtils/Global.h
include/MUtils/KeccakHash.h
src/3rd_party/keccak/LICENSE.txt [new file with mode: 0644]
src/3rd_party/keccak/include/keccak_impl.h [moved from src/3rd_party/keccak_impl.h with 99% similarity]
src/3rd_party/strnatcmp/include/strnatcmp.h [new file with mode: 0644]
src/3rd_party/strnatcmp/readme.htm [new file with mode: 0644]
src/3rd_party/strnatcmp/src/strnatcmp.cpp [new file with mode: 0644]
src/Global.cpp
src/KeccakHash.cpp
src/Startup.cpp
src/Version.cpp

index 77f48a3..793709f 100644 (file)
@@ -15,6 +15,7 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="src\3rd_party\strnatcmp\src\strnatcmp.cpp" />
     <ClCompile Include="src\CPUFeatures_Win32.cpp" />
     <ClCompile Include="src\DLLMain.cpp" />
     <ClCompile Include="src\ErrorHandler_Win32.cpp" />
@@ -38,6 +39,8 @@
     <ClInclude Include="include\MUtils\OSSupport.h" />
     <ClInclude Include="include\MUtils\Startup.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\Utils_Win32.h" />
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
       <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>
       <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>
     </ClCompile>
     <Link>
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <FloatingPointModel>Fast</FloatingPointModel>
       <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>
+      <CompileAsManaged>false</CompileAsManaged>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalLibraryDirectories>$(QTDIR)\lib</AdditionalLibraryDirectories>
       <AdditionalDependencies>QtCore4.lib;QtGui4.lib;Psapi.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <GenerateDebugInformation>false</GenerateDebugInformation>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_Static|Win32'">
       <BufferSecurityCheck>false</BufferSecurityCheck>
       <FloatingPointModel>Fast</FloatingPointModel>
       <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>
+      <CompileAsManaged>false</CompileAsManaged>
+      <DebugInformationFormat>None</DebugInformationFormat>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
index 2c07910..ef79cac 100644 (file)
     <Filter Include="Source Files\Generated">
       <UniqueIdentifier>{458f07b7-5414-4e9c-a599-222196e8d2e8}</UniqueIdentifier>
     </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>
     <ClCompile Include="src\UpdateChecker.cpp">
@@ -57,6 +63,9 @@
     <ClCompile Include="src\GUI.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\3rd_party\strnatcmp\src\strnatcmp.cpp">
+      <Filter>Source Files\3rd Party</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\CriticalSection_Win32.h">
     <ClInclude Include="src\Utils_Win32.h">
       <Filter>Header Files</Filter>
     </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>
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
index 4debf73..f44cec3 100644 (file)
@@ -88,6 +88,9 @@ namespace MUtils
        MUTILS_API bool remove_file(const QString &fileName);
        MUTILS_API bool remove_directory(const QString &folderPath);
 
+       //String sorting
+       MUTILS_API void natural_string_sort(QStringList &list, const bool bIgnoreCase);
+
        //Internal
        namespace Internal
        {
index d634a01..42ebd52 100644 (file)
 
 namespace MUtils
 {
-       // Section from KeccakSponge.h
-       // 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
+       namespace Internal
        {
-               #define KeccakPermutationSize 1600
-               #define KeccakPermutationSizeInBytes (KeccakPermutationSize/8)
-               #define KeccakMaximumRate 1536
-               #define KeccakMaximumRateInBytes (KeccakMaximumRate/8)
+               // Section from KeccakSponge.h
+               // 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
+                       #define KeccakPermutationSizeInBytes (KeccakPermutationSize/8)
+                       #define KeccakMaximumRate 1536
+                       #define KeccakMaximumRateInBytes (KeccakMaximumRate/8)
 
-               #if defined(__GNUC__)
-               #define ALIGN __attribute__ ((aligned(32)))
-               #elif defined(_MSC_VER)
-               #define ALIGN __declspec(align(32))
-               #else
-               #define ALIGN
-               #endif
+                       #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];
-                       ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes];
-                       unsigned int rate;
-                       unsigned int capacity;
-                       unsigned int bitsInQueue;
-                       unsigned int fixedOutputLength;
-                       int squeezing;
-                       unsigned int bitsAvailableForSqueezing;
+                       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;
-               typedef spongeState hashState;
+               // End Section from KeccakSponge.h
        }
-       // End Section from KeccakSponge.h
 
        class MUTILS_API KeccakHash
        {
@@ -107,7 +110,7 @@ namespace MUtils
 
        protected:
                bool m_initialized;
-               KeccakImpl::hashState *m_state;
+               Internal::KeccakImpl::hashState *m_state;
                QByteArray m_hashResult;
        };
 };
diff --git a/src/3rd_party/keccak/LICENSE.txt b/src/3rd_party/keccak/LICENSE.txt
new file mode 100644 (file)
index 0000000..f2b6226
--- /dev/null
@@ -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
+*/
similarity index 99%
rename from src/3rd_party/keccak_impl.h
rename to src/3rd_party/keccak/include/keccak_impl.h
index 7155ede..84bd6bc 100644 (file)
@@ -19,6 +19,7 @@
 ***************************************************************************/
 
 namespace MUtils {
+namespace Internal {
 namespace KeccakImpl {
 
 typedef unsigned char UINT8;
@@ -1997,5 +1998,6 @@ HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen,
 
 
 } // end of namespace KeccakImpl
+} // end of namespace Internal
 } // end of namespace MUtils
 
diff --git a/src/3rd_party/strnatcmp/include/strnatcmp.h b/src/3rd_party/strnatcmp/include/strnatcmp.h
new file mode 100644 (file)
index 0000000..cbda35d
--- /dev/null
@@ -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);
+               }
+       }
+}
diff --git a/src/3rd_party/strnatcmp/readme.htm b/src/3rd_party/strnatcmp/readme.htm
new file mode 100644 (file)
index 0000000..c443f36
--- /dev/null
@@ -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>
\ No newline at end of file
diff --git a/src/3rd_party/strnatcmp/src/strnatcmp.cpp b/src/3rd_party/strnatcmp/src/strnatcmp.cpp
new file mode 100644 (file)
index 0000000..60ca371
--- /dev/null
@@ -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);
+}
index e94c440..2676603 100644 (file)
 //MUtils
 #include <MUtils/Global.h>
 #include <MUtils/OSSupport.h>
+
+//Internal
 #include "DirLocker.h"
+#include "3rd_party/strnatcmp/include/strnatcmp.h"
 
 //Qt
 #include <QDir>
@@ -302,6 +305,25 @@ void MUtils::init_process(QProcess &process, const QString &wokringDir, const bo
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// 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
 ///////////////////////////////////////////////////////////////////////////////
 
index 1023a05..ae88817 100644 (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.                            **
 **  Copyright (C) 2013 Emanuel Eichhammer                                 **
 **                                                                        **
 #include <MUtils/KeccakHash.h>
 #include <QDebug>
 
-#include "3rd_party/keccak_impl.h"
+#include "3rd_party/keccak/include/keccak_impl.h"
 
 MUtils::KeccakHash::KeccakHash()
 {
        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)
        {
                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();
 }
 
@@ -81,7 +81,7 @@ bool MUtils::KeccakHash::init(HashBits hashBits)
        }
 
        m_hashResult.clear();
-       memset(m_state, 0, sizeof(MUtils::KeccakImpl::hashState));
+       memset(m_state, 0, sizeof(MUtils::Internal::KeccakImpl::hashState));
        int hashBitLength = 0;
 
        switch (hashBits)
@@ -93,7 +93,7 @@ bool MUtils::KeccakHash::init(HashBits hashBits)
                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!");
                return false;
@@ -118,7 +118,7 @@ bool MUtils::KeccakHash::addData(const char *data, int size)
                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!");
                m_hashResult.clear();
@@ -138,7 +138,7 @@ const QByteArray &MUtils::KeccakHash::finalize()
                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!");
                m_hashResult.clear();
index de8d6b3..3fe6dd1 100644 (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 iResult = -1;
-#if(MUTILS_DEBUG)
+#if 1||(MUTILS_DEBUG)
        iResult = startup_main(argc, argv, entry_point);
 #else //MUTILS_DEBUG
 #ifdef _MSC_VER
index 34a3061..2544bd7 100644 (file)
@@ -26,6 +26,7 @@
 //Internal
 #include <MUtils/Global.h>
 #include <MUtils/Exception.h>
+#include <MUtils/OSSupport.h>
 #include "Config.h"
 
 #ifdef _MSC_VER