Bug 1452619 - Implement mozilla::IsAsciiAlpha. r=froydnj
authorJeff Walden <jwalden@mit.edu>
Mon, 09 Apr 2018 12:02:43 -0700
changeset 412704 9ae76a38a5148b400853151a08ef22d8a7ab463a
parent 412703 6393fa23c234090d931cbaa1d8cab65edbd88a37
child 412705 51399503eb15cd14ecc5510d15927c6b0f840175
push id101986
push userjwalden@mit.edu
push dateWed, 11 Apr 2018 00:27:07 +0000
treeherdermozilla-inbound@4f2a7bac2733 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1452619
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1452619 - Implement mozilla::IsAsciiAlpha. r=froydnj
js/src/frontend/TokenStream.cpp
js/src/util/Text.h
mfbt/TextUtils.h
mfbt/moz.build
mfbt/tests/TestTextUtils.cpp
mfbt/tests/moz.build
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -7,16 +7,17 @@
 // JS lexical scanner.
 
 #include "frontend/TokenStream.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/IntegerTypeTraits.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ScopeExit.h"
+#include "mozilla/TextUtils.h"
 
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "jsexn.h"
 #include "jsnum.h"
@@ -29,16 +30,17 @@
 #include "util/StringBuffer.h"
 #include "util/Unicode.h"
 #include "vm/HelperThreads.h"
 #include "vm/JSAtom.h"
 #include "vm/JSCompartment.h"
 #include "vm/JSContext.h"
 
 using mozilla::ArrayLength;
