# # # add_file "guitone/src/util/StdioParser.cpp" # content [38a3832f54e41349f8cfabd7c7264941ca86eddb] # # add_file "guitone/src/util/StdioParser.h" # content [59d4575d22272d7beed48c8c92e02b269baa13aa] # # patch "guitone/guitone.pro" # from [3e702820638e27442e7f8faee1acaad663c97f1b] # to [795b23dd7f3e7c4cd881176e16e051a70e8ed88a] # # patch "guitone/src/monotone/Monotone.cpp" # from [b8f251abac1aee8cc276be23dc2807e1c66061f3] # to [5385c818c891beae88caba3a4be7db005e543a0e] # # patch "guitone/src/monotone/Monotone.h" # from [99eae4dc0a19bca4b8dda00a5b67dbf397016dc5] # to [8af821da17fcc7994eff7545e685ba5ae73013dc] # # patch "guitone/src/util/StanzaParser.cpp" # from [a4d3a459b736e4345c5abddf582ea8554621a830] # to [117ebd6d30d6daf217f4977fe9f68086e839f316] # # patch "guitone/src/util/StanzaParser.h" # from [f8dcbbcab5e063cd2830f06cd880e920f0be7e19] # to [2d75aaeb378815e90d66596b07883667bef4575d] # ============================================================ --- guitone/src/util/StdioParser.cpp 38a3832f54e41349f8cfabd7c7264941ca86eddb +++ guitone/src/util/StdioParser.cpp 38a3832f54e41349f8cfabd7c7264941ca86eddb @@ -0,0 +1,103 @@ +/*************************************************************************** +* Copyright (C) 2007 by Thomas Keller * +* address@hidden * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#include "StdioParser.h" + +StdioParser::StdioParser(const QByteArray & input) +{ + in = input; + size = in.length(); + charPos = 0; +} + +StdioParser::~StdioParser() {} + +bool StdioParser::parse() +{ + // chunk format: :::: + + commandNumber = getNumber(); + Q_ASSERT(getNext() == ':'); + errorCode = getNumber(); + Q_ASSERT(getNext() == ':'); + chunkType = getNext(); + Q_ASSERT( + (chunkType >= 'A' && chunkType <= 'Z') || + (chunkType >= 'a' && chunkType <= 'z') + ); + Q_ASSERT(getNext() == ':'); + chunkSize = getNumber(); + + if (chunkSize > charsLeft()) + { + return false; + } + + payload = in.mid(chunkSize); + advance(chunkSize); + + return true; +} + +int StdioParser::getNumber() +{ + int number = 0; + int origPos = charPos; + + while (char ch = whatsNext()) + { + if (ch < '0' || ch > '9') + { + // ensure that we've read at least one char + Q_ASSERT(origPos != charPos); + break; + } + number *= 10; + number += (ch - '0'); + advance(); + } + + return number; +} + +char StdioParser::whatsNext(int count /* = 0 */) +{ + if (charPos + count >= size) return '\0'; + return in.at(charPos + count); +} + +void StdioParser::advance(int count /* = 1 */) +{ + if (charPos + count >= size) return; + charPos += count; +} + +char StdioParser::getNext() +{ + char ch = in.at(charPos); + advance(); + return ch; +} + +int StdioParser::charsLeft() +{ + return size-charPos; +} + ============================================================ --- guitone/src/util/StdioParser.h 59d4575d22272d7beed48c8c92e02b269baa13aa +++ guitone/src/util/StdioParser.h 59d4575d22272d7beed48c8c92e02b269baa13aa @@ -0,0 +1,58 @@ +/*************************************************************************** +* Copyright (C) 2007 by Thomas Keller * +* address@hidden * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + +#ifndef STDIO_PARSER_H +#define STDIO_PARSER_H + +#include + +class StdioParser : public QObject +{ + Q_OBJECT +public: + StdioParser(const QByteArray &); + ~StdioParser(); + bool parse(); + inline int getCommandNumber() { return commandNumner; } + inline int getErrorNumber() { return errorNumber; } + inline char getChunkType() { return chunkType; } + inline int getChunkSize() { return chunkSize; } + inline QByteArray getPayload() { return payload; } + inline int getCharPos() { return charPos; } + +private: + char whatsNext(int count = 0); + char getNext(); + void advance(int count = 1); + int charsLeft(); + int getNumber(); + + int commandNumber; + int errorNumber; + char chunkType; + int chunkSize; + QByteArray payload; + + QByteArray in; + int charPos; + int size; +}; + +#endif ============================================================ --- guitone/guitone.pro 3e702820638e27442e7f8faee1acaad663c97f1b +++ guitone/guitone.pro 795b23dd7f3e7c4cd881176e16e051a70e8ed88a @@ -54,7 +54,8 @@ HEADERS += src/view/MainWindow.h \ src/util/SignalWaiter.h \ src/util/OpenFile.h \ src/util/TreeBuilder.h \ - src/util/DebugLog.h + src/util/DebugLog.h \ + src/util/StdioParser.h SOURCES += src/view/MainWindow.cpp \ src/view/TreeView.cpp \ src/view/Splitter.cpp \ @@ -98,6 +99,7 @@ SOURCES += src/view/MainWindow.cpp \ src/util/OpenFile.cpp \ src/util/TreeBuilder.cpp \ src/util/DebugLog.cpp \ + src/util/StdioParser.cpp \ src/main.cpp FORMS += res/forms/switch_workspace.ui \ ============================================================ --- guitone/src/monotone/Monotone.cpp b8f251abac1aee8cc276be23dc2807e1c66061f3 +++ guitone/src/monotone/Monotone.cpp 5385c818c891beae88caba3a4be7db005e543a0e @@ -79,6 +79,7 @@ #include "Monotone.h" #include "SignalWaiter.h" +#include "StdioParser.h" #include #include @@ -475,75 +476,46 @@ bool Monotone::readAndParseStdout(int & bool Monotone::readAndParseStdout(int & retCode) { - QByteArray byteArray = process->readAllStandardOutput(); - input.append(byteArray); + input.append(process->readAllStandardOutput()); - // parse out the contents of each line - QRegExp regex("^(\\d+):(\\d+):([ml]):(\\d+):"); + StdioParser parser(input); - while (regex.indexIn(input) != -1) + // if the chunk is not yet complete, try again later + if (!parser.parse()) { - QStringList list = regex.capturedTexts(); + return false; + } + + input = input.mid(parser.getCharPos()); + output.append(parser.getPayload()); + + // check if this was the last output + if (parser->getChunkType() == 'l') + { + Q_ASSERT(input.length() == 0); + retCode = parser.getErrorNumber(); - Q_ASSERT(input.length() >= regex.matchedLength()); - - // at first, throw away the data header - input = input.right(input.length() - regex.matchedLength()); - - // now determine how many bytes of real output we have - int outBytes = list[4].toInt(); - - // check if we already got all output, if not, do the processing - // when subsequent data are flushed and processed here - if (input.length() < outBytes) + // if the command did not return successfully, try to strip + // prefixes from the error output + if (retCode > 0) { - // prepend the data header again - input.prepend(QString("%1:%2:%3:%4:") - .arg(list[1]) - .arg(list[2]) - .arg(list[3]) - .arg(list[4]) - ); - return false; + + // FIXME: convert the code here + + + output = stripMtnPrefix(output); } - // add the byte amount to the output string, make sure that these - // contents are properly recognized as UTF-8 encoded - QByteArray newOutput = input.left(outBytes).toAscii(); - const char * data = newOutput.data(); - output.append(QString::fromUtf8(data)); + // command successfully parsed + return true; + } - // and remove it from the input string - input = input.right(input.length() - outBytes); - - // check if this was the last output - if (list[3].compare("l") == 0) - { - Q_ASSERT(input.length() == 0); - retCode = list[2].toInt(); - - // if the command did not return successfully, try to strip - // prefixes from the error output - if (retCode > 0) - { - output = stripMtnPrefix(output); - } - - // command successfully parsed - return true; - } - - // if this was not the last output, but there are no bytes left, - // we need to wait for further data - if (input.size() == 0) - { - return false; - } + // if this was not the last output, but there are no bytes left, + // we need to wait for further data + if (input.size() == 0) + { + return false; } - - // apparently we couldn't parse the string, this could be because not - // enough data have been flushed or the format is somehow screwed up - return false; } QString Monotone::getDataAndReset() ============================================================ --- guitone/src/monotone/Monotone.h 99eae4dc0a19bca4b8dda00a5b67dbf397016dc5 +++ guitone/src/monotone/Monotone.h 8af821da17fcc7994eff7545e685ba5ae73013dc @@ -67,8 +67,8 @@ class Monotone : public QObject bool readAndParseStdout(int &); bool timeout; - QString input; - QString output; + QByteArray input; + QByteArray output; QString commandLine; bool isProcessingData; bool isCleanExit; ============================================================ --- guitone/src/util/StanzaParser.cpp a4d3a459b736e4345c5abddf582ea8554621a830 +++ guitone/src/util/StanzaParser.cpp 117ebd6d30d6daf217f4977fe9f68086e839f316 @@ -20,7 +20,7 @@ #include "StanzaParser.h" -StanzaParser::StanzaParser(const QString input) +StanzaParser::StanzaParser(const QString & input) { in = input; size = in.length(); ============================================================ --- guitone/src/util/StanzaParser.h f8dcbbcab5e063cd2830f06cd880e920f0be7e19 +++ guitone/src/util/StanzaParser.h 2d75aaeb378815e90d66596b07883667bef4575d @@ -35,7 +35,7 @@ public: { Q_OBJECT public: - StanzaParser(const QString); + StanzaParser(const QString &); ~StanzaParser(); StanzaList getStanzas(); private: