⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 asbeautifier.cpp

📁 著名的代码自动缩进软件ASTYLE的源码,为1.21版本,支持C/C++/JAVA的各种格式的排版,支持自定的样式,功能强大
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		{
			if (ch == '}')
			{
				// first check if this '}' closes a previous block, or a static array...
				if (!bracketBlockStateStack->empty())
				{
					bool bracketBlockState = bracketBlockStateStack->back();
					bracketBlockStateStack->pop_back();
					if (!bracketBlockState)
					{
						if (!inStatementIndentStackSizeStack->empty())
						{
							// this bracket is a static array

							int previousIndentStackSize = inStatementIndentStackSizeStack->back();
							inStatementIndentStackSizeStack->pop_back();
							while (previousIndentStackSize < (int) inStatementIndentStack->size())
								inStatementIndentStack->pop_back();
							parenDepth--;
							if (i == 0)
								shouldIndentBrackettedLine = false;

							if (!parenIndentStack->empty())
							{
								int poppedIndent = parenIndentStack->back();
								parenIndentStack->pop_back();
								if (i == 0)
									spaceTabCount = poppedIndent;
							}
						}
						continue;
					}
				}

				// this bracket is block closer...

				++lineClosingBlocksNum;

				if (!inStatementIndentStackSizeStack->empty())
					inStatementIndentStackSizeStack->pop_back();

				if (!blockParenDepthStack->empty())
				{
					parenDepth = blockParenDepthStack->back();
					blockParenDepthStack->pop_back();
					isInStatement = blockStatementStack->back();
					blockStatementStack->pop_back();

					if (isInStatement)
						blockTabCount--;
				}

				closingBracketReached = true;
				int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACKET);
				if (headerPlace != -1)
				{
					const string *popped = headerStack->back();
					while (popped != &AS_OPEN_BRACKET)
					{
						headerStack->pop_back();
						popped = headerStack->back();
					}
					headerStack->pop_back();

					if (!tempStacks->empty())
					{
						vector<const string*> *temp =  tempStacks->back();
						tempStacks->pop_back();
						delete temp;
					}
				}


				ch = ' '; // needed due to cases such as '}else{', so that headers ('else' tn tih case) will be identified...
			}

			/*
			 * Create a temporary snapshot of the current block's header-list in the
			 * uppermost inner stack in tempStacks, and clear the headerStack up to
			 * the begining of the block.
			 * Thus, the next future statement will think it comes one indent past
			 * the block's '{' unless it specifically checks for a companion-header
			 * (such as a previous 'if' for an 'else' header) within the tempStacks,
			 * and recreates the temporary snapshot by manipulating the tempStacks.
			 */
			if (!tempStacks->back()->empty())
				while (!tempStacks->back()->empty())
					tempStacks->back()->pop_back();
			while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACKET)
			{
				tempStacks->back()->push_back(headerStack->back());
				headerStack->pop_back();
			}

			if (parenDepth == 0 && ch == ';')
				isInStatement = false;

			previousLastLineHeader = NULL;
			isInClassHeader = false;
			isInQuestion = false;

			continue;
		}


		// check for preBlockStatements ONLY if not within parenthesies
		// (otherwise 'struct XXX' statements would be wrongly interpreted...)
		if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0)
		{
			const string *newHeader = findHeader(line, i, preBlockStatements);
			if (newHeader != NULL)
			{
				isInClassHeader = true;
				outBuffer.append(newHeader->substr(1));
				i += newHeader->length() - 1;
				headerStack->push_back(newHeader);
			}
		}

		// Handle operators

		immediatelyPreviousAssignmentOp = NULL;

		// Check if an operator has been reached.
		const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
		if (foundAssignmentOp == &AS_RETURN)
			foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
		const string *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);

		// Since findHeader's boundry checking was not used above, it is possible
		// that both an assignment op and a non-assignment op where found,
		// e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
		// found operator.
		if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
			if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
				foundAssignmentOp = NULL;
			else
				foundNonAssignmentOp = NULL;

		if (foundNonAssignmentOp != NULL)
		{
			if (foundNonAssignmentOp->length() > 1)
			{
				outBuffer.append(foundNonAssignmentOp->substr(1));
				i += foundNonAssignmentOp->length() - 1;
			}
		}

		else if (foundAssignmentOp != NULL)
		{
			if (foundAssignmentOp->length() > 1)
			{
				outBuffer.append(foundAssignmentOp->substr(1));
				i += foundAssignmentOp->length() - 1;
			}

			if (!isInOperator && !isInTemplate && !isNonInStatementArray)
			{
				registerInStatementIndent(line, i, spaceTabCount, 0, false);
				immediatelyPreviousAssignmentOp = foundAssignmentOp;
				isInStatement = true;
			}
		}

		if (isInOperator)
			isInOperator = false;
	}

	// handle special cases of unindentation:

	/*
	 * if '{' doesn't follow an immediately previous '{' in the headerStack
	 * (but rather another header such as "for" or "if", then unindent it
	 * by one indentation relative to its block.
	 */

	if (!lineStartsInComment
	        && !blockIndent
	        && outBuffer.length() > 0
	        && outBuffer[0] == '{'
	        && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum == lineClosingBlocksNum)
	        && !(headerStack->size() > 1 && (*headerStack)[headerStack->size()-2] == &AS_OPEN_BRACKET)
	        && shouldIndentBrackettedLine)
		--tabCount;

	else if (!lineStartsInComment
	         && outBuffer.length() > 0
	         && outBuffer[0] == '}'
	         && shouldIndentBrackettedLine)
		--tabCount;

	// correctly indent one-line-blocks...
	else if (!lineStartsInComment
	         && outBuffer.length() > 0
	         && lineOpeningBlocksNum > 0
	         && lineOpeningBlocksNum == lineClosingBlocksNum
	         && previousLineProbationTab)
		--tabCount; //lineOpeningBlocksNum - (blockIndent ? 1 : 0);

	if (tabCount < 0)
		tabCount = 0;

	// take care of extra bracket indentatation option...
	if (bracketIndent && outBuffer.length() > 0 && shouldIndentBrackettedLine)
		if (outBuffer[0] == '{' || outBuffer[0] == '}')
			tabCount++;


	if (isInDefine)
	{
		if (outBuffer[0] == '#')
		{
			string preproc = trim(string(outBuffer.c_str() + 1));
			if (preproc.compare(0, 6, "define") == 0)
			{
				if (!inStatementIndentStack->empty()
				        && inStatementIndentStack->back() > 0)
				{
					defineTabCount = tabCount;
				}
				else
				{
					defineTabCount = tabCount - 1;
					tabCount--;
				}
			}
		}

		tabCount -= defineTabCount;
	}

	if (tabCount < 0)
		tabCount = 0;
	if (lineCommentNoBeautify || blockCommentNoBeautify)
		tabCount = spaceTabCount = 0;

	// finally, insert indentations into begining of line

	prevFinalLineSpaceTabCount = spaceTabCount;
	prevFinalLineTabCount = tabCount;

	if (shouldForceTabIndentation)
	{
		tabCount += spaceTabCount / indentLength;
		spaceTabCount = spaceTabCount % indentLength;
	}

	outBuffer = preLineWS(spaceTabCount, tabCount) + outBuffer;

	if (lastLineHeader != NULL)
		previousLastLineHeader = lastLineHeader;

	return outBuffer;
}


