#1024. Support for C++11 #include <regex>. --grep keys may have an optional trailer /i to indicate to ignore case.

v0.27.3
Robin Mills 10 years ago
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 ;

@ -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.

@ -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

@ -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

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save