git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidjson/internal/regex.h

normal view · raw

6c5f2c01 sago007 2017-03-15 17:56 1
// Tencent is pleased to support the open source community by making RapidJSON available.
6c5f2c01 sago007 2017-03-15 17:56 2
// 
6c5f2c01 sago007 2017-03-15 17:56 3
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
6c5f2c01 sago007 2017-03-15 17:56 4
//
6c5f2c01 sago007 2017-03-15 17:56 5
// Licensed under the MIT License (the "License"); you may not use this file except
6c5f2c01 sago007 2017-03-15 17:56 6
// in compliance with the License. You may obtain a copy of the License at
6c5f2c01 sago007 2017-03-15 17:56 7
//
6c5f2c01 sago007 2017-03-15 17:56 8
// http://opensource.org/licenses/MIT
6c5f2c01 sago007 2017-03-15 17:56 9
//
6c5f2c01 sago007 2017-03-15 17:56 10
// Unless required by applicable law or agreed to in writing, software distributed 
6c5f2c01 sago007 2017-03-15 17:56 11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
6c5f2c01 sago007 2017-03-15 17:56 12
// CONDITIONS OF ANY KIND, either express or implied. See the License for the 
6c5f2c01 sago007 2017-03-15 17:56 13
// specific language governing permissions and limitations under the License.
6c5f2c01 sago007 2017-03-15 17:56 14
6c5f2c01 sago007 2017-03-15 17:56 15
#ifndef CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
6c5f2c01 sago007 2017-03-15 17:56 16
#define CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
6c5f2c01 sago007 2017-03-15 17:56 17
6c5f2c01 sago007 2017-03-15 17:56 18
#include "../allocators.h"
6c5f2c01 sago007 2017-03-15 17:56 19
#include "../stream.h"
6c5f2c01 sago007 2017-03-15 17:56 20
#include "stack.h"
6c5f2c01 sago007 2017-03-15 17:56 21
6c5f2c01 sago007 2017-03-15 17:56 22
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 23
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 24
CEREAL_RAPIDJSON_DIAG_OFF(padded)
6c5f2c01 sago007 2017-03-15 17:56 25
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
6c5f2c01 sago007 2017-03-15 17:56 26
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
6c5f2c01 sago007 2017-03-15 17:56 27
#endif
6c5f2c01 sago007 2017-03-15 17:56 28
6c5f2c01 sago007 2017-03-15 17:56 29
#ifdef __GNUC__
6c5f2c01 sago007 2017-03-15 17:56 30
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 31
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
6c5f2c01 sago007 2017-03-15 17:56 32
#endif
6c5f2c01 sago007 2017-03-15 17:56 33
6c5f2c01 sago007 2017-03-15 17:56 34
#ifdef _MSC_VER
6c5f2c01 sago007 2017-03-15 17:56 35
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 36
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
6c5f2c01 sago007 2017-03-15 17:56 37
#endif
6c5f2c01 sago007 2017-03-15 17:56 38
6c5f2c01 sago007 2017-03-15 17:56 39
#ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 40
#define CEREAL_RAPIDJSON_REGEX_VERBOSE 0
6c5f2c01 sago007 2017-03-15 17:56 41
#endif
6c5f2c01 sago007 2017-03-15 17:56 42
6c5f2c01 sago007 2017-03-15 17:56 43
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
6c5f2c01 sago007 2017-03-15 17:56 44
namespace internal {
6c5f2c01 sago007 2017-03-15 17:56 45
6c5f2c01 sago007 2017-03-15 17:56 46
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 47
// GenericRegex
6c5f2c01 sago007 2017-03-15 17:56 48
6c5f2c01 sago007 2017-03-15 17:56 49
static const SizeType kRegexInvalidState = ~SizeType(0);  //!< Represents an invalid index in GenericRegex::State::out, out1
6c5f2c01 sago007 2017-03-15 17:56 50
static const SizeType kRegexInvalidRange = ~SizeType(0);
6c5f2c01 sago007 2017-03-15 17:56 51
6c5f2c01 sago007 2017-03-15 17:56 52
//! Regular expression engine with subset of ECMAscript grammar.
6c5f2c01 sago007 2017-03-15 17:56 53
/*!
6c5f2c01 sago007 2017-03-15 17:56 54
    Supported regular expression syntax:
6c5f2c01 sago007 2017-03-15 17:56 55
    - \c ab     Concatenation
6c5f2c01 sago007 2017-03-15 17:56 56
    - \c a|b    Alternation
6c5f2c01 sago007 2017-03-15 17:56 57
    - \c a?     Zero or one
6c5f2c01 sago007 2017-03-15 17:56 58
    - \c a*     Zero or more
6c5f2c01 sago007 2017-03-15 17:56 59
    - \c a+     One or more
6c5f2c01 sago007 2017-03-15 17:56 60
    - \c a{3}   Exactly 3 times
6c5f2c01 sago007 2017-03-15 17:56 61
    - \c a{3,}  At least 3 times
6c5f2c01 sago007 2017-03-15 17:56 62
    - \c a{3,5} 3 to 5 times
6c5f2c01 sago007 2017-03-15 17:56 63
    - \c (ab)   Grouping
6c5f2c01 sago007 2017-03-15 17:56 64
    - \c ^a     At the beginning
6c5f2c01 sago007 2017-03-15 17:56 65
    - \c a$     At the end
6c5f2c01 sago007 2017-03-15 17:56 66
    - \c .      Any character
6c5f2c01 sago007 2017-03-15 17:56 67
    - \c [abc]  Character classes
6c5f2c01 sago007 2017-03-15 17:56 68
    - \c [a-c]  Character class range
6c5f2c01 sago007 2017-03-15 17:56 69
    - \c [a-z0-9_] Character class combination
6c5f2c01 sago007 2017-03-15 17:56 70
    - \c [^abc] Negated character classes
6c5f2c01 sago007 2017-03-15 17:56 71
    - \c [^a-c] Negated character class range
6c5f2c01 sago007 2017-03-15 17:56 72
    - \c [\b]   Backspace (U+0008)
6c5f2c01 sago007 2017-03-15 17:56 73
    - \c \\| \\\\ ...  Escape characters
6c5f2c01 sago007 2017-03-15 17:56 74
    - \c \\f Form feed (U+000C)
6c5f2c01 sago007 2017-03-15 17:56 75
    - \c \\n Line feed (U+000A)
6c5f2c01 sago007 2017-03-15 17:56 76
    - \c \\r Carriage return (U+000D)
6c5f2c01 sago007 2017-03-15 17:56 77
    - \c \\t Tab (U+0009)
6c5f2c01 sago007 2017-03-15 17:56 78
    - \c \\v Vertical tab (U+000B)
6c5f2c01 sago007 2017-03-15 17:56 79
6c5f2c01 sago007 2017-03-15 17:56 80
    \note This is a Thompson NFA engine, implemented with reference to 
6c5f2c01 sago007 2017-03-15 17:56 81
        Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", 
6c5f2c01 sago007 2017-03-15 17:56 82
        https://swtch.com/~rsc/regexp/regexp1.html 
6c5f2c01 sago007 2017-03-15 17:56 83
*/
6c5f2c01 sago007 2017-03-15 17:56 84
template <typename Encoding, typename Allocator = CrtAllocator>
6c5f2c01 sago007 2017-03-15 17:56 85
class GenericRegex {
6c5f2c01 sago007 2017-03-15 17:56 86
public:
6c5f2c01 sago007 2017-03-15 17:56 87
    typedef typename Encoding::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 88
6c5f2c01 sago007 2017-03-15 17:56 89
    GenericRegex(const Ch* source, Allocator* allocator = 0) : 
6c5f2c01 sago007 2017-03-15 17:56 90
        states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), 
6c5f2c01 sago007 2017-03-15 17:56 91
        stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
6c5f2c01 sago007 2017-03-15 17:56 92
    {
6c5f2c01 sago007 2017-03-15 17:56 93
        GenericStringStream<Encoding> ss(source);
6c5f2c01 sago007 2017-03-15 17:56 94
        DecodedStream<GenericStringStream<Encoding> > ds(ss);
6c5f2c01 sago007 2017-03-15 17:56 95
        Parse(ds);
6c5f2c01 sago007 2017-03-15 17:56 96
    }
6c5f2c01 sago007 2017-03-15 17:56 97
6c5f2c01 sago007 2017-03-15 17:56 98
    ~GenericRegex() {
6c5f2c01 sago007 2017-03-15 17:56 99
        Allocator::Free(stateSet_);
6c5f2c01 sago007 2017-03-15 17:56 100
    }
6c5f2c01 sago007 2017-03-15 17:56 101
6c5f2c01 sago007 2017-03-15 17:56 102
    bool IsValid() const {
6c5f2c01 sago007 2017-03-15 17:56 103
        return root_ != kRegexInvalidState;
6c5f2c01 sago007 2017-03-15 17:56 104
    }
6c5f2c01 sago007 2017-03-15 17:56 105
6c5f2c01 sago007 2017-03-15 17:56 106
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 107
    bool Match(InputStream& is) const {
6c5f2c01 sago007 2017-03-15 17:56 108
        return SearchWithAnchoring(is, true, true);
6c5f2c01 sago007 2017-03-15 17:56 109
    }
6c5f2c01 sago007 2017-03-15 17:56 110
6c5f2c01 sago007 2017-03-15 17:56 111
    bool Match(const Ch* s) const {
6c5f2c01 sago007 2017-03-15 17:56 112
        GenericStringStream<Encoding> is(s);
6c5f2c01 sago007 2017-03-15 17:56 113
        return Match(is);
6c5f2c01 sago007 2017-03-15 17:56 114
    }
6c5f2c01 sago007 2017-03-15 17:56 115
6c5f2c01 sago007 2017-03-15 17:56 116
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 117
    bool Search(InputStream& is) const {
6c5f2c01 sago007 2017-03-15 17:56 118
        return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
6c5f2c01 sago007 2017-03-15 17:56 119
    }
6c5f2c01 sago007 2017-03-15 17:56 120
6c5f2c01 sago007 2017-03-15 17:56 121
    bool Search(const Ch* s) const {
6c5f2c01 sago007 2017-03-15 17:56 122
        GenericStringStream<Encoding> is(s);
6c5f2c01 sago007 2017-03-15 17:56 123
        return Search(is);
6c5f2c01 sago007 2017-03-15 17:56 124
    }
6c5f2c01 sago007 2017-03-15 17:56 125
6c5f2c01 sago007 2017-03-15 17:56 126
private:
6c5f2c01 sago007 2017-03-15 17:56 127
    enum Operator {
6c5f2c01 sago007 2017-03-15 17:56 128
        kZeroOrOne,
6c5f2c01 sago007 2017-03-15 17:56 129
        kZeroOrMore,
6c5f2c01 sago007 2017-03-15 17:56 130
        kOneOrMore,
6c5f2c01 sago007 2017-03-15 17:56 131
        kConcatenation,
6c5f2c01 sago007 2017-03-15 17:56 132
        kAlternation,
6c5f2c01 sago007 2017-03-15 17:56 133
        kLeftParenthesis
6c5f2c01 sago007 2017-03-15 17:56 134
    };
6c5f2c01 sago007 2017-03-15 17:56 135
6c5f2c01 sago007 2017-03-15 17:56 136
    static const unsigned kAnyCharacterClass = 0xFFFFFFFF;   //!< For '.'
6c5f2c01 sago007 2017-03-15 17:56 137
    static const unsigned kRangeCharacterClass = 0xFFFFFFFE;
6c5f2c01 sago007 2017-03-15 17:56 138
    static const unsigned kRangeNegationFlag = 0x80000000;
6c5f2c01 sago007 2017-03-15 17:56 139
6c5f2c01 sago007 2017-03-15 17:56 140
    struct Range {
6c5f2c01 sago007 2017-03-15 17:56 141
        unsigned start; // 
6c5f2c01 sago007 2017-03-15 17:56 142
        unsigned end;
6c5f2c01 sago007 2017-03-15 17:56 143
        SizeType next;
6c5f2c01 sago007 2017-03-15 17:56 144
    };
6c5f2c01 sago007 2017-03-15 17:56 145
6c5f2c01 sago007 2017-03-15 17:56 146
    struct State {
6c5f2c01 sago007 2017-03-15 17:56 147
        SizeType out;     //!< Equals to kInvalid for matching state
6c5f2c01 sago007 2017-03-15 17:56 148
        SizeType out1;    //!< Equals to non-kInvalid for split
6c5f2c01 sago007 2017-03-15 17:56 149
        SizeType rangeStart;
6c5f2c01 sago007 2017-03-15 17:56 150
        unsigned codepoint;
6c5f2c01 sago007 2017-03-15 17:56 151
    };
6c5f2c01 sago007 2017-03-15 17:56 152
6c5f2c01 sago007 2017-03-15 17:56 153
    struct Frag {
6c5f2c01 sago007 2017-03-15 17:56 154
        Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {}
6c5f2c01 sago007 2017-03-15 17:56 155
        SizeType start;
6c5f2c01 sago007 2017-03-15 17:56 156
        SizeType out; //!< link-list of all output states
6c5f2c01 sago007 2017-03-15 17:56 157
        SizeType minIndex;
6c5f2c01 sago007 2017-03-15 17:56 158
    };
6c5f2c01 sago007 2017-03-15 17:56 159
6c5f2c01 sago007 2017-03-15 17:56 160
    template <typename SourceStream>
6c5f2c01 sago007 2017-03-15 17:56 161
    class DecodedStream {
6c5f2c01 sago007 2017-03-15 17:56 162
    public:
6c5f2c01 sago007 2017-03-15 17:56 163
        DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
6c5f2c01 sago007 2017-03-15 17:56 164
        unsigned Peek() { return codepoint_; }
6c5f2c01 sago007 2017-03-15 17:56 165
        unsigned Take() {
6c5f2c01 sago007 2017-03-15 17:56 166
            unsigned c = codepoint_;
6c5f2c01 sago007 2017-03-15 17:56 167
            if (c) // No further decoding when '\0'
6c5f2c01 sago007 2017-03-15 17:56 168
                Decode();
6c5f2c01 sago007 2017-03-15 17:56 169
            return c;
6c5f2c01 sago007 2017-03-15 17:56 170
        }
6c5f2c01 sago007 2017-03-15 17:56 171
6c5f2c01 sago007 2017-03-15 17:56 172
    private:
6c5f2c01 sago007 2017-03-15 17:56 173
        void Decode() {
6c5f2c01 sago007 2017-03-15 17:56 174
            if (!Encoding::Decode(ss_, &codepoint_))
6c5f2c01 sago007 2017-03-15 17:56 175
                codepoint_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 176
        }
6c5f2c01 sago007 2017-03-15 17:56 177
6c5f2c01 sago007 2017-03-15 17:56 178
        SourceStream& ss_;
6c5f2c01 sago007 2017-03-15 17:56 179
        unsigned codepoint_;
6c5f2c01 sago007 2017-03-15 17:56 180
    };
6c5f2c01 sago007 2017-03-15 17:56 181
6c5f2c01 sago007 2017-03-15 17:56 182
    State& GetState(SizeType index) {
6c5f2c01 sago007 2017-03-15 17:56 183
        CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
6c5f2c01 sago007 2017-03-15 17:56 184
        return states_.template Bottom<State>()[index];
6c5f2c01 sago007 2017-03-15 17:56 185
    }
6c5f2c01 sago007 2017-03-15 17:56 186
6c5f2c01 sago007 2017-03-15 17:56 187
    const State& GetState(SizeType index) const {
6c5f2c01 sago007 2017-03-15 17:56 188
        CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
6c5f2c01 sago007 2017-03-15 17:56 189
        return states_.template Bottom<State>()[index];
6c5f2c01 sago007 2017-03-15 17:56 190
    }
6c5f2c01 sago007 2017-03-15 17:56 191
6c5f2c01 sago007 2017-03-15 17:56 192
    Range& GetRange(SizeType index) {
6c5f2c01 sago007 2017-03-15 17:56 193
        CEREAL_RAPIDJSON_ASSERT(index < rangeCount_);
6c5f2c01 sago007 2017-03-15 17:56 194
        return ranges_.template Bottom<Range>()[index];
6c5f2c01 sago007 2017-03-15 17:56 195
    }
6c5f2c01 sago007 2017-03-15 17:56 196
6c5f2c01 sago007 2017-03-15 17:56 197
    const Range& GetRange(SizeType index) const {
6c5f2c01 sago007 2017-03-15 17:56 198
        CEREAL_RAPIDJSON_ASSERT(index < rangeCount_);
6c5f2c01 sago007 2017-03-15 17:56 199
        return ranges_.template Bottom<Range>()[index];
6c5f2c01 sago007 2017-03-15 17:56 200
    }
6c5f2c01 sago007 2017-03-15 17:56 201
6c5f2c01 sago007 2017-03-15 17:56 202
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 203
    void Parse(DecodedStream<InputStream>& ds) {
6c5f2c01 sago007 2017-03-15 17:56 204
        Allocator allocator;
6c5f2c01 sago007 2017-03-15 17:56 205
        Stack<Allocator> operandStack(&allocator, 256);     // Frag
6c5f2c01 sago007 2017-03-15 17:56 206
        Stack<Allocator> operatorStack(&allocator, 256);    // Operator
6c5f2c01 sago007 2017-03-15 17:56 207
        Stack<Allocator> atomCountStack(&allocator, 256);   // unsigned (Atom per parenthesis)
6c5f2c01 sago007 2017-03-15 17:56 208
6c5f2c01 sago007 2017-03-15 17:56 209
        *atomCountStack.template Push<unsigned>() = 0;
6c5f2c01 sago007 2017-03-15 17:56 210
6c5f2c01 sago007 2017-03-15 17:56 211
        unsigned codepoint;
6c5f2c01 sago007 2017-03-15 17:56 212
        while (ds.Peek() != 0) {
6c5f2c01 sago007 2017-03-15 17:56 213
            switch (codepoint = ds.Take()) {
6c5f2c01 sago007 2017-03-15 17:56 214
                case '^':
6c5f2c01 sago007 2017-03-15 17:56 215
                    anchorBegin_ = true;
6c5f2c01 sago007 2017-03-15 17:56 216
                    break;
6c5f2c01 sago007 2017-03-15 17:56 217
6c5f2c01 sago007 2017-03-15 17:56 218
                case '$':
6c5f2c01 sago007 2017-03-15 17:56 219
                    anchorEnd_ = true;
6c5f2c01 sago007 2017-03-15 17:56 220
                    break;
6c5f2c01 sago007 2017-03-15 17:56 221
6c5f2c01 sago007 2017-03-15 17:56 222
                case '|':
6c5f2c01 sago007 2017-03-15 17:56 223
                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() < kAlternation)
6c5f2c01 sago007 2017-03-15 17:56 224
                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
6c5f2c01 sago007 2017-03-15 17:56 225
                            return;
6c5f2c01 sago007 2017-03-15 17:56 226
                    *operatorStack.template Push<Operator>() = kAlternation;
6c5f2c01 sago007 2017-03-15 17:56 227
                    *atomCountStack.template Top<unsigned>() = 0;
6c5f2c01 sago007 2017-03-15 17:56 228
                    break;
6c5f2c01 sago007 2017-03-15 17:56 229
6c5f2c01 sago007 2017-03-15 17:56 230
                case '(':
6c5f2c01 sago007 2017-03-15 17:56 231
                    *operatorStack.template Push<Operator>() = kLeftParenthesis;
6c5f2c01 sago007 2017-03-15 17:56 232
                    *atomCountStack.template Push<unsigned>() = 0;
6c5f2c01 sago007 2017-03-15 17:56 233
                    break;
6c5f2c01 sago007 2017-03-15 17:56 234
6c5f2c01 sago007 2017-03-15 17:56 235
                case ')':
6c5f2c01 sago007 2017-03-15 17:56 236
                    while (!operatorStack.Empty() && *operatorStack.template Top<Operator>() != kLeftParenthesis)
6c5f2c01 sago007 2017-03-15 17:56 237
                        if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
6c5f2c01 sago007 2017-03-15 17:56 238
                            return;
6c5f2c01 sago007 2017-03-15 17:56 239
                    if (operatorStack.Empty())
6c5f2c01 sago007 2017-03-15 17:56 240
                        return;
6c5f2c01 sago007 2017-03-15 17:56 241
                    operatorStack.template Pop<Operator>(1);
6c5f2c01 sago007 2017-03-15 17:56 242
                    atomCountStack.template Pop<unsigned>(1);
6c5f2c01 sago007 2017-03-15 17:56 243
                    ImplicitConcatenation(atomCountStack, operatorStack);
6c5f2c01 sago007 2017-03-15 17:56 244
                    break;
6c5f2c01 sago007 2017-03-15 17:56 245
6c5f2c01 sago007 2017-03-15 17:56 246
                case '?':
6c5f2c01 sago007 2017-03-15 17:56 247
                    if (!Eval(operandStack, kZeroOrOne))
6c5f2c01 sago007 2017-03-15 17:56 248
                        return;
6c5f2c01 sago007 2017-03-15 17:56 249
                    break;
6c5f2c01 sago007 2017-03-15 17:56 250
6c5f2c01 sago007 2017-03-15 17:56 251
                case '*':
6c5f2c01 sago007 2017-03-15 17:56 252
                    if (!Eval(operandStack, kZeroOrMore))
6c5f2c01 sago007 2017-03-15 17:56 253
                        return;
6c5f2c01 sago007 2017-03-15 17:56 254
                    break;
6c5f2c01 sago007 2017-03-15 17:56 255
6c5f2c01 sago007 2017-03-15 17:56 256
                case '+':
6c5f2c01 sago007 2017-03-15 17:56 257
                    if (!Eval(operandStack, kOneOrMore))
6c5f2c01 sago007 2017-03-15 17:56 258
                        return;
6c5f2c01 sago007 2017-03-15 17:56 259
                    break;
6c5f2c01 sago007 2017-03-15 17:56 260
6c5f2c01 sago007 2017-03-15 17:56 261
                case '{':
6c5f2c01 sago007 2017-03-15 17:56 262
                    {
6c5f2c01 sago007 2017-03-15 17:56 263
                        unsigned n, m;
6c5f2c01 sago007 2017-03-15 17:56 264
                        if (!ParseUnsigned(ds, &n))
6c5f2c01 sago007 2017-03-15 17:56 265
                            return;
6c5f2c01 sago007 2017-03-15 17:56 266
6c5f2c01 sago007 2017-03-15 17:56 267
                        if (ds.Peek() == ',') {
6c5f2c01 sago007 2017-03-15 17:56 268
                            ds.Take();
6c5f2c01 sago007 2017-03-15 17:56 269
                            if (ds.Peek() == '}')
6c5f2c01 sago007 2017-03-15 17:56 270
                                m = kInfinityQuantifier;
6c5f2c01 sago007 2017-03-15 17:56 271
                            else if (!ParseUnsigned(ds, &m) || m < n)
6c5f2c01 sago007 2017-03-15 17:56 272
                                return;
6c5f2c01 sago007 2017-03-15 17:56 273
                        }
6c5f2c01 sago007 2017-03-15 17:56 274
                        else
6c5f2c01 sago007 2017-03-15 17:56 275
                            m = n;
6c5f2c01 sago007 2017-03-15 17:56 276
6c5f2c01 sago007 2017-03-15 17:56 277
                        if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}')
6c5f2c01 sago007 2017-03-15 17:56 278
                            return;
6c5f2c01 sago007 2017-03-15 17:56 279
                        ds.Take();
6c5f2c01 sago007 2017-03-15 17:56 280
                    }
6c5f2c01 sago007 2017-03-15 17:56 281
                    break;
6c5f2c01 sago007 2017-03-15 17:56 282
6c5f2c01 sago007 2017-03-15 17:56 283
                case '.':
6c5f2c01 sago007 2017-03-15 17:56 284
                    PushOperand(operandStack, kAnyCharacterClass);
6c5f2c01 sago007 2017-03-15 17:56 285
                    ImplicitConcatenation(atomCountStack, operatorStack);
6c5f2c01 sago007 2017-03-15 17:56 286
                    break;
6c5f2c01 sago007 2017-03-15 17:56 287
6c5f2c01 sago007 2017-03-15 17:56 288
                case '[':
6c5f2c01 sago007 2017-03-15 17:56 289
                    {
6c5f2c01 sago007 2017-03-15 17:56 290
                        SizeType range;
6c5f2c01 sago007 2017-03-15 17:56 291
                        if (!ParseRange(ds, &range))
6c5f2c01 sago007 2017-03-15 17:56 292
                            return;
6c5f2c01 sago007 2017-03-15 17:56 293
                        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass);
6c5f2c01 sago007 2017-03-15 17:56 294
                        GetState(s).rangeStart = range;
6c5f2c01 sago007 2017-03-15 17:56 295
                        *operandStack.template Push<Frag>() = Frag(s, s, s);
6c5f2c01 sago007 2017-03-15 17:56 296
                    }
6c5f2c01 sago007 2017-03-15 17:56 297
                    ImplicitConcatenation(atomCountStack, operatorStack);
6c5f2c01 sago007 2017-03-15 17:56 298
                    break;
6c5f2c01 sago007 2017-03-15 17:56 299
6c5f2c01 sago007 2017-03-15 17:56 300
                case '\\': // Escape character
6c5f2c01 sago007 2017-03-15 17:56 301
                    if (!CharacterEscape(ds, &codepoint))
6c5f2c01 sago007 2017-03-15 17:56 302
                        return; // Unsupported escape character
6c5f2c01 sago007 2017-03-15 17:56 303
                    // fall through to default
6c5f2c01 sago007 2017-03-15 17:56 304
6c5f2c01 sago007 2017-03-15 17:56 305
                default: // Pattern character
6c5f2c01 sago007 2017-03-15 17:56 306
                    PushOperand(operandStack, codepoint);
6c5f2c01 sago007 2017-03-15 17:56 307
                    ImplicitConcatenation(atomCountStack, operatorStack);
6c5f2c01 sago007 2017-03-15 17:56 308
            }