string ASBeautifier::preLineWS(int spaceTabCount, int tabCount)
{
	string ws;

	for (int i = 0; i < tabCount; i++)
		ws += indentString;

	while ((spaceTabCount--) > 0)
		ws += string(" ");

	return ws;

}

/**
 * register an in-statement indent.
 */
void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
        int minIndent, bool updateParenStack)
{
	int inStatementIndent;
	int remainingCharNum = line.length() - i;
	int nextNonWSChar = getNextProgramCharDistance(line, i);

	// if indent is around the last char in the line, indent instead 2 spaces from the previous indent
	if (nextNonWSChar == remainingCharNum)
	{
		int previousIndent = spaceTabCount;
		if (!inStatementIndentStack->empty())
			previousIndent = inStatementIndentStack->back();

		inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent);
		if (updateParenStack)
			parenIndentStack->push_back(previousIndent);
		return;
	}

	if (updateParenStack)
		parenIndentStack->push_back(i + spaceTabCount);

	inStatementIndent = i + nextNonWSChar + spaceTabCount;

	if (i + nextNonWSChar < minIndent)
		inStatementIndent = minIndent + spaceTabCount;

	if (i + nextNonWSChar > maxInStatementIndent)
		inStatementIndent =  indentLength * 2 + spaceTabCount;

	if (!inStatementIndentStack->empty() &&
	        inStatementIndent < inStatementIndentStack->back())
		inStatementIndent = inStatementIndentStack->back();

	if (isNonInStatementArray)
		inStatementIndent = 0;

	inStatementIndentStack->push_back(inStatementIndent);
}

