Commit bea9d765a2d7c5592c5877ccf042e4637b99eef5

Authored by Josh Klontz
1 parent c996e5ae

implemented natural sorting

3rdparty/NaturalStringCompare2/NaturalStringCompare.cpp 0 → 100755
  1 +/*
  2 + * This software was written by people from OnShore Consulting services LLC
  3 + * <info@sabgroup.com> and placed in the public domain.
  4 + *
  5 + * We reserve no legal rights to any of this. You are free to do
  6 + * whatever you want with it. And we make no guarantee or accept
  7 + * any claims on damages as a result of this.
  8 + *
  9 + * If you change the software, please help us and others improve the
  10 + * code by sending your modifications to us. If you choose to do so,
  11 + * your changes will be included under this license, and we will add
  12 + * your name to the list of contributors.
  13 +*/
  14 +
  15 +#include "NaturalStringCompare.h"
  16 +#include <QStringList>
  17 +
  18 +#define INCBUF() { buffer += curr; ++pos; curr = ( pos < string.length() ) ? string[ pos ] : QChar(); }
  19 +
  20 +void ExtractToken( QString & buffer, const QString & string, int & pos, bool & isNumber )
  21 +{
  22 + buffer.clear();
  23 + if ( string.isNull() || pos >= string.length() )
  24 + return;
  25 +
  26 + isNumber = false;
  27 + QChar curr = string[ pos ];
  28 + if ( curr == '-' || curr == '+' || curr.isDigit() )
  29 + {
  30 + if ( curr == '-' || curr == '+' )
  31 + INCBUF();
  32 +
  33 + if ( !curr.isNull() && curr.isDigit() )
  34 + {
  35 + isNumber = true;
  36 + while ( curr.isDigit() )
  37 + INCBUF();
  38 +
  39 + if ( curr == '.' )
  40 + {
  41 + INCBUF();
  42 + while ( curr.isDigit() )
  43 + INCBUF();
  44 + }
  45 +
  46 + if ( !curr.isNull() && curr.toLower() == 'e' )
  47 + {
  48 + INCBUF();
  49 + if ( curr == '-' || curr == '+' )
  50 + INCBUF();
  51 +
  52 + if ( curr.isNull() || !curr.isDigit() )
  53 + isNumber = false;
  54 + else
  55 + while ( curr.isDigit() )
  56 + INCBUF();
  57 + }
  58 + }
  59 + }
  60 +
  61 + if ( !isNumber )
  62 + {
  63 + while ( curr != '-' && curr != '+' && !curr.isDigit() && pos < string.length() )
  64 + INCBUF();
  65 + }
  66 +}
  67 +
  68 +int NaturalStringCompare( const QString & lhs, const QString & rhs, Qt::CaseSensitivity caseSensitive )
  69 +{
  70 + int ii = 0;
  71 + int jj = 0;
  72 +
  73 + QString lhsBufferQStr;
  74 + QString rhsBufferQStr;
  75 +
  76 + int retVal = 0;
  77 +
  78 + // all status values are created on the stack outside the loop to make as fast as possible
  79 + bool lhsNumber = false;
  80 + bool rhsNumber = false;
  81 +
  82 + double lhsValue = 0.0;
  83 + double rhsValue = 0.0;
  84 + bool ok1;
  85 + bool ok2;
  86 +
  87 + while ( retVal == 0 && ii < lhs.length() && jj < rhs.length() )
  88 + {
  89 + ExtractToken( lhsBufferQStr, lhs, ii, lhsNumber );
  90 + ExtractToken( rhsBufferQStr, rhs, jj, rhsNumber );
  91 +
  92 + if ( !lhsNumber && !rhsNumber )
  93 + {
  94 + // both strings curr val is a simple strcmp
  95 + retVal = lhsBufferQStr.compare( rhsBufferQStr, caseSensitive );
  96 +
  97 + int maxLen = qMin( lhsBufferQStr.length(), rhsBufferQStr.length() );
  98 + QString tmpRight = rhsBufferQStr.left( maxLen );
  99 + QString tmpLeft = lhsBufferQStr.left( maxLen );
  100 + if ( tmpLeft.compare( tmpRight, caseSensitive ) == 0 )
  101 + {
  102 + retVal = lhsBufferQStr.length() - rhsBufferQStr.length();
  103 + if ( retVal )
  104 + {
  105 + QChar nextChar;
  106 + if ( ii < lhs.length() ) // more on the lhs
  107 + nextChar = lhs[ ii ];
  108 + else if ( jj < rhs.length() ) // more on the rhs
  109 + nextChar = rhs[ jj ];
  110 +
  111 + bool nextIsNum = ( nextChar == '-' || nextChar == '+' || nextChar.isDigit() );
  112 +
  113 + if ( nextIsNum )
  114 + retVal = -1*retVal;
  115 + }
  116 + }
  117 + }
  118 + else if ( lhsNumber && rhsNumber )
  119 + {
  120 + // both numbers, convert and compare
  121 + lhsValue = lhsBufferQStr.toDouble( &ok1 );
  122 + rhsValue = rhsBufferQStr.toDouble( &ok2 );
  123 + if ( !ok1 || !ok2 )
  124 + retVal = lhsBufferQStr.compare( rhsBufferQStr, caseSensitive );
  125 + else if ( lhsValue > rhsValue )
  126 + retVal = 1;
  127 + else if ( lhsValue < rhsValue )
  128 + retVal = -1;
  129 + }
  130 + else
  131 + {
  132 + // completely arebitrary that a number comes before a string
  133 + retVal = lhsNumber ? -1 : 1;
  134 + }
  135 + }
  136 +
  137 + if ( retVal != 0 )
  138 + return retVal;
  139 + if ( ii < lhs.length() )
  140 + return -1;
  141 + else if ( jj < rhs.length() )
  142 + return 1;
  143 + else
  144 + return 0;
  145 +}
  146 +
  147 +bool NaturalStringCompareLessThan( const QString & lhs, const QString & rhs )
  148 +{
  149 + return NaturalStringCompare( lhs, rhs, Qt::CaseSensitive ) < 0;
  150 +}
  151 +
  152 +bool NaturalStringCaseInsensitiveCompareLessThan( const QString & lhs, const QString & rhs )
  153 +{
  154 + return NaturalStringCompare( lhs, rhs, Qt::CaseInsensitive ) < 0;
  155 +}
  156 +
  157 +QStringList NaturalStringSort( const QStringList & list, Qt::CaseSensitivity caseSensitive )
  158 +{
  159 + QStringList retVal = list;
  160 + if ( caseSensitive == Qt::CaseSensitive )
  161 + qSort( retVal.begin(), retVal.end(), NaturalStringCompareLessThan );
  162 + else
  163 + qSort( retVal.begin(), retVal.end(), NaturalStringCaseInsensitiveCompareLessThan );
  164 + return retVal;
  165 +}
  166 +
  167 +