6c5f2c01 sago007 2017-03-15 17:56 309
        }
6c5f2c01 sago007 2017-03-15 17:56 310
6c5f2c01 sago007 2017-03-15 17:56 311
        while (!operatorStack.Empty())
6c5f2c01 sago007 2017-03-15 17:56 312
            if (!Eval(operandStack, *operatorStack.template Pop<Operator>(1)))
6c5f2c01 sago007 2017-03-15 17:56 313
                return;
6c5f2c01 sago007 2017-03-15 17:56 314
6c5f2c01 sago007 2017-03-15 17:56 315
        // Link the operand to matching state.
6c5f2c01 sago007 2017-03-15 17:56 316
        if (operandStack.GetSize() == sizeof(Frag)) {
6c5f2c01 sago007 2017-03-15 17:56 317
            Frag* e = operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 318
            Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
6c5f2c01 sago007 2017-03-15 17:56 319
            root_ = e->start;
6c5f2c01 sago007 2017-03-15 17:56 320
6c5f2c01 sago007 2017-03-15 17:56 321
#if CEREAL_RAPIDJSON_REGEX_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 322
            printf("root: %d\n", root_);
6c5f2c01 sago007 2017-03-15 17:56 323
            for (SizeType i = 0; i < stateCount_ ; i++) {
6c5f2c01 sago007 2017-03-15 17:56 324
                State& s = GetState(i);
6c5f2c01 sago007 2017-03-15 17:56 325
                printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint);
6c5f2c01 sago007 2017-03-15 17:56 326
            }
