mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-21 07:43:08 +02:00
Enhancements - Nibbler + parsing
- New Nibbler object greatly assists in FF4 parsing. - Unit tests for Nibbler. - Record now parses itself. - Att now parses itself.
This commit is contained in:
parent
7c0aee4a5f
commit
5263147c83
12 changed files with 623 additions and 77 deletions
44
src/Att.cpp
44
src/Att.cpp
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <text.h>
|
||||
#include "Att.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -85,26 +86,45 @@ Att::~Att ()
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Parse the following forms:
|
||||
// name [[.mod] ...] : " [value] "
|
||||
void Att::parse (const std::string& input)
|
||||
//
|
||||
// start --> name --> . --> mod --> : --> " --> value --> " --> end
|
||||
// ^ |
|
||||
// |__________|
|
||||
//
|
||||
bool Att::parse (Nibbler& n)
|
||||
{
|
||||
// Ensure a clean object first.
|
||||
mName = "";
|
||||
mValue = "";
|
||||
mMods.clear ();
|
||||
|
||||
std::string::size_type colon = input.find (":");
|
||||
if (colon != std::string::npos)
|
||||
if (n.getUntilChars (".:", mName))
|
||||
{
|
||||
std::string name = input.substr (0, colon);
|
||||
// TODO Are there mods?
|
||||
mName = name;
|
||||
while (n.skip ('.'))
|
||||
{
|
||||
std::string mod;
|
||||
if (n.getUntilChars (".:", mod))
|
||||
mMods.push_back (mod);
|
||||
else
|
||||
throw std::string ("Missing . or : after modifier");
|
||||
}
|
||||
|
||||
std::string value = input.substr (colon + 1, std::string::npos);
|
||||
dequote (value);
|
||||
decode (value);
|
||||
mValue = value;
|
||||
if (n.skip (':'))
|
||||
{
|
||||
if (n.getQuoted ('"', mValue))
|
||||
return true;
|
||||
else if (n.getUntilChar (' ', mValue))
|
||||
return true;
|
||||
|
||||
throw std::string ("Missing attribute value");
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing : after attribute name");
|
||||
}
|
||||
else
|
||||
throw std::string ("Missing : after attribute name");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Nibbler.h"
|
||||
#include "Mod.h"
|
||||
|
||||
class Att
|
||||
|
@ -41,7 +42,7 @@ public:
|
|||
Att& operator= (const Att&); // Assignment operator
|
||||
~Att (); // Destructor
|
||||
|
||||
void parse (const std::string&);
|
||||
bool parse (Nibbler&);
|
||||
std::string composeF4 () const;
|
||||
|
||||
void addMod (const Mod&);
|
||||
|
|
|
@ -2,9 +2,9 @@ bin_PROGRAMS = task
|
|||
task_SOURCES = Config.cpp Date.cpp Record.cpp T.cpp TDB.cpp Att.cpp Mod.cpp \
|
||||
Filter.cpp Sequence.cpp Table.cpp Grid.cpp Timer.cpp \
|
||||
Duration.cpp StringTable.cpp Location.cpp Subst.cpp Keymap.cpp \
|
||||
color.cpp parse.cpp task.cpp command.cpp edit.cpp report.cpp \
|
||||
util.cpp text.cpp rules.cpp import.cpp Config.h Date.h Record.h \
|
||||
T.h TDB.h Att.h Mod.h Filter.h Sequence.h Table.h Grid.h \
|
||||
Timer.h Duration.h StringTable.h Location.h Subst.h Keymap.h \
|
||||
color.h task.h
|
||||
Nibbler.cpp color.cpp parse.cpp task.cpp command.cpp edit.cpp \
|
||||
report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h \
|
||||
Date.h Record.h T.h TDB.h Att.h Mod.h Filter.h Sequence.h \
|
||||
Table.h Grid.h Timer.h Duration.h StringTable.h Location.h \
|
||||
Subst.h Keymap.h Nibbler.h color.h task.h
|
||||
|
||||
|
|
282
src/Nibbler.cpp
Normal file
282
src/Nibbler.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "Nibbler.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler::Nibbler ()
|
||||
: mInput ("")
|
||||
, mCursor (0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler::Nibbler (const char* input)
|
||||
: mInput (input)
|
||||
, mCursor (0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler::Nibbler (const std::string& input)
|
||||
: mInput (input)
|
||||
, mCursor (0)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler::Nibbler (const Nibbler& other)
|
||||
{
|
||||
mInput = other.mInput;
|
||||
mCursor = other.mCursor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler& Nibbler::operator= (const Nibbler& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
mInput = other.mInput;
|
||||
mCursor = other.mCursor;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Nibbler::~Nibbler ()
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUntilChar (char c, std::string& result)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
std::string::size_type i = mInput.find (c, mCursor);
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
result = mInput.substr (mCursor, i - mCursor);
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUntilChars (const std::string& chars, std::string& result)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
std::string::size_type i = mInput.find_first_of (chars, mCursor);
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
result = mInput.substr (mCursor, i - mCursor);
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUntilString (const std::string& terminator, std::string& result)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
std::string::size_type i = mInput.find (terminator, mCursor);
|
||||
if (i != std::string::npos)
|
||||
{
|
||||
result = mInput.substr (mCursor, i - mCursor);
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::skip (const int quantity /* = 1 */)
|
||||
{
|
||||
if (mCursor <= mInput.length () - quantity)
|
||||
{
|
||||
mCursor += quantity;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::skip (char c)
|
||||
{
|
||||
if (mCursor < mInput.length () &&
|
||||
mInput[mCursor] == c)
|
||||
{
|
||||
++mCursor;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::skipAll (char c)
|
||||
{
|
||||
std::string::size_type i = mCursor;
|
||||
while (i < mInput.length () && mInput[i] == c)
|
||||
++i;
|
||||
|
||||
if (i != mCursor)
|
||||
{
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::skipAllChars (const std::string& chars)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
std::string::size_type i = mInput.find_first_not_of (chars, mCursor);
|
||||
if (i == mCursor)
|
||||
return false;
|
||||
|
||||
if (i == std::string::npos)
|
||||
mCursor = mInput.length (); // Yes, off the end.
|
||||
else
|
||||
mCursor = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getQuoted (char c, std::string& result)
|
||||
{
|
||||
std::string::size_type start = mCursor;
|
||||
if (start < mInput.length () - 1 && mInput[start] == c)
|
||||
{
|
||||
++start;
|
||||
if (start < mInput.length ())
|
||||
{
|
||||
std::string::size_type end = mInput.find (c, start);
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
result = mInput.substr (start, end - start);
|
||||
mCursor = end + 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getInt (int& result)
|
||||
{
|
||||
std::string::size_type i = mCursor;
|
||||
|
||||
if (i < mInput.length ())
|
||||
{
|
||||
if (mInput[i] == '-')
|
||||
++i;
|
||||
else if (mInput[i] == '+')
|
||||
++i;
|
||||
}
|
||||
|
||||
while (i < mInput.length () && ::isdigit (mInput[i]))
|
||||
++i;
|
||||
|
||||
if (i > mCursor)
|
||||
{
|
||||
result = ::atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUnsignedInt (int& result)
|
||||
{
|
||||
std::string::size_type i = mCursor;
|
||||
while (i < mInput.length () && ::isdigit (mInput[i]))
|
||||
++i;
|
||||
|
||||
if (i > mCursor)
|
||||
{
|
||||
result = ::atoi (mInput.substr (mCursor, i - mCursor).c_str ());
|
||||
mCursor = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUntilEOL (std::string& result)
|
||||
{
|
||||
return getUntilChar ('\n', result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::getUntilEOS (std::string& result)
|
||||
{
|
||||
if (mCursor < mInput.length ())
|
||||
{
|
||||
result = mInput.substr (mCursor, std::string::npos);
|
||||
mCursor = mInput.length ();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool Nibbler::depleted ()
|
||||
{
|
||||
if (mCursor >= mInput.length ())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
62
src/Nibbler.h
Normal file
62
src/Nibbler.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef INCLUDED_NIBBLER
|
||||
#define INCLUDED_NIBBLER
|
||||
|
||||
#include <string>
|
||||
|
||||
class Nibbler
|
||||
{
|
||||
public:
|
||||
Nibbler (); // Default constructor
|
||||
Nibbler (const char*); // Constructor
|
||||
Nibbler (const std::string&); // Constructor
|
||||
Nibbler (const Nibbler&); // Copy constructor
|
||||
Nibbler& operator= (const Nibbler&); // Assignment operator
|
||||
~Nibbler (); // Destructor
|
||||
|
||||
bool getUntilChar (char, std::string&);
|
||||
bool getUntilChars (const std::string&, std::string&);
|
||||
bool getUntilString (const std::string&, std::string&);
|
||||
bool skip (const int quantity = 1);
|
||||
bool skip (char);
|
||||
bool skipAll (char);
|
||||
bool skipAllChars (const std::string&);
|
||||
bool getQuoted (char, std::string&);
|
||||
bool getInt (int&);
|
||||
bool getUnsignedInt (int&i);
|
||||
bool getUntilEOL (std::string&);
|
||||
bool getUntilEOS (std::string&);
|
||||
bool depleted ();
|
||||
|
||||
private:
|
||||
std::string mInput;
|
||||
std::string::size_type mCursor;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -25,9 +25,11 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include "util.h"
|
||||
#include "Nibbler.h"
|
||||
#include "Record.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,19 +86,34 @@ std::string Record::composeF4 ()
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// start --> [ --> name --> : --> " --> value --> " --> ] --> end
|
||||
// ^ |
|
||||
// |________________________________|
|
||||
// start --> name --> : --> " --> value --> " --> end
|
||||
// ^ |
|
||||
// |________________________________|
|
||||
//
|
||||
void Record::parse (const std::string& input)
|
||||
{
|
||||
if (input[0] == '[' && input[input.length () - 1] == ']')
|
||||
Nibbler n (input);
|
||||
std::string line;
|
||||
if (n.skip ('[') && n.getUntilChar (']', line))
|
||||
{
|
||||
Nibbler nl (line);
|
||||
|
||||
bool first = true;
|
||||
Att a;
|
||||
while (a.parse (nl))
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
nl.skip (' ');
|
||||
|
||||
(*this)[a.name ()] = a;
|
||||
}
|
||||
|
||||
|
||||
throw std::string ("unimplemented Record:parse");
|
||||
std::string remainder;
|
||||
nl.getUntilEOS (remainder);
|
||||
if (remainder.length ())
|
||||
throw std::string ("Unrecognized garbage at end of line");
|
||||
}
|
||||
else
|
||||
throw std::string ("Record not recognized as FF4");
|
||||
|
|
|
@ -4,7 +4,7 @@ LFLAGS =
|
|||
LIBS =
|
||||
OBJECTS = main.o Context.o TDB.o T.o ../Sequence.o ../Filter.o ../Att.o \
|
||||
../Keymap.o ../Record.o ../Mod.o ../StringTable.o ../util.o \
|
||||
../text.o ../Date.o ../Config.o ../Location.o ../Subst.o
|
||||
../text.o ../Date.o ../Config.o ../Location.o ../Subst.o ../Nibbler.o
|
||||
|
||||
all: $(PROJECT)
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <sys/file.h>
|
||||
#include "text.h"
|
||||
|
@ -155,46 +156,67 @@ void TDB::unlock ()
|
|||
// Returns number of filtered tasks.
|
||||
int TDB::load (std::vector <T>& tasks, Filter& filter)
|
||||
{
|
||||
char line[T_LINE_MAX];
|
||||
foreach (location, mLocations)
|
||||
std::string file;
|
||||
int line_number;
|
||||
|
||||
try
|
||||
{
|
||||
std::cout << "# location.path: " << location->path << std::endl;
|
||||
|
||||
while (fgets (line, T_LINE_MAX, location->pending))
|
||||
char line[T_LINE_MAX];
|
||||
foreach (location, mLocations)
|
||||
{
|
||||
int length = ::strlen (line);
|
||||
if (length > 1)
|
||||
std::cout << "# location.path: " << location->path << std::endl;
|
||||
|
||||
line_number = 1;
|
||||
file = location->path + "/pending.data";
|
||||
while (fgets (line, T_LINE_MAX, location->pending))
|
||||
{
|
||||
line[length - 1] = '\0'; // Kill \n
|
||||
std::cout << "# line: " << line << std::endl;
|
||||
|
||||
T task (line);
|
||||
|
||||
if (filter.pass (task))
|
||||
int length = ::strlen (line);
|
||||
if (length > 1)
|
||||
{
|
||||
// TODO Add hidden attribute indicating source.
|
||||
tasks.push_back (task);
|
||||
line[length - 1] = '\0'; // Kill \n
|
||||
std::cout << "# line: " << line << std::endl;
|
||||
|
||||
T task (line);
|
||||
|
||||
if (filter.pass (task))
|
||||
{
|
||||
// TODO Add hidden attribute indicating source.
|
||||
tasks.push_back (task);
|
||||
}
|
||||
}
|
||||
|
||||
++line_number;
|
||||
}
|
||||
|
||||
line_number = 1;
|
||||
file = location->path + "/completed.data";
|
||||
while (fgets (line, T_LINE_MAX, location->completed))
|
||||
{
|
||||
int length = ::strlen (line);
|
||||
if (length > 1)
|
||||
{
|
||||
line[length - 1] = '\0'; // Kill \n
|
||||
std::cout << "# line: " << line << std::endl;
|
||||
|
||||
T task (line);
|
||||
|
||||
if (filter.pass (task))
|
||||
{
|
||||
// TODO Add hidden attribute indicating source.
|
||||
tasks.push_back (task);
|
||||
}
|
||||
}
|
||||
|
||||
++line_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (fgets (line, T_LINE_MAX, location->completed))
|
||||
{
|
||||
int length = ::strlen (line);
|
||||
if (length > 1)
|
||||
{
|
||||
line[length - 1] = '\0'; // Kill \n
|
||||
std::cout << "# line: " << line << std::endl;
|
||||
|
||||
T task (line);
|
||||
|
||||
if (filter.pass (task))
|
||||
{
|
||||
// TODO Add hidden attribute indicating source.
|
||||
tasks.push_back (task);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::string& e)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << " int " << file << " at line " << line_number;
|
||||
throw e + s.str ();
|
||||
}
|
||||
|
||||
return tasks.size ();
|
||||
|
|
1
src/tests/.gitignore
vendored
1
src/tests/.gitignore
vendored
|
@ -11,3 +11,4 @@ att.t
|
|||
mod.t
|
||||
record.t
|
||||
stringtable.t
|
||||
nibbler.t
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \
|
||||
parse.t seq.t att.t mod.t stringtable.t record.t # subst.t
|
||||
parse.t seq.t att.t mod.t stringtable.t record.t nibbler.t # subst.t
|
||||
CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
|
||||
LFLAGS = -L/usr/local/lib
|
||||
OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../Duration.o \
|
||||
../util.o ../Config.o ../Sequence.o ../Att.o ../Record.o ../Mod.o \
|
||||
../StringTable.o ../Subst.o
|
||||
../StringTable.o ../Subst.o ../Nibbler.o
|
||||
|
||||
all: $(PROJECT)
|
||||
|
||||
|
@ -62,3 +62,6 @@ stringtable.t: stringtable.t.o $(OBJECTS) test.o
|
|||
subst.t: subst.t.o $(OBJECTS) test.o
|
||||
g++ subst.t.o $(OBJECTS) test.o $(LFLAGS) -o subst.t
|
||||
|
||||
nibbler.t: nibbler.t.o $(OBJECTS) test.o
|
||||
g++ nibbler.t.o $(OBJECTS) test.o $(LFLAGS) -o nibbler.t
|
||||
|
||||
|
|
|
@ -74,57 +74,75 @@ int main (int argc, char** argv)
|
|||
if (good) t.fail ("Att::addMod (fartwizzle)");
|
||||
|
||||
// Att::parse
|
||||
Nibbler n ("");
|
||||
Att a7;
|
||||
a7.parse ("");
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 ()");
|
||||
good = true;
|
||||
try {a7.parse (n);} catch (...) {t.pass ("Att::compose () -> throw"); good = false;}
|
||||
if (good) t.fail ("Att::composeF4 () -> throw");
|
||||
|
||||
a7.parse ("name:value");
|
||||
n = Nibbler ("name:value");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:value)");
|
||||
|
||||
a7.parse ("name:\"value\"");
|
||||
n = Nibbler ("name:\"value\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:\"value\")");
|
||||
|
||||
a7.parse ("name:\"one two\"");
|
||||
n = Nibbler ("name:\"one two\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"one two\"", "Att::composeF4 (name:\"one two\")");
|
||||
|
||||
a7.parse ("name:\""\"");
|
||||
n = Nibbler ("name:\""\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\""\"", "Att::composeF4 (name:\""\")");
|
||||
|
||||
a7.parse ("name:\"&tab;",&open;&close;:\"");
|
||||
n = Nibbler ("name:\"&tab;",&open;&close;:\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"&tab;",&open;&close;:\"",
|
||||
"Att::composeF4 (name:\"&tab;",&open;&close;:\")");
|
||||
|
||||
a7.parse ("total gibberish");
|
||||
n = Nibbler ("total gibberish");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (total gibberish)");
|
||||
|
||||
a7.parse ("malformed");
|
||||
n = Nibbler ("malformed");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (malformed)");
|
||||
|
||||
a7.parse (":malformed");
|
||||
n = Nibbler (":malformed");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:malformed)");
|
||||
|
||||
a7.parse (":\"\"");
|
||||
n = Nibbler (":\"\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:\"\")");
|
||||
|
||||
a7.parse (":\"");
|
||||
n = Nibbler (":\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:\")");
|
||||
|
||||
a7.parse ("name:");
|
||||
n = Nibbler ("name:");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (name:)");
|
||||
|
||||
a7.parse ("name:\"value");
|
||||
n = Nibbler ("name:\"value");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:\"value)");
|
||||
|
||||
a7.parse ("name:value\"");
|
||||
n = Nibbler ("name:value\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:value\")");
|
||||
|
||||
a7.parse ("name:val\"ue");
|
||||
n = Nibbler ("name:val\"ue");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:val\"ue)");
|
||||
|
||||
a7.parse ("name:\"\"va\"\"\"\"\"lu\"\"\"e\"\"");
|
||||
n = Nibbler ("name:\"\"va\"\"\"\"\"lu\"\"\"e\"\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "name:\"value\"", "Att::composeF4 (name:\"\"va\"\"\"\"\"lu\"\"\"e\"\")");
|
||||
|
||||
a7.parse ("name\"");
|
||||
n = Nibbler ("name\"");
|
||||
a7.parse (n);
|
||||
t.is (a7.composeF4 (), "", "Att::composeF4 (name\")");
|
||||
|
||||
return 0;
|
||||
|
|
120
src/tests/nibbler.t.cpp
Normal file
120
src/tests/nibbler.t.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// task - a command line task list manager.
|
||||
//
|
||||
// Copyright 2006 - 2009, Paul Beckingham.
|
||||
// All rights reserved.
|
||||
//
|
||||
// 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.,
|
||||
// 51 Franklin Street, Fifth Floor,
|
||||
// Boston, MA
|
||||
// 02110-1301
|
||||
// USA
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#include <Nibbler.h>
|
||||
#include <test.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
UnitTest t (52);
|
||||
|
||||
Nibbler n ("this is 'a test' of 123the,nibbler");
|
||||
std::string s;
|
||||
int i;
|
||||
|
||||
t.ok (n.getUntilChar (' ', s), "nibble word");
|
||||
t.is (s, "this", "found 'this'");
|
||||
t.ok (n.skip (' '), "skip ws");
|
||||
t.ok (n.getUntilChar (' ', s), "nibble word");
|
||||
t.is (s, "is", "found 'is'");
|
||||
t.ok (n.skip (' '), "skip ws");
|
||||
t.ok (n.getQuoted ('\'', s), "nibble quoted");
|
||||
t.is (s, "a test", "found 'a test'");
|
||||
t.ok (n.skip (' '), "skip ws");
|
||||
t.ok (n.getUntilChar (' ', s), "nibble word");
|
||||
t.is (s, "of", "found 'of'");
|
||||
t.ok (n.skip (' '), "skip ws");
|
||||
t.ok (n.getInt (i), "nibble integer");
|
||||
t.is (i, 123, "found '123'");
|
||||
t.ok (n.getUntilChar (',', s), "nibble word");
|
||||
t.ok (n.skip (','), "skip ,");
|
||||
t.is (s, "the", "found 'the'");
|
||||
t.ok (n.getUntilEOS (s), "nibble remainder");
|
||||
t.is (s, "nibbler", "found 'nibbler'");
|
||||
|
||||
// Test EOS handling.
|
||||
n = Nibbler ("xx");
|
||||
t.ok (n.skip ('x'), "skip x");
|
||||
t.ok (n.skip ('x'), "skip x");
|
||||
t.notok (n.skip ('x'), "skip x");
|
||||
|
||||
n = Nibbler ("aaaaaX");
|
||||
t.ok (n.skip (5), "aaaaaX -> skip 5 pass");
|
||||
t.notok (n.skip(2), "X -> skip 2 fail");
|
||||
t.ok (n.skip (), "X -> skip pass");
|
||||
|
||||
n = Nibbler ("aaaaaa");
|
||||
t.ok (n.skipAll ('a'), "aaaaaa -> skipAll 'a' pass");
|
||||
|
||||
n = Nibbler ("aabbabab");
|
||||
t.ok (n.skipAllChars ("ab"), "aabbabab -> skipAllChars 'ab' pass");
|
||||
|
||||
n = Nibbler ("abcX");
|
||||
t.ok (n.skipAllChars ("abc"), "abcX -> skipChars abc pass");
|
||||
t.notok (n.skipAllChars ("abc"), "X -> skipChars abc fail");
|
||||
|
||||
n = Nibbler ("-123+456 789");
|
||||
t.ok (n.getInt (i), "-123+456 789 -> getInt pass");
|
||||
t.is (i, -123, "-123+456 789 -> -123 pass");
|
||||
t.notok (n.getUnsignedInt (i), "+456 789 -> getUnsignedInt fail");
|
||||
t.ok (n.getInt (i), "+456 789 -> getInt pass");
|
||||
t.is (i, 456, "+456 789 -> getInt pass");
|
||||
t.ok (n.skip (' '), "\s789 -> skip ' ' pass");
|
||||
t.ok (n.getUnsignedInt (i), "789 -> getUnsignedInt pass");
|
||||
t.is (i, 789, "789 -> getInt pass");
|
||||
|
||||
n = Nibbler ("123");
|
||||
t.ok (n.getInt (i), "123 -> getInt pass");
|
||||
t.is (i, 123, "123 -> getInt 123 pass");
|
||||
|
||||
n = Nibbler ("abc\nd");
|
||||
t.ok (n.getUntilEOL (s), "abc\\nd -> getUntilEOL pass");
|
||||
t.is (s, "abc", "abc\\nd -> getUntilEOL abc pass");
|
||||
|
||||
n = Nibbler ("abcba'foo");
|
||||
t.ok (n.getQuoted ('a', s), "abcba'foo -> getQuoted 'a' pass");
|
||||
t.is (s, "bcb", "abcba'foo -> getQuoted 'a' bcb pass");
|
||||
t.notok (n.getQuoted ('\'', s), "'foo -> getQuoted '\\'' fail");
|
||||
|
||||
n = Nibbler ("abcde");
|
||||
t.ok (n.getUntilChars ("ed", s), "abcde -> getUntilChars 'ed' pass");
|
||||
t.is (s, "abc", "abcde -> getUntilChars 'ed abc pass");
|
||||
|
||||
n = Nibbler ("abcde");
|
||||
t.ok (n.getUntilString ("de", s), "abcde -> getUntilString 'de' pass");
|
||||
t.is (s, "abc", "abcde -> getUntilString 'de abc pass");
|
||||
|
||||
n = Nibbler ("aa");
|
||||
t.notok (n.depleted (), "'aa' -> not depleted pass");
|
||||
t.ok (n.skip ('a'), "aa -> skip 'a' pass");
|
||||
t.ok (n.skip ('a'), "aa -> skip 'a' pass");
|
||||
t.ok (n.depleted (), "'' -> depleted pass");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
Loading…
Add table
Add a link
Reference in a new issue