1 // Scintilla source code edit control 2 /** @file SubStyles.h 3 ** Manage substyles for a lexer. 4 **/ 5 // Copyright 2012 by Neil Hodgson <[email protected]> 6 // The License.txt file describes the conditions under which this software may be distributed. 7 8 #ifndef SUBSTYLES_H 9 #define SUBSTYLES_H 10 11 namespace Scintilla { 12 13 class WordClassifier { 14 int baseStyle; 15 int firstStyle; 16 int lenStyles; 17 std::map<std::string, int> wordToStyle; 18 19 public: 20 WordClassifier(int baseStyle_)21 explicit WordClassifier(int baseStyle_) : baseStyle(baseStyle_), firstStyle(0), lenStyles(0) { 22 } 23 Allocate(int firstStyle_,int lenStyles_)24 void Allocate(int firstStyle_, int lenStyles_) { 25 firstStyle = firstStyle_; 26 lenStyles = lenStyles_; 27 wordToStyle.clear(); 28 } 29 Base()30 int Base() const noexcept { 31 return baseStyle; 32 } 33 Start()34 int Start() const noexcept { 35 return firstStyle; 36 } 37 Last()38 int Last() const noexcept { 39 return firstStyle + lenStyles - 1; 40 } 41 Length()42 int Length() const noexcept { 43 return lenStyles; 44 } 45 Clear()46 void Clear() noexcept { 47 firstStyle = 0; 48 lenStyles = 0; 49 wordToStyle.clear(); 50 } 51 ValueFor(const std::string & s)52 int ValueFor(const std::string &s) const { 53 std::map<std::string, int>::const_iterator it = wordToStyle.find(s); 54 if (it != wordToStyle.end()) 55 return it->second; 56 else 57 return -1; 58 } 59 IncludesStyle(int style)60 bool IncludesStyle(int style) const noexcept { 61 return (style >= firstStyle) && (style < (firstStyle + lenStyles)); 62 } 63 RemoveStyle(int style)64 void RemoveStyle(int style) { 65 std::map<std::string, int>::iterator it = wordToStyle.begin(); 66 while (it != wordToStyle.end()) { 67 if (it->second == style) { 68 it = wordToStyle.erase(it); 69 } else { 70 ++it; 71 } 72 } 73 } 74 SetIdentifiers(int style,const char * identifiers)75 void SetIdentifiers(int style, const char *identifiers) { 76 RemoveStyle(style); 77 while (*identifiers) { 78 const char *cpSpace = identifiers; 79 while (*cpSpace && !(*cpSpace == ' ' || *cpSpace == '\t' || *cpSpace == '\r' || *cpSpace == '\n')) 80 cpSpace++; 81 if (cpSpace > identifiers) { 82 std::string word(identifiers, cpSpace - identifiers); 83 wordToStyle[word] = style; 84 } 85 identifiers = cpSpace; 86 if (*identifiers) 87 identifiers++; 88 } 89 } 90 }; 91 92 class SubStyles { 93 int classifications; 94 const char *baseStyles; 95 int styleFirst; 96 int stylesAvailable; 97 int secondaryDistance; 98 int allocated; 99 std::vector<WordClassifier> classifiers; 100 BlockFromBaseStyle(int baseStyle)101 int BlockFromBaseStyle(int baseStyle) const noexcept { 102 for (int b=0; b < classifications; b++) { 103 if (baseStyle == baseStyles[b]) 104 return b; 105 } 106 return -1; 107 } 108 BlockFromStyle(int style)109 int BlockFromStyle(int style) const { 110 int b = 0; 111 for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) { 112 if (it->IncludesStyle(style)) 113 return b; 114 b++; 115 } 116 return -1; 117 } 118 119 public: 120 SubStyles(const char * baseStyles_,int styleFirst_,int stylesAvailable_,int secondaryDistance_)121 SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) : 122 classifications(0), 123 baseStyles(baseStyles_), 124 styleFirst(styleFirst_), 125 stylesAvailable(stylesAvailable_), 126 secondaryDistance(secondaryDistance_), 127 allocated(0) { 128 while (baseStyles[classifications]) { 129 classifiers.push_back(WordClassifier(baseStyles[classifications])); 130 classifications++; 131 } 132 } 133 Allocate(int styleBase,int numberStyles)134 int Allocate(int styleBase, int numberStyles) { 135 const int block = BlockFromBaseStyle(styleBase); 136 if (block >= 0) { 137 if ((allocated + numberStyles) > stylesAvailable) 138 return -1; 139 const int startBlock = styleFirst + allocated; 140 allocated += numberStyles; 141 classifiers[block].Allocate(startBlock, numberStyles); 142 return startBlock; 143 } else { 144 return -1; 145 } 146 } 147 Start(int styleBase)148 int Start(int styleBase) noexcept { 149 const int block = BlockFromBaseStyle(styleBase); 150 return (block >= 0) ? classifiers[block].Start() : -1; 151 } 152 Length(int styleBase)153 int Length(int styleBase) noexcept { 154 const int block = BlockFromBaseStyle(styleBase); 155 return (block >= 0) ? classifiers[block].Length() : 0; 156 } 157 BaseStyle(int subStyle)158 int BaseStyle(int subStyle) const { 159 const int block = BlockFromStyle(subStyle); 160 if (block >= 0) 161 return classifiers[block].Base(); 162 else 163 return subStyle; 164 } 165 DistanceToSecondaryStyles()166 int DistanceToSecondaryStyles() const noexcept { 167 return secondaryDistance; 168 } 169 FirstAllocated()170 int FirstAllocated() const { 171 int start = 257; 172 for (std::vector<WordClassifier>::const_iterator it = classifiers.begin(); it != classifiers.end(); ++it) { 173 if (start > it->Start()) 174 start = it->Start(); 175 } 176 return (start < 256) ? start : -1; 177 } 178 LastAllocated()179 int LastAllocated() const { 180 int last = -1; 181 for (std::vector<WordClassifier>::const_iterator it = classifiers.begin(); it != classifiers.end(); ++it) { 182 if (last < it->Last()) 183 last = it->Last(); 184 } 185 return last; 186 } 187 SetIdentifiers(int style,const char * identifiers)188 void SetIdentifiers(int style, const char *identifiers) { 189 const int block = BlockFromStyle(style); 190 if (block >= 0) 191 classifiers[block].SetIdentifiers(style, identifiers); 192 } 193 Free()194 void Free() { 195 allocated = 0; 196 for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it) 197 it->Clear(); 198 } 199 Classifier(int baseStyle)200 const WordClassifier &Classifier(int baseStyle) const noexcept { 201 const int block = BlockFromBaseStyle(baseStyle); 202 return classifiers[block >= 0 ? block : 0]; 203 } 204 }; 205 206 } 207 208 #endif 209