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

📄 asbeautifier.cpp

📁 著名的代码自动缩进软件ASTYLE的源码,为1.21版本,支持C/C++/JAVA的各种格式的排版,支持自定的样式,功能强大
💻 CPP
📖 第 1 页 / 共 4 页
字号:
 */
void ASBeautifier::setLabelIndent(bool state)
{
	labelIndent = state;
}

/**
 * set the state of the preprocessor indentation option.
 * If true, multiline #define statements will be indented.
 *
 * @param   state             state of option.
 */
void ASBeautifier::setPreprocessorIndent(bool state)
{
	preprocessorIndent = state;
}

/**
 * set the state of the empty line fill option.
 * If true, empty lines will be filled with the whitespace.
 * of their previous lines.
 * If false, these lines will remain empty.
 *
 * @param   state             state of option.
 */
void ASBeautifier::setEmptyLineFill(bool state)
{
	emptyLineFill = state;
}

/**
 * get the number of spaces per indent
 *
 * @return   value of indentLength option.
*/
int ASBeautifier::getIndentLength(void)
{
	return indentLength;
}

/**
 * get the char used for indentation, space or tab
  *
 * @return   the char used for indentation.
 */
string ASBeautifier::getIndentString(void)
{
	return indentString;
}

/**
 * get the state of the case indentation option. If true, lines of 'case'
 * statements will be indented one additional indent.
 *
 * @return   state of caseIndent option.
 */
bool ASBeautifier::getCaseIndent(void)
{
	return caseIndent;
}

/**
 * get C style identifier.
 * If true, a C source is being indented.
 *
 * @return   state of isCStyle option.
 */
bool ASBeautifier::getCStyle(void)
{
	return isCStyle;
}

/**
 * get Java style identifier.
 * If true, a Java source is being indented.
 *
 * @return   state of isJavaStyle option.
 */
bool ASBeautifier::getJavaStyle(void)
{
	return isJavaStyle;
}

/**
 * get C# style identifier.
 * If true, a C# source is being indented.
 *
 * @return   state of isSharpStyle option.
 */
bool ASBeautifier::getSharpStyle(void)
{
	return isSharpStyle;
}

/**
 * get the state of the empty line fill option.
 * If true, empty lines will be filled with the whitespace.
 * of their previous lines.
 * If false, these lines will remain empty.
 *
 * @return   state of emptyLineFill option.
 */
bool ASBeautifier::getEmptyLineFill(void)
{
	return emptyLineFill;
}

/**
 * check if there are any indented lines ready to be read by nextLine()
 *
 * @return    are there any indented lines ready?
 */
bool ASBeautifier::hasMoreLines() const
{
	return sourceIterator->hasMoreLines();
}

/**
 * get the next indented line.
 *
 * @return    indented line.
 */
string ASBeautifier::nextLine()
{
	return beautify(sourceIterator->nextLine());
}

/**
 * beautify a line of source code.
 * every line of source code in a source code file should be sent
 * one after the other to the beautify method.
 *
 * @return      the indented line.
 * @param originalLine       the original unindented line.
 */
