Enhancement - Sequence object

- Implemented sequence object to encapsulate the worries of parsing
  sequences.
- Implemented unit tests.
This commit is contained in:
Paul Beckingham 2009-05-23 16:10:42 -04:00
parent 3cdfb733de
commit f3724aa714
15 changed files with 209 additions and 29 deletions

View file

@ -1,2 +1,2 @@
bin_PROGRAMS = task
task_SOURCES = Config.cpp Date.cpp Record.cpp T.cpp TDB.cpp Att.cpp Mod.cpp Table.cpp Grid.cpp Timer.cpp Duration.cpp StringTable.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 Table.h Grid.h Timer.h Duration.h StringTable.h color.h task.h
task_SOURCES = Config.cpp Date.cpp Record.cpp T.cpp TDB.cpp Att.cpp Mod.cpp Sequence.cpp Table.cpp Grid.cpp Timer.cpp Duration.cpp StringTable.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 Sequence.h Table.h Grid.h Timer.h Duration.h StringTable.h color.h task.h

View file

@ -27,7 +27,9 @@
#include <map>
#include <string>
#include <ctype.h>
#include "util.h"
#include "text.h"
#include "Sequence.h"
////////////////////////////////////////////////////////////////////////////////
@ -36,20 +38,9 @@ Sequence::Sequence ()
}
////////////////////////////////////////////////////////////////////////////////
Sequence::Sequence (const Sequence& other)
Sequence::Sequence (const std::string& input)
{
throw std::string ("unimplemented Sequence::Sequence");
}
////////////////////////////////////////////////////////////////////////////////
Sequence& Sequence::operator= (const Sequence& other)
{
throw std::string ("unimplemented Sequence::operator=");
if (this != &other)
{
}
return *this;
parse (input);
}
////////////////////////////////////////////////////////////////////////////////
@ -60,7 +51,51 @@ Sequence::~Sequence ()
////////////////////////////////////////////////////////////////////////////////
void Sequence::parse (const std::string& input)
{
throw std::string ("unimplemented Sequence::parse");
std::vector <std::string> ranges;
split (ranges, input, ',');
std::vector <std::string>::iterator it;
for (it = ranges.begin (); it != ranges.end (); ++it)
{
std::vector <std::string> range;
split (range, *it, '-');
switch (range.size ())
{
case 1:
{
if (! validId (range[0]))
throw std::string ("Invalid ID in sequence");
int id = ::atoi (range[0].c_str ());
this->push_back (id);
}
break;
case 2:
{
if (! validId (range[0]) ||
! validId (range[1]))
throw std::string ("Invalid ID in range");
int low = ::atoi (range[0].c_str ());
int high = ::atoi (range[1].c_str ());
if (low > high)
throw std::string ("Inverted sequence range high-low");
if (high - low > 1000)
throw std::string ("Range too large, exceeded 1,000 IDs");
for (int i = low; i <= high; ++i)
this->push_back (i);
}
break;
default:
throw std::string ("Not a sequence.");
break;
}
}
}
////////////////////////////////////////////////////////////////////////////////
@ -81,3 +116,16 @@ void Sequence::combine (const Sequence& other)
}
////////////////////////////////////////////////////////////////////////////////
bool Sequence::validId (const std::string& input)
{
if (input.length () == 0)
return false;
for (size_t i = 0; i < input.length (); ++i)
if (!::isdigit (input[i]))
return false;
return true;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -34,12 +34,14 @@ class Sequence : public std::vector <int>
{
public:
Sequence (); // Default constructor
Sequence (const Sequence&); // Copy constructor
Sequence& operator= (const Sequence&); // Assignment operator
Sequence (const std::string&); // Parse
~Sequence (); // Destructor
void parse (const std::string&);
void combine (const Sequence&);
private:
bool validId (const std::string&);
};
#endif

View file

@ -29,6 +29,8 @@
#include <vector>
#include <map>
#include <sys/types.h>
#include "T.h"
#include "TDB.h"
#include "Config.h"
#include "Table.h"
#include "Date.h"

View file

@ -6,3 +6,4 @@ duration.t
text.t
autocomplete.t
parse.t
seq.t

View file

@ -1,9 +1,9 @@
PROJECT = t.t tdb.t date.t duration.t t.benchmark.t text.t autocomplete.t \
parse.t
parse.t seq.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
../util.o ../Config.o ../Sequence.o
all: $(PROJECT)
@ -43,3 +43,6 @@ autocomplete.t: autocomplete.t.o $(OBJECTS) test.o
parse.t: parse.t.o $(OBJECTS) test.o
g++ parse.t.o $(OBJECTS) test.o $(LFLAGS) -o parse.t
seq.t: seq.t.o $(OBJECTS) test.o
g++ seq.t.o $(OBJECTS) test.o $(LFLAGS) -o seq.t

View file

@ -26,7 +26,8 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <test.h>
#include <../task.h>
#include <util.h>
#include <task.h>
////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)

View file

@ -30,11 +30,11 @@
////////////////////////////////////////////////////////////////////////////////
// daily, day, Nd
// weekly, Nw, sennight, biweekly, fortnight
// weekly, 1w, sennight, biweekly, fortnight
// monthly, bimonthly, Nm, semimonthly
// 1st 2nd 3rd 4th .. 31st
// quarterly, Nq
// biannual, biyearly, annual, semiannual, yearly, Ny
// quarterly, 1q
// biannual, biyearly, annual, semiannual, yearly, 1y
int convertDuration (const std::string& input)
{

View file

@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "task.h"
#include "text.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////

118
src/tests/seq.t.cpp Normal file
View file

@ -0,0 +1,118 @@
////////////////////////////////////////////////////////////////////////////////
// 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 <iostream>
#include <Sequence.h>
#include <test.h>
////////////////////////////////////////////////////////////////////////////////
Sequence parseSequence (const std::string& input)
{
try { Sequence s (input); return s; }
catch (...) {}
return Sequence ();
}
int main (int argc, char** argv)
{
UnitTest t (18);
// 1
Sequence seq = parseSequence ("1");
t.is (seq.size (), (size_t)1, "seq '1' -> 1 item");
if (seq.size () == 1)
{
t.is (seq[0], 1, "seq '1' -> [0] == 1");
}
else
{
t.fail ("seq '1' -> [0] == 1");
}
// 1,3
seq = parseSequence ("1,3");
t.is (seq.size (), (size_t)2, "seq '1,3' -> 2 items");
if (seq.size () == 2)
{
t.is (seq[0], 1, "seq '1,3' -> [0] == 1");
t.is (seq[1], 3, "seq '1,3' -> [1] == 3");
}
else
{
t.fail ("seq '1,3' -> [0] == 1");
t.fail ("seq '1,3' -> [1] == 3");
}
// 1,3-5,7
seq = parseSequence ("1,3-5,7");
t.is (seq.size (), (size_t)5, "seq '1,3-5,7' -> 5 items");
if (seq.size () == 5)
{
t.is (seq[0], 1, "seq '1,3-5,7' -> [0] == 1");
t.is (seq[1], 3, "seq '1,3-5,7' -> [1] == 3");
t.is (seq[2], 4, "seq '1,3-5,7' -> [2] == 4");
t.is (seq[3], 5, "seq '1,3-5,7' -> [3] == 5");
t.is (seq[4], 7, "seq '1,3-5,7' -> [4] == 7");
}
else
{
t.fail ("seq '1,3-5,7' -> [0] == 1");
t.fail ("seq '1,3-5,7' -> [1] == 3");
t.fail ("seq '1,3-5,7' -> [2] == 4");
t.fail ("seq '1,3-5,7' -> [3] == 5");
t.fail ("seq '1,3-5,7' -> [4] == 7");
}
// 1--2
seq = parseSequence ("1--2");
t.is (seq.size (), (size_t)0, "seq '1--2' -> 0 items (error)");
// 1-1000
seq = parseSequence ("1-1000");
t.is (seq.size (), (size_t)1000, "seq '1-1000' -> 1000 items");
if (seq.size () == 1000)
{
t.is (seq[0], 1, "seq '1-1000' -> [0] == 1");
t.is (seq[1], 2, "seq '1-1000' -> [1] == 3");
t.is (seq[998], 999, "seq '1-1000' -> [998] == 999");
t.is (seq[999], 1000, "seq '1-1000' -> [999] == 1000");
}
else
{
t.fail ("seq '1-1000' -> [0] == 1");
t.fail ("seq '1-1000' -> [1] == 2");
t.fail ("seq '1-1000' -> [998] == 999");
t.fail ("seq '1-1000' -> [999] == 1000");
}
// 1-1001
seq = parseSequence ("1-1001");
t.is (seq.size (), (size_t)0, "seq '1-1001' -> 0 items (error)");
return 0;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -25,8 +25,8 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <sys/time.h>
#include "../T.h"
#include "../task.h"
#include "T.h"
#include "task.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////

View file

@ -24,8 +24,9 @@
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include "../T.h"
#include "../task.h"
#include "TDB.h"
#include "T.h"
#include "task.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////

View file

@ -27,8 +27,8 @@
#include <iostream>
#include <unistd.h>
#include "../TDB.h"
#include "../task.h"
#include "TDB.h"
#include "task.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////

View file

@ -28,6 +28,8 @@
#include <iomanip>
#include <string>
#include <task.h>
#include <util.h>
#include <text.h>
#include "test.h"
///////////////////////////////////////////////////////////////////////////////

View file

@ -26,6 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include "task.h"
#include "text.h"
#include "test.h"
////////////////////////////////////////////////////////////////////////////////