isCharInSet refactoring.

Summary:
Made UnicodeCharSet a class, perform validity checking inside its
constructor instead of each isCharInSet call, use std::binary_search instead of
own implementation.
This patch comes with a necessary change in clang (sent separately).

Reviewers: jordan_rose, klimek

Reviewed By: klimek

CC: cfe-commits, rsmith

Differential Revision: http://llvm-reviews.chandlerc.com/D1534

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189582 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexander Kornienko 2013-08-29 12:12:13 +00:00
parent 4edfa2278a
commit 2f02ded68a
3 changed files with 76 additions and 72 deletions

View File

@ -80,7 +80,7 @@ namespace llvm {
/// Construct an ArrayRef from a C array.
template <size_t N>
/*implicit*/ ArrayRef(const T (&Arr)[N])
/*implicit*/ LLVM_CONSTEXPR ArrayRef(const T (&Arr)[N])
: Data(Arr), Length(N) {}
/// @}

View File

@ -17,82 +17,83 @@
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/raw_ostream.h"
namespace {
#include <algorithm>
namespace llvm {
namespace sys {
/// \brief Represents a closed range of Unicode code points [Lower, Upper].
struct UnicodeCharRange {
uint32_t Lower;
uint32_t Upper;
};
typedef llvm::ArrayRef<UnicodeCharRange> UnicodeCharSet;
/// Returns true if each of the ranges in \p CharSet is a proper closed range
/// [min, max], and if the ranges themselves are ordered and non-overlapping.
static inline bool isValidCharSet(UnicodeCharSet CharSet) {
#ifndef NDEBUG
static llvm::SmallPtrSet<const UnicodeCharRange *, 16> Validated;
static llvm::sys::Mutex ValidationMutex;
inline bool operator<(uint32_t Value, UnicodeCharRange Range) {
return Value < Range.Lower;
}
inline bool operator<(UnicodeCharRange Range, uint32_t Value) {
return Range.Upper < Value;
}
// Check the validation cache.
{
llvm::MutexGuard Guard(ValidationMutex);
if (Validated.count(CharSet.data()))
return true;
}
/// \brief Holds a reference to an ordered array of UnicodeCharRange and allows
/// to quickly check if a code point is contained in the set represented by this
/// array.
class UnicodeCharSet {
public:
typedef llvm::ArrayRef<UnicodeCharRange> CharRanges;
// Walk through the ranges.
uint32_t Prev = 0;
for (UnicodeCharSet::iterator I = CharSet.begin(), E = CharSet.end();
I != E; ++I) {
if (I != CharSet.begin() && Prev >= I->Lower) {
DEBUG(llvm::dbgs() << "Upper bound 0x");
DEBUG(llvm::dbgs().write_hex(Prev));
DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n");
return false;
}
if (I->Upper < I->Lower) {
DEBUG(llvm::dbgs() << "Upper bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Lower));
DEBUG(llvm::dbgs() << " should not be less than lower bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n");
return false;
}
Prev = I->Upper;
}
// Update the validation cache.
{
llvm::MutexGuard Guard(ValidationMutex);
Validated.insert(CharSet.data());
}
/// \brief Constructs a UnicodeCharSet instance from an array of
/// UnicodeCharRanges.
///
/// Array pointed by \p Ranges should have the lifetime at least as long as
/// the UnicodeCharSet instance, and should not change. Array is validated by
/// the constructor, so it makes sense to create as few UnicodeCharSet
/// instances per each array of ranges, as possible.
#ifdef NDEBUG
LLVM_CONSTEXPR
#endif
return true;
}
} // namespace
/// Returns true if the Unicode code point \p C is within the set of
/// characters specified by \p CharSet.
LLVM_READONLY static inline bool isCharInSet(uint32_t C,
UnicodeCharSet CharSet) {
assert(isValidCharSet(CharSet));
size_t LowPoint = 0;
size_t HighPoint = CharSet.size();
// Binary search the set of char ranges.
while (HighPoint != LowPoint) {
size_t MidPoint = (HighPoint + LowPoint) / 2;
if (C < CharSet[MidPoint].Lower)
HighPoint = MidPoint;
else if (C > CharSet[MidPoint].Upper)
LowPoint = MidPoint + 1;
else
return true;
UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {
assert(rangesAreValid());
}
return false;
}
/// \brief Returns true if the character set contains the Unicode code point
/// \p C.
bool contains(uint32_t C) const {
return std::binary_search(Ranges.begin(), Ranges.end(), C);
}
private:
/// \brief Returns true if each of the ranges is a proper closed range
/// [min, max], and if the ranges themselves are ordered and non-overlapping.
bool rangesAreValid() const {
uint32_t Prev = 0;
for (CharRanges::const_iterator I = Ranges.begin(), E = Ranges.end();
I != E; ++I) {
if (I != Ranges.begin() && Prev >= I->Lower) {
DEBUG(llvm::dbgs() << "Upper bound 0x");
DEBUG(llvm::dbgs().write_hex(Prev));
DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n");
return false;
}
if (I->Upper < I->Lower) {
DEBUG(llvm::dbgs() << "Upper bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Lower));
DEBUG(llvm::dbgs() << " should not be less than lower bound 0x");
DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n");
return false;
}
Prev = I->Upper;
}
return true;
}
const CharRanges Ranges;
};
} // namespace sys
} // namespace llvm
#endif // LLVM_SUPPORT_UNICODECHARRANGES_H

View File

@ -229,8 +229,9 @@ bool isPrint(int UCS) {
{ 0x2B735, 0x2B73F }, { 0x2B81E, 0x2F7FF }, { 0x2FA1E, 0xF0000 },
{ 0xFFFFE, 0xFFFFF }, { 0x10FFFE, 0x10FFFF }
};
static const UnicodeCharSet NonPrintables(NonPrintableRanges);
return UCS >= 0 && UCS <= 0x10FFFF && !isCharInSet(UCS, NonPrintableRanges);
return UCS >= 0 && UCS <= 0x10FFFF && !NonPrintables.contains(UCS);
}
/// Gets the number of positions a character is likely to occupy when output
@ -252,7 +253,7 @@ static inline int charWidth(int UCS)
// Sorted list of non-spacing and enclosing combining mark intervals as
// defined in "3.6 Combination" of
// http://www.unicode.org/versions/Unicode6.2.0/UnicodeStandard-6.2.pdf
static const UnicodeCharRange CombiningCharacters[] = {
static const UnicodeCharRange CombiningCharacterRanges[] = {
{ 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
{ 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
{ 0x05C7, 0x05C7 }, { 0x0610, 0x061A }, { 0x064B, 0x065F },
@ -327,11 +328,12 @@ static inline int charWidth(int UCS)
{ 0x1D17B, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
{ 0x1D242, 0x1D244 }, { 0xE0100, 0xE01EF },
};
static const UnicodeCharSet CombiningCharacters(CombiningCharacterRanges);
if (isCharInSet(UCS, CombiningCharacters))
if (CombiningCharacters.contains(UCS))
return 0;
static const UnicodeCharRange DoubleWidthCharacters[] = {
static const UnicodeCharRange DoubleWidthCharacterRanges[] = {
// Hangul Jamo
{ 0x1100, 0x11FF },
// Deprecated fullwidth angle brackets
@ -352,8 +354,9 @@ static inline int charWidth(int UCS)
// CJK Unified Ideographs
{ 0x20000, 0x2A6DF }, { 0x2A700, 0x2B81F }, { 0x2F800, 0x2FA1F }
};
static const UnicodeCharSet DoubleWidthCharacters(DoubleWidthCharacterRanges);
if (isCharInSet(UCS, DoubleWidthCharacters))
if (DoubleWidthCharacters.contains(UCS))
return 2;
return 1;
}