4a4d9887433cc9f4ae1314d80a3484bcd66d4a5c
[oota-llvm.git] / include / llvm / Support / UnicodeCharRanges.h
1 //===--- UnicodeCharRanges.h - Types and functions for character ranges ---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_SUPPORT_UNICODECHARRANGES_H
10 #define LLVM_SUPPORT_UNICODECHARRANGES_H
11
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/SmallPtrSet.h"
14 #include "llvm/Support/Compiler.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Mutex.h"
17 #include "llvm/Support/MutexGuard.h"
18 #include "llvm/Support/raw_ostream.h"
19
20 namespace {
21
22 struct UnicodeCharRange {
23   uint32_t Lower;
24   uint32_t Upper;
25 };
26 typedef llvm::ArrayRef<UnicodeCharRange> UnicodeCharSet;
27
28 /// Returns true if each of the ranges in \p CharSet is a proper closed range
29 /// [min, max], and if the ranges themselves are ordered and non-overlapping.
30 static inline bool isValidCharSet(UnicodeCharSet CharSet) {
31 #ifndef NDEBUG
32   static llvm::SmallPtrSet<const UnicodeCharRange *, 16> Validated;
33   static llvm::sys::Mutex ValidationMutex;
34
35   // Check the validation cache.
36   {
37     llvm::MutexGuard Guard(ValidationMutex);
38     if (Validated.count(CharSet.data()))
39       return true;
40   }
41
42   // Walk through the ranges.
43   uint32_t Prev = 0;
44   for (UnicodeCharSet::iterator I = CharSet.begin(), E = CharSet.end();
45        I != E; ++I) {
46     if (I != CharSet.begin() && Prev >= I->Lower) {
47       DEBUG(llvm::dbgs() << "Upper bound 0x");
48       DEBUG(llvm::dbgs().write_hex(Prev));
49       DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x");
50       DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n");
51       return false;
52     }
53     if (I->Upper < I->Lower) {
54       DEBUG(llvm::dbgs() << "Upper bound 0x");
55       DEBUG(llvm::dbgs().write_hex(I->Lower));
56       DEBUG(llvm::dbgs() << " should not be less than lower bound 0x");
57       DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n");
58       return false;
59     }
60     Prev = I->Upper;
61   }
62
63   // Update the validation cache.
64   {
65     llvm::MutexGuard Guard(ValidationMutex);
66     Validated.insert(CharSet.data());
67   }
68 #endif
69   return true;
70 }
71
72 } // namespace
73
74
75 /// Returns true if the Unicode code point \p C is within the set of
76 /// characters specified by \p CharSet.
77 LLVM_READONLY static inline bool isCharInSet(uint32_t C,
78                                              UnicodeCharSet CharSet) {
79   assert(isValidCharSet(CharSet));
80
81   size_t LowPoint = 0;
82   size_t HighPoint = CharSet.size();
83
84   // Binary search the set of char ranges.
85   while (HighPoint != LowPoint) {
86     size_t MidPoint = (HighPoint + LowPoint) / 2;
87     if (C < CharSet[MidPoint].Lower)
88       HighPoint = MidPoint;
89     else if (C > CharSet[MidPoint].Upper)
90       LowPoint = MidPoint + 1;
91     else
92       return true;
93   }
94
95   return false;
96 }
97
98 #endif // LLVM_SUPPORT_UNICODECHARRANGES_H