123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- #ifndef REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
- #define REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
- #if defined(_MSC_VER) || \
- (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
- (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
- #pragma once
- #endif
- #include "stream.h"
- #include "stringsource.h"
- #include "streamcharsource.h"
- namespace YAML {
- // query matches
- inline bool RegEx::Matches(char ch) const {
- std::string str;
- str += ch;
- return Matches(str);
- }
- inline bool RegEx::Matches(const std::string& str) const {
- return Match(str) >= 0;
- }
- inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
- template <typename Source>
- inline bool RegEx::Matches(const Source& source) const {
- return Match(source) >= 0;
- }
- // Match
- // . Matches the given string against this regular expression.
- // . Returns the number of characters matched.
- // . Returns -1 if no characters were matched (the reason for
- // not returning zero is that we may have an empty regex
- // which is ALWAYS successful at matching zero characters).
- // . REMEMBER that we only match from the start of the buffer!
- inline int RegEx::Match(const std::string& str) const {
- StringCharSource source(str.c_str(), str.size());
- return Match(source);
- }
- inline int RegEx::Match(const Stream& in) const {
- StreamCharSource source(in);
- return Match(source);
- }
- template <typename Source>
- inline bool RegEx::IsValidSource(const Source& source) const {
- return source;
- }
- template <>
- inline bool RegEx::IsValidSource<StringCharSource>(
- const StringCharSource& source) const {
- switch (m_op) {
- case REGEX_MATCH:
- case REGEX_RANGE:
- return source;
- default:
- return true;
- }
- }
- template <typename Source>
- inline int RegEx::Match(const Source& source) const {
- return IsValidSource(source) ? MatchUnchecked(source) : -1;
- }
- template <typename Source>
- inline int RegEx::MatchUnchecked(const Source& source) const {
- switch (m_op) {
- case REGEX_EMPTY:
- return MatchOpEmpty(source);
- case REGEX_MATCH:
- return MatchOpMatch(source);
- case REGEX_RANGE:
- return MatchOpRange(source);
- case REGEX_OR:
- return MatchOpOr(source);
- case REGEX_AND:
- return MatchOpAnd(source);
- case REGEX_NOT:
- return MatchOpNot(source);
- case REGEX_SEQ:
- return MatchOpSeq(source);
- }
- return -1;
- }
- //////////////////////////////////////////////////////////////////////////////
- // Operators
- // Note: the convention MatchOp*<Source> is that we can assume
- // IsSourceValid(source).
- // So we do all our checks *before* we call these functions
- // EmptyOperator
- template <typename Source>
- inline int RegEx::MatchOpEmpty(const Source& source) const {
- return source[0] == Stream::eof() ? 0 : -1;
- }
- template <>
- inline int RegEx::MatchOpEmpty<StringCharSource>(
- const StringCharSource& source) const {
- return !source
- ? 0
- : -1; // the empty regex only is successful on the empty string
- }
- // MatchOperator
- template <typename Source>
- inline int RegEx::MatchOpMatch(const Source& source) const {
- if (source[0] != m_a)
- return -1;
- return 1;
- }
- // RangeOperator
- template <typename Source>
- inline int RegEx::MatchOpRange(const Source& source) const {
- if (m_a > source[0] || m_z < source[0])
- return -1;
- return 1;
- }
- // OrOperator
- template <typename Source>
- inline int RegEx::MatchOpOr(const Source& source) const {
- for (std::size_t i = 0; i < m_params.size(); i++) {
- int n = m_params[i].MatchUnchecked(source);
- if (n >= 0)
- return n;
- }
- return -1;
- }
- // AndOperator
- // Note: 'AND' is a little funny, since we may be required to match things
- // of different lengths. If we find a match, we return the length of
- // the FIRST entry on the list.
- template <typename Source>
- inline int RegEx::MatchOpAnd(const Source& source) const {
- int first = -1;
- for (std::size_t i = 0; i < m_params.size(); i++) {
- int n = m_params[i].MatchUnchecked(source);
- if (n == -1)
- return -1;
- if (i == 0)
- first = n;
- }
- return first;
- }
- // NotOperator
- template <typename Source>
- inline int RegEx::MatchOpNot(const Source& source) const {
- if (m_params.empty())
- return -1;
- if (m_params[0].MatchUnchecked(source) >= 0)
- return -1;
- return 1;
- }
- // SeqOperator
- template <typename Source>
- inline int RegEx::MatchOpSeq(const Source& source) const {
- int offset = 0;
- for (std::size_t i = 0; i < m_params.size(); i++) {
- int n = m_params[i].Match(source + offset); // note Match, not
- // MatchUnchecked because we
- // need to check validity after
- // the offset
- if (n == -1)
- return -1;
- offset += n;
- }
- return offset;
- }
- }
- #endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|