// Scintilla source code edit control /** @file CharacterSet.h ** Encapsulates a set of characters. Used to test if a character is within a set. **/ // Copyright 2007 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef CHARACTERSET_H #define CHARACTERSET_H namespace Scintilla { class CharacterSet { int size; bool valueAfter; bool *bset; public: enum setBase { setNone=0, setLower=1, setUpper=2, setDigits=4, setAlpha=setLower|setUpper, setAlphaNum=setAlpha|setDigits }; CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) { size = size_; valueAfter = valueAfter_; bset = new bool[size]; for (int i=0; i < size; i++) { bset[i] = false; } AddString(initialSet); if (base & setLower) AddString("abcdefghijklmnopqrstuvwxyz"); if (base & setUpper) AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); if (base & setDigits) AddString("0123456789"); } CharacterSet(const CharacterSet &other) { size = other.size; valueAfter = other.valueAfter; bset = new bool[size]; for (int i=0; i < size; i++) { bset[i] = other.bset[i]; } } CharacterSet &operator=(CharacterSet &&other) { if (this != &other) { delete []bset; size = other.size; valueAfter = other.valueAfter; bset = other.bset; other.size = 0; other.bset = nullptr; } return *this; } ~CharacterSet() { delete []bset; bset = nullptr; size = 0; } CharacterSet &operator=(const CharacterSet &other) { if (this != &other) { bool *bsetNew = new bool[other.size]; for (int i=0; i < other.size; i++) { bsetNew[i] = other.bset[i]; } delete []bset; size = other.size; valueAfter = other.valueAfter; bset = bsetNew; } return *this; } void Add(int val) { assert(val >= 0); assert(val < size); bset[val] = true; } void AddString(const char *setToAdd) { for (const char *cp=setToAdd; *cp; cp++) { int val = static_cast(*cp); assert(val >= 0); assert(val < size); bset[val] = true; } } bool Contains(int val) const { assert(val >= 0); if (val < 0) return false; return (val < size) ? bset[val] : valueAfter; } }; // Functions for classifying characters inline bool IsASpace(int ch) { return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); } inline bool IsASpaceOrTab(int ch) { return (ch == ' ') || (ch == '\t'); } inline bool IsADigit(int ch) { return (ch >= '0') && (ch <= '9'); } inline bool IsADigit(int ch, int base) { if (base <= 10) { return (ch >= '0') && (ch < '0' + base); } else { return ((ch >= '0') && (ch <= '9')) || ((ch >= 'A') && (ch < 'A' + base - 10)) || ((ch >= 'a') && (ch < 'a' + base - 10)); } } inline bool IsASCII(int ch) { return (ch >= 0) && (ch < 0x80); } inline bool IsLowerCase(int ch) { return (ch >= 'a') && (ch <= 'z'); } inline bool IsUpperCase(int ch) { return (ch >= 'A') && (ch <= 'Z'); } inline bool IsAlphaNumeric(int ch) { return ((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')); } /** * Check if a character is a space. * This is ASCII specific but is safe with chars >= 0x80. */ inline bool isspacechar(int ch) { return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); } inline bool iswordchar(int ch) { return IsAlphaNumeric(ch) || ch == '.' || ch == '_'; } inline bool iswordstart(int ch) { return IsAlphaNumeric(ch) || ch == '_'; } inline bool isoperator(int ch) { if (IsAlphaNumeric(ch)) return false; if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || ch == '(' || ch == ')' || ch == '-' || ch == '+' || ch == '=' || ch == '|' || ch == '{' || ch == '}' || ch == '[' || ch == ']' || ch == ':' || ch == ';' || ch == '<' || ch == '>' || ch == ',' || ch == '/' || ch == '?' || ch == '!' || ch == '.' || ch == '~') return true; return false; } // Simple case functions for ASCII supersets. template inline T MakeUpperCase(T ch) { if (ch < 'a' || ch > 'z') return ch; else return ch - 'a' + 'A'; } template inline T MakeLowerCase(T ch) { if (ch < 'A' || ch > 'Z') return ch; else return ch - 'A' + 'a'; } int CompareCaseInsensitive(const char *a, const char *b); int CompareNCaseInsensitive(const char *a, const char *b, size_t len); } #endif