+using mozilla::IsAsciiAlpha;
 using mozilla::MakeScopeExit;
 using mozilla::PodArrayZero;
 using mozilla::PodCopy;
 
 struct ReservedWordInfo
 {
     const char* chars;         // C string with reserved word text
     js::frontend::TokenKind tokentype;
@@ -2007,17 +2009,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                 else if (c == 'i')
                     flag = IgnoreCaseFlag;
                 else if (c == 'm')
                     flag = MultilineFlag;
                 else if (c == 'y')
                     flag = StickyFlag;
                 else if (c == 'u')
                     flag = UnicodeFlag;
-                else if (JS7_ISLET(c))
+                else if (IsAsciiAlpha(c))
                     flag = NoFlags;
                 else
                     break;
 
                 if ((reflags & flag) || flag == NoFlags) {
                     MOZ_ASSERT(userbuf.offset() > 0);
                     char buf[2] = { char(c), '\0' };
                     errorAt(userbuf.offset() - 1, JSMSG_BAD_REGEXP_FLAG, buf);
--- a/js/src/util/Text.h
+++ b/js/src/util/Text.h
@@ -31,17 +31,16 @@ class JSLinearString;
  */
 #define JS7_ISDEC(c)    ((((unsigned)(c)) - '0') <= 9)
 #define JS7_ISA2F(c)    ((((((unsigned)(c)) - 'a') <= 5) || (((unsigned)(c)) - 'A') <= 5))
 #define JS7_UNDEC(c)    ((c) - '0')
 #define JS7_ISOCT(c)    ((((unsigned)(c)) - '0') <= 7)
 #define JS7_UNOCT(c)    (JS7_UNDEC(c))
 #define JS7_ISHEX(c)    ((c) < 128 && (JS7_ISDEC(c) || JS7_ISA2F(c)))
 #define JS7_UNHEX(c)    (unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
-#define JS7_ISLET(c)    ((c) < 128 && isalpha(c))
 
 static MOZ_ALWAYS_INLINE size_t
 js_strlen(const char16_t* s)
 {
     return std::char_traits<char16_t>::length(s);
 }
 
 template <typename CharT>
new file mode 100644
--- /dev/null
+++ b/mfbt/TextUtils.h
@@ -0,0 +1,56 @@
+/* -*- 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/. */
+
+/* Character/text operations. */
+
+#ifndef mozilla_TextUtils_h
+#define mozilla_TextUtils_h
+
+#include "mozilla/TypeTraits.h"
+
+namespace mozilla {
+
+namespace detail {
+
+template<typename Char>
+class MakeUnsignedChar
+  : public MakeUnsigned<Char>
+{};
+
+template<>
+class MakeUnsignedChar<char16_t>
+{
+public:
+  using Type = char16_t;
+};
+
+template<>
+class MakeUnsignedChar<char32_t>
+{
+public:
+  using Type = char32_t;
+};
+
+} // namespace detail
+
+/**
+ * Returns true iff |aChar| matches [a-zA-Z].
+ *
+ * This function is basically what you thought isalpha was, except its behavior
+ * doesn't depend on the user's current locale.
+ */
+template<typename Char>
+constexpr bool
+IsAsciiAlpha(Char aChar)
+{
+  using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type;
+  auto uc = static_cast<UnsignedChar>(aChar);
+  return ('a' <= uc && uc <= 'z') || ('A' <= uc && uc <= 'Z');
+}
+
+} // namespace mozilla
+
+#endif /* mozilla_TextUtils_h */
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -85,16 +85,17 @@ EXPORTS.mozilla = [
     'SHA1.h',
     'SmallPointerArray.h',
     'Span.h',
     'SplayTree.h',
     'Sprintf.h',
     'StaticAnalysisFunctions.h',
     'TaggedAnonymousMemory.h',
     'TemplateLib.h',
+    'TextUtils.h',
     'ThreadLocal.h',
     'ThreadSafeWeakPtr.h',
     'ToString.h',
     'Tuple.h',
     'TypedEnumBits.h',
     'Types.h',
     'TypeTraits.h',
     'UniquePtr.h',
new file mode 100644
--- /dev/null
+++ b/mfbt/tests/TestTextUtils.cpp
@@ -0,0 +1,106 @@
+/* -*- 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/. */
+
+#include "mozilla/Assertions.h"
+#include "mozilla/TextUtils.h"
+
+using mozilla::IsAsciiAlpha;
+
+// char
+
+static_assert(!IsAsciiAlpha('@'), "'@' isn't ASCII alpha");
+static_assert('@' == 0x40, "'@' has value 0x40");
+
+static_assert('A' == 0x41, "'A' has value 0x41");
+static_assert(IsAsciiAlpha('A'), "'A' is ASCII alpha");
+static_assert(IsAsciiAlpha('B'), "'B' is ASCII alpha");
+static_assert(IsAsciiAlpha('M'), "'M' is ASCII alpha");
+static_assert(IsAsciiAlpha('Y'), "'Y' is ASCII alpha");
+static_assert(IsAsciiAlpha('Z'), "'Z' is ASCII alpha");
+
+static_assert('Z' == 0x5A, "'Z' has value 0x5A");
+static_assert('[' == 0x5B, "'[' has value 0x5B");
+static_assert(!IsAsciiAlpha('['), "'[' isn't ASCII alpha");
+
+static_assert(!IsAsciiAlpha('`'), "'`' isn't ASCII alpha");
+static_assert('`' == 0x60, "'`' has value 0x60");
+
+static_assert('a' == 0x61, "'a' has value 0x61");
+static_assert(IsAsciiAlpha('a'), "'a' is ASCII alpha");
+static_assert(IsAsciiAlpha('b'), "'b' is ASCII alpha");
+static_assert(IsAsciiAlpha('m'), "'m' is ASCII alpha");
+static_assert(IsAsciiAlpha('y'), "'y' is ASCII alpha");
+static_assert(IsAsciiAlpha('z'), "'z' is ASCII alpha");
+
+static_assert('z' == 0x7A, "'z' has value 0x7A");
+static_assert('{' == 0x7B, "'{' has value 0x7B");
+static_assert(!IsAsciiAlpha('{'), "'{' isn't ASCII alpha");
+
+// char16_t
+
+static_assert(!IsAsciiAlpha(u'@'), "u'@' isn't ASCII alpha");
+static_assert(u'@' == 0x40, "u'@' has value 0x40");
+
+static_assert(u'A' == 0x41, "u'A' has value 0x41");
+static_assert(IsAsciiAlpha(u'A'), "u'A' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'B'), "u'B' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'M'), "u'M' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'Y'), "u'Y' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'Z'), "u'Z' is ASCII alpha");
+
+static_assert(u'Z' == 0x5A, "u'Z' has value 0x5A");
+static_assert(u'[' == 0x5B, "u'[' has value 0x5B");
+static_assert(!IsAsciiAlpha(u'['), "u'[' isn't ASCII alpha");
+
+static_assert(!IsAsciiAlpha(u'`'), "u'`' isn't ASCII alpha");
+static_assert(u'`' == 0x60, "u'`' has value 0x60");
+
+static_assert(u'a' == 0x61, "u'a' has value 0x61");
+static_assert(IsAsciiAlpha(u'a'), "u'a' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'b'), "u'b' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'm'), "u'm' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'y'), "u'y' is ASCII alpha");
+static_assert(IsAsciiAlpha(u'z'), "u'z' is ASCII alpha");
+
+static_assert(u'z' == 0x7A, "u'z' has value 0x7A");
+static_assert(u'{' == 0x7B, "u'{' has value 0x7B");
+static_assert(!IsAsciiAlpha(u'{'), "u'{' isn't ASCII alpha");
+
+// char32_t
+
+static_assert(!IsAsciiAlpha(U'@'), "U'@' isn't ASCII alpha");
+static_assert(U'@' == 0x40, "U'@' has value 0x40");
+
+static_assert(U'A' == 0x41, "U'A' has value 0x41");
+static_assert(IsAsciiAlpha(U'A'), "U'A' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'B'), "U'B' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'M'), "U'M' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'Y'), "U'Y' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'Z'), "U'Z' is ASCII alpha");
+
+static_assert(U'Z' == 0x5A, "U'Z' has value 0x5A");
+static_assert(U'[' == 0x5B, "U'[' has value 0x5B");
+static_assert(!IsAsciiAlpha(U'['), "U'[' isn't ASCII alpha");
+
+static_assert(!IsAsciiAlpha(U'`'), "U'`' isn't ASCII alpha");
+static_assert(U'`' == 0x60, "U'`' has value 0x60");
+
+static_assert(U'a' == 0x61, "U'a' has value 0x61");
+static_assert(IsAsciiAlpha(U'a'), "U'a' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'b'), "U'b' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'm'), "U'm' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'y'), "U'y' is ASCII alpha");
+static_assert(IsAsciiAlpha(U'z'), "U'z' is ASCII alpha");
+
+static_assert(U'z' == 0x7A, "U'z' has value 0x7A");
+static_assert(U'{' == 0x7B, "U'{' has value 0x7B");
+static_assert(!IsAsciiAlpha(U'{'), "U'{' isn't ASCII alpha");
+
+int
+main()
+{
+  return 0;
+}
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -46,16 +46,17 @@ CppUnitTests([
     'TestRollingMean',
     'TestSaturate',
     'TestScopeExit',
     'TestSegmentedVector',
     'TestSHA1',
     'TestSmallPointerArray',
     'TestSplayTree',
     'TestTemplateLib',
+    'TestTextUtils',
     'TestThreadSafeWeakPtr',
     'TestTuple',
     'TestTypedEnum',
     'TestTypeTraits',
     'TestUniquePtr',
     'TestVariant',
     'TestVector',
     'TestWeakPtr',