6c5f2c01 sago007 2017-03-15 17:56 327
            printf("\n");
6c5f2c01 sago007 2017-03-15 17:56 328
#endif
6c5f2c01 sago007 2017-03-15 17:56 329
        }
6c5f2c01 sago007 2017-03-15 17:56 330
6c5f2c01 sago007 2017-03-15 17:56 331
        // Preallocate buffer for SearchWithAnchoring()
6c5f2c01 sago007 2017-03-15 17:56 332
        CEREAL_RAPIDJSON_ASSERT(stateSet_ == 0);
6c5f2c01 sago007 2017-03-15 17:56 333
        if (stateCount_ > 0) {
6c5f2c01 sago007 2017-03-15 17:56 334
            stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
6c5f2c01 sago007 2017-03-15 17:56 335
            state0_.template Reserve<SizeType>(stateCount_);
6c5f2c01 sago007 2017-03-15 17:56 336
            state1_.template Reserve<SizeType>(stateCount_);
6c5f2c01 sago007 2017-03-15 17:56 337
        }
6c5f2c01 sago007 2017-03-15 17:56 338
    }
6c5f2c01 sago007 2017-03-15 17:56 339
6c5f2c01 sago007 2017-03-15 17:56 340
    SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
6c5f2c01 sago007 2017-03-15 17:56 341
        State* s = states_.template Push<State>();
