#1024. Support for C++11 #include <regex>. --grep keys may have an optional trailer /i to indicate to ignore case.
This commit is contained in:
parent
8369445c6f
commit
ab9ee2c6df
@ -37,11 +37,25 @@
|
||||
// + standard includes
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#if EXV_HAVE_REGEX
|
||||
#include <regex.h>
|
||||
typedef std::vector<regex_t> exv_grep_keys_t ;
|
||||
|
||||
#define CPLUSPLUS11 201103L
|
||||
|
||||
#if __cplusplus >= CPLUSPLUS11
|
||||
# include <regex>
|
||||
typedef std::vector<std::regex> exv_grep_keys_t ;
|
||||
#else
|
||||
typedef std::vector<std::string> exv_grep_keys_t ;
|
||||
# if EXV_HAVE_REGEX
|
||||
# include <regex.h>
|
||||
typedef std::vector<regex_t> exv_grep_keys_t ;
|
||||
# else
|
||||
struct Exiv2_grep_key_t {
|
||||
Exiv2_grep_key_t(std::string pattern,bool bIgnoreCase)
|
||||
:pattern_(pattern),bIgnoreCase_(bIgnoreCase) {}
|
||||
std::string pattern_;
|
||||
bool bIgnoreCase_;
|
||||
};
|
||||
typedef std::vector<Exiv2_grep_key_t> exv_grep_keys_t ;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*!
|
||||
|
||||
@ -49,6 +49,7 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
#include "preview.hpp"
|
||||
#include "futils.hpp"
|
||||
#include "i18n.h" // NLS support.
|
||||
#include "version.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
@ -581,10 +582,22 @@ namespace Action {
|
||||
for (Params::Greps::const_iterator g = Params::instance().greps_.begin();
|
||||
!result && g != Params::instance().greps_.end(); ++g)
|
||||
{
|
||||
#if __cplusplus >= CPLUSPLUS11
|
||||
std::smatch m;
|
||||
result = std::regex_search(key,m, *g);
|
||||
#else
|
||||
#if EXV_HAVE_REGEX
|
||||
result = regexec( &(*g), key.c_str(), 0, NULL, 0) == 0 ;
|
||||
#else
|
||||
result = key.find(*g) != std::string::npos;
|
||||
std::string Pattern(g->pattern_);
|
||||
std::string Key(key);
|
||||
if ( g->bIgnoreCase_ ) {
|
||||
// https://notfaq.wordpress.com/2007/08/04/cc-convert-string-to-upperlower-case/
|
||||
std::transform(Pattern.begin(), Pattern.end(),Pattern.begin(), ::tolower);
|
||||
std::transform(Key.begin() , Key.end() ,Key.begin() , ::tolower);
|
||||
}
|
||||
result = Key.find(Pattern) != std::string::npos;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return result ;
|
||||
|
||||
11
src/exiv2.1
11
src/exiv2.1
@ -3,7 +3,7 @@
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH EXIV2 1 "Nov 23, 2015"
|
||||
.TH EXIV2 1 "Dec 8, 2015"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
@ -222,10 +222,11 @@ Show unknown tags (default is to suppress tags which don't have a name).
|
||||
Only keys which match the given key (grep).
|
||||
.br
|
||||
Multiple \fB\-g\fP options
|
||||
can be used to grep info for several keys. This option uses the system
|
||||
regular expression engine: see man 3 regex. Platforms which do not support
|
||||
can be used to grep info for several keys. When the library is build with C++11,
|
||||
keys are matched using std::regex::extended. When build without C++11, keys are
|
||||
processed with the system regular expression engine: see man 3 regex. Platforms which do not support
|
||||
regex use key for a substring match. You can determine the availability of regex
|
||||
using the command: exiv2 -v -V -g have_regex
|
||||
using the command: exiv2 -v -V -g have_regex -g cplusplus.
|
||||
|
||||
.nf
|
||||
exiv2 \-g Date \-pt R.jpg
|
||||
@ -235,6 +236,8 @@ Exif.Photo.DateTimeDigitized Ascii 20 2011:09:18 16:25:48
|
||||
|
||||
.fi
|
||||
-g (--grep) is only applied to keys. It is not generally applied to all output such as the default -ps report.
|
||||
|
||||
The key may finish with the optional modifier /i to indicated case insensitive.
|
||||
.TP
|
||||
.B \-K \fIkey\fP
|
||||
Only report data for given key.
|
||||
|
||||
108
src/exiv2.cpp
108
src/exiv2.cpp
@ -415,15 +415,30 @@ int Params::setLogLevel(const std::string& optarg)
|
||||
return rc;
|
||||
} // Params::setLogLevel
|
||||
|
||||
// http://stackoverflow.com/questions/874134/find-if-string-ends-with-another-string-in-c
|
||||
static inline bool ends_with(std::string const & value, std::string const & ending,std::string& stub)
|
||||
{
|
||||
if (ending.size() > value.size()) return false;
|
||||
bool bResult = std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
stub = bResult ? value.substr(0,value.length() - ending.length()) : value;
|
||||
return bResult ;
|
||||
}
|
||||
|
||||
int Params::evalGrep( const std::string& optarg)
|
||||
{
|
||||
int result=0;
|
||||
std::string pattern;
|
||||
std::string ignoreCase("/i");
|
||||
bool bIgnoreCase = ends_with(optarg,ignoreCase,pattern);
|
||||
#if __cplusplus >= CPLUSPLUS11
|
||||
greps_.push_back( std::regex(pattern, bIgnoreCase ? std::regex::icase|std::regex::extended : std::regex::extended) );
|
||||
#else
|
||||
#if EXV_HAVE_REGEX
|
||||
// try to compile a reg-exp from the input argument and store it in the vector
|
||||
const size_t i = greps_.size();
|
||||
greps_.resize(i + 1);
|
||||
regex_t *pRegex = &greps_[i];
|
||||
int errcode = regcomp( pRegex, optarg.c_str(), REG_NOSUB);
|
||||
int errcode = regcomp( pRegex, pattern.c_str(), bIgnoreCase ? REG_NOSUB|REG_ICASE : REG_NOSUB);
|
||||
|
||||
// there was an error compiling the regexp
|
||||
if( errcode ) {
|
||||
@ -441,7 +456,8 @@ int Params::evalGrep( const std::string& optarg)
|
||||
result=1;
|
||||
}
|
||||
#else
|
||||
greps_.push_back(optarg);
|
||||
greps_.push_back(Exiv2_grep_key_t(pattern,bIgnoreCase));
|
||||
#endif
|
||||
#endif
|
||||
return result;
|
||||
} // Params::evalGrep
|
||||
@ -846,50 +862,50 @@ typedef std::map<std::string,std::string> long_t;
|
||||
|
||||
int Params::getopt(int argc, char* const Argv[])
|
||||
{
|
||||
char** argv = new char* [argc+1];
|
||||
argv[argc] = NULL;
|
||||
long_t longs;
|
||||
char** argv = new char* [argc+1];
|
||||
argv[argc] = NULL;
|
||||
long_t longs;
|
||||
|
||||
longs["--adjust" ] = "-a";
|
||||
longs["--binary" ] = "-b";
|
||||
longs["--comment" ] = "-c";
|
||||
longs["--delete" ] = "-d";
|
||||
longs["--days" ] = "-D";
|
||||
longs["--force" ] = "-f";
|
||||
longs["--Force" ] = "-F";
|
||||
longs["--grep" ] = "-g";
|
||||
longs["--help" ] = "-h";
|
||||
longs["--insert" ] = "-i";
|
||||
longs["--keep" ] = "-k";
|
||||
longs["--key" ] = "-K";
|
||||
longs["--location" ] = "-l";
|
||||
longs["--modify" ] = "-m";
|
||||
longs["--Modify" ] = "-M";
|
||||
longs["--encode" ] = "-n";
|
||||
longs["--months" ] = "-O";
|
||||
longs["--print" ] = "-p";
|
||||
longs["--Print" ] = "-P";
|
||||
longs["--quiet" ] = "-q";
|
||||
longs["--log" ] = "-Q";
|
||||
longs["--rename" ] = "-r";
|
||||
longs["--suffix" ] = "-S";
|
||||
longs["--timestamp"] = "-t";
|
||||
longs["--Timestamp"] = "-T";
|
||||
longs["--unknown" ] = "-u";
|
||||
longs["--verbose" ] = "-v";
|
||||
longs["--Version" ] = "-V";
|
||||
longs["--version" ] = "-V";
|
||||
longs["--years" ] = "-Y";
|
||||
longs["--adjust" ] = "-a";
|
||||
longs["--binary" ] = "-b";
|
||||
longs["--comment" ] = "-c";
|
||||
longs["--delete" ] = "-d";
|
||||
longs["--days" ] = "-D";
|
||||
longs["--force" ] = "-f";
|
||||
longs["--Force" ] = "-F";
|
||||
longs["--grep" ] = "-g";
|
||||
longs["--help" ] = "-h";
|
||||
longs["--insert" ] = "-i";
|
||||
longs["--keep" ] = "-k";
|
||||
longs["--key" ] = "-K";
|
||||
longs["--location" ] = "-l";
|
||||
longs["--modify" ] = "-m";
|
||||
longs["--Modify" ] = "-M";
|
||||
longs["--encode" ] = "-n";
|
||||
longs["--months" ] = "-O";
|
||||
longs["--print" ] = "-p";
|
||||
longs["--Print" ] = "-P";
|
||||
longs["--quiet" ] = "-q";
|
||||
longs["--log" ] = "-Q";
|
||||
longs["--rename" ] = "-r";
|
||||
longs["--suffix" ] = "-S";
|
||||
longs["--timestamp"] = "-t";
|
||||
longs["--Timestamp"] = "-T";
|
||||
longs["--unknown" ] = "-u";
|
||||
longs["--verbose" ] = "-v";
|
||||
longs["--Version" ] = "-V";
|
||||
longs["--version" ] = "-V";
|
||||
longs["--years" ] = "-Y";
|
||||
|
||||
for ( int i = 0 ; i < argc ; i++ ) {
|
||||
std::string* arg = new std::string(Argv[i]);
|
||||
if (longs.find(*arg) != longs.end() ) {
|
||||
argv[i] = ::strdup(longs[*arg].c_str());
|
||||
} else {
|
||||
argv[i] = ::strdup(Argv[i]);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
for ( int i = 0 ; i < argc ; i++ ) {
|
||||
std::string* arg = new std::string(Argv[i]);
|
||||
if (longs.find(*arg) != longs.end() ) {
|
||||
argv[i] = ::strdup(longs[*arg].c_str());
|
||||
} else {
|
||||
argv[i] = ::strdup(Argv[i]);
|
||||
}
|
||||
delete arg;
|
||||
}
|
||||
|
||||
int rc = Util::Getopt::getopt(argc, argv, optstring_);
|
||||
// Further consistency checks
|
||||
@ -958,8 +974,8 @@ int Params::getopt(int argc, char* const Argv[])
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
// cleanup the argument vector
|
||||
for ( int i = 0 ; i < argc ; i++ ) ::free((void*)argv[i]);
|
||||
// cleanup the argument vector
|
||||
for ( int i = 0 ; i < argc ; i++ ) ::free((void*)argv[i]);
|
||||
delete [] argv;
|
||||
|
||||
return rc;
|
||||
|
||||
@ -172,18 +172,32 @@ namespace Exiv2 {
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool shouldOutput(const exv_grep_keys_t& greps,const char* name,const std::string& value)
|
||||
static bool shouldOutput(const exv_grep_keys_t& greps,const char* key,const std::string& value)
|
||||
{
|
||||
bool bPrint = greps.empty();
|
||||
for( exv_grep_keys_t::const_iterator g = greps.begin();
|
||||
!bPrint && g != greps.end() ; ++g
|
||||
) {
|
||||
#if __cplusplus >= CPLUSPLUS11
|
||||
std::smatch m;
|
||||
bPrint = std::regex_search(std::string(key),m,*g) || std::regex_search(value,m,*g);
|
||||
#else
|
||||
#if EXV_HAVE_REGEX
|
||||
bPrint = ( 0 == regexec( &(*g), name , 0, NULL, 0)
|
||||
bPrint = ( 0 == regexec( &(*g), key , 0, NULL, 0)
|
||||
|| 0 == regexec( &(*g), value.c_str(), 0, NULL, 0)
|
||||
);
|
||||
#else
|
||||
bPrint = std::string(name).find(*g) != std::string::npos || value.find(*g) != std::string::npos;
|
||||
std::string Pattern(g->pattern_);
|
||||
std::string Key(key);
|
||||
std::string Value(value);
|
||||
if ( g->bIgnoreCase_ ) {
|
||||
// https://notfaq.wordpress.com/2007/08/04/cc-convert-string-to-upperlower-case/
|
||||
std::transform(Pattern.begin(), Pattern.end(),Pattern.begin(), ::tolower);
|
||||
std::transform(Key.begin() , Key.end() ,Key.begin() , ::tolower);
|
||||
std::transform(Value.begin() , Value.end() ,Value.begin() , ::tolower);
|
||||
}
|
||||
bPrint = Key.find(Pattern) != std::string::npos || Value.find(Pattern) != std::string::npos;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return bPrint;
|
||||
@ -504,6 +518,8 @@ void Exiv2::dumpLibraryInfo(std::ostream& os,const exv_grep_keys_t& keys)
|
||||
output(os,keys,"bits" , bits );
|
||||
output(os,keys,"dll" , dll );
|
||||
output(os,keys,"debug" , debug );
|
||||
output(os,keys,"cplusplus" , __cplusplus);
|
||||
output(os,keys,"cplusplus11" , __cplusplus >= CPLUSPLUS11 );
|
||||
output(os,keys,"version" , __VERSION__);
|
||||
output(os,keys,"date" , __DATE__ );
|
||||
output(os,keys,"time" , __TIME__ );
|
||||
|
||||
@ -332,6 +332,13 @@ source ./functions.source
|
||||
diff $diffargs $num-before.txt $num-after.txt > $num.txt
|
||||
diff $diffargs $num.txt $diffname
|
||||
|
||||
num=1024
|
||||
filename=exiv2-bug$num.exv
|
||||
printf "$num " >&3
|
||||
echo '------>' Bug $num '<-------' >&2
|
||||
copyTestFile $filename
|
||||
runTest exiv2 -pa --grep gpsl/i $filename
|
||||
|
||||
num=1026
|
||||
filename=exiv2-bug$num.jpg
|
||||
printf "$num " >&3
|
||||
@ -430,7 +437,7 @@ source ./functions.source
|
||||
copyTestFile $filename
|
||||
runTest exiv2 -pv -g Lens $filename
|
||||
runTest exiv2 -pa -g Lens $filename
|
||||
|
||||
|
||||
num=1137
|
||||
filename=exiv2-bug$num.jpg
|
||||
printf "$num " >&3
|
||||
@ -440,7 +447,7 @@ source ./functions.source
|
||||
runTest exiv2 -pa $filename
|
||||
runTest exiv2 -PkV --grep GPSL http://dev.exiv2.org/attachments/download/805/DSC_7154.jpg | runTest exiv2 -m- $filename
|
||||
runTest exiv2 -pa $filename
|
||||
|
||||
|
||||
|
||||
) 3>&1 > $results 2>&1
|
||||
|
||||
|
||||
Binary file not shown.
BIN
test/data/exiv2-bug1024.exv
Normal file
BIN
test/data/exiv2-bug1024.exv
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user