- Added all source code.
This commit is contained in:
191
src/Config.cpp
Normal file
191
src/Config.cpp
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include "task.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Config::Config ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Config::Config (const std::string& file)
|
||||||
|
{
|
||||||
|
load (file);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Read the Configuration filee and populate the *this map. The file format
|
||||||
|
// is simply lines with name=value pairs. Whitespace between name, = and value
|
||||||
|
// is not tolerated, but blank lines and comments starting with # are allowed.
|
||||||
|
bool Config::load (const std::string& file)
|
||||||
|
{
|
||||||
|
std::ifstream in;
|
||||||
|
in.open (file.c_str (), std::ifstream::in);
|
||||||
|
if (in.good ())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
while (getline (in, line))
|
||||||
|
{
|
||||||
|
// Remove comments.
|
||||||
|
unsigned int pound = line.find ("#");
|
||||||
|
if (pound != std::string::npos)
|
||||||
|
line = line.substr (0, pound);
|
||||||
|
|
||||||
|
line = trim (line, " \t");
|
||||||
|
|
||||||
|
// Skip empty lines.
|
||||||
|
if (line.length () > 0)
|
||||||
|
{
|
||||||
|
unsigned int equal = line.find ("=");
|
||||||
|
if (equal != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string key = trim (line.substr (0, equal), " \t");
|
||||||
|
std::string value = trim (line.substr (equal+1, line.length () - equal), " \t");
|
||||||
|
(*this)[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close ();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Return the configuration value given the specified key.
|
||||||
|
const std::string& Config::get (const char* key)
|
||||||
|
{
|
||||||
|
return this->get (std::string (key));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Return the configuration value given the specified key. If a default_value
|
||||||
|
// is present, it will be the returned value in the event of a missing key.
|
||||||
|
const std::string& Config::get (
|
||||||
|
const char* key,
|
||||||
|
const char* default_value)
|
||||||
|
{
|
||||||
|
return this->get (std::string (key), std::string (default_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Return the configuration value given the specified key.
|
||||||
|
const std::string& Config::get (const std::string& key)
|
||||||
|
{
|
||||||
|
return (*this)[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Return the configuration value given the specified key. If a default_value
|
||||||
|
// is present, it will be the returned value in the event of a missing key.
|
||||||
|
const std::string& Config::get (
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& default_value)
|
||||||
|
{
|
||||||
|
if ((*this).find (key) != (*this).end ())
|
||||||
|
return (*this)[key];
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Config::get (const std::string& key, bool default_value)
|
||||||
|
{
|
||||||
|
if ((*this).find (key) != (*this).end ())
|
||||||
|
{
|
||||||
|
std::string value = lowerCase ((*this)[key]);
|
||||||
|
|
||||||
|
if (value == "t" ||
|
||||||
|
value == "true" ||
|
||||||
|
value == "1" ||
|
||||||
|
value == "yes" ||
|
||||||
|
value == "on")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Config::get (const std::string& key, const int default_value)
|
||||||
|
{
|
||||||
|
if ((*this).find (key) != (*this).end ())
|
||||||
|
return ::atoi ((*this)[key].c_str ());
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
double Config::get (const std::string& key, const double default_value)
|
||||||
|
{
|
||||||
|
if ((*this).find (key) != (*this).end ())
|
||||||
|
return ::atof ((*this)[key].c_str ());
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Config::set (const std::string& key, const int value)
|
||||||
|
{
|
||||||
|
char v[24];
|
||||||
|
sprintf (v, "%d", value);
|
||||||
|
(*this)[key] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Config::set (const std::string& key, const double value)
|
||||||
|
{
|
||||||
|
char v[32];
|
||||||
|
sprintf (v, "%f", value);
|
||||||
|
(*this)[key] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Config::set (const std::string& key, const std::string& value)
|
||||||
|
{
|
||||||
|
(*this)[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The vector form of Config::get assumes the single value is comma-separated,
|
||||||
|
// and splits accordingly.
|
||||||
|
void Config::get (
|
||||||
|
const std::string& key,
|
||||||
|
std::vector <std::string>& values)
|
||||||
|
{
|
||||||
|
values.clear ();
|
||||||
|
split (values, (*this)[key], ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// The vector form of Config::set joins the values together with commas, and
|
||||||
|
// stores the single value.
|
||||||
|
void Config::set (
|
||||||
|
const std::string& key,
|
||||||
|
const std::vector <std::string>& values)
|
||||||
|
{
|
||||||
|
std::string conjoined;
|
||||||
|
join (conjoined, ",", values);
|
||||||
|
(*this)[key] = conjoined;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Provide a vector of all configuration keys.
|
||||||
|
void Config::all (std::vector<std::string>& items)
|
||||||
|
{
|
||||||
|
foreach (i, *this)
|
||||||
|
items.push_back (i->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
37
src/Config.h
Normal file
37
src/Config.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_CONFIG
|
||||||
|
#define INCLUDED_CONFIG
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Config : public std::map <std::string, std::string>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Config ();
|
||||||
|
Config (const std::string&);
|
||||||
|
|
||||||
|
bool load (const std::string&);
|
||||||
|
const std::string& get (const char*);
|
||||||
|
const std::string& get (const char*, const char*);
|
||||||
|
const std::string& get (const std::string&);
|
||||||
|
const std::string& get (const std::string&, const std::string&);
|
||||||
|
bool get (const std::string&, bool);
|
||||||
|
int get (const std::string&, const int);
|
||||||
|
double get (const std::string&, const double);
|
||||||
|
void get (const std::string&, std::vector <std::string>&);
|
||||||
|
void set (const std::string&, const int);
|
||||||
|
void set (const std::string&, const double);
|
||||||
|
void set (const std::string&, const std::string&);
|
||||||
|
void set (const std::string&, const std::vector <std::string>&);
|
||||||
|
void all (std::vector <std::string>&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
303
src/Date.cpp
Normal file
303
src/Date.cpp
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <time.h>
|
||||||
|
#include "task.h"
|
||||||
|
#include "Date.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Defaults to "now".
|
||||||
|
Date::Date ()
|
||||||
|
{
|
||||||
|
mT = time (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date::Date (const time_t t)
|
||||||
|
{
|
||||||
|
mT = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date::Date (const int m, const int d, const int y)
|
||||||
|
{
|
||||||
|
// Error if not valid.
|
||||||
|
struct tm t = {0};
|
||||||
|
t.tm_mday = d;
|
||||||
|
t.tm_mon = m - 1;
|
||||||
|
t.tm_year = y - 1900;
|
||||||
|
|
||||||
|
mT = mktime (&t);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date::Date (const std::string& mdy)
|
||||||
|
{
|
||||||
|
unsigned int firstSlash = mdy.find ("/");
|
||||||
|
unsigned int secondSlash = mdy.find ("/", firstSlash + 1);
|
||||||
|
if (firstSlash != std::string::npos &&
|
||||||
|
secondSlash != std::string::npos)
|
||||||
|
{
|
||||||
|
int m = ::atoi (mdy.substr (0, firstSlash ).c_str ());
|
||||||
|
int d = ::atoi (mdy.substr (firstSlash + 1, secondSlash - firstSlash).c_str ());
|
||||||
|
int y = ::atoi (mdy.substr (secondSlash + 1, std::string::npos ).c_str ());
|
||||||
|
if (!valid (m, d, y))
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
|
||||||
|
// Duplicate Date::Date (const int, const int, const int);
|
||||||
|
struct tm t = {0};
|
||||||
|
t.tm_mday = d;
|
||||||
|
t.tm_mon = m - 1;
|
||||||
|
t.tm_year = y - 1900;
|
||||||
|
|
||||||
|
mT = mktime (&t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("\"") + mdy + "\" is not a valid date.";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date::Date (const Date& rhs)
|
||||||
|
{
|
||||||
|
mT = rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date::~Date ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
time_t Date::toEpoch ()
|
||||||
|
{
|
||||||
|
return mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Date::toEpoch (time_t& epoch)
|
||||||
|
{
|
||||||
|
epoch = mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Date::toMDY (int& m, int& d, int& y)
|
||||||
|
{
|
||||||
|
struct tm* t = localtime (&mT);
|
||||||
|
|
||||||
|
m = t->tm_mon + 1;
|
||||||
|
d = t->tm_mday;
|
||||||
|
y = t->tm_year + 1900;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Date::toString (std::string& output)
|
||||||
|
{
|
||||||
|
output = toString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string Date::toString (void)
|
||||||
|
{
|
||||||
|
int m, d, y;
|
||||||
|
toMDY (m, d, y);
|
||||||
|
|
||||||
|
char formatted [11];
|
||||||
|
sprintf (formatted, "%d/%d/%d", m, d, y);
|
||||||
|
return std::string (formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::valid (const int m, const int d, const int y)
|
||||||
|
{
|
||||||
|
// Check that the year is valid.
|
||||||
|
if (y < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check that the month is valid.
|
||||||
|
if (m < 1 || m > 12)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Finally check that the days fall within the acceptable range for this
|
||||||
|
// month, and whether or not this is a leap year.
|
||||||
|
if (d < 1 || d > Date::daysInMonth (m, y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::leapYear (int year)
|
||||||
|
{
|
||||||
|
bool ly = false;
|
||||||
|
|
||||||
|
if (!(year % 4)) ly = true;
|
||||||
|
else if (!(year % 400)) ly = true;
|
||||||
|
else if (!(year % 100)) ly = false;
|
||||||
|
|
||||||
|
return ly;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Date::daysInMonth (int month, int year)
|
||||||
|
{
|
||||||
|
static int days[2][12] =
|
||||||
|
{
|
||||||
|
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
|
||||||
|
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||||
|
};
|
||||||
|
|
||||||
|
return days[Date::leapYear (year) ? 1 : 0][month - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string Date::monthName (int month)
|
||||||
|
{
|
||||||
|
static char* months[12] =
|
||||||
|
{
|
||||||
|
"January",
|
||||||
|
"February",
|
||||||
|
"March",
|
||||||
|
"April",
|
||||||
|
"May",
|
||||||
|
"June",
|
||||||
|
"July",
|
||||||
|
"August",
|
||||||
|
"September",
|
||||||
|
"October",
|
||||||
|
"November",
|
||||||
|
"December",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert (month > 0);
|
||||||
|
assert (month <= 12);
|
||||||
|
return months[month -1];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Date::dayName (int dow, std::string& name)
|
||||||
|
{
|
||||||
|
static char* days[7] =
|
||||||
|
{
|
||||||
|
"Sunday",
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
};
|
||||||
|
|
||||||
|
name = days[dow];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string Date::dayName (int dow)
|
||||||
|
{
|
||||||
|
static char* days[7] =
|
||||||
|
{
|
||||||
|
"Sunday",
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
};
|
||||||
|
|
||||||
|
return days[dow];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Date::dayOfWeek ()
|
||||||
|
{
|
||||||
|
struct tm* t = localtime (&mT);
|
||||||
|
return t->tm_wday;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Date::month ()
|
||||||
|
{
|
||||||
|
struct tm* t = localtime (&mT);
|
||||||
|
return t->tm_mon + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Date::day ()
|
||||||
|
{
|
||||||
|
struct tm* t = localtime (&mT);
|
||||||
|
return t->tm_mday;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int Date::year ()
|
||||||
|
{
|
||||||
|
struct tm* t = localtime (&mT);
|
||||||
|
return t->tm_year + 1900;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator== (const Date& rhs)
|
||||||
|
{
|
||||||
|
return rhs.mT == mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator!= (const Date& rhs)
|
||||||
|
{
|
||||||
|
return rhs.mT != mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator< (const Date& rhs)
|
||||||
|
{
|
||||||
|
return mT < rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator> (const Date& rhs)
|
||||||
|
{
|
||||||
|
return mT > rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator<= (const Date& rhs)
|
||||||
|
{
|
||||||
|
return mT <= rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool Date::operator>= (const Date& rhs)
|
||||||
|
{
|
||||||
|
return mT >= rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date Date::operator+ (const int delta)
|
||||||
|
{
|
||||||
|
return Date::Date (mT + delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date& Date::operator+= (const int delta)
|
||||||
|
{
|
||||||
|
mT += (time_t) delta;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Date& Date::operator-= (const int delta)
|
||||||
|
{
|
||||||
|
mT -= (time_t) delta;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
time_t Date::operator- (const Date& rhs)
|
||||||
|
{
|
||||||
|
return mT - rhs.mT;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
60
src/Date.h
Normal file
60
src/Date.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2005 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_DATE
|
||||||
|
#define INCLUDED_DATE
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Date;
|
||||||
|
|
||||||
|
class Date
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Date ();
|
||||||
|
Date (time_t);
|
||||||
|
Date (const int, const int, const int);
|
||||||
|
Date (const std::string&);
|
||||||
|
Date (const Date&);
|
||||||
|
virtual ~Date ();
|
||||||
|
|
||||||
|
void toEpoch (time_t&);
|
||||||
|
time_t toEpoch ();
|
||||||
|
void toMDY (int&, int&, int&);
|
||||||
|
void toString (std::string&);
|
||||||
|
std::string toString (void);
|
||||||
|
static bool valid (const int, const int, const int);
|
||||||
|
|
||||||
|
static bool leapYear (int);
|
||||||
|
static int daysInMonth (int, int);
|
||||||
|
static std::string monthName (int);
|
||||||
|
static void dayName (int, std::string&);
|
||||||
|
static std::string dayName (int);
|
||||||
|
int dayOfWeek ();
|
||||||
|
|
||||||
|
int month ();
|
||||||
|
int day ();
|
||||||
|
int year ();
|
||||||
|
|
||||||
|
bool operator== (const Date&);
|
||||||
|
bool operator!= (const Date&);
|
||||||
|
bool operator< (const Date&);
|
||||||
|
bool operator> (const Date&);
|
||||||
|
bool operator<= (const Date&);
|
||||||
|
bool operator>= (const Date&);
|
||||||
|
|
||||||
|
Date operator+ (const int);
|
||||||
|
Date& operator+= (const int);
|
||||||
|
Date& operator-= (const int);
|
||||||
|
|
||||||
|
time_t operator- (const Date&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
time_t mT;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
429
src/Makefile
Normal file
429
src/Makefile
Normal file
@@ -0,0 +1,429 @@
|
|||||||
|
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||||
|
# src/Makefile. Generated from Makefile.in by configure.
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pkgdatadir = $(datadir)/task
|
||||||
|
pkglibdir = $(libdir)/task
|
||||||
|
pkgincludedir = $(includedir)/task
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
bin_PROGRAMS = task$(EXEEXT)
|
||||||
|
subdir = src
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/auto.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
|
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||||
|
PROGRAMS = $(bin_PROGRAMS)
|
||||||
|
am_task_OBJECTS = Config.$(OBJEXT) Date.$(OBJEXT) T.$(OBJEXT) \
|
||||||
|
TDB.$(OBJEXT) Table.$(OBJEXT) color.$(OBJEXT) parse.$(OBJEXT) \
|
||||||
|
task.$(OBJEXT) util.$(OBJEXT) text.$(OBJEXT) rules.$(OBJEXT)
|
||||||
|
task_OBJECTS = $(am_task_OBJECTS)
|
||||||
|
task_LDADD = $(LDADD)
|
||||||
|
DEFAULT_INCLUDES = -I. -I$(top_builddir)
|
||||||
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
|
am__depfiles_maybe = depfiles
|
||||||
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
|
CXXLD = $(CXX)
|
||||||
|
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||||
|
-o $@
|
||||||
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
SOURCES = $(task_SOURCES)
|
||||||
|
DIST_SOURCES = $(task_SOURCES)
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = ${SHELL} /Users/paul/work/task_rel/missing --run aclocal-1.10
|
||||||
|
AMTAR = ${SHELL} /Users/paul/work/task_rel/missing --run tar
|
||||||
|
AUTOCONF = ${SHELL} /Users/paul/work/task_rel/missing --run autoconf
|
||||||
|
AUTOHEADER = ${SHELL} /Users/paul/work/task_rel/missing --run autoheader
|
||||||
|
AUTOMAKE = ${SHELL} /Users/paul/work/task_rel/missing --run automake-1.10
|
||||||
|
AWK = awk
|
||||||
|
CC = gcc
|
||||||
|
CCDEPMODE = depmode=gcc3
|
||||||
|
CFLAGS = -g -O2
|
||||||
|
CPPFLAGS =
|
||||||
|
CXX = g++
|
||||||
|
CXXCPP = g++ -E
|
||||||
|
CXXDEPMODE = depmode=gcc3
|
||||||
|
CXXFLAGS = -g -O2
|
||||||
|
CYGPATH_W = echo
|
||||||
|
DEFS = -DHAVE_CONFIG_H
|
||||||
|
DEPDIR = .deps
|
||||||
|
ECHO_C = \c
|
||||||
|
ECHO_N =
|
||||||
|
ECHO_T =
|
||||||
|
EGREP = /usr/bin/grep -E
|
||||||
|
EXEEXT =
|
||||||
|
GREP = /usr/bin/grep
|
||||||
|
INSTALL = /usr/bin/install -c
|
||||||
|
INSTALL_DATA = ${INSTALL} -m 644
|
||||||
|
INSTALL_PROGRAM = ${INSTALL}
|
||||||
|
INSTALL_SCRIPT = ${INSTALL}
|
||||||
|
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
|
||||||
|
LDFLAGS =
|
||||||
|
LIBOBJS = ${LIBOBJDIR}mktime$U.o
|
||||||
|
LIBS = -lncurses
|
||||||
|
LTLIBOBJS = ${LIBOBJDIR}mktime$U.lo
|
||||||
|
MAKEINFO = ${SHELL} /Users/paul/work/task_rel/missing --run makeinfo
|
||||||
|
MKDIR_P = .././install-sh -c -d
|
||||||
|
OBJEXT = o
|
||||||
|
PACKAGE = task
|
||||||
|
PACKAGE_BUGREPORT = bugs@beckingham.net
|
||||||
|
PACKAGE_NAME = task
|
||||||
|
PACKAGE_STRING = task 0.9.0
|
||||||
|
PACKAGE_TARNAME = task
|
||||||
|
PACKAGE_VERSION = 0.9.0
|
||||||
|
PATH_SEPARATOR = :
|
||||||
|
SET_MAKE =
|
||||||
|
SHELL = /bin/sh
|
||||||
|
STRIP =
|
||||||
|
VERSION = 0.9.0
|
||||||
|
abs_builddir = /Users/paul/work/task_rel/src
|
||||||
|
abs_srcdir = /Users/paul/work/task_rel/src
|
||||||
|
abs_top_builddir = /Users/paul/work/task_rel
|
||||||
|
abs_top_srcdir = /Users/paul/work/task_rel
|
||||||
|
ac_ct_CC = gcc
|
||||||
|
ac_ct_CXX = g++
|
||||||
|
am__include = include
|
||||||
|
am__leading_dot = .
|
||||||
|
am__quote =
|
||||||
|
am__tar = ${AMTAR} chof - "$$tardir"
|
||||||
|
am__untar = ${AMTAR} xf -
|
||||||
|
bindir = ${exec_prefix}/bin
|
||||||
|
build_alias =
|
||||||
|
builddir = .
|
||||||
|
datadir = ${datarootdir}
|
||||||
|
datarootdir = ${prefix}/share
|
||||||
|
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
|
||||||
|
dvidir = ${docdir}
|
||||||
|
exec_prefix = ${prefix}
|
||||||
|
host_alias =
|
||||||
|
htmldir = ${docdir}
|
||||||
|
includedir = ${prefix}/include
|
||||||
|
infodir = ${datarootdir}/info
|
||||||
|
install_sh = $(SHELL) /Users/paul/work/task_rel/install-sh
|
||||||
|
libdir = ${exec_prefix}/lib
|
||||||
|
libexecdir = ${exec_prefix}/libexec
|
||||||
|
localedir = ${datarootdir}/locale
|
||||||
|
localstatedir = ${prefix}/var
|
||||||
|
mandir = ${datarootdir}/man
|
||||||
|
mkdir_p = $(top_builddir)/./install-sh -c -d
|
||||||
|
oldincludedir = /usr/include
|
||||||
|
pdfdir = ${docdir}
|
||||||
|
prefix = /usr/local
|
||||||
|
program_transform_name = s,x,x,
|
||||||
|
psdir = ${docdir}
|
||||||
|
sbindir = ${exec_prefix}/sbin
|
||||||
|
sharedstatedir = ${prefix}/com
|
||||||
|
srcdir = .
|
||||||
|
subdirs = src
|
||||||
|
sysconfdir = ${prefix}/etc
|
||||||
|
target_alias =
|
||||||
|
top_builddir = ..
|
||||||
|
top_srcdir = ..
|
||||||
|
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp color.cpp parse.cpp task.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h color.h stlmacros.h task.h
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .cpp .o .obj
|
||||||
|
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
|
||||||
|
cd $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu src/Makefile
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||||
|
if test -f $$p \
|
||||||
|
; then \
|
||||||
|
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||||
|
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||||
|
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-binPROGRAMS:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||||
|
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||||
|
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||||
|
done
|
||||||
|
|
||||||
|
clean-binPROGRAMS:
|
||||||
|
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||||
|
task$(EXEEXT): $(task_OBJECTS) $(task_DEPENDENCIES)
|
||||||
|
@rm -f task$(EXEEXT)
|
||||||
|
$(CXXLINK) $(task_OBJECTS) $(task_LDADD) $(LIBS)
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
include ./$(DEPDIR)/Config.Po
|
||||||
|
include ./$(DEPDIR)/Date.Po
|
||||||
|
include ./$(DEPDIR)/T.Po
|
||||||
|
include ./$(DEPDIR)/TDB.Po
|
||||||
|
include ./$(DEPDIR)/Table.Po
|
||||||
|
include ./$(DEPDIR)/color.Po
|
||||||
|
include ./$(DEPDIR)/parse.Po
|
||||||
|
include ./$(DEPDIR)/rules.Po
|
||||||
|
include ./$(DEPDIR)/task.Po
|
||||||
|
include ./$(DEPDIR)/text.Po
|
||||||
|
include ./$(DEPDIR)/util.Po
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
# source='$<' object='$@' libtool=no \
|
||||||
|
# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
|
||||||
|
# $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
.cpp.obj:
|
||||||
|
$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
# source='$<' object='$@' libtool=no \
|
||||||
|
# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
|
||||||
|
# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
|
||||||
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
mkid -fID $$unique
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
|
$(TAGS_FILES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
|
ctags: CTAGS
|
||||||
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
|
$(TAGS_FILES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$tags $$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& cd $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) $$here
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
fi; \
|
||||||
|
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(PROGRAMS)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
`test -z '$(STRIP)' || \
|
||||||
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
|
distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-exec-am: install-binPROGRAMS
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||||
|
clean-generic ctags distclean distclean-compile \
|
||||||
|
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||||
|
html-am info info-am install install-am install-binPROGRAMS \
|
||||||
|
install-data install-data-am install-dvi install-dvi-am \
|
||||||
|
install-exec install-exec-am install-html install-html-am \
|
||||||
|
install-info install-info-am install-man install-pdf \
|
||||||
|
install-pdf-am install-ps install-ps-am install-strip \
|
||||||
|
installcheck installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||||
|
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||||
|
uninstall-am uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
||||||
2
src/Makefile.am
Normal file
2
src/Makefile.am
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
bin_PROGRAMS = task
|
||||||
|
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp color.cpp parse.cpp task.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h color.h stlmacros.h task.h
|
||||||
429
src/Makefile.in
Normal file
429
src/Makefile.in
Normal file
@@ -0,0 +1,429 @@
|
|||||||
|
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||||
|
# @configure_input@
|
||||||
|
|
||||||
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||||
|
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||||
|
# This Makefile.in is free software; the Free Software Foundation
|
||||||
|
# gives unlimited permission to copy and/or distribute it,
|
||||||
|
# with or without modifications, as long as this notice is preserved.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||||
|
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||||
|
# PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
@SET_MAKE@
|
||||||
|
|
||||||
|
VPATH = @srcdir@
|
||||||
|
pkgdatadir = $(datadir)/@PACKAGE@
|
||||||
|
pkglibdir = $(libdir)/@PACKAGE@
|
||||||
|
pkgincludedir = $(includedir)/@PACKAGE@
|
||||||
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||||
|
install_sh_DATA = $(install_sh) -c -m 644
|
||||||
|
install_sh_PROGRAM = $(install_sh) -c
|
||||||
|
install_sh_SCRIPT = $(install_sh) -c
|
||||||
|
INSTALL_HEADER = $(INSTALL_DATA)
|
||||||
|
transform = $(program_transform_name)
|
||||||
|
NORMAL_INSTALL = :
|
||||||
|
PRE_INSTALL = :
|
||||||
|
POST_INSTALL = :
|
||||||
|
NORMAL_UNINSTALL = :
|
||||||
|
PRE_UNINSTALL = :
|
||||||
|
POST_UNINSTALL = :
|
||||||
|
bin_PROGRAMS = task$(EXEEXT)
|
||||||
|
subdir = src
|
||||||
|
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||||
|
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||||
|
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||||
|
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||||
|
$(ACLOCAL_M4)
|
||||||
|
mkinstalldirs = $(install_sh) -d
|
||||||
|
CONFIG_HEADER = $(top_builddir)/auto.h
|
||||||
|
CONFIG_CLEAN_FILES =
|
||||||
|
am__installdirs = "$(DESTDIR)$(bindir)"
|
||||||
|
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
|
||||||
|
PROGRAMS = $(bin_PROGRAMS)
|
||||||
|
am_task_OBJECTS = Config.$(OBJEXT) Date.$(OBJEXT) T.$(OBJEXT) \
|
||||||
|
TDB.$(OBJEXT) Table.$(OBJEXT) color.$(OBJEXT) parse.$(OBJEXT) \
|
||||||
|
task.$(OBJEXT) util.$(OBJEXT) text.$(OBJEXT) rules.$(OBJEXT)
|
||||||
|
task_OBJECTS = $(am_task_OBJECTS)
|
||||||
|
task_LDADD = $(LDADD)
|
||||||
|
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
|
||||||
|
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||||
|
am__depfiles_maybe = depfiles
|
||||||
|
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||||
|
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||||
|
CXXLD = $(CXX)
|
||||||
|
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||||
|
-o $@
|
||||||
|
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||||
|
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||||
|
CCLD = $(CC)
|
||||||
|
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||||
|
SOURCES = $(task_SOURCES)
|
||||||
|
DIST_SOURCES = $(task_SOURCES)
|
||||||
|
ETAGS = etags
|
||||||
|
CTAGS = ctags
|
||||||
|
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||||
|
ACLOCAL = @ACLOCAL@
|
||||||
|
AMTAR = @AMTAR@
|
||||||
|
AUTOCONF = @AUTOCONF@
|
||||||
|
AUTOHEADER = @AUTOHEADER@
|
||||||
|
AUTOMAKE = @AUTOMAKE@
|
||||||
|
AWK = @AWK@
|
||||||
|
CC = @CC@
|
||||||
|
CCDEPMODE = @CCDEPMODE@
|
||||||
|
CFLAGS = @CFLAGS@
|
||||||
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CXX = @CXX@
|
||||||
|
CXXCPP = @CXXCPP@
|
||||||
|
CXXDEPMODE = @CXXDEPMODE@
|
||||||
|
CXXFLAGS = @CXXFLAGS@
|
||||||
|
CYGPATH_W = @CYGPATH_W@
|
||||||
|
DEFS = @DEFS@
|
||||||
|
DEPDIR = @DEPDIR@
|
||||||
|
ECHO_C = @ECHO_C@
|
||||||
|
ECHO_N = @ECHO_N@
|
||||||
|
ECHO_T = @ECHO_T@
|
||||||
|
EGREP = @EGREP@
|
||||||
|
EXEEXT = @EXEEXT@
|
||||||
|
GREP = @GREP@
|
||||||
|
INSTALL = @INSTALL@
|
||||||
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
|
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||||
|
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||||
|
LDFLAGS = @LDFLAGS@
|
||||||
|
LIBOBJS = @LIBOBJS@
|
||||||
|
LIBS = @LIBS@
|
||||||
|
LTLIBOBJS = @LTLIBOBJS@
|
||||||
|
MAKEINFO = @MAKEINFO@
|
||||||
|
MKDIR_P = @MKDIR_P@
|
||||||
|
OBJEXT = @OBJEXT@
|
||||||
|
PACKAGE = @PACKAGE@
|
||||||
|
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||||
|
PACKAGE_NAME = @PACKAGE_NAME@
|
||||||
|
PACKAGE_STRING = @PACKAGE_STRING@
|
||||||
|
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||||
|
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||||
|
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||||
|
SET_MAKE = @SET_MAKE@
|
||||||
|
SHELL = @SHELL@
|
||||||
|
STRIP = @STRIP@
|
||||||
|
VERSION = @VERSION@
|
||||||
|
abs_builddir = @abs_builddir@
|
||||||
|
abs_srcdir = @abs_srcdir@
|
||||||
|
abs_top_builddir = @abs_top_builddir@
|
||||||
|
abs_top_srcdir = @abs_top_srcdir@
|
||||||
|
ac_ct_CC = @ac_ct_CC@
|
||||||
|
ac_ct_CXX = @ac_ct_CXX@
|
||||||
|
am__include = @am__include@
|
||||||
|
am__leading_dot = @am__leading_dot@
|
||||||
|
am__quote = @am__quote@
|
||||||
|
am__tar = @am__tar@
|
||||||
|
am__untar = @am__untar@
|
||||||
|
bindir = @bindir@
|
||||||
|
build_alias = @build_alias@
|
||||||
|
builddir = @builddir@
|
||||||
|
datadir = @datadir@
|
||||||
|
datarootdir = @datarootdir@
|
||||||
|
docdir = @docdir@
|
||||||
|
dvidir = @dvidir@
|
||||||
|
exec_prefix = @exec_prefix@
|
||||||
|
host_alias = @host_alias@
|
||||||
|
htmldir = @htmldir@
|
||||||
|
includedir = @includedir@
|
||||||
|
infodir = @infodir@
|
||||||
|
install_sh = @install_sh@
|
||||||
|
libdir = @libdir@
|
||||||
|
libexecdir = @libexecdir@
|
||||||
|
localedir = @localedir@
|
||||||
|
localstatedir = @localstatedir@
|
||||||
|
mandir = @mandir@
|
||||||
|
mkdir_p = @mkdir_p@
|
||||||
|
oldincludedir = @oldincludedir@
|
||||||
|
pdfdir = @pdfdir@
|
||||||
|
prefix = @prefix@
|
||||||
|
program_transform_name = @program_transform_name@
|
||||||
|
psdir = @psdir@
|
||||||
|
sbindir = @sbindir@
|
||||||
|
sharedstatedir = @sharedstatedir@
|
||||||
|
srcdir = @srcdir@
|
||||||
|
subdirs = @subdirs@
|
||||||
|
sysconfdir = @sysconfdir@
|
||||||
|
target_alias = @target_alias@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
task_SOURCES = Config.cpp Date.cpp T.cpp TDB.cpp Table.cpp color.cpp parse.cpp task.cpp util.cpp text.cpp rules.cpp Config.h Date.h T.h TDB.h Table.h color.h stlmacros.h task.h
|
||||||
|
all: all-am
|
||||||
|
|
||||||
|
.SUFFIXES:
|
||||||
|
.SUFFIXES: .cpp .o .obj
|
||||||
|
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||||
|
@for dep in $?; do \
|
||||||
|
case '$(am__configure_deps)' in \
|
||||||
|
*$$dep*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||||
|
&& exit 0; \
|
||||||
|
exit 1;; \
|
||||||
|
esac; \
|
||||||
|
done; \
|
||||||
|
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
|
||||||
|
cd $(top_srcdir) && \
|
||||||
|
$(AUTOMAKE) --gnu src/Makefile
|
||||||
|
.PRECIOUS: Makefile
|
||||||
|
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||||
|
@case '$?' in \
|
||||||
|
*config.status*) \
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||||
|
*) \
|
||||||
|
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||||
|
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||||
|
esac;
|
||||||
|
|
||||||
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
|
||||||
|
$(top_srcdir)/configure: $(am__configure_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||||
|
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||||
|
install-binPROGRAMS: $(bin_PROGRAMS)
|
||||||
|
@$(NORMAL_INSTALL)
|
||||||
|
test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
|
||||||
|
if test -f $$p \
|
||||||
|
; then \
|
||||||
|
f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||||
|
echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
|
||||||
|
$(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
|
||||||
|
else :; fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
uninstall-binPROGRAMS:
|
||||||
|
@$(NORMAL_UNINSTALL)
|
||||||
|
@list='$(bin_PROGRAMS)'; for p in $$list; do \
|
||||||
|
f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
|
||||||
|
echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
|
||||||
|
rm -f "$(DESTDIR)$(bindir)/$$f"; \
|
||||||
|
done
|
||||||
|
|
||||||
|
clean-binPROGRAMS:
|
||||||
|
-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
|
||||||
|
task$(EXEEXT): $(task_OBJECTS) $(task_DEPENDENCIES)
|
||||||
|
@rm -f task$(EXEEXT)
|
||||||
|
$(CXXLINK) $(task_OBJECTS) $(task_LDADD) $(LIBS)
|
||||||
|
|
||||||
|
mostlyclean-compile:
|
||||||
|
-rm -f *.$(OBJEXT)
|
||||||
|
|
||||||
|
distclean-compile:
|
||||||
|
-rm -f *.tab.c
|
||||||
|
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Config.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Date.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/T.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TDB.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Table.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rules.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/task.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||||
|
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||||
|
|
||||||
|
.cpp.obj:
|
||||||
|
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||||
|
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||||
|
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||||
|
|
||||||
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
mkid -fID $$unique
|
||||||
|
tags: TAGS
|
||||||
|
|
||||||
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
|
$(TAGS_FILES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||||
|
test -n "$$unique" || unique=$$empty_fix; \
|
||||||
|
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||||
|
$$tags $$unique; \
|
||||||
|
fi
|
||||||
|
ctags: CTAGS
|
||||||
|
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||||
|
$(TAGS_FILES) $(LISP)
|
||||||
|
tags=; \
|
||||||
|
here=`pwd`; \
|
||||||
|
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||||
|
unique=`for i in $$list; do \
|
||||||
|
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||||
|
done | \
|
||||||
|
$(AWK) ' { files[$$0] = 1; } \
|
||||||
|
END { for (i in files) print i; }'`; \
|
||||||
|
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||||
|
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||||
|
$$tags $$unique
|
||||||
|
|
||||||
|
GTAGS:
|
||||||
|
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||||
|
&& cd $(top_srcdir) \
|
||||||
|
&& gtags -i $(GTAGS_ARGS) $$here
|
||||||
|
|
||||||
|
distclean-tags:
|
||||||
|
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||||
|
|
||||||
|
distdir: $(DISTFILES)
|
||||||
|
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||||
|
list='$(DISTFILES)'; \
|
||||||
|
dist_files=`for file in $$list; do echo $$file; done | \
|
||||||
|
sed -e "s|^$$srcdirstrip/||;t" \
|
||||||
|
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||||
|
case $$dist_files in \
|
||||||
|
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||||
|
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||||
|
sort -u` ;; \
|
||||||
|
esac; \
|
||||||
|
for file in $$dist_files; do \
|
||||||
|
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||||
|
if test -d $$d/$$file; then \
|
||||||
|
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||||
|
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||||
|
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
fi; \
|
||||||
|
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||||
|
else \
|
||||||
|
test -f $(distdir)/$$file \
|
||||||
|
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||||
|
|| exit 1; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
check-am: all-am
|
||||||
|
check: check-am
|
||||||
|
all-am: Makefile $(PROGRAMS)
|
||||||
|
installdirs:
|
||||||
|
for dir in "$(DESTDIR)$(bindir)"; do \
|
||||||
|
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
|
||||||
|
done
|
||||||
|
install: install-am
|
||||||
|
install-exec: install-exec-am
|
||||||
|
install-data: install-data-am
|
||||||
|
uninstall: uninstall-am
|
||||||
|
|
||||||
|
install-am: all-am
|
||||||
|
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||||
|
|
||||||
|
installcheck: installcheck-am
|
||||||
|
install-strip:
|
||||||
|
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||||
|
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||||
|
`test -z '$(STRIP)' || \
|
||||||
|
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||||
|
mostlyclean-generic:
|
||||||
|
|
||||||
|
clean-generic:
|
||||||
|
|
||||||
|
distclean-generic:
|
||||||
|
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||||
|
|
||||||
|
maintainer-clean-generic:
|
||||||
|
@echo "This command is intended for maintainers to use"
|
||||||
|
@echo "it deletes files that may require special tools to rebuild."
|
||||||
|
clean: clean-am
|
||||||
|
|
||||||
|
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
|
||||||
|
|
||||||
|
distclean: distclean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
distclean-am: clean-am distclean-compile distclean-generic \
|
||||||
|
distclean-tags
|
||||||
|
|
||||||
|
dvi: dvi-am
|
||||||
|
|
||||||
|
dvi-am:
|
||||||
|
|
||||||
|
html: html-am
|
||||||
|
|
||||||
|
info: info-am
|
||||||
|
|
||||||
|
info-am:
|
||||||
|
|
||||||
|
install-data-am:
|
||||||
|
|
||||||
|
install-dvi: install-dvi-am
|
||||||
|
|
||||||
|
install-exec-am: install-binPROGRAMS
|
||||||
|
|
||||||
|
install-html: install-html-am
|
||||||
|
|
||||||
|
install-info: install-info-am
|
||||||
|
|
||||||
|
install-man:
|
||||||
|
|
||||||
|
install-pdf: install-pdf-am
|
||||||
|
|
||||||
|
install-ps: install-ps-am
|
||||||
|
|
||||||
|
installcheck-am:
|
||||||
|
|
||||||
|
maintainer-clean: maintainer-clean-am
|
||||||
|
-rm -rf ./$(DEPDIR)
|
||||||
|
-rm -f Makefile
|
||||||
|
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||||
|
|
||||||
|
mostlyclean: mostlyclean-am
|
||||||
|
|
||||||
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||||
|
|
||||||
|
pdf: pdf-am
|
||||||
|
|
||||||
|
pdf-am:
|
||||||
|
|
||||||
|
ps: ps-am
|
||||||
|
|
||||||
|
ps-am:
|
||||||
|
|
||||||
|
uninstall-am: uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
.MAKE: install-am install-strip
|
||||||
|
|
||||||
|
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
|
||||||
|
clean-generic ctags distclean distclean-compile \
|
||||||
|
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||||
|
html-am info info-am install install-am install-binPROGRAMS \
|
||||||
|
install-data install-data-am install-dvi install-dvi-am \
|
||||||
|
install-exec install-exec-am install-html install-html-am \
|
||||||
|
install-info install-info-am install-man install-pdf \
|
||||||
|
install-pdf-am install-ps install-ps-am install-strip \
|
||||||
|
installcheck installcheck-am installdirs maintainer-clean \
|
||||||
|
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||||
|
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||||
|
uninstall-am uninstall-binPROGRAMS
|
||||||
|
|
||||||
|
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||||
|
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||||
|
.NOEXPORT:
|
||||||
510
src/T.cpp
Normal file
510
src/T.cpp
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "task.h"
|
||||||
|
#include "T.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Default
|
||||||
|
T::T ()
|
||||||
|
{
|
||||||
|
mUUID = uuid ();
|
||||||
|
mStatus = pending;
|
||||||
|
mId = 0;
|
||||||
|
mTags.clear ();
|
||||||
|
mAttributes.clear ();
|
||||||
|
mDescription = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Initialize by parsing storage format
|
||||||
|
T::T (const std::string& line)
|
||||||
|
{
|
||||||
|
parse (line);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
T::T (const T& other)
|
||||||
|
{
|
||||||
|
mStatus = other.mStatus;
|
||||||
|
mUUID = other.mUUID;
|
||||||
|
mId = other.mId;
|
||||||
|
mDescription = other.mDescription;
|
||||||
|
mTags = other.mTags;
|
||||||
|
mRemoveTags = other.mRemoveTags;
|
||||||
|
mAttributes = other.mAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
T& T::operator= (const T& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
mStatus = other.mStatus;
|
||||||
|
mUUID = other.mUUID;
|
||||||
|
mId = other.mId;
|
||||||
|
mDescription = other.mDescription;
|
||||||
|
mTags = other.mTags;
|
||||||
|
mRemoveTags = other.mRemoveTags;
|
||||||
|
mAttributes = other.mAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
T::~T ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool T::hasTag (const std::string& tag) const
|
||||||
|
{
|
||||||
|
std::vector <std::string>::const_iterator it = find (mTags.begin (), mTags.end (), tag);
|
||||||
|
if (it != mTags.end ())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SPECIAL METHOD - DO NOT REMOVE
|
||||||
|
void T::getRemoveTags (std::vector<std::string>& all)
|
||||||
|
{
|
||||||
|
all = mRemoveTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// SPECIAL METHOD - DO NOT REMOVE
|
||||||
|
void T::addRemoveTag (const std::string& tag)
|
||||||
|
{
|
||||||
|
if (tag.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("T::addRemoveTag - tags may not contain spaces");
|
||||||
|
|
||||||
|
mRemoveTags.push_back (tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::getTags (std::vector<std::string>& all) const
|
||||||
|
{
|
||||||
|
all = mTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::addTag (const std::string& tag)
|
||||||
|
{
|
||||||
|
if (tag.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("T::addTag - tags may not contain spaces");
|
||||||
|
|
||||||
|
if (tag[0] == '+')
|
||||||
|
{
|
||||||
|
if (! hasTag (tag.substr (1, std::string::npos)))
|
||||||
|
mTags.push_back (tag.substr (1, std::string::npos));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (! hasTag (tag))
|
||||||
|
mTags.push_back (tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::addTags (const std::vector <std::string>& tags)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < tags.size (); ++i)
|
||||||
|
{
|
||||||
|
if (tags[i].find (' ') != std::string::npos)
|
||||||
|
throw std::string ("T::addTags - tags may not contain spaces");
|
||||||
|
|
||||||
|
if (tags[i][0] == '+')
|
||||||
|
{
|
||||||
|
if (! hasTag (tags[i].substr (1, std::string::npos)))
|
||||||
|
mTags.push_back (tags[i].substr (1, std::string::npos));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (! hasTag (tags[i]))
|
||||||
|
mTags.push_back (tags[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::removeTag (const std::string& tag)
|
||||||
|
{
|
||||||
|
std::vector <std::string> copy;
|
||||||
|
for (unsigned int i = 0; i < mTags.size (); ++i)
|
||||||
|
if (mTags[i] != tag)
|
||||||
|
copy.push_back (mTags[i]);
|
||||||
|
|
||||||
|
mTags = copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::removeTags ()
|
||||||
|
{
|
||||||
|
mTags.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::getAttributes (std::map<std::string, std::string>& all)
|
||||||
|
{
|
||||||
|
all = mAttributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const std::string T::getAttribute (const std::string& name)
|
||||||
|
{
|
||||||
|
if (mAttributes.find (name) != mAttributes.end ())
|
||||||
|
return mAttributes[name];
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::setAttribute (const std::string& name, const std::string& value)
|
||||||
|
{
|
||||||
|
if (name.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("An attribute name may not contain spaces");
|
||||||
|
|
||||||
|
if (value.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("An attribute value may not contain spaces");
|
||||||
|
|
||||||
|
mAttributes[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::setAttributes (const std::map <std::string, std::string>& attributes)
|
||||||
|
{
|
||||||
|
foreach (i, attributes)
|
||||||
|
{
|
||||||
|
if (i->first.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("An attribute name may not contain spaces");
|
||||||
|
|
||||||
|
if (i->second.find (' ') != std::string::npos)
|
||||||
|
throw std::string ("An attribute value may not contain spaces");
|
||||||
|
|
||||||
|
mAttributes[i->first] = i->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::removeAttributes ()
|
||||||
|
{
|
||||||
|
mAttributes.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::removeAttribute (const std::string& name)
|
||||||
|
{
|
||||||
|
std::map <std::string, std::string> copy = mAttributes;
|
||||||
|
mAttributes.clear ();
|
||||||
|
foreach (i, copy)
|
||||||
|
if (i->first != name)
|
||||||
|
mAttributes[i->first] = i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::getSubstitution (std::string& from, std::string& to) const
|
||||||
|
{
|
||||||
|
from = mFrom;
|
||||||
|
to = mTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void T::setSubstitution (const std::string& from, const std::string& to)
|
||||||
|
{
|
||||||
|
mFrom = from;
|
||||||
|
mTo = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// uuid status [tags] [attributes] description
|
||||||
|
//
|
||||||
|
// uuid \x{8}-\x{4}-\x{4}-\x{4}-\x{12}
|
||||||
|
// status - O X
|
||||||
|
// tags \w+ \s ...
|
||||||
|
// attributes \w+:\w+ \s ...
|
||||||
|
// description .+
|
||||||
|
//
|
||||||
|
const std::string T::compose () const
|
||||||
|
{
|
||||||
|
// UUID
|
||||||
|
std::string line = mUUID + ' ';
|
||||||
|
|
||||||
|
// Status
|
||||||
|
if (mStatus == pending) line += "- [";
|
||||||
|
else if (mStatus == completed) line += "+ [";
|
||||||
|
else if (mStatus == deleted) line += "X [";
|
||||||
|
|
||||||
|
// Tags
|
||||||
|
for (unsigned int i = 0; i < mTags.size (); ++i)
|
||||||
|
{
|
||||||
|
line += (i > 0 ? " " : "");
|
||||||
|
line += mTags[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "] [";
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
int count = 0;
|
||||||
|
foreach (i, mAttributes)
|
||||||
|
{
|
||||||
|
std::string converted = i->second;
|
||||||
|
|
||||||
|
// Date attributes may need conversion to epoch.
|
||||||
|
if (i->first == "due" ||
|
||||||
|
i->first == "start" ||
|
||||||
|
i->first == "entry" ||
|
||||||
|
i->first == "end")
|
||||||
|
{
|
||||||
|
if (i->second.find ("/") != std::string::npos)
|
||||||
|
validDate (converted);
|
||||||
|
}
|
||||||
|
|
||||||
|
line += (count > 0 ? " " : "");
|
||||||
|
line += i->first + ":" + converted;
|
||||||
|
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "] ";
|
||||||
|
|
||||||
|
// Description
|
||||||
|
line += mDescription;
|
||||||
|
line += "\n";
|
||||||
|
|
||||||
|
if (line.length () > T_LINE_MAX)
|
||||||
|
throw std::string ("Line too long");
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const std::string T::composeCSV ()
|
||||||
|
{
|
||||||
|
// UUID
|
||||||
|
std::string line = "'" + mUUID + "',";
|
||||||
|
|
||||||
|
// Status
|
||||||
|
if (mStatus == pending) line += "'pending',";
|
||||||
|
else if (mStatus == completed) line += "'completed',";
|
||||||
|
else if (mStatus == deleted) line += "'deleted',";
|
||||||
|
|
||||||
|
// Tags
|
||||||
|
line += "'";
|
||||||
|
for (unsigned int i = 0; i < mTags.size (); ++i)
|
||||||
|
{
|
||||||
|
line += (i > 0 ? " " : "");
|
||||||
|
line += mTags[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
line += "',";
|
||||||
|
std::string value = mAttributes["entry"];
|
||||||
|
line += value + ",";
|
||||||
|
|
||||||
|
value = mAttributes["start"];
|
||||||
|
if (value != "")
|
||||||
|
line += value;
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["due"];
|
||||||
|
if (value != "")
|
||||||
|
line += value;
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["end"];
|
||||||
|
if (value != "")
|
||||||
|
line += value;
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["project"];
|
||||||
|
if (value != "")
|
||||||
|
line += "'" + value + "'";
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["priority"];
|
||||||
|
if (value != "")
|
||||||
|
line += "'" + value + "'";
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["fg"];
|
||||||
|
if (value != "")
|
||||||
|
line += "'" + value + "'";
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
value = mAttributes["bg"];
|
||||||
|
if (value != "")
|
||||||
|
line += "'" + value + "'";
|
||||||
|
line += ",";
|
||||||
|
|
||||||
|
line += "'" + mDescription + "'\n";
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Read all file formats, write only the latest.
|
||||||
|
void T::parse (const std::string& line)
|
||||||
|
{
|
||||||
|
switch (determineVersion (line))
|
||||||
|
{
|
||||||
|
// File format version 1, from 2006.11.27 - 2007.12.31
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// Generate a UUID for forward support.
|
||||||
|
mUUID = uuid ();
|
||||||
|
|
||||||
|
if (line.length () > 6) // ^\[\]\s\[\]\n
|
||||||
|
{
|
||||||
|
if (line[0] == 'X')
|
||||||
|
setStatus (deleted);
|
||||||
|
|
||||||
|
unsigned int openTagBracket = line.find ("[");
|
||||||
|
unsigned int closeTagBracket = line.find ("]", openTagBracket);
|
||||||
|
if (openTagBracket != std::string::npos &&
|
||||||
|
closeTagBracket != std::string::npos)
|
||||||
|
{
|
||||||
|
unsigned int openAttrBracket = line.find ("[", closeTagBracket);
|
||||||
|
unsigned int closeAttrBracket = line.find ("]", openAttrBracket);
|
||||||
|
if (openAttrBracket != std::string::npos &&
|
||||||
|
closeAttrBracket != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string tags = line.substr (
|
||||||
|
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
||||||
|
std::vector <std::string> rawTags;
|
||||||
|
split (mTags, tags, ' ');
|
||||||
|
|
||||||
|
std::string attributes = line.substr (
|
||||||
|
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
||||||
|
std::vector <std::string> pairs;
|
||||||
|
split (pairs, attributes, ' ');
|
||||||
|
for (unsigned int i = 0; i < pairs.size (); ++i)
|
||||||
|
{
|
||||||
|
std::vector <std::string> pair;
|
||||||
|
split (pair, pairs[i], ':');
|
||||||
|
if (pair[1] != "")
|
||||||
|
mAttributes[pair[0]] = pair[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Missing attribute brackets");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Missing tag brackets");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Line too short");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// File format version 2, from 2008.1.1
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
if (line.length () > 46) // ^.{36} . \[\] \[\] \n
|
||||||
|
{
|
||||||
|
mUUID = line.substr (0, 36);
|
||||||
|
|
||||||
|
mStatus = line[37] == '+' ? completed
|
||||||
|
: line[37] == 'X' ? deleted
|
||||||
|
: pending;
|
||||||
|
|
||||||
|
unsigned int openTagBracket = line.find ("[");
|
||||||
|
unsigned int closeTagBracket = line.find ("]", openTagBracket);
|
||||||
|
if (openTagBracket != std::string::npos &&
|
||||||
|
closeTagBracket != std::string::npos)
|
||||||
|
{
|
||||||
|
unsigned int openAttrBracket = line.find ("[", closeTagBracket);
|
||||||
|
unsigned int closeAttrBracket = line.find ("]", openAttrBracket);
|
||||||
|
if (openAttrBracket != std::string::npos &&
|
||||||
|
closeAttrBracket != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string tags = line.substr (
|
||||||
|
openTagBracket + 1, closeTagBracket - openTagBracket - 1);
|
||||||
|
std::vector <std::string> rawTags;
|
||||||
|
split (mTags, tags, ' ');
|
||||||
|
|
||||||
|
std::string attributes = line.substr (
|
||||||
|
openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1);
|
||||||
|
std::vector <std::string> pairs;
|
||||||
|
split (pairs, attributes, ' ');
|
||||||
|
for (unsigned int i = 0; i < pairs.size (); ++i)
|
||||||
|
{
|
||||||
|
std::vector <std::string> pair;
|
||||||
|
split (pair, pairs[i], ':');
|
||||||
|
if (pair[1] != "")
|
||||||
|
mAttributes[pair[0]] = pair[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
mDescription = line.substr (closeAttrBracket + 2, std::string::npos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Missing attribute brackets");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Missing tag brackets");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Line too short");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw std::string ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// If this code is inaccurate, data corruption ensues.
|
||||||
|
int T::determineVersion (const std::string& line)
|
||||||
|
{
|
||||||
|
// Version 1 looks like:
|
||||||
|
//
|
||||||
|
// [tags] [attributes] description\n
|
||||||
|
// X [tags] [attributes] description\n
|
||||||
|
//
|
||||||
|
// Scan for the first character being either the bracket or X.
|
||||||
|
if (line[0] == '[' ||
|
||||||
|
line[0] == 'X')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Version 2 looks like:
|
||||||
|
//
|
||||||
|
// uuid status [tags] [attributes] description\n
|
||||||
|
//
|
||||||
|
// Where uuid looks like:
|
||||||
|
//
|
||||||
|
// 27755d92-c5e9-4c21-bd8e-c3dd9e6d3cf7
|
||||||
|
//
|
||||||
|
// Scan for the hyphens in the uuid, the following space, and a valid status
|
||||||
|
// character.
|
||||||
|
if (line[8] == '-' &&
|
||||||
|
line[13] == '-' &&
|
||||||
|
line[18] == '-' &&
|
||||||
|
line[23] == '-' &&
|
||||||
|
line[36] == ' ' &&
|
||||||
|
(line[37] == '-' || line[37] == '+' || line[37] == 'X'))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
// Version 3?
|
||||||
|
//
|
||||||
|
// Fortunately, with the hindsight that will come with version 3, the
|
||||||
|
// identifying characteristics of 1 and 2 may be modified such that if 3 has
|
||||||
|
// a UUID followed by a status, then there is still a way to differentiate
|
||||||
|
// between 2 and 3.
|
||||||
|
//
|
||||||
|
// The danger is that a version 2 binary reads and misinterprets a version 2
|
||||||
|
// file. This is why it is a good idea to rely on an explicit version
|
||||||
|
// declaration rather than chance positioning.
|
||||||
|
|
||||||
|
// Zero means 'no idea'.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
80
src/T.h
Normal file
80
src/T.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2007, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_T
|
||||||
|
#define INCLUDED_T
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
// Length of longest line.
|
||||||
|
#define T_LINE_MAX 8192
|
||||||
|
|
||||||
|
class T
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum status {pending, completed, deleted};
|
||||||
|
|
||||||
|
T (); // Default constructor
|
||||||
|
T (const std::string&); // Initialize by parsing storage format
|
||||||
|
T (const T&); // Copy constructor
|
||||||
|
T& operator= (const T&); // Assignment operator
|
||||||
|
~T (); // Destructor
|
||||||
|
|
||||||
|
std::string getUUID () const { return mUUID; }
|
||||||
|
void setUUID (const std::string& uuid) { mUUID = uuid; }
|
||||||
|
|
||||||
|
int getId () const { return mId; }
|
||||||
|
void setId (int id) { mId = id; }
|
||||||
|
|
||||||
|
status getStatus () const { return mStatus; }
|
||||||
|
void setStatus (status s) { mStatus = s; }
|
||||||
|
|
||||||
|
const std::string getDescription () const { return mDescription; }
|
||||||
|
void setDescription (const std::string& description) { mDescription = description; }
|
||||||
|
|
||||||
|
void getSubstitution (std::string&, std::string&) const;
|
||||||
|
void setSubstitution (const std::string&, const std::string&);
|
||||||
|
|
||||||
|
bool hasTag (const std::string&) const;
|
||||||
|
|
||||||
|
void getRemoveTags (std::vector<std::string>&); // SPECIAL
|
||||||
|
void addRemoveTag (const std::string&); // SPECIAL
|
||||||
|
|
||||||
|
void getTags (std::vector<std::string>&) const;
|
||||||
|
void addTag (const std::string&);
|
||||||
|
void addTags (const std::vector <std::string>&);
|
||||||
|
void removeTag (const std::string&);
|
||||||
|
void removeTags ();
|
||||||
|
void getAttributes (std::map<std::string, std::string>&);
|
||||||
|
const std::string getAttribute (const std::string&);
|
||||||
|
void setAttribute (const std::string&, const std::string&);
|
||||||
|
void setAttributes (const std::map <std::string, std::string>&);
|
||||||
|
void removeAttribute (const std::string&);
|
||||||
|
void removeAttributes ();
|
||||||
|
|
||||||
|
const std::string compose () const;
|
||||||
|
const std::string composeCSV ();
|
||||||
|
void parse (const std::string&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int determineVersion (const std::string&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status mStatus;
|
||||||
|
std::string mUUID;
|
||||||
|
int mId;
|
||||||
|
std::string mDescription;
|
||||||
|
std::vector<std::string> mTags;
|
||||||
|
std::vector<std::string> mRemoveTags;
|
||||||
|
std::map<std::string, std::string> mAttributes;
|
||||||
|
|
||||||
|
std::string mFrom;
|
||||||
|
std::string mTo;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
467
src/TDB.cpp
Normal file
467
src/TDB.cpp
Normal file
@@ -0,0 +1,467 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2007, 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "task.h"
|
||||||
|
#include "TDB.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
TDB::TDB ()
|
||||||
|
: mPendingFile ("")
|
||||||
|
, mCompletedFile ("")
|
||||||
|
, mLogFile ("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
TDB::~TDB ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void TDB::dataDirectory (const std::string& directory)
|
||||||
|
{
|
||||||
|
if (! access (directory.c_str (), F_OK))
|
||||||
|
{
|
||||||
|
mPendingFile = directory + "/pending.data";
|
||||||
|
mCompletedFile = directory + "/completed.data";
|
||||||
|
mLogFile = directory + "/command.log";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string error = "Directory '";
|
||||||
|
error += directory;
|
||||||
|
error += "' does not exist, or is not readable and writable.";
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Combine allPendingT with allCompletedT.
|
||||||
|
// Note: this method is O(N1) + O(N2), where N2 is not bounded.
|
||||||
|
bool TDB::allT (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
// Retrieve all the pending records.
|
||||||
|
std::vector <T> allp;
|
||||||
|
if (allPendingT (allp))
|
||||||
|
{
|
||||||
|
std::vector <T>::iterator i;
|
||||||
|
for (i = allp.begin (); i != allp.end (); ++i)
|
||||||
|
all.push_back (*i);
|
||||||
|
|
||||||
|
// Retrieve all the completed records.
|
||||||
|
std::vector <T> allc;
|
||||||
|
if (allCompletedT (allc))
|
||||||
|
{
|
||||||
|
for (i = allc.begin (); i != allc.end (); ++i)
|
||||||
|
all.push_back (*i);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Only accesses to the pending file result in Tasks that have assigned ids.
|
||||||
|
bool TDB::pendingT (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
std::vector <std::string> lines;
|
||||||
|
if (readLockedFile (mPendingFile, lines))
|
||||||
|
{
|
||||||
|
int id = 1;
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator it;
|
||||||
|
for (it = lines.begin (); it != lines.end (); ++it)
|
||||||
|
{
|
||||||
|
T t (*it);
|
||||||
|
t.setId (id++);
|
||||||
|
if (t.getStatus () == T::pending)
|
||||||
|
all.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Only accesses to the pending file result in Tasks that have assigned ids.
|
||||||
|
bool TDB::allPendingT (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
std::vector <std::string> lines;
|
||||||
|
if (readLockedFile (mPendingFile, lines))
|
||||||
|
{
|
||||||
|
int id = 1;
|
||||||
|
|
||||||
|
std::vector <std::string>::iterator it;
|
||||||
|
for (it = lines.begin (); it != lines.end (); ++it)
|
||||||
|
{
|
||||||
|
T t (*it);
|
||||||
|
t.setId (id++);
|
||||||
|
all.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::completedT (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
std::vector <std::string> lines;
|
||||||
|
if (readLockedFile (mCompletedFile, lines))
|
||||||
|
{
|
||||||
|
std::vector <std::string>::iterator it;
|
||||||
|
for (it = lines.begin (); it != lines.end (); ++it)
|
||||||
|
{
|
||||||
|
T t (*it);
|
||||||
|
if (t.getStatus () != T::deleted)
|
||||||
|
all.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::allCompletedT (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
all.clear ();
|
||||||
|
|
||||||
|
std::vector <std::string> lines;
|
||||||
|
if (readLockedFile (mCompletedFile, lines))
|
||||||
|
{
|
||||||
|
std::vector <std::string>::iterator it;
|
||||||
|
for (it = lines.begin (); it != lines.end (); ++it)
|
||||||
|
{
|
||||||
|
T t (*it);
|
||||||
|
all.push_back (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::deleteT (const T& t) const
|
||||||
|
{
|
||||||
|
T task (t);
|
||||||
|
|
||||||
|
std::vector <T> all;
|
||||||
|
allPendingT (all);
|
||||||
|
|
||||||
|
std::vector <T>::iterator it;
|
||||||
|
for (it = all.begin (); it != all.end (); ++it)
|
||||||
|
if (task.getId () == it->getId ())
|
||||||
|
{
|
||||||
|
it->setStatus (T::deleted);
|
||||||
|
|
||||||
|
char endTime[16];
|
||||||
|
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||||
|
it->setAttribute ("end", endTime);
|
||||||
|
|
||||||
|
return overwritePending (all);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::completeT (const T& t) const
|
||||||
|
{
|
||||||
|
T task (t);
|
||||||
|
|
||||||
|
std::vector <T> all;
|
||||||
|
allPendingT (all);
|
||||||
|
|
||||||
|
std::vector <T>::iterator it;
|
||||||
|
for (it = all.begin (); it != all.end (); ++it)
|
||||||
|
if (task.getId () == it->getId ())
|
||||||
|
{
|
||||||
|
it->setStatus (T::completed);
|
||||||
|
|
||||||
|
char endTime[16];
|
||||||
|
sprintf (endTime, "%u", (unsigned int) time (NULL));
|
||||||
|
it->setAttribute ("end", endTime);
|
||||||
|
|
||||||
|
return overwritePending (all);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::addT (const T& t) const
|
||||||
|
{
|
||||||
|
T task (t);
|
||||||
|
|
||||||
|
std::vector <std::string> tags;
|
||||||
|
task.getTags (tags);
|
||||||
|
|
||||||
|
// TODO This logic smells funny.
|
||||||
|
// +tag or -tag are both considered valid tags to add to a new pending task.
|
||||||
|
// Generating an error here would not be friendly.
|
||||||
|
for (unsigned int i = 0; i < tags.size (); ++i)
|
||||||
|
{
|
||||||
|
if (tags[i][0] == '-' || tags[i][0] == '+')
|
||||||
|
{
|
||||||
|
task.removeTag (tags[i]);
|
||||||
|
task.addTag (tags[i].substr (1, std::string::npos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.getStatus () == T::pending)
|
||||||
|
return writePending (task);
|
||||||
|
|
||||||
|
return writeCompleted (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::modifyT (const T& t) const
|
||||||
|
{
|
||||||
|
T modified (t);
|
||||||
|
|
||||||
|
std::vector <T> all;
|
||||||
|
allPendingT (all);
|
||||||
|
|
||||||
|
std::vector <T> pending;
|
||||||
|
|
||||||
|
std::vector <T>::iterator it;
|
||||||
|
for (it = all.begin (); it != all.end (); ++it)
|
||||||
|
{
|
||||||
|
if (it->getId () == t.getId ())
|
||||||
|
{
|
||||||
|
modified.setUUID (it->getUUID ());
|
||||||
|
pending.push_back (modified);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pending.push_back (*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return overwritePending (pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::logRead (std::vector <std::string>& entries) const
|
||||||
|
{
|
||||||
|
entries.clear ();
|
||||||
|
return readLockedFile (mLogFile, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::logCommand (int argc, char** argv) const
|
||||||
|
{
|
||||||
|
// Get time info.
|
||||||
|
time_t now;
|
||||||
|
time (&now);
|
||||||
|
struct tm* t = localtime (&now);
|
||||||
|
|
||||||
|
// Generate timestamp.
|
||||||
|
char timestamp[20];
|
||||||
|
sprintf (timestamp, "%04d-%02d-%02d %02d:%02d:%02d",
|
||||||
|
t->tm_year + 1900,
|
||||||
|
t->tm_mon + 1,
|
||||||
|
t->tm_mday,
|
||||||
|
t->tm_hour,
|
||||||
|
t->tm_min,
|
||||||
|
t->tm_sec);
|
||||||
|
|
||||||
|
std::string command = timestamp;
|
||||||
|
command += " \"";
|
||||||
|
for (int i = 0; i < argc; ++i)
|
||||||
|
command += std::string (i ? " " : "") + argv[i];
|
||||||
|
command += "\"\n";
|
||||||
|
|
||||||
|
if (! access (mLogFile.c_str (), F_OK | W_OK))
|
||||||
|
{
|
||||||
|
FILE* out;
|
||||||
|
if ((out = fopen (mLogFile.c_str (), "a")))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
int retry = 0;
|
||||||
|
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||||
|
delay (0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf (out, command.c_str ());
|
||||||
|
|
||||||
|
fclose (out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::lock (FILE* file) const
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
return flock (fileno (file), LOCK_EX) ? false : true;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::overwritePending (std::vector <T>& all) const
|
||||||
|
{
|
||||||
|
// Write a single task to the pending file
|
||||||
|
FILE* out;
|
||||||
|
if ((out = fopen (mPendingFile.c_str (), "w")))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
int retry = 0;
|
||||||
|
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||||
|
delay (0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::vector <T>::iterator it;
|
||||||
|
for (it = all.begin (); it != all.end (); ++it)
|
||||||
|
fprintf (out, it->compose ().c_str ());
|
||||||
|
|
||||||
|
fclose (out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::writePending (const T& t) const
|
||||||
|
{
|
||||||
|
// Write a single task to the pending file
|
||||||
|
FILE* out;
|
||||||
|
if ((out = fopen (mPendingFile.c_str (), "a")))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
int retry = 0;
|
||||||
|
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||||
|
delay (0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf (out, t.compose ().c_str ());
|
||||||
|
|
||||||
|
fclose (out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::writeCompleted (const T& t) const
|
||||||
|
{
|
||||||
|
// Write a single task to the pending file
|
||||||
|
FILE* out;
|
||||||
|
if ((out = fopen (mCompletedFile.c_str (), "a")))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
int retry = 0;
|
||||||
|
while (flock (fileno (out), LOCK_EX) && ++retry <= 3)
|
||||||
|
delay (0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fprintf (out, t.compose ().c_str ());
|
||||||
|
|
||||||
|
fclose (out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool TDB::readLockedFile (
|
||||||
|
const std::string& file,
|
||||||
|
std::vector <std::string>& contents) const
|
||||||
|
{
|
||||||
|
contents.clear ();
|
||||||
|
|
||||||
|
if (! access (file.c_str (), F_OK | R_OK))
|
||||||
|
{
|
||||||
|
FILE* in;
|
||||||
|
if ((in = fopen (file.c_str (), "r")))
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FLOCK
|
||||||
|
int retry = 0;
|
||||||
|
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
|
||||||
|
delay (0.25);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char line[T_LINE_MAX];
|
||||||
|
while (fgets (line, T_LINE_MAX, in))
|
||||||
|
{
|
||||||
|
int length = ::strlen (line);
|
||||||
|
if (length > 1)
|
||||||
|
{
|
||||||
|
line[length - 1] = '\0'; // Kill \n
|
||||||
|
contents.push_back (line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose (in);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int TDB::gc () const
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
// Read everything from the pending file.
|
||||||
|
std::vector <T> all;
|
||||||
|
allPendingT (all);
|
||||||
|
|
||||||
|
// A list of the truly pending tasks.
|
||||||
|
std::vector <T> pending;
|
||||||
|
|
||||||
|
std::vector<T>::iterator it;
|
||||||
|
for (it = all.begin (); it != all.end (); ++it)
|
||||||
|
{
|
||||||
|
// Some tasks stay in the pending file.
|
||||||
|
if (it->getStatus () == T::pending)
|
||||||
|
pending.push_back (*it);
|
||||||
|
|
||||||
|
// Others are transferred to the completed file.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writeCompleted (*it);
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump all clean tasks into pending.
|
||||||
|
overwritePending (pending);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
47
src/TDB.h
Normal file
47
src/TDB.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2007, 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_TDB
|
||||||
|
#define INCLUDED_TDB
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "T.h"
|
||||||
|
|
||||||
|
class TDB
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TDB ();
|
||||||
|
~TDB ();
|
||||||
|
|
||||||
|
void dataDirectory (const std::string&);
|
||||||
|
bool allT (std::vector <T>&) const;
|
||||||
|
bool pendingT (std::vector <T>&) const;
|
||||||
|
bool allPendingT (std::vector <T>&) const;
|
||||||
|
bool completedT (std::vector <T>&) const;
|
||||||
|
bool allCompletedT (std::vector <T>&) const;
|
||||||
|
bool deleteT (const T&) const;
|
||||||
|
bool completeT (const T&) const;
|
||||||
|
bool addT (const T&) const;
|
||||||
|
bool modifyT (const T&) const;
|
||||||
|
bool logRead (std::vector <std::string>&) const;
|
||||||
|
bool logCommand (int, char**) const;
|
||||||
|
int gc () const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool lock (FILE*) const;
|
||||||
|
bool overwritePending (std::vector <T>&) const;
|
||||||
|
bool writePending (const T&) const;
|
||||||
|
bool writeCompleted (const T&) const;
|
||||||
|
bool readLockedFile (const std::string&, std::vector <std::string>&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string mPendingFile;
|
||||||
|
std::string mCompletedFile;
|
||||||
|
std::string mLogFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
1064
src/Table.cpp
Normal file
1064
src/Table.cpp
Normal file
File diff suppressed because it is too large
Load Diff
115
src/Table.h
Normal file
115
src/Table.h
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// TODO Implement height
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_TABLE
|
||||||
|
#define INCLUDED_TABLE
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
class Table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum just {left, center, right};
|
||||||
|
enum order {ascendingNumeric, ascendingCharacter, ascendingPriority,
|
||||||
|
ascendingDate, descendingNumeric, descendingCharacter,
|
||||||
|
descendingPriority, descendingDate};
|
||||||
|
enum sizing {minimum = -1, flexible = 0};
|
||||||
|
|
||||||
|
Table ();
|
||||||
|
virtual ~Table ();
|
||||||
|
|
||||||
|
void setTableColor (Text::color, Text::color);
|
||||||
|
void setTableFg (Text::color);
|
||||||
|
void setTableBg (Text::color);
|
||||||
|
void setTablePadding (int);
|
||||||
|
void setTableIntraPadding (int);
|
||||||
|
void setTableWidth (int);
|
||||||
|
|
||||||
|
int addColumn (const std::string&);
|
||||||
|
void setColumnColor (int, Text::color, Text::color);
|
||||||
|
void setColumnFg (int, Text::color);
|
||||||
|
void setColumnBg (int, Text::color);
|
||||||
|
void setColumnUnderline (int);
|
||||||
|
void setColumnPadding (int, int);
|
||||||
|
void setColumnWidth (int, int);
|
||||||
|
void setColumnWidth (int, sizing);
|
||||||
|
void setColumnJustification (int, just);
|
||||||
|
void setColumnCommify (int);
|
||||||
|
void sortOn (int, order);
|
||||||
|
|
||||||
|
int addRow ();
|
||||||
|
void setRowColor (int, Text::color, Text::color);
|
||||||
|
void setRowFg (int, Text::color);
|
||||||
|
void setRowBg (int, Text::color);
|
||||||
|
|
||||||
|
void addCell (int, int, const std::string&);
|
||||||
|
void addCell (int, int, char);
|
||||||
|
void addCell (int, int, int);
|
||||||
|
void addCell (int, int, float);
|
||||||
|
void addCell (int, int, double);
|
||||||
|
void setCellColor (int, int, Text::color, Text::color);
|
||||||
|
void setCellFg (int, int, Text::color);
|
||||||
|
void setCellBg (int, int, Text::color);
|
||||||
|
|
||||||
|
void suppressWS ();
|
||||||
|
|
||||||
|
int rowCount ();
|
||||||
|
int columnCount ();
|
||||||
|
const std::string render ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string getCell (int, int);
|
||||||
|
Text::color getFg (int, int);
|
||||||
|
Text::color getHeaderFg (int);
|
||||||
|
Text::color getBg (int, int);
|
||||||
|
Text::color getHeaderBg (int);
|
||||||
|
Text::attr getHeaderUnderline (int);
|
||||||
|
int getPadding (int);
|
||||||
|
int getIntraPadding ();
|
||||||
|
void calculateColumnWidths ();
|
||||||
|
just getJustification (int, int);
|
||||||
|
just getHeaderJustification (int);
|
||||||
|
const std::string formatHeader (int, int, int);
|
||||||
|
const std::string formatCell (int, int, int, int);
|
||||||
|
void formatCell (int, int, int, int, std::vector <std::string>&, std::string&);
|
||||||
|
void optimize (std::string&);
|
||||||
|
void sort (std::vector <int>&);
|
||||||
|
void clean (std::string&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector <std::string> mColumns;
|
||||||
|
int mRows;
|
||||||
|
int mIntraPadding;
|
||||||
|
std::map <std::string, Text::color> mFg;
|
||||||
|
std::map <std::string, Text::color> mBg;
|
||||||
|
std::map <std::string, Text::attr> mUnderline;
|
||||||
|
|
||||||
|
// Padding...
|
||||||
|
int mTablePadding;
|
||||||
|
std::vector <int> mColumnPadding;
|
||||||
|
|
||||||
|
// Width...
|
||||||
|
int mTableWidth;
|
||||||
|
std::vector <int> mSpecifiedWidth;
|
||||||
|
std::vector <int> mMaxDataWidth;
|
||||||
|
std::vector <int> mCalculatedWidth;
|
||||||
|
|
||||||
|
std::map <std::string, just> mJustification;
|
||||||
|
std::map <int, bool> mCommify;
|
||||||
|
std::map <std::string, std::string> mData;
|
||||||
|
std::vector <int> mSortColumns;
|
||||||
|
std::map <int, order> mSortOrder;
|
||||||
|
|
||||||
|
// Misc...
|
||||||
|
bool mSuppressWS;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
64
src/color.cpp
Normal file
64
src/color.cpp
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <string>
|
||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string Text::colorName (Text::color c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case black: return "black";
|
||||||
|
case red: return "red";
|
||||||
|
case green: return "green";
|
||||||
|
case yellow: return "yellow";
|
||||||
|
case blue: return "blue";
|
||||||
|
case magenta: return "magenta";
|
||||||
|
case cyan: return "cyan";
|
||||||
|
case white: return "white";
|
||||||
|
case nocolor: return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Text::color Text::colorCode (const std::string& c)
|
||||||
|
{
|
||||||
|
if (c == "black") return black;
|
||||||
|
if (c == "red") return red;
|
||||||
|
if (c == "green") return green;
|
||||||
|
if (c == "yellow") return yellow;
|
||||||
|
if (c == "blue") return blue;
|
||||||
|
if (c == "magenta") return magenta;
|
||||||
|
if (c == "cyan") return cyan;
|
||||||
|
if (c == "white") return white;
|
||||||
|
|
||||||
|
return nocolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string Text::attrName (Text::attr a)
|
||||||
|
{
|
||||||
|
switch (a)
|
||||||
|
{
|
||||||
|
case underline: return "underline";
|
||||||
|
case normal: return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Text::attr Text::attrCode (const std::string& a)
|
||||||
|
{
|
||||||
|
if (a == "underline") return underline;
|
||||||
|
|
||||||
|
return normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
23
src/color.h
Normal file
23
src/color.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2008, Paul Beckingham.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_COLOR
|
||||||
|
#define INCLUDED_COLOR
|
||||||
|
|
||||||
|
namespace Text
|
||||||
|
{
|
||||||
|
enum color {nocolor = 0, black, red, green, yellow, blue, magenta, cyan, white};
|
||||||
|
enum attr {normal = 0, underline};
|
||||||
|
|
||||||
|
std::string colorName (Text::color);
|
||||||
|
Text::color colorCode (const std::string&);
|
||||||
|
|
||||||
|
std::string attrName (Text::attr);
|
||||||
|
Text::attr attrCode (const std::string&);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
49
src/library.h
Normal file
49
src/library.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2004 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_LIBRARY
|
||||||
|
#define INCLUDED_LIBRARY
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "stlmacros.h"
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// text.cpp
|
||||||
|
void wrapText (std::vector <std::string>&, const std::string&, const int);
|
||||||
|
std::string trimLeft (const std::string& in, const std::string& t = " ");
|
||||||
|
std::string trimRight (const std::string& in, const std::string& t = " ");
|
||||||
|
std::string trim (const std::string& in, const std::string& t = " ");
|
||||||
|
std::wstring trimLeft (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
std::wstring trimRight (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
std::wstring trim (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
void extractParagraphs (const std::string&, std::vector<std::string>&);
|
||||||
|
void extractLine (std::string&, std::string&, int);
|
||||||
|
void split (std::vector<std::string>&, const std::string&, const char);
|
||||||
|
void split (std::vector<std::string>&, const std::string&, const std::string&);
|
||||||
|
void join (std::string&, const std::string&, const std::vector<std::string>&);
|
||||||
|
std::string commify (const std::string&);
|
||||||
|
std::string lowerCase (const std::string&);
|
||||||
|
|
||||||
|
// misc.cpp
|
||||||
|
void delay (float);
|
||||||
|
|
||||||
|
// list.cpp
|
||||||
|
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||||
|
|
||||||
|
// units.cpp
|
||||||
|
void formatTimeDeltaDays (std::string&, time_t);
|
||||||
|
std::string formatSeconds (time_t);
|
||||||
|
|
||||||
|
// uuid.cpp
|
||||||
|
const std::string uuid ();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
329
src/parse.cpp
Normal file
329
src/parse.cpp
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "Date.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "T.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static char* colors[] =
|
||||||
|
{
|
||||||
|
"black",
|
||||||
|
"blue",
|
||||||
|
"red",
|
||||||
|
"green",
|
||||||
|
"magenta",
|
||||||
|
"cyan",
|
||||||
|
"yellow",
|
||||||
|
"white",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* attributes[] =
|
||||||
|
{
|
||||||
|
"project",
|
||||||
|
"priority",
|
||||||
|
"fg",
|
||||||
|
"bg",
|
||||||
|
"due",
|
||||||
|
"entry",
|
||||||
|
"start",
|
||||||
|
"end",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
|
||||||
|
static char* commands[] =
|
||||||
|
{
|
||||||
|
"active",
|
||||||
|
"add",
|
||||||
|
"calendar",
|
||||||
|
"completed",
|
||||||
|
"delete",
|
||||||
|
"done",
|
||||||
|
"export",
|
||||||
|
"history",
|
||||||
|
"info",
|
||||||
|
"list",
|
||||||
|
"long",
|
||||||
|
"ls",
|
||||||
|
"next",
|
||||||
|
"overdue",
|
||||||
|
"projects",
|
||||||
|
"start",
|
||||||
|
"stats",
|
||||||
|
"summary",
|
||||||
|
"tags",
|
||||||
|
"usage",
|
||||||
|
"version",
|
||||||
|
"",
|
||||||
|
};
|
||||||
|
|
||||||
|
void guess (const std::string& type, char** list, std::string& candidate)
|
||||||
|
{
|
||||||
|
std::vector <std::string> options;
|
||||||
|
for (int i = 0; list[i][0]; ++i)
|
||||||
|
options.push_back (list[i]);
|
||||||
|
|
||||||
|
std::vector <std::string> matches;
|
||||||
|
autoComplete (candidate, options, matches);
|
||||||
|
if (1 == matches.size ())
|
||||||
|
candidate = matches[0];
|
||||||
|
|
||||||
|
else if (0 == matches.size ())
|
||||||
|
throw std::string ("Unrecognized ") + type + " '" + candidate + "'";
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string error = "Ambiguous ";
|
||||||
|
error += type;
|
||||||
|
error += " '";
|
||||||
|
error += candidate;
|
||||||
|
error += "' - could be either of ";
|
||||||
|
for (unsigned int i = 0; i < matches.size (); ++i)
|
||||||
|
{
|
||||||
|
if (i)
|
||||||
|
error += ", ";
|
||||||
|
error += matches[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool isCommand (const std::string& candidate)
|
||||||
|
{
|
||||||
|
std::vector <std::string> options;
|
||||||
|
for (int i = 0; commands[i][0]; ++i)
|
||||||
|
options.push_back (commands[i]);
|
||||||
|
|
||||||
|
std::vector <std::string> matches;
|
||||||
|
autoComplete (candidate, options, matches);
|
||||||
|
if (0 == matches.size ())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool validDate (std::string& date)
|
||||||
|
{
|
||||||
|
unsigned int firstSlash = date.find ("/");
|
||||||
|
unsigned int secondSlash = date.find ("/", firstSlash + 1);
|
||||||
|
if (firstSlash != std::string::npos &&
|
||||||
|
secondSlash != std::string::npos)
|
||||||
|
{
|
||||||
|
int m = ::atoi (date.substr (0, firstSlash ).c_str ());
|
||||||
|
int d = ::atoi (date.substr (firstSlash + 1, secondSlash - firstSlash).c_str ());
|
||||||
|
int y = ::atoi (date.substr (secondSlash + 1, std::string::npos ).c_str ());
|
||||||
|
if (!Date::valid (m, d, y))
|
||||||
|
throw std::string ("\"") + date + "\" is not a valid date.";
|
||||||
|
|
||||||
|
// Convert to epoch form.
|
||||||
|
Date dt (m, d, y);
|
||||||
|
time_t t;
|
||||||
|
dt.toEpoch (t);
|
||||||
|
char converted[12];
|
||||||
|
sprintf (converted, "%u", (unsigned int) t);
|
||||||
|
date = converted;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw std::string ("Badly formed date - use the MM/DD/YYYY format");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validPriority (std::string& input)
|
||||||
|
{
|
||||||
|
if (input != "H" &&
|
||||||
|
input != "M" &&
|
||||||
|
input != "L" &&
|
||||||
|
input != "")
|
||||||
|
throw std::string ("\"") +
|
||||||
|
input +
|
||||||
|
"\" is not a valid priority. Use H, M, L or leave blank.";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validAttribute (std::string& name, std::string& value)
|
||||||
|
{
|
||||||
|
guess ("attribute", attributes, name);
|
||||||
|
|
||||||
|
if ((name == "fg" || name == "bg") && value != "")
|
||||||
|
guess ("color", colors, value);
|
||||||
|
|
||||||
|
else if (name == "due" && value != "")
|
||||||
|
validDate (value);
|
||||||
|
|
||||||
|
else if (name == "priority")
|
||||||
|
{
|
||||||
|
for (std::string::iterator i = value.begin (); i != value.end (); ++i)
|
||||||
|
*i = ::toupper (*i);
|
||||||
|
|
||||||
|
return validPriority (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "entry" ||
|
||||||
|
name == "start" ||
|
||||||
|
name == "end")
|
||||||
|
throw std::string ("\"") +
|
||||||
|
name +
|
||||||
|
"\" is not an attribute you may modify directly.";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validId (const std::string& input)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < input.length (); ++i)
|
||||||
|
if (!::isdigit (input[i]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validTag (std::string& input)
|
||||||
|
{
|
||||||
|
if ((input[0] == '-' || input[0] == '+') &&
|
||||||
|
input.length () > 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validDescription (const std::string& input)
|
||||||
|
{
|
||||||
|
if (input.length () > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validCommand (std::string& input)
|
||||||
|
{
|
||||||
|
guess ("command", commands, input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static bool validSubstitution (
|
||||||
|
std::string& input,
|
||||||
|
std::string& from,
|
||||||
|
std::string& to)
|
||||||
|
{
|
||||||
|
unsigned int first = input.find ('/');
|
||||||
|
if (first != std::string::npos)
|
||||||
|
{
|
||||||
|
unsigned int second = input.find ('/', first + 1);
|
||||||
|
if (second != std::string::npos)
|
||||||
|
{
|
||||||
|
unsigned int third = input.find ('/', second + 1);
|
||||||
|
if (third != std::string::npos)
|
||||||
|
{
|
||||||
|
if (first == 0 &&
|
||||||
|
first < second &&
|
||||||
|
second < third &&
|
||||||
|
third == input.length () - 1)
|
||||||
|
{
|
||||||
|
from = input.substr (first + 1, second - first - 1);
|
||||||
|
to = input.substr (second + 1, third - second - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Token Distinguishing characteristic
|
||||||
|
// ------- -----------------------------
|
||||||
|
// command first positional
|
||||||
|
// id \d+
|
||||||
|
// description default, accumulate
|
||||||
|
// substitution /\w+/\w*/
|
||||||
|
// tags [-+]\w+
|
||||||
|
// attributes \w+:.+
|
||||||
|
//
|
||||||
|
void parse (
|
||||||
|
std::vector <std::string>& args,
|
||||||
|
std::string& command,
|
||||||
|
T& task)
|
||||||
|
{
|
||||||
|
command = "";
|
||||||
|
|
||||||
|
std::string descCandidate = "";
|
||||||
|
for (unsigned int i = 0; i < args.size (); ++i)
|
||||||
|
{
|
||||||
|
std::string arg (args[i]);
|
||||||
|
unsigned int colon; // Pointer to colon in argument.
|
||||||
|
std::string from;
|
||||||
|
std::string to;
|
||||||
|
|
||||||
|
// An id is the first argument found that contains all digits.
|
||||||
|
if (command != "add" && // "add" doesn't require an ID
|
||||||
|
task.getId () == 0 &&
|
||||||
|
validId (arg))
|
||||||
|
task.setId (::atoi (arg.c_str ()));
|
||||||
|
|
||||||
|
// Tags begin with + or - and contain arbitrary text.
|
||||||
|
else if (validTag (arg))
|
||||||
|
{
|
||||||
|
if (arg[0] == '+')
|
||||||
|
task.addTag (arg.substr (1, std::string::npos));
|
||||||
|
else if (arg[0] == '-')
|
||||||
|
task.addRemoveTag (arg.substr (1, std::string::npos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attributes contain a constant string followed by a colon, followed by a
|
||||||
|
// value.
|
||||||
|
else if ((colon = arg.find (":")) != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string name = arg.substr (0, colon);
|
||||||
|
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||||
|
|
||||||
|
if (validAttribute (name, value))
|
||||||
|
task.setAttribute (name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Substitution of description text.
|
||||||
|
else if (validSubstitution (arg, from, to))
|
||||||
|
{
|
||||||
|
task.setSubstitution (from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command.
|
||||||
|
else if (command == "")
|
||||||
|
{
|
||||||
|
if (!isCommand (arg))
|
||||||
|
descCandidate += std::string (arg) + " ";
|
||||||
|
else if (validCommand (arg))
|
||||||
|
command = arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anything else is just considered description.
|
||||||
|
else
|
||||||
|
descCandidate += std::string (arg) + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validDescription (descCandidate))
|
||||||
|
task.setDescription (descCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
182
src/rules.cpp
Normal file
182
src/rules.cpp
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Table.h"
|
||||||
|
#include "Date.h"
|
||||||
|
#include "T.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
static std::map <std::string, Text::color> gsFg;
|
||||||
|
static std::map <std::string, Text::color> gsBg;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// There are three supported variants:
|
||||||
|
// 1) "fg"
|
||||||
|
// 2) "on bg"
|
||||||
|
// 3) "fg on bg"
|
||||||
|
static void parseColorRule (
|
||||||
|
const std::string& rule,
|
||||||
|
Text::color& fg,
|
||||||
|
Text::color& bg)
|
||||||
|
{
|
||||||
|
fg = Text::nocolor;
|
||||||
|
bg = Text::nocolor;
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
std::vector <std::string> words;
|
||||||
|
split (words, rule, ' ');
|
||||||
|
switch (words.size ())
|
||||||
|
{
|
||||||
|
case 1: // "fg" - no spaces.
|
||||||
|
fg = Text::colorCode (words[0]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // "on bg" - one space, "on" before.
|
||||||
|
if (words[0] == "on")
|
||||||
|
bg = Text::colorCode (words[1]);
|
||||||
|
else
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // "fg on bg" - two spaces, "on" between them.
|
||||||
|
if (words[1] == "on")
|
||||||
|
{
|
||||||
|
fg = Text::colorCode (words[0]);
|
||||||
|
bg = Text::colorCode (words[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
std::cout << "Malformed color rule '" << rule << "'" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void initializeColorRules (Config& conf)
|
||||||
|
{
|
||||||
|
std::vector <std::string> ruleNames;
|
||||||
|
conf.all (ruleNames);
|
||||||
|
foreach (it, ruleNames)
|
||||||
|
{
|
||||||
|
if (it->substr (0, 6) == "color.")
|
||||||
|
{
|
||||||
|
Text::color fg;
|
||||||
|
Text::color bg;
|
||||||
|
parseColorRule (conf.get (*it), fg, bg);
|
||||||
|
gsFg[*it] = fg;
|
||||||
|
gsBg[*it] = bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void autoColorize (T& task, Text::color& fg, Text::color& bg)
|
||||||
|
{
|
||||||
|
fg = Text::nocolor;
|
||||||
|
bg = Text::nocolor;
|
||||||
|
|
||||||
|
// Colorization of the tagged.
|
||||||
|
if (gsFg["color.tagged"] != Text::nocolor ||
|
||||||
|
gsBg["color.tagged"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
std::vector <std::string> tags;
|
||||||
|
task.getTags (tags);
|
||||||
|
if (tags.size ())
|
||||||
|
{
|
||||||
|
fg = gsFg["color.tagged"];
|
||||||
|
bg = gsBg["color.tagged"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the low priority.
|
||||||
|
if (gsFg["color.pri.L"] != Text::nocolor ||
|
||||||
|
gsBg["color.pri.L"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
if (task.getAttribute ("priority") == "L")
|
||||||
|
{
|
||||||
|
fg = gsFg["color.pri.L"];
|
||||||
|
bg = gsBg["color.pri.L"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the medium priority.
|
||||||
|
if (gsFg["color.pri.M"] != Text::nocolor ||
|
||||||
|
gsBg["color.pri.M"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
if (task.getAttribute ("priority") == "M")
|
||||||
|
{
|
||||||
|
fg = gsFg["color.pri.M"];
|
||||||
|
bg = gsBg["color.pri.M"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the high priority.
|
||||||
|
if (gsFg["color.pri.H"] != Text::nocolor ||
|
||||||
|
gsBg["color.pri.H"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
if (task.getAttribute ("priority") == "H")
|
||||||
|
{
|
||||||
|
fg = gsFg["color.pri.H"];
|
||||||
|
bg = gsBg["color.pri.H"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the priority-less.
|
||||||
|
if (gsFg["color.pri.none"] != Text::nocolor ||
|
||||||
|
gsBg["color.pri.none"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
if (task.getAttribute ("priority") == "")
|
||||||
|
{
|
||||||
|
fg = gsFg["color.pri.none"];
|
||||||
|
bg = gsBg["color.pri.none"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the active.
|
||||||
|
if (gsFg["color.active"] != Text::nocolor ||
|
||||||
|
gsBg["color.active"] != Text::nocolor)
|
||||||
|
{
|
||||||
|
if (task.getAttribute ("start") != "")
|
||||||
|
{
|
||||||
|
fg = gsFg["color.active"];
|
||||||
|
bg = gsBg["color.active"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colorization of the due and overdue.
|
||||||
|
std::string due = task.getAttribute ("due");
|
||||||
|
if (due != "")
|
||||||
|
{
|
||||||
|
Date dueDate (::atoi (due.c_str ()));
|
||||||
|
Date now;
|
||||||
|
Date then (now + 7 * 86400);
|
||||||
|
|
||||||
|
// Overdue
|
||||||
|
if (dueDate < now)
|
||||||
|
{
|
||||||
|
fg = gsFg["color.overdue"];
|
||||||
|
bg = gsBg["color.overdue"];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imminent
|
||||||
|
else if (dueDate < then)
|
||||||
|
{
|
||||||
|
fg = gsFg["color.due"];
|
||||||
|
bg = gsBg["color.due"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
18
src/stlmacros.h
Normal file
18
src/stlmacros.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifndef INCLUDED_STLMACROS
|
||||||
|
#define INCLUDED_STLMACROS
|
||||||
|
|
||||||
|
#define foreach(i, c) \
|
||||||
|
for (typeof (c) *foreach_p = & (c); \
|
||||||
|
foreach_p; \
|
||||||
|
foreach_p = 0) \
|
||||||
|
for (typeof (foreach_p->begin()) i = foreach_p->begin(); \
|
||||||
|
i != foreach_p->end(); \
|
||||||
|
++i)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
2682
src/task.cpp
Normal file
2682
src/task.cpp
Normal file
File diff suppressed because it is too large
Load Diff
79
src/task.h
Normal file
79
src/task.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Table.h"
|
||||||
|
#include "color.h"
|
||||||
|
#include "TDB.h"
|
||||||
|
#include "T.h"
|
||||||
|
#include "stlmacros.h"
|
||||||
|
#include "../auto.h"
|
||||||
|
|
||||||
|
#ifndef max
|
||||||
|
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// parse.cpp
|
||||||
|
void parse (std::vector <std::string>&, std::string&, T&);
|
||||||
|
bool validDate (std::string&);
|
||||||
|
|
||||||
|
// task.cpp
|
||||||
|
void handleAdd (const TDB&, T&, Config&);
|
||||||
|
void handleProjects (const TDB&, T&, Config&);
|
||||||
|
void handleTags (const TDB&, T&, Config&);
|
||||||
|
void handleList (const TDB&, T&, Config&);
|
||||||
|
void handleInfo (const TDB&, T&, Config&);
|
||||||
|
void handleLongList (const TDB&, T&, Config&);
|
||||||
|
void handleSmallList (const TDB&, T&, Config&);
|
||||||
|
void handleCompleted (const TDB&, T&, Config&);
|
||||||
|
void handleReportSummary (const TDB&, T&, Config&);
|
||||||
|
void handleReportNext (const TDB&, T&, Config&);
|
||||||
|
void handleReportHistory (const TDB&, T&, Config&);
|
||||||
|
void handleReportUsage (const TDB&, T&, Config&);
|
||||||
|
void handleReportCalendar (const TDB&, T&, Config&);
|
||||||
|
void handleReportActive (const TDB&, T&, Config&);
|
||||||
|
void handleReportOverdue (const TDB&, T&, Config&);
|
||||||
|
void handleReportStats (const TDB&, T&, Config&);
|
||||||
|
void handleVersion (Config&);
|
||||||
|
void handleExport (const TDB&, T&, Config&);
|
||||||
|
void handleDelete (const TDB&, T&, Config&);
|
||||||
|
void handleStart (const TDB&, T&, Config&);
|
||||||
|
void handleDone (const TDB&, T&, Config&);
|
||||||
|
void handleModify (const TDB&, T&, Config&);
|
||||||
|
void gatherNextTasks (const TDB&, T&, Config&, std::vector <T>&, std::vector <int>&);
|
||||||
|
void nag (const TDB&, T&, Config&);
|
||||||
|
|
||||||
|
// util.cpp
|
||||||
|
bool confirm (const std::string&);
|
||||||
|
void wrapText (std::vector <std::string>&, const std::string&, const int);
|
||||||
|
std::string trimLeft (const std::string& in, const std::string& t = " ");
|
||||||
|
std::string trimRight (const std::string& in, const std::string& t = " ");
|
||||||
|
std::string trim (const std::string& in, const std::string& t = " ");
|
||||||
|
std::wstring trimLeft (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
std::wstring trimRight (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
std::wstring trim (const std::wstring& in, const std::wstring& t = L" "); // UNICODE safe
|
||||||
|
void extractParagraphs (const std::string&, std::vector<std::string>&);
|
||||||
|
void extractLine (std::string&, std::string&, int);
|
||||||
|
void split (std::vector<std::string>&, const std::string&, const char);
|
||||||
|
void split (std::vector<std::string>&, const std::string&, const std::string&);
|
||||||
|
void join (std::string&, const std::string&, const std::vector<std::string>&);
|
||||||
|
std::string commify (const std::string&);
|
||||||
|
std::string lowerCase (const std::string&);
|
||||||
|
void delay (float);
|
||||||
|
int autoComplete (const std::string&, const std::vector<std::string>&, std::vector<std::string>&);
|
||||||
|
void formatTimeDeltaDays (std::string&, time_t);
|
||||||
|
std::string formatSeconds (time_t);
|
||||||
|
const std::string uuid ();
|
||||||
|
|
||||||
|
// rules.cpp
|
||||||
|
void initializeColorRules (Config&);
|
||||||
|
void autoColorize (T&, Text::color&, Text::color&);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
5
src/tests/.gitignore
vendored
Normal file
5
src/tests/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
t.t
|
||||||
|
tdb.t
|
||||||
|
pending.data
|
||||||
|
completed.data
|
||||||
|
|
||||||
24
src/tests/Makefile
Normal file
24
src/tests/Makefile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
PROJECT = t.t tdb.t
|
||||||
|
CFLAGS = -I.. -I../../../library/include -Wall -pedantic -ggdb3 -fno-rtti
|
||||||
|
LFLAGS = -L/usr/local/lib -L../../../library/lib -lcompany -lpcre -lncurses -lcurl
|
||||||
|
|
||||||
|
all: $(PROJECT)
|
||||||
|
|
||||||
|
install: $(PROJECT)
|
||||||
|
@echo unimplemented
|
||||||
|
|
||||||
|
test: $(PROJECT)
|
||||||
|
@echo unimplemented
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm *.o $(PROJECT)
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
g++ -c $(CFLAGS) $<
|
||||||
|
|
||||||
|
t.t: t.t.o ../T.o ../parse.o ../../../library/lib/libcompany.a
|
||||||
|
g++ t.t.o ../T.o ../parse.o $(LFLAGS) -o t.t
|
||||||
|
|
||||||
|
tdb.t: tdb.t.o ../TDB.o ../T.o ../parse.o ../../../library/lib/libcompany.a
|
||||||
|
g++ tdb.t.o ../TDB.o ../T.o ../parse.o $(LFLAGS) -o tdb.t
|
||||||
|
|
||||||
37
src/tests/t.t.cpp
Normal file
37
src/tests/t.t.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <T.h>
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
plan (4);
|
||||||
|
|
||||||
|
T t;
|
||||||
|
std::string s = t.compose ();
|
||||||
|
is ((int)s.length (), 46, "T::T (); T::compose ()");
|
||||||
|
diag (s);
|
||||||
|
|
||||||
|
t.setStatus (T::completed);
|
||||||
|
s = t.compose ();
|
||||||
|
is (s[37], '+', "T::setStatus (completed)");
|
||||||
|
diag (s);
|
||||||
|
|
||||||
|
t.setStatus (T::deleted);
|
||||||
|
s = t.compose ();
|
||||||
|
is (s[37], 'X', "T::setStatus (deleted)");
|
||||||
|
diag (s);
|
||||||
|
|
||||||
|
// Round trip test.
|
||||||
|
std::string sample = "00000000-0000-0000-0000-000000000000 - [] [] Sample";
|
||||||
|
T t2;
|
||||||
|
t2.parse (sample);
|
||||||
|
sample += "\n";
|
||||||
|
is (t2.compose (), sample, "T::parse -> T::compose round trip");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
127
src/tests/tdb.t.cpp
Normal file
127
src/tests/tdb.t.cpp
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <TDB.h>
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
plan (43);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Remove any residual test file.
|
||||||
|
unlink ("./pending.data");
|
||||||
|
unlink ("./completed.data");
|
||||||
|
|
||||||
|
// Try reading an empty database.
|
||||||
|
TDB tdb;
|
||||||
|
tdb.dataDirectory (".");
|
||||||
|
std::vector <T> all;
|
||||||
|
ok (!tdb.pendingT (all), "TDB::pendingT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.allPendingT (all), "TDB::allPendingT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.completedT (all), "TDB::completedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
|
||||||
|
// Add a new task.
|
||||||
|
T t1;
|
||||||
|
t1.setId (1);
|
||||||
|
t1.setStatus (T::pending);
|
||||||
|
t1.setAttribute ("project", "p1");
|
||||||
|
t1.setDescription ("task 1");
|
||||||
|
diag (t1.compose ());
|
||||||
|
ok (tdb.addT (t1), "TDB::addT t1");
|
||||||
|
|
||||||
|
// Verify as above.
|
||||||
|
ok (tdb.pendingT (all), "TDB::pendingT read db");
|
||||||
|
is ((int) all.size (), 1, "empty db");
|
||||||
|
ok (tdb.allPendingT (all), "TDB::allPendingT read db");
|
||||||
|
is ((int) all.size (), 1, "empty db");
|
||||||
|
ok (!tdb.completedT (all), "TDB::completedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
|
||||||
|
// TODO Modify task.
|
||||||
|
fail ("modify");
|
||||||
|
fail ("verify");
|
||||||
|
|
||||||
|
// Complete task.
|
||||||
|
ok (tdb.completeT (t1), "TDB::completeT t1");;
|
||||||
|
ok (!tdb.pendingT (all), "TDB::pendingT read db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (tdb.allPendingT (all), "TDB::allPendingT read db");
|
||||||
|
is ((int) all.size (), 1, "empty db");
|
||||||
|
ok (!tdb.completedT (all), "TDB::completedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.allCompletedT (all), "TDB::allCompletedT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
|
||||||
|
is (tdb.gc (), 1, "TDB::gc");
|
||||||
|
ok (!tdb.pendingT (all), "TDB::pendingT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (!tdb.allPendingT (all), "TDB::allPendingT read empty db");
|
||||||
|
is ((int) all.size (), 0, "empty db");
|
||||||
|
ok (tdb.completedT (all), "TDB::completedT read db");
|
||||||
|
is ((int) all.size (), 1, "empty db");
|
||||||
|
ok (tdb.allCompletedT (all), "TDB::allCompletedT read db");
|
||||||
|
is ((int) all.size (), 1, "empty db");
|
||||||
|
|
||||||
|
// Add a new task.
|
||||||
|
T t2;
|
||||||
|
t2.setId (2);
|
||||||
|
t2.setAttribute ("project", "p2");
|
||||||
|
t2.setDescription ("task 2");
|
||||||
|
diag (t2.compose ());
|
||||||
|
ok (tdb.addT (t2), "TDB::addT t2");
|
||||||
|
|
||||||
|
fail ("verify");
|
||||||
|
|
||||||
|
// Delete task.
|
||||||
|
ok (tdb.deleteT (t2), "TDB::deleteT t2");
|
||||||
|
|
||||||
|
fail ("verify");
|
||||||
|
|
||||||
|
// GC the files.
|
||||||
|
is (tdb.gc (), 1, "1 <- TDB::gc");
|
||||||
|
|
||||||
|
// Read log file.
|
||||||
|
std::vector <std::string> entries;
|
||||||
|
tdb.logRead (entries);
|
||||||
|
std::vector <std::string>::iterator it;
|
||||||
|
for (it = entries.begin (); it != entries.end (); ++it)
|
||||||
|
diag (*it);
|
||||||
|
|
||||||
|
// TODO Verify contents of above transactions.
|
||||||
|
fail ("verify");
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (std::string& error)
|
||||||
|
{
|
||||||
|
diag (error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
diag ("Unknown error.");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
unlink ("./pending.data");
|
||||||
|
unlink ("./completed.data");
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
277
src/text.cpp
Normal file
277
src/text.cpp
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2004 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void wrapText (
|
||||||
|
std::vector <std::string>& lines,
|
||||||
|
const std::string& text,
|
||||||
|
const int width)
|
||||||
|
{
|
||||||
|
std::string copy = text;
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (copy.length ())
|
||||||
|
{
|
||||||
|
extractLine (copy, line, width);
|
||||||
|
lines.push_back (line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void split (std::vector<std::string>& results, const std::string& input, const char delimiter)
|
||||||
|
{
|
||||||
|
std::string temp = input;
|
||||||
|
std::string::size_type i;
|
||||||
|
while ((i = temp.find (delimiter)) != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string token = temp.substr (0, i);
|
||||||
|
results.push_back (token);
|
||||||
|
temp.erase (0, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.length ()) results.push_back (temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void split (std::vector<std::string>& results, const std::string& input, const std::string& delimiter)
|
||||||
|
{
|
||||||
|
std::string temp = input;
|
||||||
|
std::string::size_type i;
|
||||||
|
while ((i = temp.find (delimiter)) != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string token = temp.substr (0, i);
|
||||||
|
results.push_back (token);
|
||||||
|
temp.erase (0, i + delimiter.length ());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.length ()) results.push_back (temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void join (
|
||||||
|
std::string& result,
|
||||||
|
const std::string& separator,
|
||||||
|
const std::vector<std::string>& items)
|
||||||
|
{
|
||||||
|
result = "";
|
||||||
|
unsigned int size = items.size ();
|
||||||
|
for (unsigned int i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
result += items[i];
|
||||||
|
if (i < size - 1)
|
||||||
|
result += separator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void extractParagraphs (const std::string& input, std::vector<std::string>& output)
|
||||||
|
{
|
||||||
|
std::string copy = input;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
unsigned int so = copy.find ("<p>");
|
||||||
|
unsigned int eo = copy.find ("</p>");
|
||||||
|
|
||||||
|
if (so == std::string::npos && eo == std::string::npos)
|
||||||
|
break;
|
||||||
|
|
||||||
|
std::string extract = trim (copy.substr (so + 3, eo - so - 3));
|
||||||
|
copy = copy.substr (eo + 4, std::string::npos);
|
||||||
|
output.push_back (extract);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There were no paragraphs.
|
||||||
|
if (!output.size ())
|
||||||
|
output.push_back (input);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string trimLeft (const std::string& in, const std::string& t /*= " "*/)
|
||||||
|
{
|
||||||
|
std::string out = in;
|
||||||
|
return out.erase (0, in.find_first_not_of (t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNICODE safe
|
||||||
|
std::wstring trimLeft (const std::wstring& in, const std::wstring& t /*= L" "*/)
|
||||||
|
{
|
||||||
|
std::wstring out = in;
|
||||||
|
return out.erase (0, in.find_first_not_of (t));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string trimRight (const std::string& in, const std::string& t /*= " "*/)
|
||||||
|
{
|
||||||
|
std::string out = in;
|
||||||
|
return out.erase (out.find_last_not_of (t) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNICODE safe
|
||||||
|
std::wstring trimRight (const std::wstring& in, const std::wstring& t /*= L" "*/)
|
||||||
|
{
|
||||||
|
std::wstring out = in;
|
||||||
|
return out.erase (out.find_last_not_of (t) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string trim (const std::string& in, const std::string& t /*= " "*/)
|
||||||
|
{
|
||||||
|
std::string out = in;
|
||||||
|
return trimLeft (trimRight (out, t), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UNICODE safe
|
||||||
|
std::wstring trim (const std::wstring& in, const std::wstring& t /*= L" "*/)
|
||||||
|
{
|
||||||
|
std::wstring out = in;
|
||||||
|
return trimLeft (trimRight (out, t), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Remove enclosing balanced quotes. Assumes trimmed text.
|
||||||
|
void unquoteText (std::string& text)
|
||||||
|
{
|
||||||
|
char quote = text[0];
|
||||||
|
if (quote == '\'' || quote == '"')
|
||||||
|
if (text[text.length () - 1] == quote)
|
||||||
|
text = text.substr (1, text.length () - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void extractLine (std::string& text, std::string& line, int length)
|
||||||
|
{
|
||||||
|
unsigned int eol = text.find ("\n");
|
||||||
|
|
||||||
|
// Special case: found \n in first length characters.
|
||||||
|
if (eol != std::string::npos && eol < (unsigned) length)
|
||||||
|
{
|
||||||
|
line = text.substr (0, eol); // strip \n
|
||||||
|
text = text.substr (eol + 1, std::string::npos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case: no \n, and less than length characters total.
|
||||||
|
// special case: text.find ("\n") == std::string::npos && text.length () < length
|
||||||
|
if (eol == std::string::npos && text.length () <= (unsigned) length)
|
||||||
|
{
|
||||||
|
line = text;
|
||||||
|
text = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Safe to ASSERT text.length () > length
|
||||||
|
|
||||||
|
// Look for the last space prior to length
|
||||||
|
eol = length;
|
||||||
|
while (eol && text[eol] != ' ' && text[eol] != '\n')
|
||||||
|
--eol;
|
||||||
|
|
||||||
|
// If a space was found, break there.
|
||||||
|
if (eol)
|
||||||
|
{
|
||||||
|
line = text.substr (0, eol);
|
||||||
|
text = text.substr (eol + 1, std::string::npos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no space was found, hyphenate.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line = text.substr (0, length - 1) + "-";
|
||||||
|
text = text.substr (length - 1, std::string::npos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string commify (const std::string& data)
|
||||||
|
{
|
||||||
|
// First scan for decimal point and end of digits.
|
||||||
|
int decimalPoint = -1;
|
||||||
|
int end = -1;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (int i = 0; i < (int) data.length (); ++i)
|
||||||
|
{
|
||||||
|
if (::isdigit (data[i]))
|
||||||
|
end = i;
|
||||||
|
|
||||||
|
if (data[i] == '.')
|
||||||
|
decimalPoint = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
if (decimalPoint != -1)
|
||||||
|
{
|
||||||
|
// In reverse order, transfer all digits up to, and including the decimal
|
||||||
|
// point.
|
||||||
|
for (i = (int) data.length () - 1; i >= decimalPoint; --i)
|
||||||
|
result += data[i];
|
||||||
|
|
||||||
|
int consecutiveDigits = 0;
|
||||||
|
for (; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (::isdigit (data[i]))
|
||||||
|
{
|
||||||
|
result += data[i];
|
||||||
|
|
||||||
|
if (++consecutiveDigits == 3 && i && ::isdigit (data[i - 1]))
|
||||||
|
{
|
||||||
|
result += ',';
|
||||||
|
consecutiveDigits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result += data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// In reverse order, transfer all digits up to, but not including the last
|
||||||
|
// digit.
|
||||||
|
for (i = (int) data.length () - 1; i > end; --i)
|
||||||
|
result += data[i];
|
||||||
|
|
||||||
|
int consecutiveDigits = 0;
|
||||||
|
for (; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (::isdigit (data[i]))
|
||||||
|
{
|
||||||
|
result += data[i];
|
||||||
|
|
||||||
|
if (++consecutiveDigits == 3 && i && ::isdigit (data[i - 1]))
|
||||||
|
{
|
||||||
|
result += ',';
|
||||||
|
consecutiveDigits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result += data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reverse result into data.
|
||||||
|
std::string done;
|
||||||
|
for (int i = (int) result.length () - 1; i >= 0; --i)
|
||||||
|
done += result[i];
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string lowerCase (const std::string& input)
|
||||||
|
{
|
||||||
|
std::string output = input;
|
||||||
|
for (int i = 0; i < (int) input.length (); ++i)
|
||||||
|
if (::isupper (input[i]))
|
||||||
|
output[i] = ::tolower (input[i]);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
212
src/util.cpp
Normal file
212
src/util.cpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2006 - 2008, Paul Beckingham. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "Table.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "../auto.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool confirm (const std::string& question)
|
||||||
|
{
|
||||||
|
std::cout << question << " (y/n) ";
|
||||||
|
std::string answer;
|
||||||
|
std::cin >> answer;
|
||||||
|
|
||||||
|
answer = trim (answer);
|
||||||
|
if (answer == "y" || answer == "Y")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void delay (float f)
|
||||||
|
{
|
||||||
|
struct timeval t;
|
||||||
|
t.tv_sec = (int) f;
|
||||||
|
t.tv_usec = int ((f - (int)f) * 1000000);
|
||||||
|
|
||||||
|
select (0, NULL, NULL, NULL, &t);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convert a quantity in seconds to a more readable format.
|
||||||
|
// Long version:
|
||||||
|
// 0-59 S seconds
|
||||||
|
// 60-3599 M minutes, S seconds
|
||||||
|
// 3600-86399 H hours, M minutes, S seconds
|
||||||
|
// 86400- D days, H hours, M minutes, S seconds
|
||||||
|
// Short version:
|
||||||
|
// 0-59 S seconds
|
||||||
|
// 60-3599 M minutes, S seconds
|
||||||
|
// 3600-86399 H hours, M minutes, S seconds
|
||||||
|
//
|
||||||
|
void formatTimeDeltaDays (std::string& output, time_t delta)
|
||||||
|
{
|
||||||
|
char formatted[24];
|
||||||
|
float days = (float) delta / 86400.0;
|
||||||
|
|
||||||
|
if (days > 365)
|
||||||
|
sprintf (formatted, "%.1f yrs", (days / 365.2422));
|
||||||
|
else if (days > 84)
|
||||||
|
sprintf (formatted, "%1d mths", (int) (days / 30.6));
|
||||||
|
else if (days > 13)
|
||||||
|
sprintf (formatted, "%d wks", (int) (days / 7.0));
|
||||||
|
else if (days > 5.0)
|
||||||
|
sprintf (formatted, "%d days", (int) days);
|
||||||
|
else if (days > 1.0)
|
||||||
|
sprintf (formatted, "%.1f days", days);
|
||||||
|
else if (days * 24 > 1.0)
|
||||||
|
sprintf (formatted, "%d hrs", (int) (days * 24.0));
|
||||||
|
else if (days * 24 * 60 > 1)
|
||||||
|
sprintf (formatted, "%d mins", (int) (days * 24 * 60));
|
||||||
|
else if (days * 24 * 60 * 60 > 1)
|
||||||
|
sprintf (formatted, "%d secs", (int) (days * 24 * 60 * 60));
|
||||||
|
else
|
||||||
|
strcpy (formatted, "-");
|
||||||
|
|
||||||
|
output = formatted;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
std::string formatSeconds (time_t delta)
|
||||||
|
{
|
||||||
|
char formatted[24];
|
||||||
|
float days = (float) delta / 86400.0;
|
||||||
|
|
||||||
|
if (days > 365)
|
||||||
|
sprintf (formatted, "%.1f yrs", (days / 365.2422));
|
||||||
|
else if (days > 84)
|
||||||
|
sprintf (formatted, "%1d mths", (int) (days / 30.6));
|
||||||
|
else if (days > 13)
|
||||||
|
sprintf (formatted, "%d wks", (int) (days / 7.0));
|
||||||
|
else if (days > 5.0)
|
||||||
|
sprintf (formatted, "%d days", (int) days);
|
||||||
|
else if (days > 1.0)
|
||||||
|
sprintf (formatted, "%.1f days", days);
|
||||||
|
else if (days * 24 > 1.0)
|
||||||
|
sprintf (formatted, "%d hrs", (int) (days * 24.0));
|
||||||
|
else if (days * 24 * 60 > 1)
|
||||||
|
sprintf (formatted, "%d mins", (int) (days * 24 * 60));
|
||||||
|
else if (days * 24 * 60 * 60 > 1)
|
||||||
|
sprintf (formatted, "%d secs", (int) (days * 24 * 60 * 60));
|
||||||
|
else
|
||||||
|
strcpy (formatted, "-");
|
||||||
|
|
||||||
|
return std::string (formatted);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int autoComplete (
|
||||||
|
const std::string& partial,
|
||||||
|
const std::vector<std::string>& list,
|
||||||
|
std::vector<std::string>& matches)
|
||||||
|
{
|
||||||
|
matches.erase (matches.begin (), matches.end ());
|
||||||
|
|
||||||
|
// Handle trivial case.
|
||||||
|
unsigned int length = partial.length ();
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < list.size (); ++i)
|
||||||
|
{
|
||||||
|
// Special case where there is an exact match.
|
||||||
|
if (partial == list[i])
|
||||||
|
{
|
||||||
|
matches.erase (matches.begin (), matches.end ());
|
||||||
|
matches.push_back (list[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain a list of partial matches.
|
||||||
|
if (length <= list[i].length () &&
|
||||||
|
! strncmp (partial.c_str (), list[i].c_str (), length))
|
||||||
|
matches.push_back (list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef HAVE_UUID
|
||||||
|
|
||||||
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
|
const std::string uuid ()
|
||||||
|
{
|
||||||
|
uuid_t id;
|
||||||
|
uuid_generate (id);
|
||||||
|
char buffer[100];
|
||||||
|
uuid_unparse_lower (id, buffer);
|
||||||
|
|
||||||
|
return std::string (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#else
|
||||||
|
#warning "Using custom UUID generator"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
static char randomHexDigit ()
|
||||||
|
{
|
||||||
|
static char digits[] = "0123456789abcdef";
|
||||||
|
return digits[random () % 16];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
const std::string uuid ()
|
||||||
|
{
|
||||||
|
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
char id [37];
|
||||||
|
id[0] = randomHexDigit ();
|
||||||
|
id[1] = randomHexDigit ();
|
||||||
|
id[2] = randomHexDigit ();
|
||||||
|
id[3] = randomHexDigit ();
|
||||||
|
id[4] = randomHexDigit ();
|
||||||
|
id[5] = randomHexDigit ();
|
||||||
|
id[6] = randomHexDigit ();
|
||||||
|
id[7] = randomHexDigit ();
|
||||||
|
id[8] = '-';
|
||||||
|
id[9] = randomHexDigit ();
|
||||||
|
id[10] = randomHexDigit ();
|
||||||
|
id[11] = randomHexDigit ();
|
||||||
|
id[12] = randomHexDigit ();
|
||||||
|
id[13] = '-';
|
||||||
|
id[14] = randomHexDigit ();
|
||||||
|
id[15] = randomHexDigit ();
|
||||||
|
id[16] = randomHexDigit ();
|
||||||
|
id[17] = randomHexDigit ();
|
||||||
|
id[18] = '-';
|
||||||
|
id[19] = randomHexDigit ();
|
||||||
|
id[20] = randomHexDigit ();
|
||||||
|
id[21] = randomHexDigit ();
|
||||||
|
id[22] = randomHexDigit ();
|
||||||
|
id[23] = '-';
|
||||||
|
id[24] = randomHexDigit ();
|
||||||
|
id[25] = randomHexDigit ();
|
||||||
|
id[26] = randomHexDigit ();
|
||||||
|
id[27] = randomHexDigit ();
|
||||||
|
id[28] = randomHexDigit ();
|
||||||
|
id[29] = randomHexDigit ();
|
||||||
|
id[30] = randomHexDigit ();
|
||||||
|
id[31] = randomHexDigit ();
|
||||||
|
id[32] = randomHexDigit ();
|
||||||
|
id[33] = randomHexDigit ();
|
||||||
|
id[34] = randomHexDigit ();
|
||||||
|
id[35] = randomHexDigit ();
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
Reference in New Issue
Block a user