3rdparty/NaturalStringCompare2/NaturalStringCompare.h 0 → 100755
  1 +#ifndef __NATURALSTRINGCOMPARE_H
  2 +#define __NATURALSTRINGCOMPARE_H
  3 +
  4 +/*
  5 + * This software was written by people from OnShore Consulting services LLC
  6 + * <info@sabgroup.com> and placed in the public domain.
  7 + *
  8 + * We reserve no legal rights to any of this. You are free to do
  9 + * whatever you want with it. And we make no guarantee or accept
  10 + * any claims on damages as a result of this.
  11 + *
  12 + * If you change the software, please help us and others improve the
  13 + * code by sending your modifications to us. If you choose to do so,
  14 + * your changes will be included under this license, and we will add
  15 + * your name to the list of contributors.
  16 +*/
  17 +
  18 +#include <QString>
  19 +#include <QStringList>
  20 +
  21 +int NaturalStringCompare( const QString & lhs, const QString & rhs, Qt::CaseSensitivity caseSensitive=Qt::CaseSensitive );
  22 +QStringList NaturalStringSort( const QStringList & list, Qt::CaseSensitivity caseSensitive=Qt::CaseSensitive );
  23 +bool NaturalStringCompareLessThan( const QString & lhs, const QString & rhs );
  24 +bool NaturalStringCaseInsensitiveCompareLessThan( const QString & lhs, const QString & rhs );
  25 +
  26 +#endif