6c5f2c01 sago007 2017-03-15 17:56 342
        s->out = out;
6c5f2c01 sago007 2017-03-15 17:56 343
        s->out1 = out1;
6c5f2c01 sago007 2017-03-15 17:56 344
        s->codepoint = codepoint;
6c5f2c01 sago007 2017-03-15 17:56 345
        s->rangeStart = kRegexInvalidRange;
6c5f2c01 sago007 2017-03-15 17:56 346
        return stateCount_++;
6c5f2c01 sago007 2017-03-15 17:56 347
    }
6c5f2c01 sago007 2017-03-15 17:56 348
6c5f2c01 sago007 2017-03-15 17:56 349
    void PushOperand(Stack<Allocator>& operandStack, unsigned codepoint) {
6c5f2c01 sago007 2017-03-15 17:56 350
        SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint);
6c5f2c01 sago007 2017-03-15 17:56 351
        *operandStack.template Push<Frag>() = Frag(s, s, s);
6c5f2c01 sago007 2017-03-15 17:56 352
    }
6c5f2c01 sago007 2017-03-15 17:56 353
6c5f2c01 sago007 2017-03-15 17:56 354
    void ImplicitConcatenation(Stack<Allocator>& atomCountStack, Stack<Allocator>& operatorStack) {
6c5f2c01 sago007 2017-03-15 17:56 355
        if (*atomCountStack.template Top<unsigned>())
6c5f2c01 sago007 2017-03-15 17:56 356
            *operatorStack.template Push<Operator>() = kConcatenation;
6c5f2c01 sago007 2017-03-15 17:56 357
        (*atomCountStack.template Top<unsigned>())++;
6c5f2c01 sago007 2017-03-15 17:56 358
    }
