Skip to content

Commit 8f17daa

Browse files
committed
optimize gtk console
1 parent 6c4238e commit 8f17daa

File tree

1 file changed

+95
-114
lines changed

1 file changed

+95
-114
lines changed

src/string_utils.cpp

+95-114
Original file line numberDiff line numberDiff line change
@@ -95,67 +95,72 @@ enum ANSI_ESCAPE: ansi_escape_code {
9595
ANSI_BG_WHITE = 47,
9696
};
9797

98+
struct pango_tag {
99+
const char* str;
100+
int len;
101+
};
102+
103+
constexpr int strlen_constexpr(const char* str, int count = 0) {
104+
return (*str == '\0') ? count : strlen_constexpr(str + 1, count + 1);
105+
}
106+
107+
constexpr pango_tag PangoTag(const char* str) {
108+
return { str, strlen_constexpr(str) };
109+
}
110+
111+
constexpr pango_tag FONT_TAGS[] = {
112+
PangoTag("<span foreground='black'>"),
113+
PangoTag("<span foreground='red'>"),
114+
PangoTag("<span foreground='green'>"),
115+
PangoTag("<span foreground='yellow'>"),
116+
PangoTag("<span foreground='blue'>"),
117+
PangoTag("<span foreground='magenta'>"),
118+
PangoTag("<span foreground='cyan'>"),
119+
PangoTag("<span foreground='white'>")
120+
};
121+
122+
constexpr pango_tag BG_TAGS[] = {
123+
PangoTag("<span background='black'>"),
124+
PangoTag("<span background='red'>"),
125+
PangoTag("<span background='green'>"),
126+
PangoTag("<span background='yellow'>"),
127+
PangoTag("<span background='blue'>"),
128+
PangoTag("<span background='magenta'>"),
129+
PangoTag("<span background='cyan'>"),
130+
PangoTag("<span background='white'>")
131+
};
132+
98133
// Get opening markup tag from ANSI escape sequence
99-
static const char* GetOpeningTag(ansi_escape_code code) {
100-
switch (code) {
101-
case ANSI_BOLD:
102-
return "<b>";
103-
case ANSI_ITALIC:
104-
return "<i>";
105-
case ANSI_UNDERLINE:
106-
return "<u>";
107-
case ANSI_STRIKETHROUGH:
108-
return "<s>";
109-
case ANSI_FONT_BLACK:
110-
return "<span foreground='black'>";
111-
case ANSI_FONT_RED:
112-
return "<span foreground='red'>";
113-
case ANSI_FONT_GREEN:
114-
return "<span foreground='green'>";
115-
case ANSI_FONT_YELLOW:
116-
return "<span foreground='yellow'>";
117-
case ANSI_FONT_BLUE:
118-
return "<span foreground='blue'>";
119-
case ANSI_FONT_MAGENTA:
120-
return "<span foreground='magenta'>";
121-
case ANSI_FONT_CYAN:
122-
return "<span foreground='cyan'>";
123-
case ANSI_FONT_WHITE:
124-
return "<span foreground='white'>";
125-
case ANSI_BG_BLACK:
126-
return "<span background='black'>";
127-
case ANSI_BG_RED:
128-
return "<span background='red'>";
129-
case ANSI_BG_GREEN:
130-
return "<span background='green'>";
131-
case ANSI_BG_YELLOW:
132-
return "<span background='yellow'>";
133-
case ANSI_BG_BLUE:
134-
return "<span background='blue'>";
135-
case ANSI_BG_MAGENTA:
136-
return "<span background='magenta'>";
137-
case ANSI_BG_CYAN:
138-
return "<span background='cyan'>";
139-
case ANSI_BG_WHITE:
140-
return "<span background='white'>";
141-
}
142-
return "";
134+
static const pango_tag GetOpeningTag(ansi_escape_code code) {
135+
if (code == ANSI_BOLD)
136+
return PangoTag("<b>");
137+
else if (code == ANSI_ITALIC)
138+
return PangoTag("<i>");
139+
else if (code == ANSI_UNDERLINE)
140+
return PangoTag("<u>");
141+
else if (code == ANSI_STRIKETHROUGH)
142+
return PangoTag("<s>");
143+
else if (ANSI_FONT_BLACK <= code && code <= ANSI_FONT_WHITE)
144+
return FONT_TAGS[code - ANSI_FONT_BLACK];
145+
else if (ANSI_BG_BLACK <= code && code <= ANSI_BG_WHITE)
146+
return BG_TAGS[code - ANSI_BG_BLACK];
147+
return PangoTag("");
143148
}
144149

145150
// Get closing markup tag from ANSI escape sequence
146-
static const char* GetClosingTag(ansi_escape_code code) {
151+
static const pango_tag GetClosingTag(ansi_escape_code code) {
147152
if (code == ANSI_BOLD)
148-
return "</b>";
153+
return PangoTag("</b>");
149154
else if (code == ANSI_ITALIC)
150-
return "</i>";
155+
return PangoTag("</i>");
151156
else if (code == ANSI_UNDERLINE)
152-
return "</u>";
157+
return PangoTag("</u>");
153158
else if (code == ANSI_STRIKETHROUGH)
154-
return "</s>";
159+
return PangoTag("</s>");
155160
else if ((ANSI_FONT_BLACK <= code && code <= ANSI_FONT_WHITE) ||
156161
(ANSI_BG_BLACK <= code && code <= ANSI_BG_WHITE))
157-
return "</span>";
158-
return "";
162+
return PangoTag("</span>");
163+
return PangoTag("");
159164
}
160165

161166
#define MAX_STACK_SIZE 64
@@ -167,7 +172,7 @@ class TagStack {
167172
int m_top;
168173

169174
public:
170-
TagStack() : m_top(-1) {}
175+
TagStack() : m_tags(), m_top(-1) {}
171176

172177
void Push(ansi_escape_code code) {
173178
if (m_top < MAX_STACK_SIZE - 1)
@@ -178,58 +183,44 @@ class TagStack {
178183

179184
void Clear() { m_top = -1; }
180185

181-
// Get length of stacked opening tags
182-
int OpeningTagLength() {
183-
if (m_top < 0)
184-
return 0;
186+
using GetTagFunc = const pango_tag (*)(ansi_escape_code);
187+
188+
// Get length of stacked tags
189+
int GetTagLength(GetTagFunc GetTag) const {
185190
int len = 0;
186-
for (ansi_escape_code* code = m_tags; code < m_tags + Size(); code++) {
187-
const char* closing_tag = GetOpeningTag(*code);
188-
len += strlen(closing_tag);
191+
ansi_escape_code* max_tag = m_tags + m_top;
192+
for (ansi_escape_code* code = m_tags; code <= max_tag; code++) {
193+
len += GetTag(*code).len;
189194
}
190195
return len;
191196
}
192197

193-
// Get length of stacked closing tags
194-
int ClosingTagLength() {
195-
if (m_top < 0)
196-
return 0;
197-
int len = 0;
198-
for (ansi_escape_code* code = m_tags; code < m_tags + Size(); code++) {
199-
const char* closing_tag = GetClosingTag(*code);
200-
len += strlen(closing_tag);
201-
}
202-
return len;
198+
inline int OpeningTagLength() const {
199+
return GetTagLength(GetOpeningTag);
203200
}
204201

205-
// Copy stacked opening tags to char*
206-
int CopyOpeningTag(char* output) {
207-
if (m_top < 0)
208-
return 0;
209-
int len = 0;
210-
for (ansi_escape_code* code = m_tags; code < m_tags + Size(); code++) {
211-
const char *opening_tag = GetOpeningTag(*code);
212-
int opening_tag_len = strlen(opening_tag);
213-
memcpy(output, opening_tag, opening_tag_len);
214-
output += opening_tag_len;
215-
len += opening_tag_len;
216-
}
217-
return len;
202+
inline int ClosingTagLength() const {
203+
return GetTagLength(GetClosingTag);
218204
}
219205

220-
// Copy stacked closing tags to char*
221-
int CopyClosingTag(char* output) {
222-
if (m_top < 0)
223-
return 0;
224-
int len = 0;
225-
for (ansi_escape_code* code = m_tags + m_top; code >= m_tags; code--) {
226-
const char *closing_tag = GetClosingTag(*code);
227-
int closing_tag_len = strlen(closing_tag);
228-
memcpy(output, closing_tag, closing_tag_len);
229-
output += closing_tag_len;
230-
len += closing_tag_len;
206+
// Copy stacked tags to char*
207+
int CopyTag(char* output, GetTagFunc GetTag, bool reverse) const {
208+
char* start = output;
209+
for (int i = 0; i <= m_top; i++) {
210+
int idx = reverse ? m_top - i : i;
211+
const pango_tag opening_tag = GetTag(m_tags[idx]);
212+
memcpy(output, opening_tag.str, opening_tag.len);
213+
output += opening_tag.len;
231214
}
232-
return len;
215+
return static_cast<int>(output - start);
216+
}
217+
218+
inline int CopyOpeningTag(char* output) const {
219+
return CopyTag(output, GetOpeningTag, false);
220+
}
221+
222+
inline int CopyClosingTag(char* output) const {
223+
return CopyTag(output, GetClosingTag, true);
233224
}
234225
};
235226

@@ -256,35 +247,29 @@ int ConvertAnsiToPangoLength(TagStack* stack, const char *input) {
256247
len += closing_tag_len;
257248
closing_tag_len = 0;
258249
} else {
259-
const char *opening_tag = GetOpeningTag(code);
260-
len += strlen(opening_tag);
261-
const char *closing_tag = GetClosingTag(code);
262-
closing_tag_len += strlen(closing_tag);
250+
len += GetOpeningTag(code).len;
251+
closing_tag_len += GetClosingTag(code).len;
263252
}
264253
if (c == 'm')
265254
break;
266255
}
267256
}
257+
continue;
268258
} else if (*p == '&') {
269-
p++;
270259
len += 5; // &amp;
271260
} else if (*p == '<') {
272-
p++;
273261
len += 4; // &lt;
274262
} else if (*p == '>') {
275-
p++;
276263
len += 4; // &gt;
277264
} else if (*p == '\'') {
278-
p++;
279265
len += 6; // &apos;
280266
} else if (*p == '"') {
281-
p++;
282267
len += 6; // &quot;
283268
} else {
284269
// Copy regular characters
285-
p++;
286270
len++;
287271
}
272+
p++;
288273
}
289274

290275
len += closing_tag_len;
@@ -318,40 +303,36 @@ void ConvertAnsiToPango(TagStack* stack, const char *input, char *output) {
318303
q += stack->CopyClosingTag(q);
319304
stack->Clear();
320305
} else {
321-
const char *opening_tag = GetOpeningTag(code);
322-
int opening_tag_len = strlen(opening_tag);
323-
memcpy(q, opening_tag, opening_tag_len);
324-
q += opening_tag_len;
306+
const pango_tag opening_tag = GetOpeningTag(code);
307+
memcpy(q, opening_tag.str, opening_tag.len);
308+
q += opening_tag.len;
325309
stack->Push(code);
326310
}
327311
if (c == 'm')
328312
break;
329313
}
330314
}
315+
continue;
331316
} else if (*p == '&') {
332-
p++;
333317
memcpy(q, "&amp;", 5);
334318
q += 5;
335319
} else if (*p == '<') {
336-
p++;
337320
memcpy(q, "&lt;", 4);
338321
q += 4;
339322
} else if (*p == '>') {
340-
p++;
341323
memcpy(q, "&gt;", 4);
342324
q += 4;
343325
} else if (*p == '\'') {
344-
p++;
345326
memcpy(q, "&apos;", 6);
346327
q += 6;
347328
} else if (*p == '"') {
348-
p++;
349329
memcpy(q, "&quot;", 6);
350330
q += 6;
351331
} else {
352332
// Copy regular characters
353-
*q++ = *p++;
333+
*q++ = *p;
354334
}
335+
p++;
355336
}
356337

357338
// Add closing tags

0 commit comments

Comments
 (0)