Free Electron
regeximpl.h
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
Definition: anchor.h:12