js/src/vm/MatchPairs.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/vm/MatchPairs.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,174 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef vm_MatchPairs_h
    1.11 +#define vm_MatchPairs_h
    1.12 +
    1.13 +#include "jsalloc.h"
    1.14 +
    1.15 +#include "ds/LifoAlloc.h"
    1.16 +#include "js/Vector.h"
    1.17 +
    1.18 +/*
    1.19 + * RegExp match results are succinctly represented by pairs of integer
    1.20 + * indices delimiting (start, limit] segments of the input string.
    1.21 + *
    1.22 + * The pair count for a given RegExp match is the capturing parentheses
    1.23 + * count plus one for the "0 capturing paren" whole text match.
    1.24 + */
    1.25 +
    1.26 +namespace js {
    1.27 +
    1.28 +struct MatchPair
    1.29 +{
    1.30 +    int start;
    1.31 +    int limit;
    1.32 +
    1.33 +    MatchPair()
    1.34 +      : start(-1), limit(-1)
    1.35 +    { }
    1.36 +
    1.37 +    MatchPair(int start, int limit)
    1.38 +      : start(start), limit(limit)
    1.39 +    { }
    1.40 +
    1.41 +    size_t length()      const { JS_ASSERT(!isUndefined()); return limit - start; }
    1.42 +    bool isEmpty()       const { return length() == 0; }
    1.43 +    bool isUndefined()   const { return start < 0; }
    1.44 +
    1.45 +    void displace(size_t amount) {
    1.46 +        start += (start < 0) ? 0 : amount;
    1.47 +        limit += (limit < 0) ? 0 : amount;
    1.48 +    }
    1.49 +
    1.50 +    inline bool check() const {
    1.51 +        JS_ASSERT(limit >= start);
    1.52 +        JS_ASSERT_IF(start < 0, start == -1);
    1.53 +        JS_ASSERT_IF(limit < 0, limit == -1);
    1.54 +        return true;
    1.55 +    }
    1.56 +};
    1.57 +
    1.58 +/* Base class for RegExp execution output. */
    1.59 +class MatchPairs
    1.60 +{
    1.61 +  protected:
    1.62 +    size_t     pairCount_;   /* Length of pairs_. */
    1.63 +    MatchPair *pairs_;       /* Raw pointer into an allocated MatchPair buffer. */
    1.64 +
    1.65 +  protected:
    1.66 +    /* Not used directly: use ScopedMatchPairs or VectorMatchPairs. */
    1.67 +    MatchPairs()
    1.68 +      : pairCount_(0), pairs_(nullptr)
    1.69 +    { }
    1.70 +
    1.71 +  protected:
    1.72 +    /* Functions used by friend classes. */
    1.73 +    friend class RegExpShared;
    1.74 +    friend class RegExpStatics;
    1.75 +
    1.76 +    /* MatchPair buffer allocator: set pairs_ and pairCount_. */
    1.77 +    virtual bool allocOrExpandArray(size_t pairCount) = 0;
    1.78 +
    1.79 +    bool initArray(size_t pairCount);
    1.80 +    bool initArrayFrom(MatchPairs &copyFrom);
    1.81 +    void forgetArray() { pairs_ = nullptr; }
    1.82 +
    1.83 +    void displace(size_t disp);
    1.84 +    void checkAgainst(size_t inputLength) {
    1.85 +#ifdef DEBUG
    1.86 +        for (size_t i = 0; i < pairCount_; i++) {
    1.87 +            const MatchPair &p = pair(i);
    1.88 +            JS_ASSERT(p.check());
    1.89 +            if (p.isUndefined())
    1.90 +                continue;
    1.91 +            JS_ASSERT(size_t(p.limit) <= inputLength);
    1.92 +        }
    1.93 +#endif
    1.94 +    }
    1.95 +
    1.96 +  public:
    1.97 +    /* Querying functions in the style of RegExpStatics. */
    1.98 +    bool   empty() const           { return pairCount_ == 0; }
    1.99 +    size_t pairCount() const       { JS_ASSERT(pairCount_ > 0); return pairCount_; }
   1.100 +    size_t parenCount() const      { return pairCount_ - 1; }
   1.101 +
   1.102 +  public:
   1.103 +    unsigned *rawBuf() const { return reinterpret_cast<unsigned *>(pairs_); }
   1.104 +    size_t length() const { return pairCount_; }
   1.105 +
   1.106 +    /* Pair accessors. */
   1.107 +    const MatchPair &pair(size_t i) const {
   1.108 +        JS_ASSERT(pairCount_ && i < pairCount_);
   1.109 +        JS_ASSERT(pairs_);
   1.110 +        return pairs_[i];
   1.111 +    }
   1.112 +
   1.113 +    const MatchPair &operator[](size_t i) const { return pair(i); }
   1.114 +};
   1.115 +
   1.116 +/* MatchPairs allocated into temporary storage, removed when out of scope. */
   1.117 +class ScopedMatchPairs : public MatchPairs
   1.118 +{
   1.119 +    LifoAllocScope lifoScope_;
   1.120 +
   1.121 +  public:
   1.122 +    /* Constructs an implicit LifoAllocScope. */
   1.123 +    ScopedMatchPairs(LifoAlloc *lifoAlloc)
   1.124 +      : lifoScope_(lifoAlloc)
   1.125 +    { }
   1.126 +
   1.127 +    const MatchPair &operator[](size_t i) const { return pair(i); }
   1.128 +
   1.129 +  protected:
   1.130 +    bool allocOrExpandArray(size_t pairCount);
   1.131 +};
   1.132 +
   1.133 +/*
   1.134 + * MatchPairs allocated into permanent storage, for RegExpStatics.
   1.135 + * The Vector of MatchPairs is reusable by Vector expansion.
   1.136 + */
   1.137 +class VectorMatchPairs : public MatchPairs
   1.138 +{
   1.139 +    Vector<MatchPair, 10, SystemAllocPolicy> vec_;
   1.140 +
   1.141 +  public:
   1.142 +    VectorMatchPairs() {
   1.143 +        vec_.clear();
   1.144 +    }
   1.145 +
   1.146 +    const MatchPair &operator[](size_t i) const { return pair(i); }
   1.147 +
   1.148 +  protected:
   1.149 +    friend class RegExpStatics;
   1.150 +    bool allocOrExpandArray(size_t pairCount);
   1.151 +};
   1.152 +
   1.153 +/*
   1.154 + * Passes either MatchPair or MatchPairs through ExecuteRegExp()
   1.155 + * to avoid duplication of generic code.
   1.156 + */
   1.157 +struct MatchConduit
   1.158 +{
   1.159 +    union {
   1.160 +        MatchPair  *pair;
   1.161 +        MatchPairs *pairs;
   1.162 +    } u;
   1.163 +    bool isPair;
   1.164 +
   1.165 +    explicit MatchConduit(MatchPair *pair) {
   1.166 +        isPair = true;
   1.167 +        u.pair = pair;
   1.168 +    }
   1.169 +    explicit MatchConduit(MatchPairs *pairs) {
   1.170 +        isPair = false;
   1.171 +        u.pairs = pairs;
   1.172 +    }
   1.173 +};
   1.174 +
   1.175 +} /* namespace js */
   1.176 +
   1.177 +#endif /* vm_MatchPairs_h */

mercurial