# # # add_file "src/util/StanzaParser.cpp" # content [f445e11ea79131a8ac7ccbb88692eb4eebe87027] # # add_file "src/util/StanzaParser.h" # content [06eef3f8b021197948a09ef78331a9db95fdeb31] # # patch "guitone.pro" # from [b74cf308de08421ab0678cc1bcdec204cbe8e7ec] # to [485dea4eaf2df0efbbda95b82ac9c2e58f383446] # # patch "src/model/Manifest.cpp" # from [1e6f8ec9929d88ea4414c7dfdfc00f07301c433d] # to [a4a1118533f18ba49b2be1e9da11f13a46ba7c4a] # # patch "src/model/Manifest.h" # from [7d896190c8ae3ff10ab30c458a97ff2991dd60c0] # to [0427f245fa7314ac16fa40f8053c1894fe461fd5] # ============================================================ --- src/util/StanzaParser.cpp f445e11ea79131a8ac7ccbb88692eb4eebe87027 +++ src/util/StanzaParser.cpp f445e11ea79131a8ac7ccbb88692eb4eebe87027 @@ -0,0 +1,152 @@ +/*************************************************************************** +* Copyright (C) 2006 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 "StanzaParser.h" + +StanzaParser::StanzaParser(const QString input) +{ + in = input; + size = in.size(); + charPos = 0; +} + +StanzaParser::~StanzaParser() {} + +StanzaList StanzaParser::getStanzas() +{ + StanzaList list; + while (true) + { + Stanza stanza = getStanza(); + if (stanza.empty()) break; + list.append(stanza); + } + return list; +} + +Stanza StanzaParser::getStanza() +{ + Stanza stanza; + + while (true) + { + QChar next = whatsNext(); + if (next == QChar('\n') || next == QChar('\0')) break; + + StanzaEntry entry; + entry.sym = getSymbol(); + if (entry.sym.size() == 0) + { + qWarning("StanzaParser::getStanza(): %d: Couldn't get symbol.", charPos); + } + entry.val1 = getHash(); + // not a hash? + if (entry.val1.size() == 0) + { + entry.val1 = getValue(); + if (entry.val1.size() == 0) + { + qWarning("StanzaParser::getStanza(): %d: Couldn't get string.", charPos); + } + // optional: second string (e.g. for attribute sets) + entry.val2 = getValue(); + } + + stanza.append(entry); + + eatSpaces(); + QChar cur = getNext(); + if (cur != QChar('\n')) + qWarning("StanzaParser::getStanza(): %d: expected '\\n', got %c", charPos, cur.toLatin1()); + } + + return stanza; +} + +QChar StanzaParser::whatsNext(int count) +{ + if (charPos + count >= size) return QChar('\0'); + return in.at(charPos + count); +} + +void StanzaParser::eatSpaces() +{ + while (whatsNext() == QChar(' ')) { charPos++; } +} + +QString StanzaParser::getSymbol() +{ + eatSpaces(); + int pos = in.indexOf(QRegExp("[^\\w]"), charPos); + if (pos == -1) return QString(); + QString sym = in.mid(charPos, pos - charPos); + charPos = pos; + return sym; +} + +QString StanzaParser::getValue() +{ + eatSpaces(); + if (whatsNext() != QChar('"')) return QString(); + advance(); + + QString ret; + QChar last('\0'); + while (true) + { + QChar cur = getNext(); + // string end? + if (cur == '\0' || (cur == '"' && last != '\\')) break; + last = cur; + ret.append(cur); + } + return ret; +} + +QString StanzaParser::getHash() +{ + eatSpaces(); + if (whatsNext() != QChar('[')) return QString(); + advance(); + + int hashLen = 40; + QString ret = in.mid(charPos, hashLen); + advance(hashLen); + + QChar ch = getNext(); + if (ch == QChar(']')) + advance(); + else + qWarning("StanzaParser::getHash(): %d: expected ], got %c", charPos, ch.toLatin1()); + + return ret; +} + +void StanzaParser::advance(int count) +{ + charPos += count; +} + +QChar StanzaParser::getNext() +{ + QChar ch = in.at(charPos); + advance(); + return ch; +} ============================================================ --- src/util/StanzaParser.h 06eef3f8b021197948a09ef78331a9db95fdeb31 +++ src/util/StanzaParser.h 06eef3f8b021197948a09ef78331a9db95fdeb31 @@ -0,0 +1,55 @@ +/*************************************************************************** +* Copyright (C) 2006 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 STANZA_PARSER_H +#define STANZA_PARSER_H + +typedef struct { + QString sym; + QString val1; + QString val2; +} StanzaEntry; + +typedef QList Stanza; +typedef QList StanzaList; + +class StanzaParser : public QObject +{ + Q_OBJECT +public: + StanzaParser(const QString); + ~StanzaParser(); + StanzaList getStanzas(); +private: + QChar whatsNext(int count = 1); + QChar getNext(); + Stanza getStanza(); + void eatSpaces(); + QString getSymbol(); + QString getValue(); + QString getHash(); + void advance(int count = 1); + + QString in; + int charPos; + int size; +}; + +#endif ============================================================ --- guitone.pro b74cf308de08421ab0678cc1bcdec204cbe8e7ec +++ guitone.pro 485dea4eaf2df0efbbda95b82ac9c2e58f383446 @@ -8,7 +8,8 @@ src/model/ProxyModel.h \ src/model/Manifest.h \ src/util/IconProvider.h \ - src/util/Settings.h + src/util/StanzaParser.h \ + src/util/Settings.h SOURCES += src/view/Guitone.cpp \ src/view/WorkspaceView.cpp \ src/view/PropertiesView.cpp \ @@ -18,7 +19,8 @@ src/model/ProxyModel.cpp \ src/model/Manifest.cpp \ src/util/IconProvider.cpp \ - src/util/Settings.cpp \ + src/util/StanzaParser.cpp \ + src/util/Settings.cpp \ src/main.cpp TEMPLATE = app DEPENDPATH += src ============================================================ --- src/model/Manifest.cpp 1e6f8ec9929d88ea4414c7dfdfc00f07301c433d +++ src/model/Manifest.cpp a4a1118533f18ba49b2be1e9da11f13a46ba7c4a @@ -20,6 +20,7 @@ #include "Manifest.h" #include "../monotone/Monotone.h" +#include "../util/StanzaParser.h" Manifest::Manifest() : revision("") {} @@ -61,35 +62,62 @@ return; } - QStringList *lines = new QStringList(); - for (QStringList::Iterator it = output->begin(); it != output->end(); ++it) - { - QStringList tmp = (*it).split("\n"); - for (QStringList::Iterator it2 = tmp.begin(); it2 != tmp.end(); ++it) - { - lines->append(*it2); - } - } + StanzaParser* parser = new StanzaParser(output->join("\n")); + StanzaList list = parser->getStanzas(); + ManifestMap* map = new ManifestMap(); - ManifestMap * map = new ManifestMap(); - - QRegExp regex("^\\s*(file|content)\\s+(?:\\[\")(.+?)(?:\"|\\])$"); - QString lastFile; - - for (QStringList::Iterator it = output->begin(); it != output->end(); ++it) + for (int i=0, size = list.size(); i < size; ++i) { - if (regex.indexIn(*it) == -1) + Stanza stanza = list.at(i); + + QString path; + ManifestItem item; + bool isItem = false; + + for (int j=0, size2 = stanza.size(); j < size2; j++) { - continue; + StanzaEntry entry = stanza.at(j); + if (i == 0 && j == 0) + { + if (entry.sym != "format_version") + { + qWarning("Manifest::parseOutput(): First entry in first stanza should be used format version."); + } else + if (entry.val1 != "1") + { + qWarning("Manifest::parseOutput(): Format version is unequal to '1' - newer interface version?"); + } + break; + } + + // we're now only interested in stanzas starting with a "file" or "dir" entry + if (j == 0 && entry.sym != "file" && entry.sym != "dir") break; + + isItem = true; + + if (entry.sym == "file" || entry.sym == "dir") + { + path = entry.val1; + continue; + } + + if (entry.sym == "content") + { + item.fileId = entry.val1; + continue; + } + + if (entry.sym == "attr") + { + item.attr[entry.val1] = entry.val2; + continue; + } } - QStringList list = regex.capturedTexts(); - if (list[0] == "file") - { - lastFile = list[0]; - continue; - } - map->insert(lastFile, list[1]); + // check if we really processed an item entry + if (!isItem) continue; + map->insert(path, item); } + emit manifestRead(map); } ============================================================ --- src/model/Manifest.h 7d896190c8ae3ff10ab30c458a97ff2991dd60c0 +++ src/model/Manifest.h 0427f245fa7314ac16fa40f8053c1894fe461fd5 @@ -21,7 +21,12 @@ #ifndef MANIFEST_H #define MANIFEST_H -typedef QMap ManifestMap; +typedef QMap ItemAttributes; +typedef struct { + QString fileId; + ItemAttributes attr; +} ManifestItem; +typedef QMap ManifestMap; class Manifest : public QObject {