string ASBeautifier::beautify(const string &originalLine)
{
	string line;
	bool isInLineComment = false;
	bool lineStartsInComment = false;
	bool isInClass = false;
	bool isInSwitch = false;
	bool isImmediatelyAfterConst = false;
	bool isSpecialChar = false;
	char ch = ' ';
	char prevCh;
	string outBuffer; // the newly idented line is bufferd here
	int tabCount = 0;
	const string *lastLineHeader = NULL;
	bool closingBracketReached = false;
	int spaceTabCount = 0;
	char tempCh;
	size_t headerStackSize = headerStack->size();
	bool shouldIndentBrackettedLine = true;
	int lineOpeningBlocksNum = 0;
	int lineClosingBlocksNum = 0;
	bool previousLineProbation = (probationHeader != NULL);
	int i;

	currentHeader = NULL;
	lineStartsInComment = isInComment;
	blockCommentNoBeautify = blockCommentNoIndent;
	previousLineProbationTab = false;
	outLineNumber++;

	// handle and remove white spaces around the line:
	// If not in comment, first find out size of white space before line,
	// so that possible comments starting in the line continue in
	// relation to the preliminary white-space.
	if (!isInComment)
	{
		int strlen = originalLine.length();
		leadingWhiteSpaces = 0;

		for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++)
		{
			if (originalLine[j] == '\t')
				leadingWhiteSpaces += indentLength;
			else
				leadingWhiteSpaces++;
		}
		line = trim(originalLine);
	}
	else
	{
		// convert leading tabs to spaces
		string spaceTabs(indentLength, ' ');
		string newLine = originalLine;
		int strlen = newLine.length();

		for (int j=0; j < leadingWhiteSpaces && j < strlen; j++)
		{
			if (newLine[j] == '\t')
			{
				newLine.replace(j, 1, spaceTabs);
				strlen = newLine.length();
			}
		}

		// trim the comment leaving the new leading whitespace
		int trimSize = 0;
		strlen = newLine.length();

		while (trimSize < strlen
		        && trimSize < leadingWhiteSpaces
		        && isWhiteSpace(newLine[trimSize]))
			trimSize++;


		while (trimSize < strlen && isWhiteSpace(newLine[strlen-1]))
			strlen--;

		line = newLine.substr(trimSize, strlen);
		size_t trimEnd = line.find_last_not_of(" \t");
		if (trimEnd != string::npos)
		{
			int spacesToDelete = line.length() - 1 - trimEnd;
			if (spacesToDelete > 0)
				line.erase(trimEnd + 1, spacesToDelete);
		}
	}


	if (line.length() == 0)
	{
		if (backslashEndsPrevLine)	// must continue to clear variables
			line = ' ';
		else if (emptyLineFill)
			return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
		else
			return line;
	}

	// handle preprocessor commands

	if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
	{
		if (line[0] == '#')
		{
			string preproc = trim(string(line.c_str() + 1));

			// When finding a multi-lined #define statement, the original beautifier
			// 1. sets its isInDefineDefinition flag
			// 2. clones a new beautifier that will be used for the actual indentation
			//    of the #define. This clone is put into the activeBeautifierStack in order
			//    to be called for the actual indentation.
			// The original beautifier will have isInDefineDefinition = true, isInDefine = false
			// The cloned beautifier will have   isInDefineDefinition = true, isInDefine = true
			if (preprocessorIndent && preproc.compare(0, 6, "define") == 0 &&  line[line.length() - 1] == '\\')
			{
				if (!isInDefineDefinition)
				{
					ASBeautifier *defineBeautifier;

					// this is the original beautifier
					isInDefineDefinition = true;

					// push a new beautifier into the active stack
					// this beautifier will be used for the indentation of this define
					defineBeautifier = new ASBeautifier(*this);
					activeBeautifierStack->push_back(defineBeautifier);
				}
				else
				{
					// the is the cloned beautifier that is in charge of indenting the #define.
					isInDefine = true;
				}
			}
			else if (preproc.compare(0, 2, "if") == 0)
			{
				// push a new beautifier into the stack
				waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
				activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
				waitingBeautifierStack->push_back(new ASBeautifier(*this));
			}
			else if (preproc.compare(0, 4/*2*/, "else") == 0)
			{
				if (waitingBeautifierStack && !waitingBeautifierStack->empty())
				{
					// MOVE current waiting beautifier to active stack.
					activeBeautifierStack->push_back(waitingBeautifierStack->back());
					waitingBeautifierStack->pop_back();
				}
			}
			else if (preproc.compare(0, 4, "elif") == 0)
			{
				if (waitingBeautifierStack && !waitingBeautifierStack->empty())
				{
					// append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
					activeBeautifierStack->push_back(new ASBeautifier(*(waitingBeautifierStack->back())));
				}
			}
			else if (preproc.compare(0, 5, "endif") == 0)
			{
				int stackLength;
				ASBeautifier *beautifier;

				if (waitingBeautifierStackLengthStack && !waitingBeautifierStackLengthStack->empty())
				{
					stackLength = waitingBeautifierStackLengthStack->back();
					waitingBeautifierStackLengthStack->pop_back();
					while ((int) waitingBeautifierStack->size() > stackLength)
					{
						beautifier = waitingBeautifierStack->back();
						waitingBeautifierStack->pop_back();
						delete beautifier;
					}
				}

				if (!activeBeautifierStackLengthStack->empty())
				{
					stackLength = activeBeautifierStackLengthStack->back();
					activeBeautifierStackLengthStack->pop_back();
					while ((int) activeBeautifierStack->size() > stackLength)
					{
						beautifier = activeBeautifierStack->back();
						activeBeautifierStack->pop_back();
						delete beautifier;
					}
				}
			}
		}

		// check if the last char is a backslash
		if (line.length() > 0)
			backslashEndsPrevLine = (line[line.length() - 1] == '\\');
		else
			backslashEndsPrevLine = false;

		// check if this line ends a multi-line #define
		// if so, use the #define's cloned beautifier for the line's indentation
		// and then remove it from the active beautifier stack and delete it.
		if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
		{
			string beautifiedLine;
			ASBeautifier *defineBeautifier;

			isInDefineDefinition = false;
			defineBeautifier = activeBeautifierStack->back();
			activeBeautifierStack->pop_back();

			beautifiedLine = defineBeautifier->beautify(line);
			delete defineBeautifier;
			return beautifiedLine;
		}

		// unless this is a multi-line #define, return this precompiler line as is.
		if (!isInDefine && !isInDefineDefinition)
			return originalLine;
	}

	// if there exists any worker beautifier in the activeBeautifierStack,
	// then use it instead of me to indent the current line.
	// variables set by ASFormatter must be updated.
	if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
	{
		activeBeautifierStack->back()->inLineNumber = inLineNumber;
		activeBeautifierStack->back()->outLineNumber = outLineNumber;
		activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
		activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
		return activeBeautifierStack->back()->beautify(line);
	}

	// calculate preliminary indentation based on data from past lines
	if (!inStatementIndentStack->empty())
		spaceTabCount = inStatementIndentStack->back();


	for (i = 0; i < (int) headerStackSize; i++)
	{
		isInClass = false;

		if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
		                      && (*headerStack)[i] == &AS_OPEN_BRACKET)))
			++tabCount;

		if (!isJavaStyle && !namespaceIndent && i >= 1
		        && (*headerStack)[i-1] == &AS_NAMESPACE
		        && (*headerStack)[i] == &AS_OPEN_BRACKET)
			--tabCount;

		if (isCStyle && i >= 1
		        && (*headerStack)[i-1] == &AS_CLASS
		        && (*headerStack)[i] == &AS_OPEN_BRACKET)
		{
			if (classIndent)
				++tabCount;
			isInClass = true;
		}

		// is the switchIndent option is on, indent switch statements an additional indent.
		else if (switchIndent && i > 1 &&
		         (*headerStack)[i-1] == &AS_SWITCH &&
		         (*headerStack)[i] == &AS_OPEN_BRACKET
		        )
		{
			++tabCount;
			isInSwitch = true;
		}

	}

	if (!lineStartsInComment
	        && isCStyle
	        && isInClass
	        && classIndent
	        && headerStackSize >= 2
	        && (*headerStack)[headerStackSize-2] == &AS_CLASS
	        && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
	        && line[0] == '}')
		--tabCount;

	else if (!lineStartsInComment
	         && isInSwitch
	         && switchIndent
	         && headerStackSize >= 2
	         && (*headerStack)[headerStackSize-2] == &AS_SWITCH
	         && (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
	         && line[0] == '}')
		--tabCount;

	if (isInClassHeader)
	{
		isInClassHeaderTab = true;
		tabCount += 2;
	}

	if (isInConditional)
	{
		--tabCount;
	}


	// parse characters in the current line.

	for (i = 0; i < (int) line.length(); i++)
	{
		tempCh = line[i];

		prevCh = ch;
		ch = tempCh;

		outBuffer.append(1, ch);

		if (isWhiteSpace(ch))
			continue;

		// check for utf8 characters
		// isalnum() will display an assert message in debug if not bypassed here
		if (ch < 0)
			continue;

		// handle special characters (i.e. backslash+character such as \n, \t, ...)
		if (isSpecialChar)
		{
			isSpecialChar = false;
			continue;
		}
		if (!(isInComment || isInLineComment) && line.compare(i, 2, "\\\\") == 0)
		{
			outBuffer.append(1, '\\');
			i++;
			continue;
		}
		if (!(isInComment || isInLineComment) && ch == '\\')
		{
			isSpecialChar = true;
			continue;
		}

		// handle quotes (such as 'x' and "Hello Dolly")
		if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\''))
			if (!isInQuote)
			{
				quoteChar = ch;
				isInQuote = true;
			}
			else if (quoteChar == ch)
			{
				isInQuote = false;
				isInStatement = true;
				continue;
			}
		if (isInQuote)

⌨️ 快捷键说明

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