6c5f2c01 sago007 2017-03-15 17:56 359
6c5f2c01 sago007 2017-03-15 17:56 360
    SizeType Append(SizeType l1, SizeType l2) {
6c5f2c01 sago007 2017-03-15 17:56 361
        SizeType old = l1;
6c5f2c01 sago007 2017-03-15 17:56 362
        while (GetState(l1).out != kRegexInvalidState)
6c5f2c01 sago007 2017-03-15 17:56 363
            l1 = GetState(l1).out;
6c5f2c01 sago007 2017-03-15 17:56 364
        GetState(l1).out = l2;
6c5f2c01 sago007 2017-03-15 17:56 365
        return old;
6c5f2c01 sago007 2017-03-15 17:56 366
    }
6c5f2c01 sago007 2017-03-15 17:56 367
6c5f2c01 sago007 2017-03-15 17:56 368
    void Patch(SizeType l, SizeType s) {
6c5f2c01 sago007 2017-03-15 17:56 369
        for (SizeType next; l != kRegexInvalidState; l = next) {
6c5f2c01 sago007 2017-03-15 17:56 370
            next = GetState(l).out;
6c5f2c01 sago007 2017-03-15 17:56 371
            GetState(l).out = s;
6c5f2c01 sago007 2017-03-15 17:56 372
        }
6c5f2c01 sago007 2017-03-15 17:56 373
    }
6c5f2c01 sago007 2017-03-15 17:56 374
6c5f2c01 sago007 2017-03-15 17:56 375
    bool Eval(Stack<Allocator>& operandStack, Operator op) {
6c5f2c01 sago007 2017-03-15 17:56 376
        switch (op) {
6c5f2c01 sago007 2017-03-15 17:56 377
            case kConcatenation:
6c5f2c01 sago007 2017-03-15 17:56 378
                CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
6c5f2c01 sago007 2017-03-15 17:56 379
                {
6c5f2c01 sago007 2017-03-15 17:56 380
                    Frag e2 = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 381
                    Frag e1 = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 382
                    Patch(e1.out, e2.start);
6c5f2c01 sago007 2017-03-15 17:56 383
                    *operandStack.template Push<Frag>() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex));
6c5f2c01 sago007 2017-03-15 17:56 384
                }
6c5f2c01 sago007 2017-03-15 17:56 385
                return true;
6c5f2c01 sago007 2017-03-15 17:56 386
6c5f2c01 sago007 2017-03-15 17:56 387
            case kAlternation:
6c5f2c01 sago007 2017-03-15 17:56 388
                if (operandStack.GetSize() >= sizeof(Frag) * 2) {
6c5f2c01 sago007 2017-03-15 17:56 389
                    Frag e2 = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 390
                    Frag e1 = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 391
                    SizeType s = NewState(e1.start, e2.start, 0);
6c5f2c01 sago007 2017-03-15 17:56 392
                    *operandStack.template Push<Frag>() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex));
6c5f2c01 sago007 2017-03-15 17:56 393
                    return true;
6c5f2c01 sago007 2017-03-15 17:56 394
                }
6c5f2c01 sago007 2017-03-15 17:56 395
                return false;
6c5f2c01 sago007 2017-03-15 17:56 396
6c5f2c01 sago007 2017-03-15 17:56 397
            case kZeroOrOne:
6c5f2c01 sago007 2017-03-15 17:56 398
                if (operandStack.GetSize() >= sizeof(Frag)) {
6c5f2c01 sago007 2017-03-15 17:56 399
                    Frag e = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 400
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
6c5f2c01 sago007 2017-03-15 17:56 401
                    *operandStack.template Push<Frag>() = Frag(s, Append(e.out, s), e.minIndex);
6c5f2c01 sago007 2017-03-15 17:56 402
                    return true;
6c5f2c01 sago007 2017-03-15 17:56 403
                }
6c5f2c01 sago007 2017-03-15 17:56 404
                return false;
6c5f2c01 sago007 2017-03-15 17:56 405
6c5f2c01 sago007 2017-03-15 17:56 406
            case kZeroOrMore:
6c5f2c01 sago007 2017-03-15 17:56 407
                if (operandStack.GetSize() >= sizeof(Frag)) {
6c5f2c01 sago007 2017-03-15 17:56 408
                    Frag e = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 409
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
6c5f2c01 sago007 2017-03-15 17:56 410
                    Patch(e.out, s);
6c5f2c01 sago007 2017-03-15 17:56 411
                    *operandStack.template Push<Frag>() = Frag(s, s, e.minIndex);
6c5f2c01 sago007 2017-03-15 17:56 412
                    return true;
6c5f2c01 sago007 2017-03-15 17:56 413
                }
6c5f2c01 sago007 2017-03-15 17:56 414
                return false;
6c5f2c01 sago007 2017-03-15 17:56 415
6c5f2c01 sago007 2017-03-15 17:56 416
            default: 
6c5f2c01 sago007 2017-03-15 17:56 417
                CEREAL_RAPIDJSON_ASSERT(op == kOneOrMore);
6c5f2c01 sago007 2017-03-15 17:56 418
                if (operandStack.GetSize() >= sizeof(Frag)) {
6c5f2c01 sago007 2017-03-15 17:56 419
                    Frag e = *operandStack.template Pop<Frag>(1);
6c5f2c01 sago007 2017-03-15 17:56 420
                    SizeType s = NewState(kRegexInvalidState, e.start, 0);
6c5f2c01 sago007 2017-03-15 17:56 421
                    Patch(e.out, s);
6c5f2c01 sago007 2017-03-15 17:56 422
                    *operandStack.template Push<Frag>() = Frag(e.start, s, e.minIndex);
6c5f2c01 sago007 2017-03-15 17:56 423
                    return true;
6c5f2c01 sago007 2017-03-15 17:56 424
                }
6c5f2c01 sago007 2017-03-15 17:56 425
                return false;
6c5f2c01 sago007 2017-03-15 17:56 426
        }
6c5f2c01 sago007 2017-03-15 17:56 427
    }
6c5f2c01 sago007 2017-03-15 17:56 428
6c5f2c01 sago007 2017-03-15 17:56 429
    bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
6c5f2c01 sago007 2017-03-15 17:56 430
        CEREAL_RAPIDJSON_ASSERT(n <= m);
6c5f2c01 sago007 2017-03-15 17:56 431
        CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
6c5f2c01 sago007 2017-03-15 17:56 432
6c5f2c01 sago007 2017-03-15 17:56 433
        if (n == 0) {
6c5f2c01 sago007 2017-03-15 17:56 434
            if (m == 0)                             // a{0} not support
6c5f2c01 sago007 2017-03-15 17:56 435
                return false;
6c5f2c01 sago007 2017-03-15 17:56 436
            else if (m == kInfinityQuantifier)
6c5f2c01 sago007 2017-03-15 17:56 437
                Eval(operandStack, kZeroOrMore);    // a{0,} -> a*
6c5f2c01 sago007 2017-03-15 17:56 438
            else {
6c5f2c01 sago007 2017-03-15 17:56 439
                Eval(operandStack, kZeroOrOne);         // a{0,5} -> a?
6c5f2c01 sago007 2017-03-15 17:56 440
                for (unsigned i = 0; i < m - 1; i++)
6c5f2c01 sago007 2017-03-15 17:56 441
                    CloneTopOperand(operandStack);      // a{0,5} -> a? a? a? a? a?
6c5f2c01 sago007 2017-03-15 17:56 442
                for (unsigned i = 0; i < m - 1; i++)
6c5f2c01 sago007 2017-03-15 17:56 443
                    Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a?
6c5f2c01 sago007 2017-03-15 17:56 444
            }
6c5f2c01 sago007 2017-03-15 17:56 445
            return true;
6c5f2c01 sago007 2017-03-15 17:56 446
        }
