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

📄 sgfparser.cpp

📁 qgo-1.5.4-r3.tar.gz linux下一个很好玩的游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/** sgfparser.cpp*/#include "qgo.h"#include "sgfparser.h"#include "boardhandler.h"#include "board.h"#include "move.h"#include "tree.h"#include "stonehandler.h"#include "matrix.h"#include "globals.h"#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <qfile.h>#include <qtextstream.h>#include <qprogressdialog.h>#include "xmlparser.h"#include "parserdefs.h"#include <qmessagebox.h>#include <qbig5codec.h>#include <qeucjpcodec.h> #include <qjiscodec.h> #include <qsjiscodec.h>#include <qgbkcodec.h>#include <qeuckrcodec.h>#include <qtsciicodec.h>#include <qstrlist.h>#include <qregexp.h>#include <qptrstack.h>#define STR_OFFSET 2000/* #define DEBUG_CODEC */// Note: This class is a DIRTY UGLY HACK.// It probably does all the stuff books tell you never ever to do.// But it speeds up sgf reading of large files (Kogo) significantly.class MyString{public:	MyString()	{	}		MyString(const QString &src)	{		Str = src;		strLength = src.length();	}	virtual ~MyString()	{	}		virtual const QChar at(uint i) const { return Str.at(i); }		virtual uint next_nonspace (uint i) const	{		// ignore lower characters, too		while (at(i).isSpace() || // == ' ' || at(i) == '\n' || at(i) == '\t' || 			   at(i) >= 'a' && at(i) <= 'z')			i++;		return i;	}		virtual int find(const char *c, unsigned int index) const	{		if (index >= strLength)			return -1;				// Offset. Hope that is enough. TODO Long comments check?		unsigned int l = index+STR_OFFSET<strLength ? index+STR_OFFSET : strLength,			cl = strlen(c),			i,			found;				do {			found = i = 0;			do {				if (Str.at(index+i) != c[i])					break;				found ++;				if (found == cl)					return index;			} while (i++ < cl);		} while (index++ < l);		if (index == l)			return -1;		return index;	}		virtual int find(char c, unsigned int index) const	{		if (index >= strLength)			return -1;		// Offset. Hope that is enough. TODO Long comments check?		unsigned int l = index+STR_OFFSET<strLength ? index+STR_OFFSET : strLength;				while (Str.at(index) != c && index++ < l);		if (index == l)			return -1;		return index;	}		virtual unsigned int length() const	{		return strLength;	}		unsigned int strLength;	private:	QString Str;};class MySimpleString : public MyString{public:	MySimpleString(const QString &src)	{		Str = src.latin1();		strLength = src.length();	}		virtual ~MySimpleString()	{	}		const QChar at(uint i) const { return Str[i]; }		int find(const char *c, unsigned int index) const	{		if (index >= strLength)			return -1;				// Offset. Hope that is enough. TODO Long comments check?		unsigned int l = index+STR_OFFSET<strLength ? index+STR_OFFSET : strLength,			cl = strlen(c),			i,			found;				do {			found = i = 0;			do {				if (Str[index+i] != c[i])					break;				found ++;				if (found == cl)					return index;			} while (i++ < cl);		} while (index++ < l);		if (index == l)			return -1;		return index;	}		int find(char c, unsigned int index) const	{		if (index >= strLength)			return -1;				// Offset. Hope that is enough. TODO Long comments check?		unsigned int l = index+STR_OFFSET<strLength ? index+STR_OFFSET : strLength;				while (Str[index] != c && index++ < l);		if (index == l)			return -1;		return index;	}	private:	const char* Str;    };// End dirty ugly hack. :*)SGFParser::SGFParser(BoardHandler *bh): boardHandler(bh){	CHECK_PTR(boardHandler);	stream = NULL;	xmlParser = NULL;}SGFParser::~SGFParser(){	delete xmlParser;}bool SGFParser::parse(const QString &fileName, const QString &filter, bool fastLoad){	if (fileName.isNull() || fileName.isEmpty())	{		qWarning("No filename given!");		return false;	}		CHECK_PTR(boardHandler);		QString toParse = loadFile(fileName);	if (toParse.isNull() || toParse.isEmpty())		return false;	// Convert old sgf/mgt format into new//	if (toParse.find("White[") != -1)  // Do a quick test if this is necassary.//		convertOldSgf(toParse);		// Check for filter, if given	if (!filter.isNull())	{		// XML		if (filter == Board::tr("XML"))		{			// Init xmlparser if not yet done			if (xmlParser == NULL)				xmlParser = new XMLParser(boardHandler);			xmlParser->parse(fileName);			return true;		}	}		if (!initGame(toParse, fileName))		return corruptSgf();	return doParse(toParse, fastLoad);}// Called from clipboard SGF importbool SGFParser::parseString(const QString &toParse){	if (toParse.isNull() || toParse.isEmpty() || !initGame(toParse, NULL))		return corruptSgf();	return doParse(toParse);}QString SGFParser::loadFile(const QString &fileName){	qDebug("Trying to load file <%s>", fileName.latin1());		QFile file(fileName);		if (!file.exists())	{		QMessageBox::warning(0, PACKAGE, Board::tr("Could not find file:") + " " + fileName);		return NULL;	}		if (!file.open(IO_ReadOnly))	{		QMessageBox::warning(0, PACKAGE, Board::tr("Could not open file:") + " " + fileName);		return NULL;	}		QTextStream txt(&file);	if (!initStream(&txt))	{		QMessageBox::critical(0, PACKAGE, Board::tr("Invalid text encoding given. Please check preferences!"));		return NULL;	}		QString toParse;		// Read file in string toParse	while (!txt.eof())		toParse.append(txt.readLine() + "\n");		file.close();#ifdef DEBUG_CODEC	QMessageBox::information(0, "READING", toParse);#endif	return toParse;}bool SGFParser::initStream(QTextStream *stream){	QTextCodec *codec = NULL;		stream->setEncoding(QTextStream::Locale);#ifdef DEBUG_CODEC	QMessageBox::information(0, "LOCALE", QTextCodec::locale());#endif		switch (static_cast<Codec>(setting->readIntEntry("CODEC")))	{	case codecNone:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "NONE");#endif		break;			case codecBig5:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "Big5");#endif#ifndef Q_WS_WIN		codec = new QBig5Codec();#endif		break;	case codecEucJP:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "EUC JP");#endif		codec = new QEucJpCodec();		break;			case codecJIS:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "JIS");#endif		codec = new QJisCodec();		break;			case codecSJIS:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "Shift JIS");#endif		codec = new QSjisCodec();		break;			case codecEucKr:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "EUC KR");#endif		codec = new QEucKrCodec();		break;			case codecGBK:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "GBK");#endif		codec = new QGbkCodec();		break;			case codecTscii:#ifdef DEBUG_CODEC		QMessageBox::information(0, "CODEC", "TSCII");#endif		codec = new QTsciiCodec();		break;			default:		return false;	}		if (codec != NULL && stream != NULL)		stream->setCodec(codec);		return true;}bool SGFParser::doParse(const QString &toParseStr, bool fastLoad){	if (toParseStr.isNull() || toParseStr.isEmpty())	{		qWarning("Failed loading from file. Is it empty?");		return false;	}		const MyString *toParse = NULL;	if (static_cast<Codec>(setting->readIntEntry("CODEC")) == codecNone)		toParse = new MySimpleString(toParseStr);	else		toParse = new MyString(toParseStr);	CHECK_PTR(toParse);		int pos = 0,		posVarBegin = 0,		posVarEnd = 0,		posNode = 0,		moves = 0,		i, x=-1, y=-1;	unsigned int pointer = 0,		strLength = toParse->length();	bool black = true,		setup = false,		old_label = false,		new_node = false;	isRoot = true;	bool remember_root;	QString unknownProperty;	State state;	MarkType markType;	QString moveStr, commentStr;	Position *position;	MoveNum *moveNum;	QPtrStack<Move> stack;	QPtrStack<MoveNum> movesStack;	QPtrStack<Position> toRemove;	stack.setAutoDelete(FALSE);	movesStack.setAutoDelete(TRUE);	toRemove.setAutoDelete(TRUE);	Tree *tree = boardHandler->getTree();		state = stateVarBegin;		bool cancel = false;	int progressCounter = 0;	QProgressDialog progress(Board::tr("Reading sgf file..."), Board::tr("Abort"), strLength,		boardHandler->board, "progress", true);		// qDebug("File length = %d", strLength);		progress.setProgress(0);	QString sss="";	do {		if (!(++progressCounter%10))		{			progress.setProgress(pointer);			if (progress.wasCancelled())			{				cancel = true;				break;			}		}				// qDebug("POINTER = %d: %c", pointer, toParse->Str[pointer]);				posVarBegin = toParse->find('(', pointer);		posVarEnd = toParse->find(')', pointer);		posNode = toParse->find(';', pointer);				pos = minPos(posVarBegin, posVarEnd, posNode);		// qDebug("VarBegin %d, VarEnd %d, Move %d, MINPOS %d", posVarBegin, posVarEnd, posNode, pos);		// qDebug("State before switch = %d", state);		// Switch states		// Node -> VarEnd		if (state == stateNode && pos == posVarEnd)			state = stateVarEnd;				// Node -> VarBegin		if (state == stateNode && pos == posVarBegin)			state = stateVarBegin;				// VarBegin -> Node		else if (state == stateVarBegin && pos == posNode)			state = stateNode;				// VarEnd -> VarBegin		else if (state == stateVarEnd && pos == posVarBegin)			state = stateVarBegin;				// qDebug("State after switch = %d", state);				// Do the work		switch (state)		{		case stateVarBegin:			if (pos != posVarBegin)			{				delete toParse;				return corruptSgf(pos);			}						// qDebug("Var BEGIN at %d, moves = %d", pos, moves);						stack.push(tree->getCurrent());			moveNum = new MoveNum;			moveNum->n = moves;			movesStack.push(moveNum);			pointer = pos + 1;			break;					case stateVarEnd:			if (pos != posVarEnd)			{				delete toParse;				return corruptSgf(pos);			}						// qDebug("VAR END");						if (!movesStack.isEmpty() && !stack.isEmpty())			{				Move *m = stack.pop();				CHECK_PTR(m);				x = movesStack.pop()->n;								// qDebug("Var END at %d, moves = %d, moves from stack = %d", pos, moves, x);								for (i=moves; i > x; i--)				{					position = toRemove.pop();					if (position == NULL)						continue;					boardHandler->getStoneHandler()->removeStone(position->x, position->y);					// qDebug("Removing %d %d from stoneHandler.", position->x, position->y);				}								moves = x;								if (!fastLoad)					boardHandler->getStoneHandler()->updateAll(m->getMatrix(), false);								tree->setCurrent(m);			}			pointer = pos + 1;			break;					case stateNode:			if (pos != posNode)			{				delete toParse;				return corruptSgf(pos);			}						// qDebug("Node at %d", pos);			commentStr = QString();			setup = false;			markType = markNone;						// Create empty node			remember_root = isRoot;			if (!isRoot)			{				boardHandler->createMoveSGF();				unknownProperty = QString();if (tree->getCurrent()->getTimeinfo())	qWarning("*** Timeinfo set !!!!");				//tree->getCurrent()->setTimeinfo(false);			}			else				isRoot = false;						new_node = true;						Property prop;			pos ++;			do {				uint tmppos=0;				pos = toParse->next_nonspace (pos);								// qDebug("READING PROPERTY AT %d: %c", pos, toParse->at(pos));								// if (toParse->find("B[", pos) == pos)				if (toParse->at(pos) == 'B' && toParse->at(tmppos = toParse->next_nonspace (pos + 1)) == '[')				{					prop = moveBlack;					pos = tmppos;					black = true;				}				// else if (toParse->find("W[", pos) == pos)				else if (toParse->at(pos) == 'W' && toParse->at(tmppos = toParse->next_nonspace (pos + 1)) == '[')				{					prop = moveWhite;					pos = tmppos;					black = false;				}				else if (toParse->at(pos) == 'N' && toParse->at(tmppos = toParse->next_nonspace (pos + 1)) == '[')				{					prop = nodeName;					pos = tmppos;				}				else if (toParse->find("AB", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editBlack;					pos = tmppos;					setup = true;					black = true;				}				else if (toParse->find("AW", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editWhite;					pos = tmppos;					setup = true;					black = false;				}				else if (toParse->find("AE", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editErase;					pos = tmppos;					setup = true;				}				else if (toParse->find("TR", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editMark;					markType = markTriangle;					pos = tmppos;				}				else if (toParse->find("CR", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editMark;					markType = markCircle;					pos = tmppos;				}				else if (toParse->find("SQ", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editMark;					markType = markSquare;					pos = tmppos;				}				else if (toParse->find("MA", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editMark;					markType = markCross;					pos = tmppos;				}				// old definition				else if (toParse->find("M", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 1)) == '[')				{					prop = editMark;					markType = markCross;					pos = tmppos;				}				else if (toParse->find("LB", pos) == pos && toParse->at(tmppos = toParse->next_nonspace (pos + 2)) == '[')				{					prop = editMark;					markType = markText;					pos = tmppos;					old_label = false;				}

⌨️ 快捷键说明

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