regeximpl.h (4944B)
1 #ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 2 #define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 3 4 #if defined(_MSC_VER) || \ 5 (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \ 6 (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 7 #pragma once 8 #endif 9 10 #include "stream.h" 11 #include "streamcharsource.h" 12 #include "stringsource.h" 13 14 namespace YAML { 15 // query matches 16 inline bool RegEx::Matches(char ch) const { 17 std::string str; 18 str += ch; 19 return Matches(str); 20 } 21 22 inline bool RegEx::Matches(const std::string& str) const { 23 return Match(str) >= 0; 24 } 25 26 inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; } 27 28 template <typename Source> 29 inline bool RegEx::Matches(const Source& source) const { 30 return Match(source) >= 0; 31 } 32 33 // Match 34 // . Matches the given string against this regular expression. 35 // . Returns the number of characters matched. 36 // . Returns -1 if no characters were matched (the reason for 37 // not returning zero is that we may have an empty regex 38 // which is ALWAYS successful at matching zero characters). 39 // . REMEMBER that we only match from the start of the buffer! 40 inline int RegEx::Match(const std::string& str) const { 41 StringCharSource source(str.c_str(), str.size()); 42 return Match(source); 43 } 44 45 inline int RegEx::Match(const Stream& in) const { 46 StreamCharSource source(in); 47 return Match(source); 48 } 49 50 template <typename Source> 51 inline bool RegEx::IsValidSource(const Source& source) const { 52 return source; 53 } 54 55 template <> 56 inline bool RegEx::IsValidSource<StringCharSource>( 57 const StringCharSource& source) const { 58 switch (m_op) { 59 case REGEX_MATCH: 60 case REGEX_RANGE: 61 return source; 62 default: 63 return true; 64 } 65 } 66 67 template <typename Source> 68 inline int RegEx::Match(const Source& source) const { 69 return IsValidSource(source) ? MatchUnchecked(source) : -1; 70 } 71 72 template <typename Source> 73 inline int RegEx::MatchUnchecked(const Source& source) const { 74 switch (m_op) { 75 case REGEX_EMPTY: 76 return MatchOpEmpty(source); 77 case REGEX_MATCH: 78 return MatchOpMatch(source); 79 case REGEX_RANGE: 80 return MatchOpRange(source); 81 case REGEX_OR: 82 return MatchOpOr(source); 83 case REGEX_AND: 84 return MatchOpAnd(source); 85 case REGEX_NOT: 86 return MatchOpNot(source); 87 case REGEX_SEQ: 88 return MatchOpSeq(source); 89 } 90 91 return -1; 92 } 93 94 ////////////////////////////////////////////////////////////////////////////// 95 // Operators 96 // Note: the convention MatchOp*<Source> is that we can assume 97 // IsSourceValid(source). 98 // So we do all our checks *before* we call these functions 99 100 // EmptyOperator 101 template <typename Source> 102 inline int RegEx::MatchOpEmpty(const Source& source) const { 103 return source[0] == Stream::eof() ? 0 : -1; 104 } 105 106 template <> 107 inline int RegEx::MatchOpEmpty<StringCharSource>( 108 const StringCharSource& source) const { 109 return !source ? 0 : -1; // the empty regex only is successful on the empty 110 // string 111 } 112 113 // MatchOperator 114 template <typename Source> 115 inline int RegEx::MatchOpMatch(const Source& source) const { 116 if (source[0] != m_a) 117 return -1; 118 return 1; 119 } 120 121 // RangeOperator 122 template <typename Source> 123 inline int RegEx::MatchOpRange(const Source& source) const { 124 if (m_a > source[0] || m_z < source[0]) 125 return -1; 126 return 1; 127 } 128 129 // OrOperator 130 template <typename Source> 131 inline int RegEx::MatchOpOr(const Source& source) const { 132 for (const RegEx& param : m_params) { 133 int n = param.MatchUnchecked(source); 134 if (n >= 0) 135 return n; 136 } 137 return -1; 138 } 139 140 // AndOperator 141 // Note: 'AND' is a little funny, since we may be required to match things 142 // of different lengths. If we find a match, we return the length of 143 // the FIRST entry on the list. 144 template <typename Source> 145 inline int RegEx::MatchOpAnd(const Source& source) const { 146 int first = -1; 147 for (std::size_t i = 0; i < m_params.size(); i++) { 148 int n = m_params[i].MatchUnchecked(source); 149 if (n == -1) 150 return -1; 151 if (i == 0) 152 first = n; 153 } 154 return first; 155 } 156 157 // NotOperator 158 template <typename Source> 159 inline int RegEx::MatchOpNot(const Source& source) const { 160 if (m_params.empty()) 161 return -1; 162 if (m_params[0].MatchUnchecked(source) >= 0) 163 return -1; 164 return 1; 165 } 166 167 // SeqOperator 168 template <typename Source> 169 inline int RegEx::MatchOpSeq(const Source& source) const { 170 int offset = 0; 171 for (const RegEx& param : m_params) { 172 int n = param.Match(source + offset); // note Match, not 173 // MatchUnchecked because we 174 // need to check validity after 175 // the offset 176 if (n == -1) 177 return -1; 178 offset += n; 179 } 180 181 return offset; 182 } 183 } // namespace YAML 184 185 #endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66