6c5f2c01 sago007 2017-03-15 17:56 447
6c5f2c01 sago007 2017-03-15 17:56 448
        for (unsigned i = 0; i < n - 1; i++)        // a{3} -> a a a
6c5f2c01 sago007 2017-03-15 17:56 449
            CloneTopOperand(operandStack);
6c5f2c01 sago007 2017-03-15 17:56 450
6c5f2c01 sago007 2017-03-15 17:56 451
        if (m == kInfinityQuantifier)
6c5f2c01 sago007 2017-03-15 17:56 452
            Eval(operandStack, kOneOrMore);         // a{3,} -> a a a+
6c5f2c01 sago007 2017-03-15 17:56 453
        else if (m > n) {
6c5f2c01 sago007 2017-03-15 17:56 454
            CloneTopOperand(operandStack);          // a{3,5} -> a a a a
6c5f2c01 sago007 2017-03-15 17:56 455
            Eval(operandStack, kZeroOrOne);         // a{3,5} -> a a a a?
6c5f2c01 sago007 2017-03-15 17:56 456
            for (unsigned i = n; i < m - 1; i++)
6c5f2c01 sago007 2017-03-15 17:56 457
                CloneTopOperand(operandStack);      // a{3,5} -> a a a a? a?
6c5f2c01 sago007 2017-03-15 17:56 458
            for (unsigned i = n; i < m; i++)
6c5f2c01 sago007 2017-03-15 17:56 459
                Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a?
6c5f2c01 sago007 2017-03-15 17:56 460
        }
6c5f2c01 sago007 2017-03-15 17:56 461
6c5f2c01 sago007 2017-03-15 17:56 462
        for (unsigned i = 0; i < n - 1; i++)
6c5f2c01 sago007 2017-03-15 17:56 463
            Eval(operandStack, kConcatenation);     // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a?
6c5f2c01 sago007 2017-03-15 17:56 464
6c5f2c01 sago007 2017-03-15 17:56 465
        return true;
6c5f2c01 sago007 2017-03-15 17:56 466
    }
6c5f2c01 sago007 2017-03-15 17:56 467
6c5f2c01 sago007 2017-03-15 17:56 468
    static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; }
6c5f2c01 sago007 2017-03-15 17:56 469
6c5f2c01 sago007 2017-03-15 17:56 470
    void CloneTopOperand(Stack<Allocator>& operandStack) {
6c5f2c01 sago007 2017-03-15 17:56 471
        const Frag src = *operandStack.template Top<Frag>(); // Copy constructor to prevent invalidation
6c5f2c01 sago007 2017-03-15 17:56 472
        SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_)
6c5f2c01 sago007 2017-03-15 17:56 473
        State* s = states_.template Push<State>(count);
6c5f2c01 sago007 2017-03-15 17:56 474
        memcpy(s, &GetState(src.minIndex), count * sizeof(State));
6c5f2c01 sago007 2017-03-15 17:56 475
        for (SizeType j = 0; j < count; j++) {
6c5f2c01 sago007 2017-03-15 17:56 476
            if (s[j].out != kRegexInvalidState)
6c5f2c01 sago007 2017-03-15 17:56 477
                s[j].out += count;
6c5f2c01 sago007 2017-03-15 17:56 478
            if (s[j].out1 != kRegexInvalidState)
6c5f2c01 sago007 2017-03-15 17:56 479
                s[j].out1 += count;
6c5f2c01 sago007 2017-03-15 17:56 480
        }
6c5f2c01 sago007 2017-03-15 17:56 481
        *operandStack.template Push<Frag>() = Frag(src.start + count, src.out + count, src.minIndex + count);
6c5f2c01 sago007 2017-03-15 17:56 482
        stateCount_ += count;
6c5f2c01 sago007 2017-03-15 17:56 483
    }
6c5f2c01 sago007 2017-03-15 17:56 484
6c5f2c01 sago007 2017-03-15 17:56 485
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 486
    bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
6c5f2c01 sago007 2017-03-15 17:56 487
        unsigned r = 0;
6c5f2c01 sago007 2017-03-15 17:56 488
        if (ds.Peek() < '0' || ds.Peek() > '9')
6c5f2c01 sago007 2017-03-15 17:56 489
            return false;
6c5f2c01 sago007 2017-03-15 17:56 490
        while (ds.Peek() >= '0' && ds.Peek() <= '9') {
6c5f2c01 sago007 2017-03-15 17:56 491
            if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295
6c5f2c01 sago007 2017-03-15 17:56 492
                return false; // overflow
6c5f2c01 sago007 2017-03-15 17:56 493
            r = r * 10 + (ds.Take() - '0');
6c5f2c01 sago007 2017-03-15 17:56 494
        }
6c5f2c01 sago007 2017-03-15 17:56 495
        *u = r;
6c5f2c01 sago007 2017-03-15 17:56 496
        return true;
6c5f2c01 sago007 2017-03-15 17:56 497
    }
6c5f2c01 sago007 2017-03-15 17:56 498
6c5f2c01 sago007 2017-03-15 17:56 499
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 500
    bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
6c5f2c01 sago007 2017-03-15 17:56 501
        bool isBegin = true;
6c5f2c01 sago007 2017-03-15 17:56 502
        bool negate = false;
6c5f2c01 sago007 2017-03-15 17:56 503
        int step = 0;
6c5f2c01 sago007 2017-03-15 17:56 504
        SizeType start = kRegexInvalidRange;
6c5f2c01 sago007 2017-03-15 17:56 505
        SizeType current = kRegexInvalidRange;
6c5f2c01 sago007 2017-03-15 17:56 506
        unsigned codepoint;
