1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Regular expression flags. */
#ifndef js_RegExpFlags_h
#define js_RegExpFlags_h
#include "mozilla/Assertions.h" // MOZ_ASSERT
#include "mozilla/Attributes.h" // MOZ_IMPLICIT
#include <ostream> // ostream
#include <stdint.h> // uint8_t
namespace JS {
/**
* Regular expression flag values, suitable for initializing a collection of
* regular expression flags as defined below in |RegExpFlags|. Flags are listed
* in alphabetical order by syntax -- /d, /g, /i, /m, /s, /u, /v, /y.
*/
class RegExpFlag {
// WARNING TO SPIDERMONKEY HACKERS (embedders must assume these values can
// change):
//
// Flag-bit values appear in XDR and structured clone data formats, so none of
// these values can be changed (including to assign values in numerically
// ascending order) unless you also add a translation layer.
public:
/**
* Add .indices property to the match result, i.e. /d
*/
static constexpr uint8_t HasIndices = 0b0100'0000;
/**
* Act globally and find *all* matches (rather than stopping after just the
* first one), i.e. /g.
*/
static constexpr uint8_t Global = 0b0000'0010;
/**
* Interpret regular expression source text case-insensitively by folding
* uppercase letters to lowercase, i.e. /i.
*/
static constexpr uint8_t IgnoreCase = 0b0000'0001;
/** Treat ^ and $ as begin and end of line, i.e. /m. */
static constexpr uint8_t Multiline = 0b0000'0100;
/* Allow . to match newline characters, i.e. /s. */
static constexpr uint8_t DotAll = 0b0010'0000;
/** Use Unicode semantics, i.e. /u. */
static constexpr uint8_t Unicode = 0b0001'0000;
/** Use Unicode Sets semantics, i.e. /v. */
static constexpr uint8_t UnicodeSets = 0b1000'0000;
/** Only match starting from <regular expression>.lastIndex, i.e. /y. */
static constexpr uint8_t Sticky = 0b0000'1000;
/** No regular expression flags. */
static constexpr uint8_t NoFlags = 0b0000'0000;
/** All regular expression flags. */
static constexpr uint8_t AllFlags = 0b1111'1111;
};
/**
* A collection of regular expression flags. Individual flag values may be
* combined into a collection using bitwise operators.
*/
class RegExpFlags {
public:
using Flag = uint8_t;
private:
Flag flags_ = 0;
public:
RegExpFlags() = default;
MOZ_IMPLICIT RegExpFlags(Flag flags) : flags_(flags) {
MOZ_ASSERT((flags & RegExpFlag::AllFlags) == flags,
"flags must not contain unrecognized flags");
}
RegExpFlags(const RegExpFlags&) = default;
RegExpFlags& operator=(const RegExpFlags&) = default;
bool operator==(const RegExpFlags& other) const {
return flags_ == other.flags_;
}
bool operator!=(const RegExpFlags& other) const { return !(*this == other); }
RegExpFlags& operator&=(const RegExpFlags& rhs) {
flags_ &= rhs.flags_;
return *this;
}
RegExpFlags& operator|=(const RegExpFlags& rhs) {
flags_ |= rhs.flags_;
return *this;
}
RegExpFlags operator&(Flag flag) const { return RegExpFlags(flags_ & flag); }
RegExpFlags operator|(Flag flag) const { return RegExpFlags(flags_ | flag); }
RegExpFlags operator^(Flag flag) const { return RegExpFlags(flags_ ^ flag); }
RegExpFlags operator~() const {
return RegExpFlags(~flags_ & RegExpFlag::AllFlags);
}
bool hasIndices() const { return flags_ & RegExpFlag::HasIndices; }
bool global() const { return flags_ & RegExpFlag::Global; }
bool ignoreCase() const { return flags_ & RegExpFlag::IgnoreCase; }
bool multiline() const { return flags_ & RegExpFlag::Multiline; }
bool dotAll() const { return flags_ & RegExpFlag::DotAll; }
bool unicode() const { return flags_ & RegExpFlag::Unicode; }
bool unicodeSets() const { return flags_ & RegExpFlag::UnicodeSets; }
bool sticky() const { return flags_ & RegExpFlag::Sticky; }
explicit operator bool() const { return flags_ != 0; }
Flag value() const { return flags_; }
constexpr operator Flag() const { return flags_; }
void set(Flag flags, bool value) {
if (value) {
flags_ |= flags;
} else {
flags_ &= ~flags;
}
}
};
inline RegExpFlags& operator&=(RegExpFlags& flags, RegExpFlags::Flag flag) {
flags = flags & flag;
return flags;
}
inline RegExpFlags& operator|=(RegExpFlags& flags, RegExpFlags::Flag flag) {
flags = flags | flag;
return flags;
}
inline RegExpFlags& operator^=(RegExpFlags& flags, RegExpFlags::Flag flag) {
flags = flags ^ flag;
return flags;
}
inline RegExpFlags operator&(const RegExpFlags& lhs, const RegExpFlags& rhs) {
RegExpFlags result = lhs;
result &= rhs;
return result;
}
inline RegExpFlags operator|(const RegExpFlags& lhs, const RegExpFlags& rhs) {
RegExpFlags result = lhs;
result |= rhs;
return result;
}
inline bool MaybeParseRegExpFlag(char c, RegExpFlags::Flag* flag) {
switch (c) {
case 'd':
*flag = RegExpFlag::HasIndices;
return true;
case 'g':
*flag = RegExpFlag::Global;
return true;
case 'i':
*flag = RegExpFlag::IgnoreCase;
return true;
case 'm':
*flag = RegExpFlag::Multiline;
return true;
case 's':
*flag = RegExpFlag::DotAll;
return true;
case 'u':
*flag = RegExpFlag::Unicode;
return true;
case 'v':
*flag = RegExpFlag::UnicodeSets;
return true;
case 'y':
*flag = RegExpFlag::Sticky;
return true;
default:
return false;
}
}
std::ostream& operator<<(std::ostream& os, RegExpFlags flags);
} // namespace JS
#endif // js_RegExpFlags_h
|