summaryrefslogtreecommitdiffstats
path: root/xpcom/ds/Tokenizer.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/ds/Tokenizer.h')
-rw-r--r--xpcom/ds/Tokenizer.h60
1 files changed, 60 insertions, 0 deletions
diff --git a/xpcom/ds/Tokenizer.h b/xpcom/ds/Tokenizer.h
index 713b63f269..6a4ec89d51 100644
--- a/xpcom/ds/Tokenizer.h
+++ b/xpcom/ds/Tokenizer.h
@@ -439,6 +439,66 @@ class TTokenizer : public TokenizerBase<TChar> {
}
/**
+ * This is an hexadecimal read helper. It returns false and doesn't move the
+ * read cursor when any of the following happens:
+ * - the token at the read cursor is not 0, and it's not followed by x
+ * - the token(s) that follow don't make a valid hexadecimal number
+ * - the final number doesn't fit the T type
+ * Otherwise true is returned, aValue is filled with the integral number
+ * and the cursor is moved forward.
+ */
+ template <typename T>
+ [[nodiscard]] bool ReadHexadecimal(T* aValue, bool aPrefixed = true) {
+ MOZ_RELEASE_ASSERT(aValue);
+
+ typename base::TAString::const_char_iterator rollback = mRollback;
+ typename base::TAString::const_char_iterator cursor = base::mCursor;
+ auto revert = MakeScopeExit([&] {
+ // Move to a state as if Check() call has failed
+ mRollback = rollback;
+ base::mCursor = cursor;
+ base::mHasFailed = true;
+ });
+
+ if (aPrefixed) {
+ typename base::Token t;
+ if (!Check(base::TOKEN_INTEGER, t) && t.AsInteger() != 0) {
+ return false;
+ }
+
+ if (!CheckChar([](const TChar aChar) { return aChar == 'x'; })) {
+ return false;
+ }
+ }
+
+ TChar c = 'z';
+ mozilla::CheckedInt<T> resultingNumber = 0;
+ while (ReadChar(
+ [](const TChar aChar) {
+ return (aChar >= '0' && aChar <= '9') ||
+ (aChar >= 'A' && aChar <= 'F') ||
+ (aChar >= 'a' && aChar <= 'f');
+ },
+ &c)) {
+ resultingNumber *= 16;
+ if (c <= '9') {
+ resultingNumber += static_cast<uint64_t>(c - '0');
+ } else if (c <= 'F') {
+ resultingNumber += static_cast<uint64_t>(c - 'A') + 0xa;
+ } else {
+ resultingNumber += static_cast<uint64_t>(c - 'a') + 0xa;
+ }
+ }
+ if (c == 'z' || !resultingNumber.isValid()) {
+ return false;
+ }
+
+ *aValue = resultingNumber.value();
+ revert.release();
+ return true;
+ }
+
+ /**
* Returns the read cursor position back as it was before the last call of any
* parsing method of TTokenizer (Next, Check*, Skip*, Read*) so that the last
* operation can be repeated. Rollback cannot be used multiple times, it only