/
zOMGdev
/
cppcms
Обзор
Документация
Войти
/
zOMGdev
/
cppcms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
booster/lib/regex/src/pcre_regex.cpp
262 строки
5 KB
Artyom Beilis
Added support of std regex as PCRE alternative
21 авг 2020, 00:03
21 авг 2020, 00:03
731bc83
Код
Авторство
О чём код?
// // Copyright (C) 2009-2012 Artyom Beilis (Tonkikh) // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #define BOOSTER_SOURCE #include <booster/regex.h> #include <string.h> #include <pcre.h> #include <sstream> #include <algorithm> namespace booster { bool regex::utf8_supported() { int flag = 0; #ifdef PCRE_UTF8 pcre_config(PCRE_CONFIG_UTF8,&flag); #endif return flag; } struct regex::data { std::string expression; int flags; pcre *re; pcre *are; size_t re_size; size_t are_size; int match_size; data() : flags(0), re(0), are(0), re_size(0), are_size(0), match_size(0) { } void swap(data &other) { expression.swap(other.expression); std::swap(flags, other.flags); std::swap(re, other.re); std::swap(are, other.are); std::swap(re_size, other.re_size); std::swap(are_size, other.are_size); std::swap(match_size, other.match_size); } data(data const &other) : expression(other.expression), flags(other.flags), re(0), are(0), re_size(other.re_size), are_size(other.are_size), match_size(other.match_size) { try { if(other.re!=0) { re = (pcre *)(pcre_malloc(re_size)); if(!re) { throw std::bad_alloc(); } memcpy(re,other.re,re_size); } if(other.are!=0) { are = (pcre *)(pcre_malloc(are_size)); if(!are) { throw std::bad_alloc(); } memcpy(are,other.are,are_size); } } catch(...) { if(re) pcre_free(re); if(are) pcre_free(are); throw; } } data const &operator=(data const &other) { if(this != &other) { data tmp(other); swap(tmp); } return *this; } ~data() { if(re) pcre_free(re); if(are) pcre_free(are); } }; regex::regex() : d(new data()) { } regex::regex(regex const &other) : d(other.d) { } regex const ®ex::operator=(regex const &other) { d=other.d; return *this; } regex::regex(regex &&other) : d(std::move(other.d)) { } regex ®ex::operator=(regex &&other) { d = std::move(other.d); return *this; } regex::~regex() { } regex::regex(std::string const &pattern,int flags) { assign(pattern,flags); } void regex::assign(std::string const &pattern,int flags) { d.reset(new data()); d->expression=pattern; d->flags = flags; char const *err_ptr = 0; int offset = 0; int pcre_flags = 0; if(flags & icase) { pcre_flags |= PCRE_CASELESS; } if(flags & utf8) { #ifndef PCRE_UTF8 throw regex_error("PCRE Library does not support UTF-8 please upgrade"); #else pcre_flags |= PCRE_UTF8; #endif } pcre *p=pcre_compile(pattern.c_str(),pcre_flags,&err_ptr,&offset,0); if(!p) { std::ostringstream ss; ss << "booster::regex:" << err_ptr <<", at offset "<<offset; throw regex_error(ss.str()); } d->re = p; if( pcre_fullinfo(d->re,NULL,PCRE_INFO_SIZE,&d->re_size) < 0 || pcre_fullinfo(d->re,NULL,PCRE_INFO_CAPTURECOUNT,&d->match_size) < 0) { throw regex_error("booster::regex: Internal error"); } std::string anchored; anchored.reserve(pattern.size()+6); anchored+= "(?:"; anchored+=pattern; anchored+=")\\z"; p=pcre_compile(anchored.c_str(),pcre_flags,&err_ptr,&offset,0); if(!p) { throw regex_error("booster::regex: Internal error"); } d->are = p; if(pcre_fullinfo(d->are,NULL,PCRE_INFO_SIZE,&d->are_size) != 0) { throw regex_error("booster::regex: Internal error"); } } int regex::flags() const { return d->flags; } std::string regex::str() const { return d->expression; } unsigned regex::mark_count() const { if(d->match_size < 0) return 0; return d->match_size; } bool regex::search(char const *begin,char const *end,int /*flags*/) const { if(!d->re) throw regex_error("booster::regex: Empty expression"); int res = pcre_exec(d->re,0,begin,end-begin,0,0,0,0); if(res < 0) return false; return true; } bool regex::search(char const *begin,char const *end,std::vector<std::pair<int,int> > &marks,int /* flags */) const { if(!d->re) throw regex_error("booster::regex: Empty expression"); marks.clear(); int pat_size = mark_count() + 1; marks.resize(pat_size,std::pair<int,int>(-1,-1)); std::vector<int> ovec((mark_count()+1)*3,0); int res = pcre_exec(d->re,0,begin,end-begin,0,0,&ovec.front(),ovec.size()); if(res < 0) return false; for(int i=0;i<pat_size && i < res;i++) { marks[i].first=ovec[i*2]; marks[i].second = ovec[i*2+1]; } return true; } bool regex::empty() const { return d->re == 0; } bool regex::match(char const *begin,char const *end,int /*flags*/) const { if(!d->are) throw regex_error("booster::regex: Empty expression"); int res = pcre_exec(d->are,0,begin,end-begin,0,PCRE_ANCHORED,0,0); if(res < 0) return false; return true; } bool regex::match(char const *begin,char const *end,std::vector<std::pair<int,int> > &marks,int /*flags*/) const { if(!d->are) throw regex_error("booster::regex: Empty expression"); marks.clear(); int pat_size = mark_count() + 1; marks.resize(pat_size,std::pair<int,int>(-1,-1)); std::vector<int> ovec((mark_count()+1)*3,0); int res = pcre_exec(d->are,0,begin,end-begin,0,PCRE_ANCHORED,&ovec.front(),ovec.size()); if(res < 0) return false; if(ovec[0]!=0 || ovec[1]!=end-begin) return false; for(int i=0;i<pat_size && i < res;i++) { marks[i].first=ovec[i*2]; marks[i].second = ovec[i*2+1]; } return true; } } // booster