58{
60
62
63
65 int lineNr=1;
66 char c=0;
67 const char *foundOpen=nullptr;
68 std::unordered_map<std::string,BlockMarker> candidates;
69 while ((c=*s))
70 {
71 if (c=='[')
72 {
73 foundOpen=s;
74 }
75 else if (foundOpen && c==']' && foundOpen+1<s)
76 {
77 std::string key(foundOpen+1,s-foundOpen-1);
78 candidates[key].lines.push_back(lineNr);
79 }
80 else if (c=='\n')
81 {
82 foundOpen=nullptr;
83 lineNr++;
84 }
85 s++;
86 }
87
88
89
90
91 for (auto &kv : candidates)
92 {
93 auto &marker = kv.second;
94 if (marker.lines.size()==2 && marker.lines[0]+1<=marker.lines[1]-1)
95 {
96 marker.key = kv.first;
97 int startLine = marker.lines[0];
98 blocks[startLine] = marker;
100 }
101 }
102
103
105 static auto gotoLine = [](const char *startBuf, const char *startPos, int startLine, int targetLine) -> const char *
106 {
107 char cc=0;
108 if (targetLine<startLine)
109 {
110
111 while (startLine>=targetLine && startPos>=startBuf && (cc=*startPos--)) { if (cc=='\n') startLine--; }
112 if (startPos>startBuf)
113 {
114
115
116
117
118
119
120 startPos+=2;
121 }
122
123 }
124 else
125 {
126
127 while (startLine<targetLine && (cc=*startPos++)) { if (cc=='\n') startLine++; }
128
129 }
130 return startPos;
131 };
132 static auto lineIndent = [](const char *&ss, int orgCol) -> int
133 {
135 int col = 0;
136 char cc = 0;
137 while ((cc=*ss++))
138 {
139 if (cc==' ') col++;
140 else if (cc=='\t') col+=tabSize-(col%tabSize);
141 else if (cc=='\n') return orgCol;
142 else
143 {
144
145 while ((cc=*ss++) && cc!='\n');
146 return col;
147 }
148 }
149 return orgCol;
150 };
151 lineNr=1;
152 const char *startBuf = s;
154 {
155 auto &marker = kv.second;
156 s = gotoLine(startBuf,s,lineNr,marker.lines[0]+1);
157 lineNr=marker.lines[1];
158 const char *e = gotoLine(startBuf,s,marker.lines[0]+1,lineNr);
159
160 const char *ss = s;
161 int minIndent=100000;
162 int indent = minIndent;
163 while (ss<e)
164 {
165 indent = lineIndent(ss, indent);
166 if (indent<minIndent)
167 {
168 minIndent=indent;
169 if (minIndent==0) break;
170 }
171 }
172 marker.indent = minIndent;
173
175 marker.key,
176 marker.lines[0]+1,
177 marker.lines[1]-1,
178 marker.indent);
179 s=e;
180 }
181}