6c5f2c01 sago007 2017-03-15 17:56 507
        while ((codepoint = ds.Take()) != 0) {
6c5f2c01 sago007 2017-03-15 17:56 508
            if (isBegin) {
6c5f2c01 sago007 2017-03-15 17:56 509
                isBegin = false;
6c5f2c01 sago007 2017-03-15 17:56 510
                if (codepoint == '^') {
6c5f2c01 sago007 2017-03-15 17:56 511
                    negate = true;
6c5f2c01 sago007 2017-03-15 17:56 512
                    continue;
6c5f2c01 sago007 2017-03-15 17:56 513
                }
6c5f2c01 sago007 2017-03-15 17:56 514
            }
6c5f2c01 sago007 2017-03-15 17:56 515
6c5f2c01 sago007 2017-03-15 17:56 516
            switch (codepoint) {
6c5f2c01 sago007 2017-03-15 17:56 517
            case ']':
6c5f2c01 sago007 2017-03-15 17:56 518
                if (start == kRegexInvalidRange)
6c5f2c01 sago007 2017-03-15 17:56 519
                    return false;   // Error: nothing inside []
6c5f2c01 sago007 2017-03-15 17:56 520
                if (step == 2) { // Add trailing '-'
6c5f2c01 sago007 2017-03-15 17:56 521
                    SizeType r = NewRange('-');
6c5f2c01 sago007 2017-03-15 17:56 522
                    CEREAL_RAPIDJSON_ASSERT(current != kRegexInvalidRange);
6c5f2c01 sago007 2017-03-15 17:56 523
                    GetRange(current).next = r;
6c5f2c01 sago007 2017-03-15 17:56 524
                }
6c5f2c01 sago007 2017-03-15 17:56 525
                if (negate)
6c5f2c01 sago007 2017-03-15 17:56 526
                    GetRange(start).start |= kRangeNegationFlag;
6c5f2c01 sago007 2017-03-15 17:56 527
                *range = start;
6c5f2c01 sago007 2017-03-15 17:56 528
                return true;
6c5f2c01 sago007 2017-03-15 17:56 529
6c5f2c01 sago007 2017-03-15 17:56 530
            case '\\':
6c5f2c01 sago007 2017-03-15 17:56 531
                if (ds.Peek() == 'b') {
6c5f2c01 sago007 2017-03-15 17:56 532
                    ds.Take();
6c5f2c01 sago007 2017-03-15 17:56 533
                    codepoint = 0x0008; // Escape backspace character
6c5f2c01 sago007 2017-03-15 17:56 534
                }
6c5f2c01 sago007 2017-03-15 17:56 535
                else if (!CharacterEscape(ds, &codepoint))
6c5f2c01 sago007 2017-03-15 17:56 536
                    return false;
6c5f2c01 sago007 2017-03-15 17:56 537
                // fall through to default
6c5f2c01 sago007 2017-03-15 17:56 538
6c5f2c01 sago007 2017-03-15 17:56 539
            default:
6c5f2c01 sago007 2017-03-15 17:56 540
                switch (step) {
6c5f2c01 sago007 2017-03-15 17:56 541
                case 1:
6c5f2c01 sago007 2017-03-15 17:56 542
                    if (codepoint == '-') {
6c5f2c01 sago007 2017-03-15 17:56 543
                        step++;
6c5f2c01 sago007 2017-03-15 17:56 544
                        break;
6c5f2c01 sago007 2017-03-15 17:56 545
                    }
6c5f2c01 sago007 2017-03-15 17:56 546
                    // fall through to step 0 for other characters
6c5f2c01 sago007 2017-03-15 17:56 547
6c5f2c01 sago007 2017-03-15 17:56 548
                case 0:
6c5f2c01 sago007 2017-03-15 17:56 549
                    {
6c5f2c01 sago007 2017-03-15 17:56 550
                        SizeType r = NewRange(codepoint);
6c5f2c01 sago007 2017-03-15 17:56 551
                        if (current != kRegexInvalidRange)
6c5f2c01 sago007 2017-03-15 17:56 552
                            GetRange(current).next = r;
6c5f2c01 sago007 2017-03-15 17:56 553
                        if (start == kRegexInvalidRange)
6c5f2c01 sago007 2017-03-15 17:56 554
                            start = r;
6c5f2c01 sago007 2017-03-15 17:56 555
                        current = r;
6c5f2c01 sago007 2017-03-15 17:56 556
                    }
6c5f2c01 sago007 2017-03-15 17:56 557
                    step = 1;
6c5f2c01 sago007 2017-03-15 17:56 558
                    break;
6c5f2c01 sago007 2017-03-15 17:56 559
6c5f2c01 sago007 2017-03-15 17:56 560
                default:
6c5f2c01 sago007 2017-03-15 17:56 561
                    CEREAL_RAPIDJSON_ASSERT(step == 2);
6c5f2c01 sago007 2017-03-15 17:56 562
                    GetRange(current).end = codepoint;
6c5f2c01 sago007 2017-03-15 17:56 563
                    step = 0;
6c5f2c01 sago007 2017-03-15 17:56 564
                }
6c5f2c01 sago007 2017-03-15 17:56 565
            }
6c5f2c01 sago007 2017-03-15 17:56 566
        }
6c5f2c01 sago007 2017-03-15 17:56 567
        return false;
6c5f2c01 sago007 2017-03-15 17:56 568
    }
6c5f2c01 sago007 2017-03-15 17:56 569
    
6c5f2c01 sago007 2017-03-15 17:56 570
    SizeType NewRange(unsigned codepoint) {
6c5f2c01 sago007 2017-03-15 17:56 571
        Range* r = ranges_.template Push<Range>();
6c5f2c01 sago007 2017-03-15 17:56 572
        r->start = r->end = codepoint;
6c5f2c01 sago007 2017-03-15 17:56 573
        r->next = kRegexInvalidRange;
6c5f2c01 sago007 2017-03-15 17:56 574
        return rangeCount_++;
6c5f2c01 sago007 2017-03-15 17:56 575
    }
6c5f2c01 sago007 2017-03-15 17:56 576
6c5f2c01 sago007 2017-03-15 17:56 577
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 578
    bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
6c5f2c01 sago007 2017-03-15 17:56 579
        unsigned codepoint;
6c5f2c01 sago007 2017-03-15 17:56 580
        switch (codepoint = ds.Take()) {
6c5f2c01 sago007 2017-03-15 17:56 581
            case '^':
6c5f2c01 sago007 2017-03-15 17:56 582
            case '$':
6c5f2c01 sago007 2017-03-15 17:56 583
            case '|':
6c5f2c01 sago007 2017-03-15 17:56 584
            case '(':
6c5f2c01 sago007 2017-03-15 17:56 585
            case ')':
6c5f2c01 sago007 2017-03-15 17:56 586
            case '?':
6c5f2c01 sago007 2017-03-15 17:56 587
            case '*':
6c5f2c01 sago007 2017-03-15 17:56 588
            case '+':
6c5f2c01 sago007 2017-03-15 17:56 589
            case '.':
6c5f2c01 sago007 2017-03-15 17:56 590
            case '[':
6c5f2c01 sago007 2017-03-15 17:56 591
            case ']':
6c5f2c01 sago007 2017-03-15 17:56 592
            case '{':
6c5f2c01 sago007 2017-03-15 17:56 593
            case '}':
6c5f2c01 sago007 2017-03-15 17:56 594
            case '\\':
6c5f2c01 sago007 2017-03-15 17:56 595
                *escapedCodepoint = codepoint; return true;
6c5f2c01 sago007 2017-03-15 17:56 596
            case 'f': *escapedCodepoint = 0x000C; return true;
6c5f2c01 sago007 2017-03-15 17:56 597
            case 'n': *escapedCodepoint = 0x000A; return true;
6c5f2c01 sago007 2017-03-15 17:56 598
            case 'r': *escapedCodepoint = 0x000D; return true;
6c5f2c01 sago007 2017-03-15 17:56 599
            case 't': *escapedCodepoint = 0x0009; return true;
6c5f2c01 sago007 2017-03-15 17:56 600
            case 'v': *escapedCodepoint = 0x000B; return true;
6c5f2c01 sago007 2017-03-15 17:56 601
            default:
6c5f2c01 sago007 2017-03-15 17:56 602
                return false; // Unsupported escape character
6c5f2c01 sago007 2017-03-15 17:56 603
        }
6c5f2c01 sago007 2017-03-15 17:56 604
    }
6c5f2c01 sago007 2017-03-15 17:56 605
6c5f2c01 sago007 2017-03-15 17:56 606
    template <typename InputStream>
6c5f2c01 sago007 2017-03-15 17:56 607
    bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
6c5f2c01 sago007 2017-03-15 17:56 608
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 609
        DecodedStream<InputStream> ds(is);
6c5f2c01 sago007 2017-03-15 17:56 610
6c5f2c01 sago007 2017-03-15 17:56 611
        state0_.Clear();
6c5f2c01 sago007 2017-03-15 17:56 612
        Stack<Allocator> *current = &state0_, *next = &state1_;
