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