3rdparty/NaturalStringCompare2/NaturalStringCompare.pro 0 → 100755
  1 +######################################################################
  2 +# Automatically generated by qmake (2.01a) Mon Feb 25 10:13:54 2008
  3 +######################################################################
  4 +
  5 +TEMPLATE = app
  6 +TARGET =
  7 +DEPENDPATH += .
  8 +INCLUDEPATH += .
  9 +
  10 +# Input
  11 +HEADERS += NaturalStringCompare.h
  12 +SOURCES += main.cpp NaturalStringCompare.cpp
  13 +
  14 +CONFIG += console qtestlib
  15 +QT-=gui
  16 +
3rdparty/NaturalStringCompare2/main.cpp 0 → 100755
  1 +/*
  2 + * This software was written by people from OnShore Consulting services LLC
  3 + * <info@sabgroup.com> and placed in the public domain.
  4 + *
  5 + * We reserve no legal rights to any of this. You are free to do
  6 + * whatever you want with it. And we make no guarantee or accept
  7 + * any claims on damages as a result of this.
  8 + *
  9 + * If you change the software, please help us and others improve the
  10 + * code by sending your modifications to us. If you choose to do so,
  11 + * your changes will be included under this license, and we will add
  12 + * your name to the list of contributors.
  13 +*/
  14 +
  15 +#include <QCoreApplication>
  16 +#include <QtTest>
  17 +#include <QDebug>
  18 +#include "NaturalStringCompare.h"
  19 +
  20 +class CTestNaturalStringCompare : public QObject
  21 +{
  22 + Q_OBJECT
  23 +private slots:
  24 + void compareString()
  25 + {
  26 + QString str1 = "abcdef";
  27 + QString str2 = "aabc";
  28 + QVERIFY( NaturalStringCompare(str1,str2) > 0 );
  29 + QVERIFY( NaturalStringCompare(str2,str1) < 0 );
  30 + QVERIFY( NaturalStringCompare(str1,str1) == 0 );
  31 + QVERIFY( NaturalStringCompare(str2,str2) == 0 );
  32 +
  33 + QVERIFY( NaturalStringCompare(str1,str1.left(2)) > 0 );
  34 + QVERIFY( NaturalStringCompare(str1.left(2),str1) < 0 );
  35 + }
  36 +
  37 + void compareInteger()
  38 + {
  39 + for( int ii = -15; ii <= 15; ii++ )
  40 + {
  41 + QString currVal = QString( "%1" ).arg( ii );
  42 + QString nextVal = QString( "%1" ).arg( ii+1 );
  43 +
  44 + QVERIFY( NaturalStringCompare(currVal,nextVal) < 0 );
  45 + QVERIFY( NaturalStringCompare( "prefix" + currVal, "prefix" + nextVal) < 0 );
  46 + QVERIFY( NaturalStringCompare( currVal + "postfix", nextVal + "postfix") < 0 );
  47 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "postfix", "prefix" + nextVal + "postfix") < 0 );
  48 +
  49 + QVERIFY( NaturalStringCompare(nextVal,currVal) > 0 );
  50 + QVERIFY( NaturalStringCompare( "prefix" + nextVal, "prefix" + currVal) > 0 );
  51 + QVERIFY( NaturalStringCompare( nextVal + "postfix", currVal + "postfix") > 0 );
  52 + QVERIFY( NaturalStringCompare( "prefix" + nextVal + "postfix", "prefix" + currVal + "postfix") > 0 );
  53 +
  54 + QVERIFY( NaturalStringCompare(currVal,currVal) == 0 );
  55 + QVERIFY( NaturalStringCompare( "prefix" + currVal, "prefix" + currVal) == 0 );
  56 + QVERIFY( NaturalStringCompare( currVal + "postfix", currVal + "postfix") == 0 );
  57 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "postfix", "prefix" + currVal + "postfix") == 0 );
  58 +
  59 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "middle" + currVal, "prefix" + currVal + "middle" + nextVal ) < 0 );
  60 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "middle" + nextVal, "prefix" + currVal + "middle" + currVal ) > 0 );
  61 + }
  62 + }
  63 +
  64 + void compareDouble()
  65 + {
  66 + for( int ii = -15; ii <= 15; ii++ )
  67 + {
  68 + QString currVal = QString( "%1" ).arg( 1.0*ii - 0.05 );
  69 + QString nextVal = QString( "%1" ).arg( 1.0*ii + 0.05 );
  70 +
  71 + QVERIFY( NaturalStringCompare(currVal,nextVal) < 0 );
  72 + QVERIFY( NaturalStringCompare( "prefix" + currVal, "prefix" + nextVal) < 0 );
  73 + QVERIFY( NaturalStringCompare( currVal + "postfix", nextVal + "postfix") < 0 );
  74 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "postfix", "prefix" + nextVal + "postfix") < 0 );
  75 +
  76 + QVERIFY( NaturalStringCompare(nextVal,currVal) > 0 );
  77 + QVERIFY( NaturalStringCompare( "prefix" + nextVal, "prefix" + currVal) > 0 );
  78 + QVERIFY( NaturalStringCompare( nextVal + "postfix", currVal + "postfix") > 0 );
  79 + QVERIFY( NaturalStringCompare( "prefix" + nextVal + "postfix", "prefix" + currVal + "postfix") > 0 );
  80 +
  81 + QVERIFY( NaturalStringCompare(currVal,currVal) == 0 );
  82 + QVERIFY( NaturalStringCompare( "prefix" + currVal, "prefix" + currVal) == 0 );
  83 + QVERIFY( NaturalStringCompare( currVal + "postfix", currVal + "postfix") == 0 );
  84 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "postfix", "prefix" + currVal + "postfix") == 0 );
  85 +
  86 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "middle" + currVal, "prefix" + currVal + "middle" + nextVal ) < 0 );
  87 + QVERIFY( NaturalStringCompare( "prefix" + currVal + "middle" + nextVal, "prefix" + currVal + "middle" + currVal ) > 0 );
  88 + }
  89 + }
  90 +
  91 + void sortStringList()
  92 + {
  93 + QStringList orig;
  94 + for( int ii = 15; ii >= -15; ii-- )
  95 + {
  96 + QString currVal = QString( "%1" ).arg( 1.0*ii - 0.05 );
  97 + orig << "prefix" + currVal + "postfix";
  98 + orig << "Prefix" + currVal + "posTfIx";
  99 + currVal = QString( "%1" ).arg( ii );
  100 + orig << "Prefix" + currVal;
  101 + orig << currVal + "PostFIX";
  102 + orig << currVal + "PostFix";
  103 + }
  104 +
  105 + QStringList toBeSorted = orig;
  106 + qSort( toBeSorted.begin(), toBeSorted.end(), NaturalStringCompareLessThan );
  107 +
  108 +
  109 + int cnt = toBeSorted.count();
  110 + QVERIFY( toBeSorted.count() == 31 * 5 );
  111 + QVERIFY( toBeSorted.front() == "-15PostFIX" );
  112 + QVERIFY( toBeSorted.back() == "prefix14.95postfix" );
  113 +
  114 + QStringList tmp = NaturalStringSort( orig );
  115 + QVERIFY( tmp.count() == toBeSorted.count() );
  116 + for( int ii = 0; ii < tmp.count(); ++ii )
  117 + {
  118 + QVERIFY( tmp[ ii ] == toBeSorted[ ii ] );
  119 + }
  120 +
  121 + toBeSorted = orig;
  122 + qSort( toBeSorted.begin(), toBeSorted.end(), NaturalStringCaseInsensitiveCompareLessThan );
  123 + cnt = toBeSorted.count();
  124 + QVERIFY( toBeSorted.count() == 31 * 5 );
  125 + // QVERIFY( toBeSorted.front() == "-15PostFix" ); for case insensitive, PostFix vs PostFIX is non-deterministic which comes firs
  126 + // QVERIFY( toBeSorted.back() == "Prefix15" );
  127 +
  128 + tmp = NaturalStringSort( orig, Qt::CaseInsensitive );
  129 + QVERIFY( tmp.count() == toBeSorted.count() );
  130 + for( int ii = 0; ii < tmp.count(); ++ii )
  131 + {
  132 + QVERIFY( tmp[ ii ] == toBeSorted[ ii ] );
  133 + }
  134 + }
  135 +
  136 + void lingfaYangTest()
  137 + {
  138 + // this is actually not what the spec wants, however, the 8 causes the first compare to be
  139 + // ppt/slides/slide vs ppt/slides/slide.xml which means embedded numbers will come first.
  140 +
  141 + QVERIFY( NaturalStringCompare( "ppt/slides/slide8.xml", "ppt/slides/slide.xml2", Qt::CaseInsensitive ) > 0 );
  142 +
  143 + QStringList orderedList = QStringList() // from Ligfa Ya email
  144 + << "[Content_Types].xml"
  145 + << "_rels/.rels"
  146 + << "ppt/media/image8.wmf"
  147 + << "ppt/media/image9.jpeg"
  148 + << "ppt/media/image10.png"
  149 + << "ppt/media/image11.gif"
  150 + << "ppt/slides/_rels/slide9.xml.rels"
  151 + << "ppt/slides/_rels/slide10.xml.rels"
  152 + << "ppt/slides/slide.xml"
  153 + << "ppt/slides/slide8.xml"
  154 + << "PPT/SLIDES/SLIDE9.XML"
  155 + << "ppt/slides/slide10.xml"
  156 + << "ppt/slides/slide11.xml"
  157 + << "slide.xml"
  158 + ;
  159 +
  160 + QStringList toBeSorted = QStringList();
  161 + QStringList tmp = orderedList;
  162 + qsrand( QDateTime::currentDateTime().toTime_t() );
  163 + while( !tmp.isEmpty() )
  164 + {
  165 + double randVal = qrand();
  166 + randVal /= RAND_MAX;
  167 + int val = (int)( tmp.count() - 1 ) * randVal;
  168 + toBeSorted << tmp[ val ];
  169 + tmp.removeAt( val );
  170 + }
  171 + tmp = NaturalStringSort( toBeSorted, Qt::CaseInsensitive );
  172 + for( int ii = 0; ii < tmp.count(); ++ii )
  173 + {
  174 + QVERIFY( tmp[ ii ] == orderedList[ ii ] );
  175 + }
  176 + }
  177 +
  178 +};
  179 +
  180 +QTEST_MAIN(CTestNaturalStringCompare)
  181 +#include "main.moc"
