1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef nsASCIIMask_h_
8 #define nsASCIIMask_h_
9
10 #include <array>
11 #include <utility>
12
13 #include "mozilla/Attributes.h"
14
15 typedef std::array<bool, 128> ASCIIMaskArray;
16
17 namespace mozilla {
18
19 // Boolean arrays, fixed size and filled in at compile time, meant to
20 // record something about each of the (standard) ASCII characters.
21 // No extended ASCII for now, there has been no use case.
22 // If you have loops that go through a string character by character
23 // and test for equality to a certain set of characters before deciding
24 // on a course of action, chances are building up one of these arrays
25 // and using it is going to be faster, especially if the set of
26 // characters is more than one long, and known at compile time.
27 class ASCIIMask {
28 public:
29 // Preset masks for some common character groups
30 // When testing, you must check if the index is < 128 or use IsMasked()
31 //
32 // if (someChar < 128 && MaskCRLF()[someChar]) this is \r or \n
33
34 static const ASCIIMaskArray& MaskCRLF();
35 static const ASCIIMaskArray& Mask0to9();
36 static const ASCIIMaskArray& MaskCRLFTab();
37 static const ASCIIMaskArray& MaskWhitespace();
38
IsMasked(const ASCIIMaskArray & aMask,uint32_t aChar)39 static MOZ_ALWAYS_INLINE bool IsMasked(const ASCIIMaskArray& aMask,
40 uint32_t aChar) {
41 return aChar < 128 && aMask[aChar];
42 }
43 };
44
45 // Outside of the preset ones, use these templates to create more masks.
46 //
47 // The example creation will look like this:
48 //
49 // constexpr bool TestABC(char c) { return c == 'A' || c == 'B' || c == 'C'; }
50 // constexpr std::array<bool, 128> sABCMask = CreateASCIIMask(TestABC);
51 // ...
52 // if (someChar < 128 && sABCMask[someChar]) this is A or B or C
53
54 namespace asciimask_details {
55 template <typename F, size_t... Indices>
CreateASCIIMask(F fun,std::index_sequence<Indices...>)56 constexpr std::array<bool, 128> CreateASCIIMask(
57 F fun, std::index_sequence<Indices...>) {
58 return {{fun(Indices)...}};
59 }
60 } // namespace asciimask_details
61
62 template <typename F>
CreateASCIIMask(F fun)63 constexpr std::array<bool, 128> CreateASCIIMask(F fun) {
64 return asciimask_details::CreateASCIIMask(fun,
65 std::make_index_sequence<128>{});
66 }
67
68 } // namespace mozilla
69
70 #endif // nsASCIIMask_h_
71