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