1 // ASResource.cpp
2 // Copyright (c) 2017 by Jim Pattee <jimp03@email.com>.
3 // This code is licensed under the MIT License.
4 // License.md describes the conditions under which this software may be distributed.
5
6 //-----------------------------------------------------------------------------
7 // headers
8 //-----------------------------------------------------------------------------
9
10 #include "astyle.h"
11 #include <algorithm>
12
13 //-----------------------------------------------------------------------------
14 // astyle namespace
15 //-----------------------------------------------------------------------------
16
17 namespace astyle {
18 //
19 const string ASResource::_AS_EXCEPT = string("__except");
20 const string ASResource::_AS_FINALLY = string("__finally");
21 const string ASResource::_AS_TRY = string("__try");
22 const string ASResource::AS_ADD = string("add");
23 const string ASResource::AS_AUTO = string("auto");
24 const string ASResource::AS_AUTORELEASEPOOL = string("autoreleasepool");
25 const string ASResource::AS_CASE = string("case");
26 const string ASResource::AS_CATCH = string("catch");
27 const string ASResource::AS_CLASS = string("class");
28 const string ASResource::AS_CONST = string("const");
29 const string ASResource::AS_CONST_CAST = string("const_cast");
30 const string ASResource::AS_DEFAULT = string("default");
31 const string ASResource::AS_DELEGATE = string("delegate");
32 const string ASResource::AS_DELETE = string("delete");
33 const string ASResource::AS_DO = string("do");
34 const string ASResource::AS_DYNAMIC_CAST = string("dynamic_cast");
35 const string ASResource::AS_ELSE = string("else");
36 const string ASResource::AS_END = string("end");
37 const string ASResource::AS_ENUM = string("enum");
38 const string ASResource::AS_EXTERN = string("extern");
39 const string ASResource::AS_FINAL = string("final");
40 const string ASResource::AS_FINALLY = string("finally");
41 const string ASResource::AS_FIXED = string("fixed");
42 const string ASResource::AS_FOR = string("for");
43 const string ASResource::AS_FOREACH = string("foreach");
44 const string ASResource::AS_FOREVER = string("forever");
45 const string ASResource::AS_GET = string("get");
46 const string ASResource::AS_IF = string("if");
47 const string ASResource::AS_INTERFACE = string("interface");
48 const string ASResource::AS_INTERRUPT = string("interrupt");
49 const string ASResource::AS_LET = string("let");
50 const string ASResource::AS_LOCK = string("lock");
51 const string ASResource::AS_MODULE = string("module"); // CORBA IDL module definition
52 const string ASResource::AS_NAMESPACE = string("namespace");
53 const string ASResource::AS_NEW = string("new");
54 const string ASResource::AS_NOEXCEPT = string("noexcept");
55 const string ASResource::AS_NS_DURING = string("NS_DURING");
56 const string ASResource::AS_NS_HANDLER = string("NS_HANDLER");
57 const string ASResource::AS_OPERATOR = string("operator");
58 const string ASResource::AS_OVERRIDE = string("override");
59 const string ASResource::AS_PRIVATE = string("private");
60 const string ASResource::AS_PROTECTED = string("protected");
61 const string ASResource::AS_PUBLIC = string("public");
62 const string ASResource::AS_QFOREACH = string("Q_FOREACH");
63 const string ASResource::AS_QFOREVER = string("Q_FOREVER");
64 const string ASResource::AS_REINTERPRET_CAST = string("reinterpret_cast");
65 const string ASResource::AS_REMOVE = string("remove");
66 const string ASResource::AS_SEALED = string("sealed");
67 const string ASResource::AS_SELECTOR = string("selector");
68 const string ASResource::AS_SET = string("set");
69 const string ASResource::AS_STATIC = string("static");
70 const string ASResource::AS_STATIC_CAST = string("static_cast");
71 const string ASResource::AS_STRUCT = string("struct");
72 const string ASResource::AS_SWITCH = string("switch");
73 const string ASResource::AS_SYNCHRONIZED = string("synchronized");
74 const string ASResource::AS_TEMPLATE = string("template");
75 const string ASResource::AS_THROW = string("throw");
76 const string ASResource::AS_THROWS = string("throws");
77 const string ASResource::AS_TRY = string("try");
78 const string ASResource::AS_UNCHECKED = string("unchecked");
79 const string ASResource::AS_UNION = string("union");
80 const string ASResource::AS_UNSAFE = string("unsafe");
81 const string ASResource::AS_USING = string("using");
82 const string ASResource::AS_VOLATILE = string("volatile");
83 const string ASResource::AS_WHERE = string("where");
84 const string ASResource::AS_WHILE = string("while");
85
86 const string ASResource::AS_ASM = string("asm");
87 const string ASResource::AS__ASM__ = string("__asm__");
88 const string ASResource::AS_MS_ASM = string("_asm");
89 const string ASResource::AS_MS__ASM = string("__asm");
90
91 const string ASResource::AS_BAR_DEFINE = string("#define");
92 const string ASResource::AS_BAR_INCLUDE = string("#include");
93 const string ASResource::AS_BAR_IF = string("#if");
94 const string ASResource::AS_BAR_EL = string("#el");
95 const string ASResource::AS_BAR_ENDIF = string("#endif");
96
97 const string ASResource::AS_OPEN_BRACE = string("{");
98 const string ASResource::AS_CLOSE_BRACE = string("}");
99 const string ASResource::AS_OPEN_LINE_COMMENT = string("//");
100 const string ASResource::AS_OPEN_COMMENT = string("/*");
101 const string ASResource::AS_CLOSE_COMMENT = string("*/");
102
103 const string ASResource::AS_ASSIGN = string("=");
104 const string ASResource::AS_PLUS_ASSIGN = string("+=");
105 const string ASResource::AS_MINUS_ASSIGN = string("-=");
106 const string ASResource::AS_MULT_ASSIGN = string("*=");
107 const string ASResource::AS_DIV_ASSIGN = string("/=");
108 const string ASResource::AS_MOD_ASSIGN = string("%=");
109 const string ASResource::AS_OR_ASSIGN = string("|=");
110 const string ASResource::AS_AND_ASSIGN = string("&=");
111 const string ASResource::AS_XOR_ASSIGN = string("^=");
112 const string ASResource::AS_GR_GR_ASSIGN = string(">>=");
113 const string ASResource::AS_LS_LS_ASSIGN = string("<<=");
114 const string ASResource::AS_GR_GR_GR_ASSIGN = string(">>>=");
115 const string ASResource::AS_LS_LS_LS_ASSIGN = string("<<<=");
116 const string ASResource::AS_GCC_MIN_ASSIGN = string("<?");
117 const string ASResource::AS_GCC_MAX_ASSIGN = string(">?");
118
119 const string ASResource::AS_RETURN = string("return");
120 const string ASResource::AS_CIN = string("cin");
121 const string ASResource::AS_COUT = string("cout");
122 const string ASResource::AS_CERR = string("cerr");
123
124 const string ASResource::AS_EQUAL = string("==");
125 const string ASResource::AS_PLUS_PLUS = string("++");
126 const string ASResource::AS_MINUS_MINUS = string("--");
127 const string ASResource::AS_NOT_EQUAL = string("!=");
128 const string ASResource::AS_GR_EQUAL = string(">=");
129 const string ASResource::AS_GR_GR = string(">>");
130 const string ASResource::AS_GR_GR_GR = string(">>>");
131 const string ASResource::AS_LS_EQUAL = string("<=");
132 const string ASResource::AS_LS_LS = string("<<");
133 const string ASResource::AS_LS_LS_LS = string("<<<");
134 const string ASResource::AS_QUESTION_QUESTION = string("??");
135 const string ASResource::AS_LAMBDA = string("=>"); // C# lambda expression arrow
136 const string ASResource::AS_ARROW = string("->");
137 const string ASResource::AS_AND = string("&&");
138 const string ASResource::AS_OR = string("||");
139 const string ASResource::AS_SCOPE_RESOLUTION = string("::");
140
141 const string ASResource::AS_PLUS = string("+");
142 const string ASResource::AS_MINUS = string("-");
143 const string ASResource::AS_MULT = string("*");
144 const string ASResource::AS_DIV = string("/");
145 const string ASResource::AS_MOD = string("%");
146 const string ASResource::AS_GR = string(">");
147 const string ASResource::AS_LS = string("<");
148 const string ASResource::AS_NOT = string("!");
149 const string ASResource::AS_BIT_OR = string("|");
150 const string ASResource::AS_BIT_AND = string("&");
151 const string ASResource::AS_BIT_NOT = string("~");
152 const string ASResource::AS_BIT_XOR = string("^");
153 const string ASResource::AS_QUESTION = string("?");
154 const string ASResource::AS_COLON = string(":");
155 const string ASResource::AS_COMMA = string(",");
156 const string ASResource::AS_SEMICOLON = string(";");
157
158 /**
159 * Sort comparison function.
160 * Compares the length of the value of pointers in the vectors.
161 * The LONGEST strings will be first in the vector.
162 *
163 * @param a and b, the string pointers to be compared.
164 */
sortOnLength(const string * a,const string * b)165 bool sortOnLength(const string* a, const string* b)
166 {
167 return (*a).length() > (*b).length();
168 }
169
170 /**
171 * Sort comparison function.
172 * Compares the value of pointers in the vectors.
173 *
174 * @param a and b, the string pointers to be compared.
175 */
sortOnName(const string * a,const string * b)176 bool sortOnName(const string* a, const string* b)
177 {
178 return *a < *b;
179 }
180
181 /**
182 * Build the vector of assignment operators.
183 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
184 *
185 * @param assignmentOperators a reference to the vector to be built.
186 */
buildAssignmentOperators(vector<const string * > * assignmentOperators)187 void ASResource::buildAssignmentOperators(vector<const string*>* assignmentOperators)
188 {
189 const size_t elements = 15;
190 static bool reserved = false;
191 if (!reserved)
192 {
193 assignmentOperators->reserve(elements);
194 reserved = true;
195 }
196
197 assignmentOperators->emplace_back(&AS_ASSIGN);
198 assignmentOperators->emplace_back(&AS_PLUS_ASSIGN);
199 assignmentOperators->emplace_back(&AS_MINUS_ASSIGN);
200 assignmentOperators->emplace_back(&AS_MULT_ASSIGN);
201 assignmentOperators->emplace_back(&AS_DIV_ASSIGN);
202 assignmentOperators->emplace_back(&AS_MOD_ASSIGN);
203 assignmentOperators->emplace_back(&AS_OR_ASSIGN);
204 assignmentOperators->emplace_back(&AS_AND_ASSIGN);
205 assignmentOperators->emplace_back(&AS_XOR_ASSIGN);
206
207 // Java
208 assignmentOperators->emplace_back(&AS_GR_GR_GR_ASSIGN);
209 assignmentOperators->emplace_back(&AS_GR_GR_ASSIGN);
210 assignmentOperators->emplace_back(&AS_LS_LS_ASSIGN);
211
212 // Unknown
213 assignmentOperators->emplace_back(&AS_LS_LS_LS_ASSIGN);
214
215 assert(assignmentOperators->size() < elements);
216 sort(assignmentOperators->begin(), assignmentOperators->end(), sortOnLength);
217 }
218
219 /**
220 * Build the vector of C++ cast operators.
221 * Used by ONLY ASFormatter.cpp
222 *
223 * @param castOperators a reference to the vector to be built.
224 */
buildCastOperators(vector<const string * > * castOperators)225 void ASResource::buildCastOperators(vector<const string*>* castOperators)
226 {
227 const size_t elements = 5;
228 static bool reserved = false;
229 if (!reserved)
230 {
231 castOperators->reserve(elements);
232 reserved = true;
233 }
234
235 castOperators->emplace_back(&AS_CONST_CAST);
236 castOperators->emplace_back(&AS_DYNAMIC_CAST);
237 castOperators->emplace_back(&AS_REINTERPRET_CAST);
238 castOperators->emplace_back(&AS_STATIC_CAST);
239
240 assert(castOperators->size() < elements);
241 sort(castOperators->begin(), castOperators->end(), sortOnName);
242 }
243
244 /**
245 * Build the vector of header words.
246 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp
247 *
248 * @param headers a reference to the vector to be built.
249 */
buildHeaders(vector<const string * > * headers,int fileType,bool beautifier)250 void ASResource::buildHeaders(vector<const string*>* headers, int fileType, bool beautifier)
251 {
252 const size_t elements = 25;
253 static bool reserved = false;
254 if (!reserved)
255 {
256 headers->reserve(elements);
257 reserved = true;
258 }
259
260 headers->emplace_back(&AS_IF);
261 headers->emplace_back(&AS_ELSE);
262 headers->emplace_back(&AS_FOR);
263 headers->emplace_back(&AS_WHILE);
264 headers->emplace_back(&AS_DO);
265 headers->emplace_back(&AS_SWITCH);
266 headers->emplace_back(&AS_CASE);
267 headers->emplace_back(&AS_DEFAULT);
268 headers->emplace_back(&AS_TRY);
269 headers->emplace_back(&AS_CATCH);
270 headers->emplace_back(&AS_QFOREACH); // QT
271 headers->emplace_back(&AS_QFOREVER); // QT
272 headers->emplace_back(&AS_FOREACH); // QT & C#
273 headers->emplace_back(&AS_FOREVER); // Qt & Boost
274
275 if (fileType == C_TYPE)
276 {
277 headers->emplace_back(&_AS_TRY); // __try
278 headers->emplace_back(&_AS_FINALLY); // __finally
279 headers->emplace_back(&_AS_EXCEPT); // __except
280 }
281 if (fileType == JAVA_TYPE)
282 {
283 headers->emplace_back(&AS_FINALLY);
284 headers->emplace_back(&AS_SYNCHRONIZED);
285 }
286
287 if (fileType == SHARP_TYPE)
288 {
289 headers->emplace_back(&AS_FINALLY);
290 headers->emplace_back(&AS_LOCK);
291 headers->emplace_back(&AS_FIXED);
292 headers->emplace_back(&AS_GET);
293 headers->emplace_back(&AS_SET);
294 headers->emplace_back(&AS_ADD);
295 headers->emplace_back(&AS_REMOVE);
296 headers->emplace_back(&AS_USING);
297 }
298
299 if (beautifier)
300 {
301 if (fileType == C_TYPE)
302 {
303 headers->emplace_back(&AS_TEMPLATE);
304 }
305
306 if (fileType == JAVA_TYPE)
307 {
308 headers->emplace_back(&AS_STATIC); // for static constructor
309 }
310 }
311
312 assert(headers->size() < elements);
313 sort(headers->begin(), headers->end(), sortOnName);
314 }
315
316 /**
317 * Build the vector of indentable headers.
318 * Used by ONLY ASBeautifier.cpp
319 *
320 * @param indentableHeaders a reference to the vector to be built.
321 */
buildIndentableHeaders(vector<const string * > * indentableHeaders)322 void ASResource::buildIndentableHeaders(vector<const string*>* indentableHeaders)
323 {
324 indentableHeaders->emplace_back(&AS_RETURN);
325
326 // sort(indentableHeaders->begin(), indentableHeaders->end(), sortOnName);
327 }
328
329 /**
330 * Build the vector of indentable macros pairs.
331 * Initialized by ASFormatter, used by ONLY ASEnhancer.cpp
332 *
333 * @param indentableMacros a reference to the vector to be built.
334 */
buildIndentableMacros(vector<const pair<const string,const string> * > * indentableMacros)335 void ASResource::buildIndentableMacros(vector<const pair<const string, const string>* >* indentableMacros)
336 {
337 const size_t elements = 10;
338 static bool reserved = false;
339 if (!reserved)
340 {
341 indentableMacros->reserve(elements);
342 reserved = true;
343 }
344
345 // the pairs must be retained in memory because of pair pointers
346 typedef pair<const string, const string> macro_pair;
347 static const macro_pair macros[] =
348 {
349 // wxWidgets
350 macro_pair("BEGIN_EVENT_TABLE", "END_EVENT_TABLE"),
351 macro_pair("wxBEGIN_EVENT_TABLE", "wxEND_EVENT_TABLE"),
352 // MFC
353 macro_pair("BEGIN_DISPATCH_MAP", "END_DISPATCH_MAP"),
354 macro_pair("BEGIN_EVENT_MAP", "END_EVENT_MAP"),
355 macro_pair("BEGIN_MESSAGE_MAP", "END_MESSAGE_MAP"),
356 macro_pair("BEGIN_PROPPAGEIDS", "END_PROPPAGEIDS"),
357 };
358
359 size_t entries = sizeof(macros) / sizeof(macros[0]);
360 for (size_t i = 0; i < entries; i++)
361 indentableMacros->emplace_back(¯os[i]);
362
363 assert(indentableMacros->size() < elements);
364 }
365
366 /**
367 * Build the vector of non-assignment operators.
368 * Used by ONLY ASBeautifier.cpp
369 *
370 * @param nonAssignmentOperators a reference to the vector to be built.
371 */
buildNonAssignmentOperators(vector<const string * > * nonAssignmentOperators)372 void ASResource::buildNonAssignmentOperators(vector<const string*>* nonAssignmentOperators)
373 {
374 const size_t elements = 15;
375 static bool reserved = false;
376 if (!reserved)
377 {
378 nonAssignmentOperators->reserve(elements);
379 reserved = true;
380 }
381
382 nonAssignmentOperators->emplace_back(&AS_EQUAL);
383 nonAssignmentOperators->emplace_back(&AS_PLUS_PLUS);
384 nonAssignmentOperators->emplace_back(&AS_MINUS_MINUS);
385 nonAssignmentOperators->emplace_back(&AS_NOT_EQUAL);
386 nonAssignmentOperators->emplace_back(&AS_GR_EQUAL);
387 nonAssignmentOperators->emplace_back(&AS_GR_GR_GR);
388 nonAssignmentOperators->emplace_back(&AS_GR_GR);
389 nonAssignmentOperators->emplace_back(&AS_LS_EQUAL);
390 nonAssignmentOperators->emplace_back(&AS_LS_LS_LS);
391 nonAssignmentOperators->emplace_back(&AS_LS_LS);
392 nonAssignmentOperators->emplace_back(&AS_ARROW);
393 nonAssignmentOperators->emplace_back(&AS_AND);
394 nonAssignmentOperators->emplace_back(&AS_OR);
395 nonAssignmentOperators->emplace_back(&AS_LAMBDA);
396
397 assert(nonAssignmentOperators->size() < elements);
398 sort(nonAssignmentOperators->begin(), nonAssignmentOperators->end(), sortOnLength);
399 }
400
401 /**
402 * Build the vector of header non-paren headers.
403 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
404 * NOTE: Non-paren headers should also be included in the headers vector.
405 *
406 * @param nonParenHeaders a reference to the vector to be built.
407 */
buildNonParenHeaders(vector<const string * > * nonParenHeaders,int fileType,bool beautifier)408 void ASResource::buildNonParenHeaders(vector<const string*>* nonParenHeaders, int fileType, bool beautifier)
409 {
410 const size_t elements = 20;
411 static bool reserved = false;
412 if (!reserved)
413 {
414 nonParenHeaders->reserve(elements);
415 reserved = true;
416 }
417
418 nonParenHeaders->emplace_back(&AS_ELSE);
419 nonParenHeaders->emplace_back(&AS_DO);
420 nonParenHeaders->emplace_back(&AS_TRY);
421 nonParenHeaders->emplace_back(&AS_CATCH); // can be paren or non-paren
422 nonParenHeaders->emplace_back(&AS_CASE); // can be paren or non-paren
423 nonParenHeaders->emplace_back(&AS_DEFAULT);
424 nonParenHeaders->emplace_back(&AS_QFOREVER); // QT
425 nonParenHeaders->emplace_back(&AS_FOREVER); // Boost
426
427 if (fileType == C_TYPE)
428 {
429 nonParenHeaders->emplace_back(&_AS_TRY); // __try
430 nonParenHeaders->emplace_back(&_AS_FINALLY); // __finally
431 }
432 if (fileType == JAVA_TYPE)
433 {
434 nonParenHeaders->emplace_back(&AS_FINALLY);
435 }
436
437 if (fileType == SHARP_TYPE)
438 {
439 nonParenHeaders->emplace_back(&AS_FINALLY);
440 nonParenHeaders->emplace_back(&AS_GET);
441 nonParenHeaders->emplace_back(&AS_SET);
442 nonParenHeaders->emplace_back(&AS_ADD);
443 nonParenHeaders->emplace_back(&AS_REMOVE);
444 }
445
446 if (beautifier)
447 {
448 if (fileType == C_TYPE)
449 {
450 nonParenHeaders->emplace_back(&AS_TEMPLATE);
451 }
452 if (fileType == JAVA_TYPE)
453 {
454 nonParenHeaders->emplace_back(&AS_STATIC);
455 }
456 }
457
458 assert(nonParenHeaders->size() < elements);
459 sort(nonParenHeaders->begin(), nonParenHeaders->end(), sortOnName);
460 }
461
462 /**
463 * Build the vector of operators.
464 * Used by ONLY ASFormatter.cpp
465 *
466 * @param operators a reference to the vector to be built.
467 */
buildOperators(vector<const string * > * operators,int fileType)468 void ASResource::buildOperators(vector<const string*>* operators, int fileType)
469 {
470 const size_t elements = 50;
471 static bool reserved = false;
472 if (!reserved)
473 {
474 operators->reserve(elements);
475 reserved = true;
476 }
477
478
479 operators->emplace_back(&AS_PLUS_ASSIGN);
480 operators->emplace_back(&AS_MINUS_ASSIGN);
481 operators->emplace_back(&AS_MULT_ASSIGN);
482 operators->emplace_back(&AS_DIV_ASSIGN);
483 operators->emplace_back(&AS_MOD_ASSIGN);
484 operators->emplace_back(&AS_OR_ASSIGN);
485 operators->emplace_back(&AS_AND_ASSIGN);
486 operators->emplace_back(&AS_XOR_ASSIGN);
487 operators->emplace_back(&AS_EQUAL);
488 operators->emplace_back(&AS_PLUS_PLUS);
489 operators->emplace_back(&AS_MINUS_MINUS);
490 operators->emplace_back(&AS_NOT_EQUAL);
491 operators->emplace_back(&AS_GR_EQUAL);
492 operators->emplace_back(&AS_GR_GR_GR_ASSIGN);
493 operators->emplace_back(&AS_GR_GR_ASSIGN);
494 operators->emplace_back(&AS_GR_GR_GR);
495 operators->emplace_back(&AS_GR_GR);
496 operators->emplace_back(&AS_LS_EQUAL);
497 operators->emplace_back(&AS_LS_LS_LS_ASSIGN);
498 operators->emplace_back(&AS_LS_LS_ASSIGN);
499 operators->emplace_back(&AS_LS_LS_LS);
500 operators->emplace_back(&AS_LS_LS);
501 operators->emplace_back(&AS_QUESTION_QUESTION);
502 operators->emplace_back(&AS_LAMBDA);
503 operators->emplace_back(&AS_ARROW);
504 operators->emplace_back(&AS_AND);
505 operators->emplace_back(&AS_OR);
506 operators->emplace_back(&AS_SCOPE_RESOLUTION);
507 operators->emplace_back(&AS_PLUS);
508 operators->emplace_back(&AS_MINUS);
509 operators->emplace_back(&AS_MULT);
510 operators->emplace_back(&AS_DIV);
511 operators->emplace_back(&AS_MOD);
512 operators->emplace_back(&AS_QUESTION);
513 operators->emplace_back(&AS_COLON);
514 operators->emplace_back(&AS_ASSIGN);
515 operators->emplace_back(&AS_LS);
516 operators->emplace_back(&AS_GR);
517 operators->emplace_back(&AS_NOT);
518 operators->emplace_back(&AS_BIT_OR);
519 operators->emplace_back(&AS_BIT_AND);
520 operators->emplace_back(&AS_BIT_NOT);
521 operators->emplace_back(&AS_BIT_XOR);
522 if (fileType == C_TYPE)
523 {
524 operators->emplace_back(&AS_GCC_MIN_ASSIGN);
525 operators->emplace_back(&AS_GCC_MAX_ASSIGN);
526 }
527
528 assert(operators->size() < elements);
529 sort(operators->begin(), operators->end(), sortOnLength);
530 }
531
532 /**
533 * Build the vector of pre-block statements.
534 * Used by ONLY ASBeautifier.cpp
535 * NOTE: Cannot be both a header and a preBlockStatement.
536 *
537 * @param preBlockStatements a reference to the vector to be built.
538 */
buildPreBlockStatements(vector<const string * > * preBlockStatements,int fileType)539 void ASResource::buildPreBlockStatements(vector<const string*>* preBlockStatements, int fileType)
540 {
541 const size_t elements = 10;
542 static bool reserved = false;
543 if (!reserved)
544 {
545 preBlockStatements->reserve(elements);
546 reserved = true;
547 }
548
549 preBlockStatements->emplace_back(&AS_CLASS);
550 if (fileType == C_TYPE)
551 {
552 preBlockStatements->emplace_back(&AS_STRUCT);
553 preBlockStatements->emplace_back(&AS_UNION);
554 preBlockStatements->emplace_back(&AS_NAMESPACE);
555 preBlockStatements->emplace_back(&AS_MODULE); // for CORBA IDL
556 preBlockStatements->emplace_back(&AS_INTERFACE); // for CORBA IDL
557 }
558 if (fileType == JAVA_TYPE)
559 {
560 preBlockStatements->emplace_back(&AS_INTERFACE);
561 preBlockStatements->emplace_back(&AS_THROWS);
562 }
563 if (fileType == SHARP_TYPE)
564 {
565 preBlockStatements->emplace_back(&AS_INTERFACE);
566 preBlockStatements->emplace_back(&AS_NAMESPACE);
567 preBlockStatements->emplace_back(&AS_WHERE);
568 preBlockStatements->emplace_back(&AS_STRUCT);
569 }
570
571 assert(preBlockStatements->size() < elements);
572 sort(preBlockStatements->begin(), preBlockStatements->end(), sortOnName);
573 }
574
575 /**
576 * Build the vector of pre-command headers.
577 * Used by BOTH ASFormatter.cpp and ASBeautifier.cpp.
578 * NOTE: Cannot be both a header and a preCommandHeader.
579 *
580 * A preCommandHeader is in a function definition between
581 * the closing paren and the opening brace.
582 * e.g. in "void foo() const {}", "const" is a preCommandHeader.
583 */
buildPreCommandHeaders(vector<const string * > * preCommandHeaders,int fileType)584 void ASResource::buildPreCommandHeaders(vector<const string*>* preCommandHeaders, int fileType)
585 {
586 const size_t elements = 10;
587 static bool reserved = false;
588 if (!reserved)
589 {
590 preCommandHeaders->reserve(elements);
591 reserved = true;
592 }
593
594 if (fileType == C_TYPE)
595 {
596 preCommandHeaders->emplace_back(&AS_CONST);
597 preCommandHeaders->emplace_back(&AS_FINAL);
598 preCommandHeaders->emplace_back(&AS_INTERRUPT);
599 preCommandHeaders->emplace_back(&AS_NOEXCEPT);
600 preCommandHeaders->emplace_back(&AS_OVERRIDE);
601 preCommandHeaders->emplace_back(&AS_VOLATILE);
602 preCommandHeaders->emplace_back(&AS_SEALED); // Visual C only
603 preCommandHeaders->emplace_back(&AS_AUTORELEASEPOOL); // Obj-C only
604 }
605
606 if (fileType == JAVA_TYPE)
607 {
608 preCommandHeaders->emplace_back(&AS_THROWS);
609 }
610
611 if (fileType == SHARP_TYPE)
612 {
613 preCommandHeaders->emplace_back(&AS_WHERE);
614 }
615
616 assert(preCommandHeaders->size() < elements);
617 sort(preCommandHeaders->begin(), preCommandHeaders->end(), sortOnName);
618 }
619
620 /**
621 * Build the vector of pre-definition headers.
622 * Used by ONLY ASFormatter.cpp
623 * NOTE: Do NOT add 'enum' here. It is an array type brace.
624 * NOTE: Do NOT add 'extern' here. Do not want an extra indent.
625 *
626 * @param preDefinitionHeaders a reference to the vector to be built.
627 */
buildPreDefinitionHeaders(vector<const string * > * preDefinitionHeaders,int fileType)628 void ASResource::buildPreDefinitionHeaders(vector<const string*>* preDefinitionHeaders, int fileType)
629 {
630 const size_t elements = 10;
631 static bool reserved = false;
632 if (!reserved)
633 {
634 preDefinitionHeaders->reserve(elements);
635 reserved = true;
636 }
637
638 preDefinitionHeaders->emplace_back(&AS_CLASS);
639 if (fileType == C_TYPE)
640 {
641 preDefinitionHeaders->emplace_back(&AS_STRUCT);
642 preDefinitionHeaders->emplace_back(&AS_UNION);
643 preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
644 preDefinitionHeaders->emplace_back(&AS_MODULE); // for CORBA IDL
645 preDefinitionHeaders->emplace_back(&AS_INTERFACE); // for CORBA IDL
646 }
647 if (fileType == JAVA_TYPE)
648 {
649 preDefinitionHeaders->emplace_back(&AS_INTERFACE);
650 }
651 if (fileType == SHARP_TYPE)
652 {
653 preDefinitionHeaders->emplace_back(&AS_STRUCT);
654 preDefinitionHeaders->emplace_back(&AS_INTERFACE);
655 preDefinitionHeaders->emplace_back(&AS_NAMESPACE);
656 }
657
658 assert(preDefinitionHeaders->size() < elements);
659 sort(preDefinitionHeaders->begin(), preDefinitionHeaders->end(), sortOnName);
660 }
661
662 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
663 * ASBase Functions
664 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
665
666 // check if a specific line position contains a header.
findHeader(const string & line,int i,const vector<const string * > * possibleHeaders) const667 const string* ASBase::findHeader(const string& line, int i,
668 const vector<const string*>* possibleHeaders) const
669 {
670 assert(isCharPotentialHeader(line, i));
671 // check the word
672 size_t maxHeaders = possibleHeaders->size();
673 for (size_t p = 0; p < maxHeaders; p++)
674 {
675 const string* header = (*possibleHeaders)[p];
676 const size_t wordEnd = i + header->length();
677 if (wordEnd > line.length())
678 continue;
679 int result = (line.compare(i, header->length(), *header));
680 if (result > 0)
681 continue;
682 if (result < 0)
683 break;
684 // check that this is not part of a longer word
685 if (wordEnd == line.length())
686 return header;
687 if (isLegalNameChar(line[wordEnd]))
688 continue;
689 const char peekChar = peekNextChar(line, wordEnd - 1);
690 // is not a header if part of a definition
691 if (peekChar == ',' || peekChar == ')')
692 break;
693 // the following accessor definitions are NOT headers
694 // goto default; is NOT a header
695 // default(int) keyword in C# is NOT a header
696 else if ((header == &AS_GET
697 || header == &AS_SET
698 || header == &AS_DEFAULT)
699 && (peekChar == ';' || peekChar == '(' || peekChar == '='))
700 break;
701 return header;
702 }
703 return nullptr;
704 }
705
706 // check if a specific line position contains a keyword.
findKeyword(const string & line,int i,const string & keyword) const707 bool ASBase::findKeyword(const string& line, int i, const string& keyword) const
708 {
709 assert(isCharPotentialHeader(line, i));
710 // check the word
711 const size_t keywordLength = keyword.length();
712 const size_t wordEnd = i + keywordLength;
713 if (wordEnd > line.length())
714 return false;
715 if (line.compare(i, keywordLength, keyword) != 0)
716 return false;
717 // check that this is not part of a longer word
718 if (wordEnd == line.length())
719 return true;
720 if (isLegalNameChar(line[wordEnd]))
721 return false;
722 // is not a keyword if part of a definition
723 const char peekChar = peekNextChar(line, (int) wordEnd - 1);
724 if (peekChar == ',' || peekChar == ')')
725 return false;
726 return true;
727 }
728
729 // check if a specific line position contains an operator.
findOperator(const string & line,int i,const vector<const string * > * possibleOperators) const730 const string* ASBase::findOperator(const string& line, int i,
731 const vector<const string*>* possibleOperators) const
732 {
733 assert(isCharPotentialOperator(line[i]));
734 // find the operator in the vector
735 // the vector contains the LONGEST operators first
736 // must loop thru the entire vector
737 size_t maxOperators = possibleOperators->size();
738 for (size_t p = 0; p < maxOperators; p++)
739 {
740 const size_t wordEnd = i + (*(*possibleOperators)[p]).length();
741 if (wordEnd > line.length())
742 continue;
743 if (line.compare(i, (*(*possibleOperators)[p]).length(), *(*possibleOperators)[p]) == 0)
744 return (*possibleOperators)[p];
745 }
746 return nullptr;
747 }
748
749 // get the current word on a line
750 // index must point to the beginning of the word
getCurrentWord(const string & line,size_t index) const751 string ASBase::getCurrentWord(const string& line, size_t index) const
752 {
753 assert(isCharPotentialHeader(line, index));
754 size_t lineLength = line.length();
755 size_t i;
756 for (i = index; i < lineLength; i++)
757 {
758 if (!isLegalNameChar(line[i]))
759 break;
760 }
761 return line.substr(index, i - index);
762 }
763
764 // check if a specific character can be used in a legal variable/method/class name
isLegalNameChar(char ch) const765 bool ASBase::isLegalNameChar(char ch) const
766 {
767 if (isWhiteSpace(ch))
768 return false;
769 if ((unsigned char) ch > 127)
770 return false;
771 return (isalnum((unsigned char) ch)
772 || ch == '.' || ch == '_'
773 || (isJavaStyle() && ch == '$')
774 || (isSharpStyle() && ch == '@')); // may be used as a prefix
775 }
776
777 // check if a specific character can be part of a header
isCharPotentialHeader(const string & line,size_t i) const778 bool ASBase::isCharPotentialHeader(const string& line, size_t i) const
779 {
780 assert(!isWhiteSpace(line[i]));
781 char prevCh = ' ';
782 if (i > 0)
783 prevCh = line[i - 1];
784 if (!isLegalNameChar(prevCh) && isLegalNameChar(line[i]))
785 return true;
786 return false;
787 }
788
789 // check if a specific character can be part of an operator
isCharPotentialOperator(char ch) const790 bool ASBase::isCharPotentialOperator(char ch) const
791 {
792 assert(!isWhiteSpace(ch));
793 if ((unsigned) ch > 127)
794 return false;
795 return (ispunct((unsigned char) ch)
796 && ch != '{' && ch != '}'
797 && ch != '(' && ch != ')'
798 && ch != '[' && ch != ']'
799 && ch != ';' && ch != ','
800 && ch != '#' && ch != '\\'
801 && ch != '\'' && ch != '\"');
802 }
803
804 // check if a specific character is a digit
805 // NOTE: Visual C isdigit() gives assert error if char > 256
isDigit(char ch) const806 bool ASBase::isDigit(char ch) const
807 {
808 return (ch >= '0' && ch <= '9');
809 }
810
811 // check if a specific character is a digit separator
isDigitSeparator(const string & line,int i) const812 bool ASBase::isDigitSeparator(const string& line, int i) const
813 {
814 assert(line[i] == '\'');
815 // casting to (unsigned char) eliminates negative characters
816 // will get a "Debug Assertion Failed" if not cast
817 bool foundDigitSeparator = i > 0
818 && isxdigit((unsigned char) line[i - 1])
819 && i < (int) line.length() - 1
820 && isxdigit((unsigned char) line[i + 1]);
821 return foundDigitSeparator;
822 }
823
824 // peek at the next unread character.
peekNextChar(const string & line,int i) const825 char ASBase::peekNextChar(const string& line, int i) const
826 {
827 char ch = ' ';
828 size_t peekNum = line.find_first_not_of(" \t", i + 1);
829 if (peekNum == string::npos)
830 return ch;
831 ch = line[peekNum];
832 return ch;
833 }
834
835 } // end namespace astyle
836