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:
44
src/Att.cpp
44
src/Att.cpp
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <text.h>
|
||||||
#include "Att.h"
|
#include "Att.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -85,26 +86,45 @@ Att::~Att ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Parse the following forms:
|
//
|
||||||
// name [[.mod] ...] : " [value] "
|
// start --> name --> . --> mod --> : --> " --> value --> " --> end
|
||||||
void Att::parse (const std::string& input)
|
// ^ |
|
||||||
|
// |__________|
|
||||||
|
//
|
||||||
|
bool Att::parse (Nibbler& n)
|
||||||
{
|
{
|
||||||
|
// Ensure a clean object first.
|
||||||
mName = "";
|
mName = "";
|
||||||
mValue = "";
|
mValue = "";
|
||||||
mMods.clear ();
|
mMods.clear ();
|
||||||
|
|
||||||
std::string::size_type colon = input.find (":");
|
if (n.getUntilChars (".:", mName))
|
||||||
if (colon != std::string::npos)
|
|
||||||
{
|
{
|
||||||
std::string name = input.substr (0, colon);
|
while (n.skip ('.'))
|
||||||
// TODO Are there mods?
|
{
|
||||||
mName = name;
|
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);
|
if (n.skip (':'))
|
||||||
dequote (value);
|
{
|
||||||
decode (value);
|
if (n.getQuoted ('"', mValue))
|
||||||
mValue = value;
|
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 <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "Nibbler.h"
|
||||||
#include "Mod.h"
|
#include "Mod.h"
|
||||||
|
|
||||||
class Att
|
class Att
|
||||||
@@ -41,7 +42,7 @@ public:
|
|||||||
Att& operator= (const Att&); // Assignment operator
|
Att& operator= (const Att&); // Assignment operator
|
||||||
~Att (); // Destructor
|
~Att (); // Destructor
|
||||||
|
|
||||||
void parse (const std::string&);
|
bool parse (Nibbler&);
|
||||||
std::string composeF4 () const;
|
std::string composeF4 () const;
|
||||||
|
|
||||||
void addMod (const Mod&);
|
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 \
|
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 \
|
Filter.cpp Sequence.cpp Table.cpp Grid.cpp Timer.cpp \
|
||||||
Duration.cpp StringTable.cpp Location.cpp Subst.cpp Keymap.cpp \
|
Duration.cpp StringTable.cpp Location.cpp Subst.cpp Keymap.cpp \
|
||||||
color.cpp parse.cpp task.cpp command.cpp edit.cpp report.cpp \
|
Nibbler.cpp color.cpp parse.cpp task.cpp command.cpp edit.cpp \
|
||||||
util.cpp text.cpp rules.cpp import.cpp Config.h Date.h Record.h \
|
report.cpp util.cpp text.cpp rules.cpp import.cpp Config.h \
|
||||||
T.h TDB.h Att.h Mod.h Filter.h Sequence.h Table.h Grid.h \
|
Date.h Record.h T.h TDB.h Att.h Mod.h Filter.h Sequence.h \
|
||||||
Timer.h Duration.h StringTable.h Location.h Subst.h Keymap.h \
|
Table.h Grid.h Timer.h Duration.h StringTable.h Location.h \
|
||||||
color.h task.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 <sstream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "Nibbler.h"
|
||||||
#include "Record.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)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string remainder;
|
||||||
throw std::string ("unimplemented Record:parse");
|
nl.getUntilEOS (remainder);
|
||||||
|
if (remainder.length ())
|
||||||
|
throw std::string ("Unrecognized garbage at end of line");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::string ("Record not recognized as FF4");
|
throw std::string ("Record not recognized as FF4");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ LFLAGS =
|
|||||||
LIBS =
|
LIBS =
|
||||||
OBJECTS = main.o Context.o TDB.o T.o ../Sequence.o ../Filter.o ../Att.o \
|
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 \
|
../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)
|
all: $(PROJECT)
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
@@ -155,46 +156,67 @@ void TDB::unlock ()
|
|||||||
// Returns number of filtered tasks.
|
// Returns number of filtered tasks.
|
||||||
int TDB::load (std::vector <T>& tasks, Filter& filter)
|
int TDB::load (std::vector <T>& tasks, Filter& filter)
|
||||||
{
|
{
|
||||||
char line[T_LINE_MAX];
|
std::string file;
|
||||||
foreach (location, mLocations)
|
int line_number;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
std::cout << "# location.path: " << location->path << std::endl;
|
char line[T_LINE_MAX];
|
||||||
|
foreach (location, mLocations)
|
||||||
while (fgets (line, T_LINE_MAX, location->pending))
|
|
||||||
{
|
{
|
||||||
int length = ::strlen (line);
|
std::cout << "# location.path: " << location->path << std::endl;
|
||||||
if (length > 1)
|
|
||||||
|
line_number = 1;
|
||||||
|
file = location->path + "/pending.data";
|
||||||
|
while (fgets (line, T_LINE_MAX, location->pending))
|
||||||
{
|
{
|
||||||
line[length - 1] = '\0'; // Kill \n
|
int length = ::strlen (line);
|
||||||
std::cout << "# line: " << line << std::endl;
|
if (length > 1)
|
||||||
|
|
||||||
T task (line);
|
|
||||||
|
|
||||||
if (filter.pass (task))
|
|
||||||
{
|
{
|
||||||
// TODO Add hidden attribute indicating source.
|
line[length - 1] = '\0'; // Kill \n
|
||||||
tasks.push_back (task);
|
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))
|
catch (std::string& e)
|
||||||
{
|
{
|
||||||
int length = ::strlen (line);
|
std::stringstream s;
|
||||||
if (length > 1)
|
s << " int " << file << " at line " << line_number;
|
||||||
{
|
throw e + s.str ();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tasks.size ();
|
return tasks.size ();
|
||||||
|
|||||||
1
src/tests/.gitignore
vendored
1
src/tests/.gitignore
vendored
@@ -11,3 +11,4 @@ att.t
|
|||||||
mod.t
|
mod.t
|
||||||
record.t
|
record.t
|
||||||
stringtable.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 \
|
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
|
CFLAGS = -I. -I.. -Wall -pedantic -ggdb3 -fno-rtti
|
||||||
LFLAGS = -L/usr/local/lib
|
LFLAGS = -L/usr/local/lib
|
||||||
OBJECTS = ../TDB.o ../T.o ../parse.o ../text.o ../Date.o ../Duration.o \
|
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 \
|
../util.o ../Config.o ../Sequence.o ../Att.o ../Record.o ../Mod.o \
|
||||||
../StringTable.o ../Subst.o
|
../StringTable.o ../Subst.o ../Nibbler.o
|
||||||
|
|
||||||
all: $(PROJECT)
|
all: $(PROJECT)
|
||||||
|
|
||||||
@@ -62,3 +62,6 @@ stringtable.t: stringtable.t.o $(OBJECTS) test.o
|
|||||||
subst.t: subst.t.o $(OBJECTS) test.o
|
subst.t: subst.t.o $(OBJECTS) test.o
|
||||||
g++ subst.t.o $(OBJECTS) test.o $(LFLAGS) -o subst.t
|
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)");
|
if (good) t.fail ("Att::addMod (fartwizzle)");
|
||||||
|
|
||||||
// Att::parse
|
// Att::parse
|
||||||
|
Nibbler n ("");
|
||||||
Att a7;
|
Att a7;
|
||||||
a7.parse ("");
|
good = true;
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 ()");
|
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)");
|
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\")");
|
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\")");
|
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:\""\")");
|
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;:\"",
|
t.is (a7.composeF4 (), "name:\"&tab;",&open;&close;:\"",
|
||||||
"Att::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)");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (total gibberish)");
|
||||||
|
|
||||||
a7.parse ("malformed");
|
n = Nibbler ("malformed");
|
||||||
|
a7.parse (n);
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 (malformed)");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (malformed)");
|
||||||
|
|
||||||
a7.parse (":malformed");
|
n = Nibbler (":malformed");
|
||||||
|
a7.parse (n);
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:malformed)");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (:malformed)");
|
||||||
|
|
||||||
a7.parse (":\"\"");
|
n = Nibbler (":\"\"");
|
||||||
|
a7.parse (n);
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:\"\")");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (:\"\")");
|
||||||
|
|
||||||
a7.parse (":\"");
|
n = Nibbler (":\"");
|
||||||
|
a7.parse (n);
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 (:\")");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (:\")");
|
||||||
|
|
||||||
a7.parse ("name:");
|
n = Nibbler ("name:");
|
||||||
|
a7.parse (n);
|
||||||
t.is (a7.composeF4 (), "", "Att::composeF4 (name:)");
|
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)");
|
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\")");
|
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)");
|
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\"\")");
|
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\")");
|
t.is (a7.composeF4 (), "", "Att::composeF4 (name\")");
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Reference in New Issue
Block a user