diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h | 1262 |
1 files changed, 1262 insertions, 0 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h new file mode 100644 index 00000000..cf3b987f --- /dev/null +++ b/debian/uncrustify-trinity/uncrustify-trinity-0.75.0/src/chunk.h @@ -0,0 +1,1262 @@ +/** + * @file chunk.h + * Manages and navigates the list of chunks. + * + * @author Ben Gardner + * @license GPL v2+ + */ + +#ifndef CHUNK_LIST_H_INCLUDED +#define CHUNK_LIST_H_INCLUDED + +#include "uncrustify_types.h" +// necessary to not sort it +#include "char_table.h" +#include "language_tools.h" + + +/* + * TODO: better use a namespace for all chunk related operations. + * The function "chunk_is_comment()" would for instance + * become "chunk::is_comment()". This makes the usage of the chunks easier + * and more intuitive. + */ + + +static constexpr int ANY_LEVEL = -1; + + +/** + * Specifies which chunks should/should not be found. + * ALL (default) + * - return the true next/prev + * + * PREPROC + * - If not in a preprocessor, skip over any encountered preprocessor stuff + * - If in a preprocessor, fail to leave (return nullptr) + */ +enum class E_Scope : unsigned int +{ + ALL, //! search in all kind of chunks + PREPROC, //! search only in preprocessor chunks +}; + + +/** + * Specifies which direction or location an operation shall be performed. + */ +enum class E_Direction : unsigned int +{ + FORWARD, + BACKWARD +}; + + +/** + * Temporary internal typedef. Will be progressively be replaced by Chunk::CheckFnPtr. + * + * @brief prototype for a function that checks a chunk to have a given type + * + * @note this typedef defines the function type "check_t" + * for a function pointer of type + * bool function(Chunk *pc) + */ +// TODO remove when finished +typedef bool (*check_t)(Chunk *pc); + + +// This is the main type of this program +class Chunk +{ +public: + static Chunk NullChunk; // Null Chunk + static Chunk *const NullChunkPtr; // Pointer to the Null Chunk + + //! constructors + Chunk(bool null_c = false); // default + Chunk(const Chunk &o); // !!! partial copy: chunk is not linked to others + + Chunk &operator=(const Chunk &o); // !!! partial copy: chunk is not linked to others + + //! whether this is a null Chunk or not + bool IsNullChunk() const { return(null_chunk); } + bool IsNotNullChunk() const { return(!null_chunk); } + + //! sets all elements of the struct to their default value + void Reset(); + + //! provides the number of characters of string + size_t Len() const; + + //! provides the content of a string a zero terminated character pointer + const char *Text() const; + + // Issue #2984, fill up, if necessary, a copy of the first chars of the Text() string + const char *ElidedText(char *for_the_copy) const; + + + // --------- Get* chunk functions + + /** + * @brief returns the head of the chunk list + * @return pointer to the first chunk + */ + static Chunk *GetHead(void); + + /** + * @brief returns the tail of the chunk list + * @return pointer to the last chunk + */ + static Chunk *GetTail(void); + + /** + * @brief returns the next chunk in a list of chunks + * @param scope code region to search in + * @return pointer to next chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNext(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the previous chunk in a list of chunks + * @param scope code region to search in + * @return pointer to previous chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrev(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next newline chunk + * @param scope code region to search in + * @return pointer to next newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev newline chunk + * @param scope code region to search in + * @return pointer to prev newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next non-newline chunk + * @param scope code region to search in + * @return pointer to next non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-newline chunk + * @param scope code region to search in + * @return pointer to prev non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next non-comment chunk + * @param scope code region to search in + * @return pointer to next non-comment chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNc(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-comment chunk + * @param scope code region to search in + * @return pointer to prev non-comment chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNc(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next non-comment and non-newline chunk + * @param scope code region to search in + * @return pointer to next non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNcNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-comment and non-newline chunk + * @param scope code region to search in + * @return pointer to prev non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNcNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next non-comment, non-newline, non-preprocessor chunk + * @param scope code region to search in + * @return pointer to next non-comment, non-newline, non-preprocessor chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNcNnlNpp(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-comment, non-newline, non-preprocessor chunk + * @param scope code region to search in + * @return pointer to prev non-comment, non-newline, non-preprocessor chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNcNnlNpp(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next non-preprocessor or non-comment, non-newline chunk + * @param scope code region to search in + * @return pointer to next non-preprocessor or non-comment, non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNppOrNcNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-preprocessor or non-comment, non-newline chunk + * @param scope code region to search in + * @return pointer to prev non-preprocessor or non-comment, non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNppOrNcNnl(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the next preprocessor aware non-comment and non-newline chunk + * Unlike Chunk::GetNextNcNnl, this will also ignore a line continuation if + * the starting chunk is in a preprocessor directive, and may return a newline + * if the search reaches the end of a preprocessor directive. + * @return pointer to next preprocessor aware non-comment and non-newline chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *PpaGetNextNcNnl() const; + + /** + * @brief returns the next non-comment, non-newline, non-empty text chunk + * @param scope code region to search in + * @return pointer to next non-comment, non-newline, non-empty text chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNcNnlNet(const E_Scope scope = E_Scope::ALL) const; + + /** + * @brief returns the prev non-comment, non-newline, non-empty text chunk + * @param scope code region to search in + * @return pointer to prev non-comment, non-newline, non-empty text chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNcNnlNet(const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the prev non-comment, non-newline, non-ignored chunk + * @param scope code region to search in + * @return pointer to prev non-comment, non-newline, non-ignored chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNcNnlNi(const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the next chunk not in or part of balanced square + * brackets. This handles stacked [] instances to accommodate + * multi-dimensional array declarations + * @param scope code region to search in + * @return nullptr or the next chunk not in or part of square brackets + */ + Chunk *GetNextNisq(const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the next non-virtual brace chunk + * @param scope code region to search in + * @return pointer to next non-virtual brace chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextNvb(const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the prev non-virtual brace chunk + * @param scope code region to search in + * @return pointer to prev non-virtual brace chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevNvb(const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the next chunk of the given type at the level. + * @param cType the type to look for + * @param cLevel the level to match, -1 or ANY_LEVEL (any level) + * @param scope code region to search in + * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextType(const E_Token cType, const int cLevel, const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the prev chunk of the given type at the level. + * @param cType the type to look for + * @param cLevel the level to match, -1 or ANY_LEVEL (any level) + * @param scope code region to search in + * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevType(const E_Token type, int level, E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the next chunk that holds a given string at a given level. + * @param cStr string to search for + * @param len length of string + * @param cLevel -1 or ANY_LEVEL (any level) or the level to match + * @param scope code region to search in + * @return pointer to the next matching chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetNextString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL) const; + + + /** + * @brief returns the prev chunk that holds a given string at a given level. + * @param cStr string to search for + * @param len length of string + * @param cLevel -1 or ANY_LEVEL (any level) or the level to match + * @param scope code region to search in + * @return pointer to the prev matching chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *GetPrevString(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL) const; + + + // --------- Search functions + + /** + * @brief defines a member function pointer for a function of type + * Chunk *Chunk::function(const E_Scope scope) + * that will search for a new chunk + */ + typedef Chunk *(Chunk::*T_SearchFnPtr)(const E_Scope scope) const; + + /** + * @brief defines a member function pointer for a function of type + * bool Chunk::function() const; + * that checks whether a chunk satisty a specific condition + */ + typedef bool (Chunk::*T_CheckFnPtr)() const; + + /** + * @brief determines the search direction to use and returns a pointer + * to the corresponding search function. + * @param dir search direction + * @return pointer to search function + */ + static T_SearchFnPtr GetSearchFn(const E_Direction dir = E_Direction::FORWARD); + + /** + * @brief search for a chunk that satisfies a condition in a chunk list + * + * A generic function that traverses a chunks list either + * in forward or reverse direction. The traversal continues until a + * chunk satisfies the condition defined by the compare function. + * Depending on the parameter cond the condition will either be + * checked to be true or false. + * + * @param checkFn compare function + * @param scope code parts to consider for search + * @param dir search direction (forward or backward) + * @param cond success condition + * + * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *Search(const T_CheckFnPtr checkFn, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD, const bool cond = true) const; + + /** + * @brief search for a chunk that satisfies a condition in a chunk list, + * but being aware of preprocessor chucks. + * + * This function is similar to Search, except that it is tweaked to + * handle searches inside of preprocessor directives. Specifically, if the + * starting token is inside a preprocessor directive, it will ignore a line + * continuation, and will abort the search if it reaches the end of the + * directive. This function only searches forward. + * + * @param checkFn compare function + * @param cond success condition + * + * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *SearchPpa(const T_CheckFnPtr checkFn, const bool cond = true) const; + + /** + * @brief search a chunk of a given type and level. Traverses a chunk list in the + * specified direction until a chunk of a given type is found. + * + * This function is a specialization of Chunk::Search. + * + * @param cType category to search for + * @param scope code parts to consider for search + * @param dir search direction + * @param cLevel nesting level to match or -1 / ANY_LEVEL + * + * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *SearchTypeLevel(const E_Token cType, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD, const int cLevel = -1) const; + + + /** + * @brief searches a chunk that holds a specific string + * + * Traverses a chunk list either in forward or backward direction until a chunk + * with the provided string was found. Additionally a nesting level can be + * provided to narrow down the search. + * + * @param cStr string that searched chunk needs to have + * @param len length of the string + * @param cLevel nesting level of the searched chunk, ignored when negative + * @param scope code parts to consider for search + * @param dir search direction + * + * @return pointer to the found chunk or Chunk::NullChunkPtr if no chunk was found + */ + Chunk *SearchStringLevel(const char *cStr, const size_t len, const int cLevel, const E_Scope scope = E_Scope::ALL, const E_Direction dir = E_Direction::FORWARD) const; + + + // --------- Is* functions + + /** + * @brief checks whether the chunk is a specific token + * @token the token to check for + * @return true if the chunk type matches the specified token, false otherwise + */ + bool Is(E_Token token) const; + + /** + * @brief checks whether the chunk is not a specific token + * @token the token to check for + * @return true if the chunk type does not matches the specified token, false otherwise + */ + bool IsNot(E_Token token) const; + + /** + * @brief checks whether the chunk is a newline + * @return true if the chunk is a newline, false otherwise + */ + bool IsNewline() const; + + /** + * @brief checks whether the chunk is a comment + * This means any kind of: + * - single line comment + * - multiline comment + * - C comment + * - C++ comment + */ + bool IsComment() const; + + /** + * @brief checks whether the chunk is valid and has an empty text + * @return true if the chunk is valid and has an empty text + */ + bool IsEmptyText() const; + + /** + * @brief checks whether the chunk is a preprocessor + * @return true if the chunk is a preprocessor, false otherwise + */ + bool IsPreproc() const; + + /** + * @brief checks whether the chunk is either a comment or a newline + * @return true if the chunk is either a comment or a newline, false otherwise + */ + bool IsCommentOrNewline() const; + + /** + * @brief checks whether the chunk is either a comment, a newline or ignored + * @return true if the chunk is either a comment, a newline or ignored, false otherwise + */ + bool IsCommentNewlineOrIgnored() const; + + /** + * @brief checks whether the chunk is a comment, a newline or a preprocessor + * @return true if the chunk is a comment, a newline or a preprocessor, false otherwise + */ + bool IsCommentNewlineOrPreproc() const; + + /** + * @brief checks whether the chunk is a preprocessor and either a comment or a newline + * @return true if the chunk is a preprocessor and either a comment or a newline, false otherwise + */ + bool IsCommentOrNewlineInPreproc() const; + + /** + * @brief checks whether the chunk is a comment, a newline or has an empty text + * @return true if the chunk is a comment, a newline or has an empty text + */ + bool IsCommentNewlineOrEmptyText() const; + + /** + * @brief checks whether the chunk is a square bracket + * @return true if the chunk is a square bracket + */ + bool IsSquareBracket() const; + + /** + * @brief checks whether the chunk is a virtual brace + * @return true if the chunk is a virtual brace + */ + bool IsVBrace() const; + + /** + * @brief checks whether the chunk matches a given type and level + * @param type category to search for + * @param level nesting level to match + * @return true if the chunk matches a given type and level + */ + bool IsTypeAndLevel(const E_Token cType, const int cLevel) const; + + + /** + * @brief checks whether the chunk matches a given string and level + * @param cStr the expected string + * @param len length of the string + * @param cLevel nesting level of the searched chunk, ignored when negative + * @return true if the chunk matches a given string and level + */ + bool IsStringAndLevel(const char *cStr, const size_t len, const int cLevel) const; + + + /** + * @brief checks whether the chunk is a star/asterisk + * @return true if the chunk is a star/asterisk + */ + bool IsStar() const; + + + // --------- Data members + + Chunk *next; //! pointer to next chunk in list + Chunk *prev; //! pointer to previous chunk in list + Chunk *parent; //! pointer to parent chunk(not always set) + + align_ptr_t align; + indent_ptr_t indent; + E_Token type; //! type of the chunk itself + E_Token parent_type; //! type of the parent chunk usually CT_NONE + //! might be different from parent->parent_type (above) + size_t orig_line; //! line number of chunk in input file + size_t orig_col; //! column where chunk started in the input file, is always > 0 + size_t orig_col_end; //! column where chunk ended in the input file, is always > 1 + UINT32 orig_prev_sp; //! whitespace before this token + pcf_flags_t flags; //! see PCF_xxx + size_t column; //! column of chunk + size_t column_indent; /** if 1st on a line, set to the 'indent' + * column, which may be less than the real + * column used to indent with tabs */ + size_t nl_count; //! number of newlines in CT_NEWLINE + size_t nl_column; //! column of the subsequent newline entries(all of them should have the same column) + size_t level; /** nest level in {, (, or [ + * only to help vim command } */ + size_t brace_level; //! nest level in braces only + size_t pp_level; //! nest level in preprocessor + bool after_tab; //! whether this token was after a tab + unc_text str; //! the token text + + // for debugging purpose only + track_list *tracking; + +private: + void copyFrom(const Chunk &o); // !!! partial copy: chunk is not linked to others + + const bool null_chunk; //! true for null chunks +}; + + +/** + * @brief Add a copy of a chunk to a chunk list after the given position. + * + * @note If ref is nullptr, add at the tail of the chunk list + * + * @todo is ref=nullptr really useful ? + * + * @param pc_in pointer to chunk to add to list + * @param ref position where insertion takes place + * + * @return pointer to the added chunk + */ +Chunk *chunk_add_after(const Chunk *pc_in, Chunk *ref); + + +/** + * @brief Add a copy of a chunk to a chunk list before the given position + * + * @note If ref is nullptr, add at the head of the chunk list + * + * @todo is ref=nullptr really useful ? + * + * \bug code adds it before the tail, either code or comment is wrong + * + * @param pc_in pointer to chunk to add to list + * @param ref position where insertion takes place + * + * @retval pointer to the added chunk + */ +Chunk *chunk_add_before(const Chunk *pc_in, Chunk *ref); + + +/** + * delete a chunk from a chunk list + * + * @param pc chunk to delete + */ +void chunk_del(Chunk * &pc); + + +/** + * move a chunk to after the reference position in a chunk list + * + * @param pc_in chunk to move + * @param ref chunk after which to move + */ +void chunk_move_after(Chunk *pc_in, Chunk *ref); + + +/** + * Swaps two chunks + * + * @param pc1 The first chunk + * @param pc2 The second chunk + */ +void chunk_swap(Chunk *pc1, Chunk *pc2); + + +/** + * Swaps two lines that are started with the specified chunks. + * + * @param pc1 The first chunk of line 1 + * @param pc2 The first chunk of line 2 + */ +void chunk_swap_lines(Chunk *pc1, Chunk *pc2); + + +/** + * Finds the first chunk on the line that pc is on. + * This just backs up until a newline or nullptr is hit. + * + * given: [ a - b - c - n1 - d - e - n2 ] + * input: [ a | b | c | n1 ] => a + * input: [ d | e | n2 ] => d + * + * @param pc chunk to start with + */ +Chunk *chunk_first_on_line(Chunk *pc); + + +//! check if a given chunk is the last on its line +bool chunk_is_last_on_line(Chunk *pc); + + +/** + * Gets the next chunk not in or part of balanced square + * brackets.This handles stacked[] instances to accommodate + * multi - dimensional array declarations + * + * @param cur chunk to use as start point + * + * @return nullptr or the next chunk not in or part of square brackets + */ +Chunk *chunk_get_next_ssq(Chunk *cur); + +/** + * Gets the prev chunk not in or part of balanced square + * brackets.This handles stacked[] instances to accommodate + * multi - dimensional array declarations + * + * @param cur chunk to use as start point + * + * @return nullptr or the prev chunk not in or part of square brackets + */ +Chunk *chunk_get_prev_ssq(Chunk *cur); + + +/** + * Gets the corresponding start chunk if the given chunk is within a + * preprocessor directive, or nullptr otherwise. + * + * @param cur chunk to use as start point + * + * @return nullptr or start chunk of the preprocessor directive + */ +Chunk *chunk_get_pp_start(Chunk *cur); + + +/** + * @brief reverse search a chunk of a given category in a chunk list + * + * @param pc chunk list to search in + * @param cat category to search for + * + * @retval nullptr no object found, or invalid parameters provided + * @retval Chunk pointer to the found object + */ +Chunk *chunk_search_prev_cat(Chunk *pc, const E_Token cat); + + +/** + * @brief forward search a chunk of a given category in a chunk list + * + * @param pc chunk list to search in + * @param cat category to search for + * + * @retval nullptr no object found, or invalid parameters provided + * @retval Chunk pointer to the found object + */ +Chunk *chunk_search_next_cat(Chunk *pc, const E_Token cat); + + +/** + * @brief checks wether two chunks are in same line + * + * @param start + * @param end + * + * @return true if there is no newline between start and end chunks + */ +bool are_chunks_in_same_line(Chunk *start, Chunk *end); + + +inline bool Chunk::IsTypeAndLevel(const E_Token cType, const int cLevel) const +{ + return( ( cLevel < 0 + || level == static_cast<size_t>(cLevel)) + && type == cType); +} + + +inline bool Chunk::IsStringAndLevel(const char *cStr, const size_t len, const int cLevel) const +{ + return( ( cLevel < 0 + || level == static_cast<size_t>(cLevel)) + && Len() == len // the length is as expected + && memcmp(cStr, Text(), len) == 0); // the strings are equal +} + + +inline bool Chunk::Is(E_Token token) const +{ + return( IsNotNullChunk() + && type == token); +} + + +inline bool Chunk::IsNot(E_Token token) const +{ + return(!Is(token)); +} + + +inline bool Chunk::IsNewline() const +{ + return( Is(CT_NEWLINE) + || Is(CT_NL_CONT)); +} + + +inline bool Chunk::IsComment() const +{ + return( Is(CT_COMMENT) + || Is(CT_COMMENT_MULTI) + || Is(CT_COMMENT_CPP)); +} + + +inline bool Chunk::IsEmptyText() const +{ + return( IsNotNullChunk() + && Len() == 0); +} + + +inline bool Chunk::IsPreproc() const +{ + return( IsNotNullChunk() + && flags.test(PCF_IN_PREPROC)); +} + + +inline bool Chunk::IsCommentOrNewline() const +{ + return( IsComment() + || IsNewline()); +} + + +inline bool Chunk::IsCommentNewlineOrPreproc() const +{ + return( IsComment() + || IsNewline() + || IsPreproc()); +} + + +inline bool Chunk::IsCommentOrNewlineInPreproc() const +{ + return( IsPreproc() + && ( IsComment() + || IsNewline())); +} + + +inline bool Chunk::IsCommentNewlineOrEmptyText() const +{ + return( IsComment() + || IsNewline() + || IsEmptyText()); +} + + +inline bool Chunk::IsCommentNewlineOrIgnored() const +{ + return( IsComment() + || IsNewline() + || Is(CT_IGNORED)); +} + + +inline bool Chunk::IsSquareBracket() const +{ + return( Is(CT_SQUARE_OPEN) + || Is(CT_TSQUARE) + || Is(CT_SQUARE_CLOSE)); +} + + +inline bool Chunk::IsVBrace() const +{ + return( Is(CT_VBRACE_OPEN) + || Is(CT_VBRACE_CLOSE)); +} + + +inline bool Chunk::IsStar() const +{ + return( Len() == 1 + && str[0] == '*' + && IsNot(CT_OPERATOR_VAL)); +} + + +// TODO remove when possible +static inline bool chunk_is_token(const Chunk *pc, E_Token c_token) +{ + return( pc != nullptr + && pc->IsNotNullChunk() + && pc->type == c_token); +} + + +// TODO remove when possible +static inline bool chunk_is_not_token(const Chunk *pc, E_Token c_token) +{ + return( pc != nullptr + && pc->IsNotNullChunk() + && pc->type != c_token); +} + + +/** + * Skips to the closing match for the current paren/brace/square. + * + * @param cur The opening or closing paren/brace/square + * @param scope chunk section to consider + * + * @return nullptr or the matching paren/brace/square + */ +static inline Chunk *chunk_skip_to_match(Chunk *cur, E_Scope scope = E_Scope::ALL) +{ + if ( cur != nullptr + && ( chunk_is_token(cur, CT_PAREN_OPEN) + || chunk_is_token(cur, CT_SPAREN_OPEN) + || chunk_is_token(cur, CT_FPAREN_OPEN) + || chunk_is_token(cur, CT_TPAREN_OPEN) + || chunk_is_token(cur, CT_BRACE_OPEN) + || chunk_is_token(cur, CT_VBRACE_OPEN) + || chunk_is_token(cur, CT_ANGLE_OPEN) + || chunk_is_token(cur, CT_SQUARE_OPEN))) + { + return(cur->GetNextType((E_Token)(cur->type + 1), cur->level, scope)); + } + return(cur); +} + + +static inline Chunk *chunk_skip_to_match_rev(Chunk *cur, E_Scope scope = E_Scope::ALL) +{ + if ( cur != nullptr + && ( chunk_is_token(cur, CT_PAREN_CLOSE) + || chunk_is_token(cur, CT_SPAREN_CLOSE) + || chunk_is_token(cur, CT_FPAREN_CLOSE) + || chunk_is_token(cur, CT_TPAREN_CLOSE) + || chunk_is_token(cur, CT_BRACE_CLOSE) + || chunk_is_token(cur, CT_VBRACE_CLOSE) + || chunk_is_token(cur, CT_ANGLE_CLOSE) + || chunk_is_token(cur, CT_SQUARE_CLOSE))) + { + return(cur->GetPrevType((E_Token)(cur->type - 1), cur->level, scope)); + } + return(cur); +} + + +//! skip to the final word/type in a :: chain +Chunk *chunk_skip_dc_member(Chunk *start, E_Scope scope = E_Scope::ALL); +Chunk *chunk_skip_dc_member_rev(Chunk *start, E_Scope scope = E_Scope::ALL); + + +/** + * Returns true if the chunk under test is an inheritance access specifier + */ +static inline bool chunk_is_cpp_inheritance_access_specifier(Chunk *pc) +{ + return( language_is_set(LANG_CPP) + && pc != nullptr + && pc->IsNotNullChunk() + && ( chunk_is_token(pc, CT_ACCESS) + || chunk_is_token(pc, CT_QUALIFIER)) + && ( std::strncmp(pc->str.c_str(), "private", 7) == 0 + || std::strncmp(pc->str.c_str(), "protected", 9) == 0 + || std::strncmp(pc->str.c_str(), "public", 6) == 0)); +} // chunk_is_cpp_inheritance_access_specifier + + +static inline bool chunk_is_colon(Chunk *pc) +{ + return( chunk_is_token(pc, CT_ACCESS_COLON) + || chunk_is_token(pc, CT_ASM_COLON) + || chunk_is_token(pc, CT_BIT_COLON) + || chunk_is_token(pc, CT_CASE_COLON) + || chunk_is_token(pc, CT_CLASS_COLON) + || chunk_is_token(pc, CT_COLON) + || chunk_is_token(pc, CT_COND_COLON) + || chunk_is_token(pc, CT_CONSTR_COLON) + || chunk_is_token(pc, CT_CS_SQ_COLON) + || chunk_is_token(pc, CT_D_ARRAY_COLON) + || chunk_is_token(pc, CT_FOR_COLON) + || chunk_is_token(pc, CT_LABEL_COLON) + || chunk_is_token(pc, CT_OC_COLON) + || chunk_is_token(pc, CT_OC_DICT_COLON) + || chunk_is_token(pc, CT_TAG_COLON) + || chunk_is_token(pc, CT_WHERE_COLON)); +} + + +static inline bool chunk_is_single_line_comment(Chunk *pc) +{ + return( chunk_is_token(pc, CT_COMMENT) + || chunk_is_token(pc, CT_COMMENT_CPP)); +} + + +// TODO remove when possible +static inline bool chunk_is_newline(Chunk *pc) +{ + return( chunk_is_token(pc, CT_NEWLINE) + || chunk_is_token(pc, CT_NL_CONT)); +} + + +static inline bool chunk_is_semicolon(Chunk *pc) +{ + return( chunk_is_token(pc, CT_SEMICOLON) + || chunk_is_token(pc, CT_VSEMICOLON)); +} + + +static inline bool chunk_is_Doxygen_comment(Chunk *pc) +{ + if ( pc == nullptr + || !pc->IsComment()) + { + return(false); + } + // check the third character + const char *sComment = pc->Text(); + const size_t len = strlen(sComment); + + if (len < 3) + { + return(false); + } + return( (sComment[2] == '/') + || (sComment[2] == '!') + || (sComment[2] == '@')); +} + + +static inline bool chunk_is_type(Chunk *pc) +{ + return( chunk_is_token(pc, CT_TYPE) + || chunk_is_token(pc, CT_PTR_TYPE) + || chunk_is_token(pc, CT_BYREF) + || chunk_is_token(pc, CT_DC_MEMBER) + || chunk_is_token(pc, CT_QUALIFIER) + || chunk_is_token(pc, CT_STRUCT) + || chunk_is_token(pc, CT_ENUM) + || chunk_is_token(pc, CT_UNION)); +} + + +static inline bool chunk_is_str(Chunk *pc, const char *str) +{ + size_t len = strlen(str); + + return( pc != nullptr // valid pc pointer + && (pc->Len() == len) // token size equals size parameter + && (memcmp(pc->Text(), str, len) == 0)); // token name is the same as str parameter + + /* + * TODO: possible access beyond array for memcmp, check this + * why not use strncmp here? + */ +} + + +static inline bool chunk_is_str_case(Chunk *pc, const char *str, size_t len) +{ + return( pc != nullptr + && (pc->Len() == len) + && (strncasecmp(pc->Text(), str, len) == 0)); +} + + +static inline bool chunk_is_word(Chunk *pc) +{ + return( pc != nullptr + && (pc->Len() >= 1) + && CharTable::IsKw1(pc->str[0])); +} + + +static inline bool chunk_is_nullable(Chunk *pc) +{ + return( language_is_set(LANG_CS | LANG_VALA) + && (pc != nullptr) + && (pc->Len() == 1) + && (pc->str[0] == '?')); +} + + +static inline bool chunk_is_addr(Chunk *pc) +{ + if ( pc != nullptr + && pc->IsNotNullChunk() + && ( chunk_is_token(pc, CT_BYREF) + || ( (pc->Len() == 1) + && (pc->str[0] == '&') + && pc->type != CT_OPERATOR_VAL))) + { + Chunk *prev = pc->GetPrev(); + + if ( pc->flags.test(PCF_IN_TEMPLATE) + && ( chunk_is_token(prev, CT_COMMA) + || chunk_is_token(prev, CT_ANGLE_OPEN))) + { + return(false); + } + return(true); + } + return(false); +} + + +static inline bool chunk_is_msref(Chunk *pc) // ms compilers for C++/CLI and WinRT use '^' instead of '*' for marking up reference types vs pointer types +{ + return( language_is_set(LANG_CPP) + && ( pc != nullptr + && (pc->Len() == 1) + && (pc->str[0] == '^') + && pc->type != CT_OPERATOR_VAL)); +} + + +static inline bool chunk_is_ptr_operator(Chunk *pc) +{ + return( pc != nullptr + && ( ( pc->IsStar() + || chunk_is_addr(pc) + || chunk_is_msref(pc)) + || chunk_is_nullable(pc))); +} + + +static inline bool chunk_is_pointer_or_reference(Chunk *pc) +{ + return( chunk_is_ptr_operator(pc) + || chunk_is_token(pc, CT_BYREF)); +} + + +//! Check to see if there is a newline between the two chunks +bool chunk_is_newline_between(Chunk *start, Chunk *end); + + +static inline bool chunk_is_closing_brace(Chunk *pc) +{ + return( chunk_is_token(pc, CT_BRACE_CLOSE) + || chunk_is_token(pc, CT_VBRACE_CLOSE)); +} + + +static inline bool chunk_is_opening_brace(Chunk *pc) +{ + return( chunk_is_token(pc, CT_BRACE_OPEN) + || chunk_is_token(pc, CT_VBRACE_OPEN)); +} + + +static inline bool chunk_is_paren_open(Chunk *pc) +{ + return( chunk_is_token(pc, CT_PAREN_OPEN) + || chunk_is_token(pc, CT_SPAREN_OPEN) + || chunk_is_token(pc, CT_TPAREN_OPEN) + || chunk_is_token(pc, CT_FPAREN_OPEN) + || chunk_is_token(pc, CT_LPAREN_OPEN)); +} + + +static inline bool chunk_is_paren_close(Chunk *pc) +{ + return( chunk_is_token(pc, CT_PAREN_CLOSE) + || chunk_is_token(pc, CT_SPAREN_CLOSE) + || chunk_is_token(pc, CT_TPAREN_CLOSE) + || chunk_is_token(pc, CT_FPAREN_CLOSE)); +} + + +/** + * Returns true if either chunk is null or both have the same preproc flags. + * If this is true, you can remove a newline/nl_cont between the two. + */ +static inline bool chunk_same_preproc(Chunk *pc1, Chunk *pc2) +{ + return( pc1 == nullptr + || pc1->IsNullChunk() + || pc2 == nullptr + || pc2->IsNullChunk() + || ((pc1->flags & PCF_IN_PREPROC) == (pc2->flags & PCF_IN_PREPROC))); +} + + +/** + * Returns true if it is safe to delete the newline token. + * The prev and next chunks must have the same PCF_IN_PREPROC flag AND + * the newline can't be after a C++ comment. + */ +static inline bool chunk_safe_to_del_nl(Chunk *nl) +{ + if (nl == nullptr) + { + nl = Chunk::NullChunkPtr; + } + Chunk *tmp = nl->GetPrev(); + + if (chunk_is_token(tmp, CT_COMMENT_CPP)) + { + return(false); + } + return(chunk_same_preproc(tmp, nl->GetNext())); +} + + +/** + * Checks if a chunk points to the opening parenthese of a + * for(...in...) loop in Objective-C. + * + * @return true - the chunk is the opening parentheses of a for in loop + */ +static inline bool chunk_is_forin(Chunk *pc) +{ + if ( language_is_set(LANG_OC) + && chunk_is_token(pc, CT_SPAREN_OPEN)) + { + Chunk *prev = pc->GetPrevNcNnl(); + + if (chunk_is_token(prev, CT_FOR)) + { + Chunk *next = pc; + + while ( next != nullptr + && next->type != CT_SPAREN_CLOSE + && next->type != CT_IN) + { + next = next->GetNextNcNnl(); + } + + if (chunk_is_token(next, CT_IN)) + { + return(true); + } + } + } + return(false); +} + + +/** + * Returns true if pc is an CT_ATTRIBUTE or CT_DECLSPEC + */ +bool chunk_is_attribute_or_declspec(Chunk *pc); + + +/** + * Returns true if pc is one of CT_CLASS, CT_ENUM, CT_ENUM_CLASS, CT_STRUCT or CT_UNION + */ +bool chunk_is_class_enum_struct_union(Chunk *pc); + + +/** + * Returns true if pc is a CT_CLASS or CT_STRUCT + */ +bool chunk_is_class_or_struct(Chunk *pc); + + +/** + * Returns true if pc is one of CT_CLASS, CT_STRUCT or CT_UNION + */ +bool chunk_is_class_struct_union(Chunk *pc); + + +/** + * Returns true if pc is a CT_ENUM or CT_ENUM_CLASS + */ +bool chunk_is_enum(Chunk *pc); + + +void set_chunk_type_real(Chunk *pc, E_Token tt, const char *func, int line); + + +void set_chunk_parent_real(Chunk *pc, E_Token tt, const char *func, int line); + + +#define set_chunk_type(pc, tt) set_chunk_type_real((pc), (tt), __unqualified_func__, __LINE__) + + +#define set_chunk_parent(pc, tt) set_chunk_parent_real((pc), (tt), __unqualified_func__, __LINE__) + + +E_Token get_chunk_parent_type(Chunk *pc); + + +void chunk_flags_set_real(Chunk *pc, pcf_flags_t clr_bits, pcf_flags_t set_bits); + + +#define chunk_flags_upd(pc, cc, ss) chunk_flags_set_real((pc), (cc), (ss)) + + +#define chunk_flags_set(pc, ss) chunk_flags_set_real((pc), {}, (ss)) + + +#define chunk_flags_clr(pc, cc) chunk_flags_set_real((pc), (cc), {}) + + +void chunk_set_parent(Chunk *pc, Chunk *parent); + + +E_Token get_type_of_the_parent(Chunk *pc); + + +/** + * @brief compare the positions of two tokens in a file. + * + * The function compares the two positions of two tokens. + * + * @param A_token + * @param B_token + * + * @return returns an integer less than, equal to, or greater than zero + * if A_token is found, respectively, to be less/before than, to + * match, or be greater/after than B_token. + */ +int chunk_compare_position(const Chunk *A_token, const Chunk *B_token); + + +#endif /* CHUNK_LIST_H_INCLUDED */ |