소스 검색

HV: * Added regular expressions from jive5ab (from pcint originally)

git-svn-id: svn+ssh://code.jive.eu/code/svn/vbs_fs@4 5b2df0cb-e17b-44c8-90c8-480d528b6e0d
master
JIVE Software Dev 5 년 전
부모
커밋
9d07b52760
  1. 2
      Makefile
  2. 151
      ezexcept.h
  3. 155
      regular_expression.cc
  4. 116
      regular_expression.h

2
Makefile

@ -2,7 +2,7 @@ CXX=g++
INCS=-I.
CXXOPT=-g -fPIC $(OPT) -Wall -W -Werror -Wextra -pedantic -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -D__STDC_FORMAT_MACROS -Wcast-qual -Wwrite-strings -Wredundant-decls -Wfloat-equal -Wshadow -D_FILE_OFFSET_BITS=64
OBJS=evlbidebug.o
OBJS=evlbidebug.o regular_expression.o
vbs_fs: vbs_fs.cc $(OBJS)

151
ezexcept.h

@ -0,0 +1,151 @@
// use this to define/declare exceptions of your own type
// Copyright (C) 2007-2008 Harro Verkouter
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Author: Harro Verkouter - verkouter@jive.nl
// Joint Institute for VLBI in Europe
// P.O. Box 2
// 7990 AA Dwingeloo
//
// All exceptions take "const std::string&" as c'tor arg and are
// derived off of std::exception.
//
// Usagage:
// in .h file:
// #include <ezexcept.h>
// DECLARE_EZEXCEPT(Whatchamacallem);
//
// in .cc
// DEFINE_EZEXCEPT(Whatchamacallem);
// ...
/// if( usr_fscked_up )
// throw Whatchamacallem("Usr fscked up!");
#ifndef JIVE5A_EZEXCEPT_H
#define JIVE5A_EZEXCEPT_H
#include <exception>
#include <string>
#include <sstream>
// Declare the prototype of the exception
#define DECLARE_EZEXCEPT(xept) \
struct xept:\
public std::exception\
{\
xept( const std::string& m = std::string() );\
virtual const char* what( void ) const throw();\
virtual ~xept() throw();\
const std::string __m;\
};
// For the xtra-lzy ppl: throws + prefixed with
// FILE:LINE
#define THROW_EZEXCEPT(xept, msg) \
do { int eZ_Lijn_gH = __LINE__; \
const std::string eZ_Fijl_9q( __FILE__ );\
std::ostringstream eZ_Stroom_yw;\
eZ_Stroom_yw << eZ_Fijl_9q << "@" << eZ_Lijn_gH << " - " << msg;\
throw xept(eZ_Stroom_yw.str());\
} while( 0 );
// And this is to go in your .cc file
#define DEFINE_EZEXCEPT(xept) \
xept::xept( const std::string& m ):\
__m( m )\
{} \
const char* xept::what( void ) const throw() {\
return __m.c_str();\
}\
xept::~xept() throw() \
{}
// Set up the defines to make it all readable (ahem) and usable
#define EZCALLLOCATION \
std::string ez_fn_( __FILE__); int ez_ln_(__LINE__);
#define EZCALLSTUFF(fubarvar) \
std::ostringstream ezlclSvar_0a;\
ezlclSvar_0a << ez_fn_ << "@" << ez_ln_ << " assertion [" << fubarvar << "] fails ";
// EZINFO
// can be used to add extra info to the errormessage. Use as (one of) the
// entries in the EZASSERT2_*() macros: eg:
// EZASSERT2(idx<length,
// EZINFO("idx " << idx << ">= length " << length));
#define EZINFO(a) \
ezlclSvar_0a << a;
// The actual assertions:
// The throw 'e' if 'a' is not met, executing 'b' before throwing
// generic assertion "a"
// [w/o cleanup is just "with cleanup" where the cleanup is a nop]
#define EZASSERT2(a, e, b) \
do {\
if( !(a) ) { \
EZCALLLOCATION;\
EZCALLSTUFF(#a);\
b;\
throw e( ezlclSvar_0a.str() ); \
} \
} while( 0 );
#define EZASSERT(a, e) \
EZASSERT2(a, e, ;)
// assert "a==0"
// [w/o cleanup is just "with cleanup" where the cleanup is a nop]
#define EZASSERT2_ZERO(a, e, b) \
do {\
if( !((a)==0) ) { \
EZCALLLOCATION;\
EZCALLSTUFF(#a);\
b;\
throw e( ezlclSvar_0a.str() ); \
} \
} while( 0 );
#define EZASSERT_ZERO(a, e) \
EZASSERT2_ZERO(a, e, ;)
// assert "a!=0"
// [w/o cleanup is just "with cleanup" where the cleanup is a nop]
#define EZASSERT2_NZERO(a, e, b) \
do {\
if( !((a)!=0) ) { \
EZCALLLOCATION;\
EZCALLSTUFF(#a);\
b;\
throw e( ezlclSvar_0a.str() ); \
} \
} while( 0 );
#define EZASSERT_NZERO(a, e) \
EZASSERT2_NZERO(a, e, ;)
// assert "a>=0" [a is non-negative]
// [w/o cleanup is just "with cleanup" where the cleanup is a nop]
#define EZASSERT2_POS(a, e, b) \
do {\
if( !((a)>=0) ) { \
EZCALLLOCATION;\
EZCALLSTUFF(#a);\
b;\
throw e( ezlclSvar_0a.str() ); \
} \
} while( 0 );
#define EZASSERT_POS(a, e) \
EZASSERT2_POS(a, e, ;)
#endif

155
regular_expression.cc

@ -0,0 +1,155 @@
// Implementation of the RegularExpression class
#include <regular_expression.h>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using std::cerr;
using std::endl;
using std::flush;
using std::string;
DEFINE_EZEXCEPT(Regular_Expression_Exception)
// support classes
pcintregmatch_t::pcintregmatch_t() {
this->::regmatch_t::rm_so = -1;
this->::regmatch_t::rm_eo = -1;
}
pcintregmatch_t::pcintregmatch_t( const ::regmatch_t& rm ) {
this->::regmatch_t::rm_so = rm.rm_so;
this->::regmatch_t::rm_eo = rm.rm_eo;
}
pcintregmatch_t::operator bool() const {
return (rm_so!=-1 && rm_eo!=-1);
}
matchresult::matchresult()
{}
matchresult::matchresult( const matchresult::matchvec_t& mv,
const char* os ):
__matches( mv ),
__org_string( os )
{}
matchresult::matchresult( const matchresult::matchvec_t& mv,
const std::string& os ):
__matches( mv ),
__org_string( os )
{}
matchresult::operator bool() const {
return (__matches.size()!=0);
}
matchresult::matchvec_t::value_type matchresult::operator[]( unsigned int m ) const {
if( m>=__matches.size() ) {
THROW_EZEXCEPT(Regular_Expression_Exception,
"requesting group " << m << ", but only " << __matches.size() << " groups matched");
}
return __matches[m];
}
std::string matchresult::operator[]( const matchvec_t::value_type& m ) const {
if( !m ) {
THROW_EZEXCEPT(Regular_Expression_Exception,
"requesting string from invalid group");
}
return __org_string.substr(m.rm_so, (m.rm_eo-m.rm_so));
}
std::string matchresult::group( unsigned int m ) const {
return (*this)[(*this)[m]];
}
bool operator==( const char* tocheck, const Regular_Expression& against ) {
return against.matches( tocheck );
}
bool operator!=( const char* tocheck, const Regular_Expression& against ) {
return !(against.matches( tocheck ));
}
bool operator==( const string& s, const Regular_Expression& against ) {
return against.matches( s.c_str() );
}
bool operator!=( const string& s, const Regular_Expression& against ) {
return !(against.matches(s.c_str()));
}
Regular_Expression::Regular_Expression( const char* pattern_text, int flags ) :
myOriginalPattern( ((pattern_text!=0)?(strdup(pattern_text)):(strdup(""))) )
{
// Compile the pattern....
int r;
char errbuf[ 512 ];
if( (r=::regcomp(&myCompiledExpression,
myOriginalPattern,
flags))!=0 ) {
::regerror(r, &myCompiledExpression, errbuf, sizeof(errbuf));
THROW_EZEXCEPT(Regular_Expression_Exception,
"Failed to compile RegEx(" << myOriginalPattern << "): " << errbuf);
}
// After compiling the regexp, the re_nsub member informs how many
// sub expressions/match groups there were. Together with the zeroth
// group (the whole) match, we know how many there are in total
mySubexprs = new ::regmatch_t[ 1 + myCompiledExpression.re_nsub ];
}
Regular_Expression::Regular_Expression( const string& pattern_text, int flags ) :
myOriginalPattern( ((pattern_text.size()!=0)?(strdup(pattern_text.c_str())):(strdup(""))) )
{
// Compile the pattern....
int r;
char errbuf[ 512 ];
if( (r=::regcomp(&myCompiledExpression,
myOriginalPattern,
flags))!=0 ) {
::regerror(r, &myCompiledExpression, errbuf, sizeof(errbuf));
THROW_EZEXCEPT(Regular_Expression_Exception,
"Failed to compile RegEx(" << myOriginalPattern << "): " << errbuf);
}
// After compiling the regexp, the re_nsub member informs how many
// sub expressions/match groups there were. Together with the zeroth
// group (the whole) match, we know how many there are in total
mySubexprs = new ::regmatch_t[ 1 + myCompiledExpression.re_nsub ];
}
matchresult Regular_Expression::matches( const char* s ) const {
matchresult rv;
if( !s )
return rv;
if( ::regexec(&myCompiledExpression, s, (size_t)(1+myCompiledExpression.re_nsub), mySubexprs, 0)==0 ) {
// The "+1" is from the zeroth sub expression (the whole match)
rv = matchresult(matchresult::matchvec_t(mySubexprs, mySubexprs+myCompiledExpression.re_nsub+1), s);
}
return rv;
}
matchresult Regular_Expression::matches( const string& s ) const {
return this->matches( s.c_str() );
}
string Regular_Expression::pattern( void ) const {
return myOriginalPattern;
}
Regular_Expression::~Regular_Expression() {
if( myOriginalPattern )
::free( myOriginalPattern );
::regfree( &myCompiledExpression );
delete [] mySubexprs;
}

116
regular_expression.h

@ -0,0 +1,116 @@
//
// Wrapper class around POSIX regex, imported from pcint
//
#ifndef REGULAR_EXPRESSION_H
#define REGULAR_EXPRESSION_H
#include <ezexcept.h>
#include <sys/types.h>
#include <regex.h>
#include <string>
#include <vector>
DECLARE_EZEXCEPT(Regular_Expression_Exception)
// wrapper around regmatch_t which
// allows to give it some extra functionality
struct pcintregmatch_t:
::regmatch_t
{
// creates invalid one
pcintregmatch_t();
// init with a given regmatch
pcintregmatch_t( const ::regmatch_t& rm );
// this'un valid?
// regex(3) sais that an invalid
// regmatch has -1 for both offsets
operator bool() const;
};
// matchresult holds a vector
// of matches. Size <> 0 indicates
// a successfull match
// Size >1 implies possible matchgroups
// Not all matchgroups are required to be valid
struct matchresult {
typedef std::vector<pcintregmatch_t> matchvec_t;
// empty matchresult
matchresult();
// fully construct, a list of matches (possibly
// empty) AND a pointer to the original string
matchresult( const matchvec_t& mv, const char* os );
matchresult( const matchvec_t& mv, const std::string& os );
// implement operator bool
// which tells the truthiness
// of the matchresult
operator bool() const;
// return the m'th regmatch.
// Most likely use:
// matchresult m = rx.match(<some string>);
// if( m[1] )
// cout << "matchgroup 1=" << m.matchgroup(1) << endl;
matchvec_t::value_type operator[]( unsigned int m ) const;
// nice.. operator overloading :)
std::string operator[]( const matchvec_t::value_type& m ) const;
// snip the indicated match out of
// the original string.
// string interface, caller doesn't
// have to do mem.management, the
std::string group( unsigned int m ) const;
// our attributes
matchvec_t __matches;
std::string __org_string;
};
// A generic regex....
class Regular_Expression
{
friend bool operator==( const char* tocheck, const Regular_Expression& against );
friend bool operator!=( const char* tocheck, const Regular_Expression& against );
friend bool operator==( const std::string& s, const Regular_Expression& against );
friend bool operator!=( const std::string& s, const Regular_Expression& against );
public:
// Create from a pattern,
// note that one match for the whole pattern will be returned in matches()[0]
// so maxmatch should be at least <number of expectect matches> + 1
Regular_Expression( const char* pattern, int flags=REG_EXTENDED );
Regular_Expression( const std::string& pattern, int flags=REG_EXTENDED );
// match the string 's' against this RX
matchresult matches( const char* s ) const;
matchresult matches( const std::string& s ) const;
// Return the pattern
std::string pattern( void ) const;
// Delete all allocated stuff
~Regular_Expression();
private:
// Our private parts
char* myOriginalPattern;
regex_t myCompiledExpression;
::regmatch_t* mySubexprs;
// Prohibit these
Regular_Expression();
Regular_Expression( const Regular_Expression& );
Regular_Expression& operator=( const Regular_Expression& );
};
#endif
불러오는 중...
취소
저장