6c5f2c01 sago007 2017-03-15 17:56 613
        const size_t stateSetSize = GetStateSetSize();
6c5f2c01 sago007 2017-03-15 17:56 614
        std::memset(stateSet_, 0, stateSetSize);
6c5f2c01 sago007 2017-03-15 17:56 615
6c5f2c01 sago007 2017-03-15 17:56 616
        bool matched = AddState(*current, root_);
6c5f2c01 sago007 2017-03-15 17:56 617
        unsigned codepoint;
6c5f2c01 sago007 2017-03-15 17:56 618
        while (!current->Empty() && (codepoint = ds.Take()) != 0) {
6c5f2c01 sago007 2017-03-15 17:56 619
            std::memset(stateSet_, 0, stateSetSize);
6c5f2c01 sago007 2017-03-15 17:56 620
            next->Clear();
6c5f2c01 sago007 2017-03-15 17:56 621
            matched = false;
6c5f2c01 sago007 2017-03-15 17:56 622
            for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
6c5f2c01 sago007 2017-03-15 17:56 623
                const State& sr = GetState(*s);
6c5f2c01 sago007 2017-03-15 17:56 624
                if (sr.codepoint == codepoint ||
6c5f2c01 sago007 2017-03-15 17:56 625
                    sr.codepoint == kAnyCharacterClass || 
6c5f2c01 sago007 2017-03-15 17:56 626
                    (sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
6c5f2c01 sago007 2017-03-15 17:56 627
                {
6c5f2c01 sago007 2017-03-15 17:56 628
                    matched = AddState(*next, sr.out) || matched;
6c5f2c01 sago007 2017-03-15 17:56 629
                    if (!anchorEnd && matched)
6c5f2c01 sago007 2017-03-15 17:56 630
                        return true;
6c5f2c01 sago007 2017-03-15 17:56 631
                }
6c5f2c01 sago007 2017-03-15 17:56 632
                if (!anchorBegin)
6c5f2c01 sago007 2017-03-15 17:56 633
                    AddState(*next, root_);
6c5f2c01 sago007 2017-03-15 17:56 634
            }
6c5f2c01 sago007 2017-03-15 17:56 635
            internal::Swap(current, next);
6c5f2c01 sago007 2017-03-15 17:56 636
        }
6c5f2c01 sago007 2017-03-15 17:56 637
6c5f2c01 sago007 2017-03-15 17:56 638
        return matched;
6c5f2c01 sago007 2017-03-15 17:56 639
    }
6c5f2c01 sago007 2017-03-15 17:56 640
6c5f2c01 sago007 2017-03-15 17:56 641
    size_t GetStateSetSize() const {
6c5f2c01 sago007 2017-03-15 17:56 642
        return (stateCount_ + 31) / 32 * 4;
6c5f2c01 sago007 2017-03-15 17:56 643
    }
6c5f2c01 sago007 2017-03-15 17:56 644
6c5f2c01 sago007 2017-03-15 17:56 645
    // Return whether the added states is a match state
6c5f2c01 sago007 2017-03-15 17:56 646
    bool AddState(Stack<Allocator>& l, SizeType index) const {
6c5f2c01 sago007 2017-03-15 17:56 647
        CEREAL_RAPIDJSON_ASSERT(index != kRegexInvalidState);
6c5f2c01 sago007 2017-03-15 17:56 648
6c5f2c01 sago007 2017-03-15 17:56 649
        const State& s = GetState(index);
6c5f2c01 sago007 2017-03-15 17:56 650
        if (s.out1 != kRegexInvalidState) { // Split
6c5f2c01 sago007 2017-03-15 17:56 651
            bool matched = AddState(l, s.out);
6c5f2c01 sago007 2017-03-15 17:56 652
            return AddState(l, s.out1) || matched;
6c5f2c01 sago007 2017-03-15 17:56 653
        }
6c5f2c01 sago007 2017-03-15 17:56 654
        else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
6c5f2c01 sago007 2017-03-15 17:56 655
            stateSet_[index >> 5] |= (1 << (index & 31));
6c5f2c01 sago007 2017-03-15 17:56 656
            *l.template PushUnsafe<SizeType>() = index;
6c5f2c01 sago007 2017-03-15 17:56 657
        }
6c5f2c01 sago007 2017-03-15 17:56 658
        return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
6c5f2c01 sago007 2017-03-15 17:56 659
    }
6c5f2c01 sago007 2017-03-15 17:56 660
6c5f2c01 sago007 2017-03-15 17:56 661
    bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
6c5f2c01 sago007 2017-03-15 17:56 662
        bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
6c5f2c01 sago007 2017-03-15 17:56 663
        while (rangeIndex != kRegexInvalidRange) {
6c5f2c01 sago007 2017-03-15 17:56 664
            const Range& r = GetRange(rangeIndex);
6c5f2c01 sago007 2017-03-15 17:56 665
            if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
6c5f2c01 sago007 2017-03-15 17:56 666
                return yes;
6c5f2c01 sago007 2017-03-15 17:56 667
            rangeIndex = r.next;
6c5f2c01 sago007 2017-03-15 17:56 668
        }
6c5f2c01 sago007 2017-03-15 17:56 669
        return !yes;
6c5f2c01 sago007 2017-03-15 17:56 670
    }
6c5f2c01 sago007 2017-03-15 17:56 671
6c5f2c01 sago007 2017-03-15 17:56 672
    Stack<Allocator> states_;
6c5f2c01 sago007 2017-03-15 17:56 673
    Stack<Allocator> ranges_;
6c5f2c01 sago007 2017-03-15 17:56 674
    SizeType root_;
6c5f2c01 sago007 2017-03-15 17:56 675
    SizeType stateCount_;
6c5f2c01 sago007 2017-03-15 17:56 676
    SizeType rangeCount_;
6c5f2c01 sago007 2017-03-15 17:56 677
6c5f2c01 sago007 2017-03-15 17:56 678
    static const unsigned kInfinityQuantifier = ~0u;
6c5f2c01 sago007 2017-03-15 17:56 679
6c5f2c01 sago007 2017-03-15 17:56 680
    // For SearchWithAnchoring()
6c5f2c01 sago007 2017-03-15 17:56 681
    uint32_t* stateSet_;        // allocated by states_.GetAllocator()
6c5f2c01 sago007 2017-03-15 17:56 682
    mutable Stack<Allocator> state0_;
6c5f2c01 sago007 2017-03-15 17:56 683
    mutable Stack<Allocator> state1_;
6c5f2c01 sago007 2017-03-15 17:56 684
    bool anchorBegin_;
6c5f2c01 sago007 2017-03-15 17:56 685
    bool anchorEnd_;
6c5f2c01 sago007 2017-03-15 17:56 686
};
6c5f2c01 sago007 2017-03-15 17:56 687
6c5f2c01 sago007 2017-03-15 17:56 688
typedef GenericRegex<UTF8<> > Regex;
6c5f2c01 sago007 2017-03-15 17:56 689
6c5f2c01 sago007 2017-03-15 17:56 690
} // namespace internal
6c5f2c01 sago007 2017-03-15 17:56 691
CEREAL_RAPIDJSON_NAMESPACE_END
6c5f2c01 sago007 2017-03-15 17:56 692
6c5f2c01 sago007 2017-03-15 17:56 693
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 694
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 695
#endif
6c5f2c01 sago007 2017-03-15 17:56 696
6c5f2c01 sago007 2017-03-15 17:56 697
#ifdef _MSC_VER
6c5f2c01 sago007 2017-03-15 17:56 698
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 699
#endif
6c5f2c01 sago007 2017-03-15 17:56 700
6c5f2c01 sago007 2017-03-15 17:56 701
#endif // CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
1970-01-01 00:00 702