/**
 * get distance to the next non-white sspace, non-comment character in the line.
 * if no such character exists, return the length remaining to the end of the line.
 */
int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
{
	bool inComment = false;
	int  remainingCharNum = line.length() - i;
	int  charDistance;
	char ch;

	for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
	{
		ch = line[i + charDistance];
		if (inComment)
		{
			if (line.compare(i + charDistance, 2, "*/") == 0)
			{
				charDistance++;
				inComment = false;
			}
			continue;
		}
		else if (isWhiteSpace(ch))
			continue;
		else if (ch == '/')
		{
			if (line.compare(i + charDistance, 2, "//") == 0)
				return remainingCharNum;
			else if (line.compare(i + charDistance, 2, "/*") == 0)
			{
				charDistance++;
				inComment = true;
			}
		}
		else
			return charDistance;
	}

	return charDistance;
}


/**
 * check if a specific line position contains a header, out of several possible headers.
 *
 * @return    a pointer to the found header. if no header was found then return NULL.
 */
const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
{
	int maxHeaders = possibleHeaders.size();
	// const string *header = NULL;
	int p;

	for (p = 0; p < maxHeaders; p++)
	{
		const string *header = possibleHeaders[p];

		if (line.compare(i, header->length(), header->c_str()) == 0)
		{
			// check that this is a header and not a part of a longer word
			// (e.g. not at its begining, not at its middle...)

			int lineLength = line.length();
			int headerEnd = i + header->length();
			char startCh = (*header)[0];   // first char of header
			char endCh = 0;                // char just after header
			char prevCh = 0;               // char just before header

			if (headerEnd < lineLength)
			{
				endCh = line[headerEnd];
			}
			if (i > 0)
			{
				prevCh = line[i-1];
			}

			if (!checkBoundry)
			{
				return header;
			}
			else if (prevCh != 0
			         && isLegalNameChar(startCh)
			         && isLegalNameChar(prevCh))
			{
				return NULL;
			}
			else if (headerEnd >= lineLength
			         || !isLegalNameChar(startCh)
			         || !isLegalNameChar(endCh))
			{
				return header;
			}
			else
			{
				return NULL;
			}
		}
	}

	return NULL;
}

/**
 * find the index number of a string element in a container of strings
 *
 * @return              the index number of element in the ocntainer. -1 if element not found.
 * @param container     a vector of strings.
 * @param element       the element to find .
 */
int ASBeautifier::indexOf(vector<const string*> &container, const string *element)
{
	vector<const string*>::const_iterator where;

	where = find(container.begin(), container.end(), element);
	if (where == container.end())
		return -1;
	else
		return (int) (where - container.begin());
}

/**
 * trim removes the white space surrounding a line.
 *
 * @return          the trimmed line.
 * @param str       the line to trim.
 */
string ASBeautifier::trim(const string &str)
{

	int start = 0;
	int end = str.length() - 1;

	while (start < end && isWhiteSpace(str[start]))
		start++;

	while (start <= end && isWhiteSpace(str[end]))
		end--;

	string returnStr(str, start, end + 1 - start);
	return returnStr;
}

/**
* peek at the next unread character.
*
* @return     	the next unread character.
* @param line   the line to check.
* @param i      the current char position on the line.
*/
char ASBeautifier::peekNextChar(string &line, int i)
{
	char ch = ' ';
	size_t peekNum = line.find_first_not_of(" \t", i + 1);

	if (peekNum == string::npos)
		return ch;

	ch = line[peekNum];

	return ch;
}


}   // end namespace astyle

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -