00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00015 #include <ders/wldcrd_mtchr.hpp>
00016 #include <ders/mem.hpp>
00017
00018 namespace ders {
00019
00020 using namespace std;
00021
00022 void wldcrd_mtchr::add_sg()
00023 {
00024 sav_sgs.push_back(segm());
00025 sgs.push_back(&sav_sgs.back());
00026 }
00027
00028 bool wldcrd_mtchr::eq(const char* str, const segm& sg, int beg) const
00029 {
00030 for (int i=beg, end=sg.wds.size(); i<end; i++) {
00031 const ch_rng& wstr=sg.wds[i].str;
00032 if (memcmp(str+sg.wds[i].off, wstr.beg, wstr.size())) return false;
00033 }
00034
00035 return true;
00036 }
00037
00038 const char* wldcrd_mtchr::fnd(const ch_rng& str, const segm& sg) const
00039 {
00040 if (sg.wds.size()==0) return (str.size()>=sg.len) ? str.beg : 0;
00041
00042 const word& wd=sg.wds.front();
00043 for (ch_rng s=str; s.size()>=sg.len; ) {
00044 const char* ptr=static_cast<const char*>(mem_find(s.beg+wd.off, s.size()-
00045 sg.len+wd.str.size(), wd.str.beg, wd.str.size()));
00046 if (!ptr) return 0;
00047
00048 ptr-=wd.off;
00049 if (eq(ptr, sg, 1)) return ptr;
00050
00051 s.beg=ptr+1;
00052 }
00053
00054 return 0;
00055 }
00056
00057 wldcrd_mtchr::wldcrd_mtchr(mem_pool& m, const ch_rng& mask) :
00058 mp(m), len(0), sav_msk(nt(m, mask)), sav_sgs(stl_allocator<segm>(mp))
00059 {
00060 for (char* ptr=sav_msk->begin(); ptr<sav_msk->end(); ptr++) {
00061 switch (*ptr) {
00062 case '*': {
00063 if (sgs.size()==0 || sgs.back()) sgs.push_back(0);
00064 break;
00065 }
00066 case '?': {
00067 if (sgs.size()==0 || !sgs.back()) add_sg();
00068 sgs.back()->len++;
00069
00070 break;
00071 }
00072 default: {
00073 if (sgs.size()==0 || !sgs.back()) add_sg();
00074 segm& bs=*sgs.back();
00075
00076 if (*ptr=='\\' && ptr+1<sav_msk->end()) {
00077 ptr++;
00078 bs.wds.push_back(word(bs.len, ch_rng(ptr, ptr+1)));
00079 }
00080 else {
00081 if (bs.wds.size()==0 || bs.len!=bs.wds.back().off+
00082 bs.wds.back().str.size())
00083 bs.wds.push_back(word(bs.len, ch_rng(ptr, ptr+1)));
00084 else bs.wds.back().str.end++;
00085 }
00086
00087 bs.len++;
00088 }
00089 }
00090 }
00091
00092 for (int i=0, end=sgs.size(); i<end; i++)
00093 if (sgs[i]) len+=sgs[i]->len;
00094 }
00095
00096 bool wldcrd_mtchr::match(const ch_rng& str) const
00097 {
00098 if (str.size()<len) return false;
00099
00100 int sgfr=0, sgbk=sgs.size()-1;
00101 if (sgfr>sgbk) return true;
00102
00103 ch_rng s=str;
00104 if (sgs[sgfr]) {
00105 if (!eq(s.beg, *sgs[sgfr])) return false;
00106
00107 s.beg+=sgs[sgfr]->len;
00108 sgfr++;
00109 }
00110
00111 if (sgfr<=sgbk && sgs[sgbk]) {
00112 if (!eq(s.end-sgs[sgbk]->len, *sgs[sgbk])) return false;
00113
00114 s.end-=sgs[sgbk]->len;
00115 sgbk--;
00116 }
00117
00118 if (sgfr>sgbk) return s.beg==s.end;
00119
00120 assert(!sgs[sgbk]);
00121 for (int i=sgfr; i<sgbk; i++) {
00122 if (sgs[i]) {
00123 s.beg=fnd(s, *sgs[i]);
00124 if (!s.beg) return false;
00125
00126 s.beg+=sgs[i]->len;
00127 }
00128 }
00129
00130 return true;
00131 }
00132
00133 sh_wldcrd_mtchr new_wldcrd_mtchr(mem_pool& mp, const ch_rng& mask)
00134 {
00135 mp_newbuf<wldcrd_mtchr> buf(mp);
00136 return sh_wldcrd_mtchr(buf.pool(), buf.rls(::new(buf.get()) wldcrd_mtchr(mp,
00137 mask)));
00138 }
00139
00140 }
00141