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