CHANGELOG.md
1 0.3.0 - ??/??/?? 1 0.3.0 - ??/??/??
2 ================ 2 ================
  3 +* Enrolling files/folders are now sorted naturally instead of alpha numerically
3 * YouTubeFacesDBTransform implements Dr. Wolf's experimental protocol 4 * YouTubeFacesDBTransform implements Dr. Wolf's experimental protocol
4 * NEC3 refactored 5 * NEC3 refactored
5 6
CMakeLists.txt
@@ -75,6 +75,9 @@ find_package(OpenCV REQUIRED) @@ -75,6 +75,9 @@ find_package(OpenCV REQUIRED)
75 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${OpenCV_LIBS}) 75 set(BR_THIRDPARTY_LIBS ${BR_THIRDPARTY_LIBS} ${OpenCV_LIBS})
76 set(OPENCV_DEPENDENCIES calib3d contrib core features2d flann gpu highgui imgproc legacy ml nonfree objdetect photo stitching video videostab) 76 set(OPENCV_DEPENDENCIES calib3d contrib core features2d flann gpu highgui imgproc legacy ml nonfree objdetect photo stitching video videostab)
77 77
  78 +# Find NaturalStringCompare
  79 +find_package(NaturalStringCompare REQUIRED)
  80 +
78 # Compiler flags 81 # Compiler flags
79 if(UNIX) 82 if(UNIX)
80 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-strict-overflow -fvisibility=hidden -fno-omit-frame-pointer") 83 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-strict-overflow -fvisibility=hidden -fno-omit-frame-pointer")
sdk/CMakeLists.txt
@@ -7,7 +7,7 @@ aux_source_directory(. SRC) @@ -7,7 +7,7 @@ aux_source_directory(. SRC)
7 aux_source_directory(core BR_CORE) 7 aux_source_directory(core BR_CORE)
8 include(plugins/plugins.cmake) 8 include(plugins/plugins.cmake)
9 9
10 -add_library(openbr SHARED ${SRC} ${BR_CORE} ${BR_PLUGIN} ${BR_THIRDPARTY_SRC} ${BR_RESOURCES}) 10 +add_library(openbr SHARED ${SRC} ${BR_CORE} ${BR_PLUGIN} ${BR_THIRDPARTY_SRC} ${BR_RESOURCES} ${NATURALSTRINGCOMPARE_SRC})
11 qt5_use_modules(openbr ${QT_DEPENDENCIES}) 11 qt5_use_modules(openbr ${QT_DEPENDENCIES})
12 set_target_properties(openbr PROPERTIES 12 set_target_properties(openbr PROPERTIES
13 DEFINE_SYMBOL BR_LIBRARY 13 DEFINE_SYMBOL BR_LIBRARY
sdk/core/qtutils.cpp
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 #include <QUrl> 28 #include <QUrl>
29 #include <openbr_plugin.h> 29 #include <openbr_plugin.h>
30 30
  31 +#include "NaturalStringCompare.h"
31 #include "qtutils.h" 32 #include "qtutils.h"
32 33
33 using namespace br; 34 using namespace br;
@@ -37,12 +38,12 @@ QStringList QtUtils::getFiles(QDir dir, bool recursive) @@ -37,12 +38,12 @@ QStringList QtUtils::getFiles(QDir dir, bool recursive)
37 dir = QDir(dir.canonicalPath()); 38 dir = QDir(dir.canonicalPath());
38 39
39 QStringList files; 40 QStringList files;
40 - foreach (const QString &file, dir.entryList(QDir::Files)) 41 + foreach (const QString &file, NaturalStringSort(dir.entryList(QDir::Files)))
41 files.append(QDir::cleanPath(dir.absoluteFilePath(file))); 42 files.append(QDir::cleanPath(dir.absoluteFilePath(file)));
42 43
43 if (!recursive) return files; 44 if (!recursive) return files;
44 45
45 - foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { 46 + foreach (const QString &folder, NaturalStringSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))) {
46 QDir subdir(dir); 47 QDir subdir(dir);
47 bool success = subdir.cd(folder); if (!success) qFatal("cd failure."); 48 bool success = subdir.cd(folder); if (!success) qFatal("cd failure.");
48 files.append(getFiles(subdir, true)); 49 files.append(getFiles(subdir, true));
sdk/plugins/gallery.cpp
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 #endif // BR_EMBEDDED 24 #endif // BR_EMBEDDED
25 #include <openbr_plugin.h> 25 #include <openbr_plugin.h>
26 26
  27 +#include "NaturalStringCompare.h"
27 #include "core/bee.h" 28 #include "core/bee.h"
28 #include "core/opencvutils.h" 29 #include "core/opencvutils.h"
29 #include "core/qtutils.h" 30 #include "core/qtutils.h"
@@ -102,7 +103,7 @@ class EmptyGallery : public Gallery @@ -102,7 +103,7 @@ class EmptyGallery : public Gallery
102 103
103 // Add immediate subfolders 104 // Add immediate subfolders
104 QDir dir(file); 105 QDir dir(file);
105 - foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) 106 + foreach (const QString &folder, NaturalStringSort(dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)))
106 foreach (const QString &file, QtUtils::getFiles(dir.absoluteFilePath(folder), true)) 107 foreach (const QString &file, QtUtils::getFiles(dir.absoluteFilePath(folder), true))
107 templates.append(File(file, folder)); 108 templates.append(File(file, folder));
108 109
share/openbr/cmake/FindNaturalStringCompare.cmake 0 → 100644
  1 +find_path(NATURALSTRINGCOMPARE_DIR NaturalStringCompare.h ${CMAKE_SOURCE_DIR}/3rdparty/*)
  2 +
  3 +include_directories(${NATURALSTRINGCOMPARE_DIR})
  4 +set(NATURALSTRINGCOMPARE_SRC ${NATURALSTRINGCOMPARE_DIR}/NaturalStringCompare.cpp)