예제 #1
0
void main()
{
	srand(time(NULL));
	//파일경로를 파라미터로 클래스 생성 
	Nibbler testfile = Nibbler(DEMOFILE);


	//파일을 손상시키는 함수
	//1. nibbleRandom
	//	전체 구간에서 랜덤으로 파일을 손상시킴
	//	파라미터1 : 손상시킬 퍼센테이지 (소수점 4자리까지 입력가능)

	//2. nibbleGeader
	//	헤더 구간에서 지정된 확률만큼 파일을 손상시킴
	//	파라미터1 : 헤더크기(바이트)
	//	파라미터2 : 손상시킬 퍼센테이지 (소수점 4자리까지 입력가능)
	
	//3. nibbleBody
	//	헤더를 제외한 구간에서 지정된 확률만큼 파일을 손상시킴
	//	파라미터1 : 헤더크기(바이트)
	//	파라미터2 : 손상시킬 퍼센테이지 (소수점 4자리까지 입력가능)

	testfile.nibbleRandom	(0.0001);
	//헤더는 7%이상 손상 시키면 재생이 불가능해진다.
	testfile.nibbleHeader	(8	,2);
	testfile.nibbleBody		(8	,0.01);


}
예제 #2
0
파일: main.cpp 프로젝트: luxsypher/nibbler
int			main(int ac, char **av)
{
  void			*handle;
  IGui			*(*ext_ctor)();
  Nibbler		nibbler;

  try
    {
      if (ac != 4)
	throw myException((GamePart)42, "Usage: ./nibbler width height libXXX.so");
      handle = dlopen(av[3], RTLD_LAZY);
      if (!handle)
	throw Nibbler::nibblerException(NIBBLER, dlerror(), DLERROR);
      ext_ctor = reinterpret_cast<IGui* (*)()>(dlsym(handle, "create"));
      if (!ext_ctor)
	throw Nibbler::nibblerException(NIBBLER, dlerror(), DLERROR);
      if (!nibbler.checkArg(av[1]) || !nibbler.checkArg(av[2]))
	throw Nibbler::nibblerException(NIBBLER, "Bad map values", BADARG);
      nibbler.setGui(ext_ctor);
      nibbler.execNibbler(nibbler.getnbr(av[1]), nibbler.getnbr(av[2]));
      nibbler.deleteGui();
      nibbler.getCore()->printEndgame();
      if (dlclose(handle) != 0)
	throw Nibbler::nibblerException(NIBBLER, dlerror(), DLERROR);
    }
  catch (myException const &ex)
    {
      nibbler.deleteGui();
      std::cerr << ex.where() << " : " << ex.what() << std::endl;
      return (1);
    }
  return (0);
}
예제 #3
0
파일: Duration.cpp 프로젝트: SEJeff/task
bool Duration::valid (const std::string& input)
{
  std::string lower_input = lowerCase (input);

  // Assume the ordinal is 1, but look for an integer, just in case.
  double value = 1;
  Nibbler n (lower_input);
  n.getNumber (value);

  if (value < 0.0)
    value = -value;

  std::string units;
  n.getUntilEOS (units);

  // Non-trivial value with no units means the duration is specified in
  // seconds, and therefore a time_t.  Consider it valid.
  if (value != 0.0 &&
      units == "")
    return true;

  // Auto complete against all supported durations.
  std::vector <std::string> supported;
  for (unsigned int i = 0; i < NUM_DURATIONS; ++i)
    supported.push_back (durations[i]);

  std::vector <std::string> matches;
  if (autoComplete (units,
                    supported,
                    matches,
                    context.config.getInteger ("abbreviation.minimum")) == 1)
    return true;

  return false;
}
예제 #4
0
파일: Hooks.cpp 프로젝트: SEJeff/task
////////////////////////////////////////////////////////////////////////////////
// Enumerate all hooks, and tell API about the script files it must load in
// order to call them.  Note that API will perform a deferred read, which means
// that if it isn't called, a script will not be loaded.
void Hooks::initialize ()
{
#ifdef HAVE_LIBLUA
  _api.initialize ();
#endif

  // Allow a master switch to turn the whole thing off.
  bool big_red_switch = context.config.getBoolean ("extensions");
  if (big_red_switch)
  {
    std::vector <std::string> vars;
    context.config.all (vars);

    std::vector <std::string>::iterator it;
    for (it = vars.begin (); it != vars.end (); ++it)
    {
      std::string type;
      std::string name;
      std::string value;

      // "<type>.<name>"
      Nibbler n (*it);
      if (n.getUntil ('.', type) &&
          type == "hook"         &&
          n.skip ('.')           &&
          n.getUntilEOS (name))
      {
        std::string value = context.config.get (*it);
        Nibbler n (value);

        // <path>:<function> [, ...]
        while (!n.depleted ())
        {
          std::string file;
          std::string function;
          if (n.getUntil (':', file) &&
              n.skip (':')           &&
              n.getUntil (',', function))
          {
            context.debug (std::string ("Event '") + name + "' hooked by " + file + ", function " + function);
            Hook h (name, Path::expand (file), function);
            _all.push_back (h);

            (void) n.skip (',');
          }
          else
            throw std::string (format (STRING_LUA_BAD_HOOK_DEF, *it));
        }
      }
    }
  }
  else
    context.debug ("Hooks::initialize --> off");
}
예제 #5
0
Gui::Gui(Nibbler &nibbler) : AGui(nibbler)
{
  screen = NULL;
  if (SDL_Init(SDL_INIT_VIDEO) == -1)
    throw (NibError("SDL_init", "fail"));
  atexit(SDL_Quit);
  TTF_Init();
  screen = SDL_SetVideoMode(nibbler.getWidth() * 25, nibbler.getHeight() * 25, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
  SDL_WM_SetCaption("NIBBLER", NULL);
  if (screen == NULL)
    throw (NibError("Video_mode", "fail"));   
}
예제 #6
0
Gui::Gui(Nibbler &nibbler) : AGui(nibbler)
{
  size_t	height = nibbler.getHeight();
  size_t	width = nibbler.getWidth();

  height_base = static_cast<double>(2) / static_cast<double>(height);
  weight_base = static_cast<double>(2) / static_cast<double>(width);
  if (SDL_Init(SDL_INIT_VIDEO) == -1)
    throw (NibError("opengl_SDL_init", "fail"));
  if (atexit(SDL_Quit) != 0)
    throw (NibError("opengl_atexit", "fail"));
  TTF_Init();
  if (SDL_SetVideoMode(width * 25,  height * 25, 16, SDL_OPENGL | SDL_HWSURFACE | SDL_DOUBLEBUF) == NULL)
    throw (NibError("opengl_SDL_SetVideoMode", "fail"));
  SDL_WM_SetCaption("nibbler OpenGL", NULL);
}
예제 #7
0
파일: Hooks.cpp 프로젝트: georgebrock/task
////////////////////////////////////////////////////////////////////////////////
// Enumerate all hooks, and tell API about the script files it must load in
// order to call them.  Note that API will perform a deferred read, which means
// that if it isn't called, a script will not be loaded.
void Hooks::initialize ()
{
  // Allow a master switch to turn the whole thing off.
  bool big_red_switch = context.config.getBoolean ("extensions");
  if (big_red_switch)
  {
    Config::const_iterator it;
    for (it = context.config.begin (); it != context.config.end (); ++it)
    {
      std::string type;
      std::string name;
      std::string value;

      // "<type>.<name>"
      Nibbler n (it->first);
      if (n.getUntil ('.', type) &&
          type == "hook"         &&
          n.skip ('.')           &&
          n.getUntilEOS (name))
      {
        Nibbler n (it->second);

        // <path>:<function> [, ...]
        while (!n.depleted ())
        {
          std::string file;
          std::string function;
          if (n.getUntil (':', file) &&
              n.skip (':')           &&
              n.getUntil (',', function))
          {
            context.debug (std::string ("Event '") + name + "' hooked by " + file + ", function " + function);
            Hook h (name, Path::expand (file), function);
            _all.push_back (h);

            (void) n.skip (',');
          }
          else
            ; // Was: throw std::string (format ("Malformed hook definition '{1}'.", it->first));
        }
      }
    }
  }
  else
    context.debug ("Hooks::initialize --> off");
}
예제 #8
0
파일: Date.cpp 프로젝트: SEJeff/task
Date::Date (const std::string& input, const std::string& format /* = "m/d/Y" */)
{
  // Before parsing according to "format", perhaps this is a relative date?
  if (isRelativeDate (input))
    return;

  // Parse an ISO date.
  Nibbler n (input);
  if (n.getDateISO (_t) && n.depleted ())
    return;

  // Parse a formatted date.
  if (n.getDate (format, _t) && n.depleted ())
    return;

  // Perhaps it is an epoch date, in string form?
  if (isEpoch (input))
    return;

  throw ::format (STRING_DATE_INVALID_FORMAT, input, format);
}
예제 #9
0
int		main(int ac, char **av)
{
  Nibbler	*nibbler;
  void		*handle;
  std::pair<int, int>	map;

  if (ac != 4)
    {
      std::cerr << "Usage : ./nibler width[10..55] height[10..55] ./LIB.so" << std::endl;
      return (-1);
    }
  if ((handle = Glibc::Libdl::_dlopen(av[3], RTLD_LAZY)) == NULL)
    {
      std::cerr << Glibc::Libdl::_dlerror() << std::endl;
      return (-1);
    }
  if (!check_size(Glibc::Atoi::_atoi(av[1]), Glibc::Atoi::_atoi(av[2])))
    {
      std::cerr << "Entrer a size between 10x10 and 55x55" << std::endl;
      return (-1);
    }
  try
    {
      map.first = Glibc::Atoi::_atoi(av[1]);
      map.second = Glibc::Atoi::_atoi(av[2]);
      nibbler = new Nibbler(handle, map);
      nibbler->runGame();
      std::cout << "Game Over" << std::endl;
      delete nibbler;
    }
  catch (std::exception& e)
    {
      std::cerr << e.what() << std::endl;
      return (-1);
    }
  return (0);
}
예제 #10
0
파일: Subst.cpp 프로젝트: lmacken/task
////////////////////////////////////////////////////////////////////////////////
// A Path and a Subst may look similar, and so the rule is that if a Subst looks
// like a path, it must also not exist in the file system in order to actually
// be a Subst.
bool Subst::valid (const std::string& input) const
{
  std::string ignored;
  Nibbler n (input);
  if (n.skip     ('/')            &&
      n.getUntil ('/', ignored)   &&
      n.skip     ('/')            &&
      n.getUntil ('/', ignored)   &&
      n.skip     ('/'))
  {
    n.skip ('g');
    if (n.depleted ())
      return ! Directory (input).exists ();
  }

  return false;
}
예제 #11
0
파일: Subst.cpp 프로젝트: lmacken/task
void Subst::parse (const std::string& input)
{
  Nibbler n (input);
  if (n.skip     ('/')        &&
      n.getUntil ('/', mFrom) &&
      n.skip     ('/')        &&
      n.getUntil ('/', mTo)   &&
      n.skip     ('/'))
  {
      mGlobal = n.skip ('g');

    if (mFrom == "")
      throw context.stringtable.get (SUBST_EMPTY,
                                     "Cannot substitute an empty string.");

    if (!n.depleted ())
      throw context.stringtable.get (SUBST_BAD_CHARS,
                                     "Unrecognized character(s) at end of substitution.");
  }
  else
    throw context.stringtable.get (SUBST_MALFORMED,
                                   "Malformed substitution.");
}
예제 #12
0
파일: nibbler.t.cpp 프로젝트: JensErat/task
int main (int argc, char** argv)
{
#ifdef NIBBLER_FEATURE_DATE
#ifdef NIBBLER_FEATURE_REGEX
  UnitTest t (410);
#else
  UnitTest t (380);
#endif
#else
#ifdef NIBBLER_FEATURE_REGEX
  UnitTest t (346);
#else
  UnitTest t (322);
#endif
#endif

  // Ensure environment has no influence.
  unsetenv ("TASKDATA");
  unsetenv ("TASKRC");

  try
  {
    Nibbler n;
    std::string s;
    int i;
    double d;
    time_t ti;

#ifdef NIBBLER_FEATURE_DATE
    Date dt;
#endif
    std::vector <std::string> options;

    // Make sure the nibbler behaves itself with trivial input.
    t.diag ("Test all nibbler calls given empty input");
    n = Nibbler ("");
    t.notok (n.getUntil (' ', s),        "trivial: getUntil");
    t.notok (n.getUntil ("hi", s),       "trivial: getUntil");
    t.notok (n.getUntilOneOf ("ab", s),  "trivial: getUntilOneOf");
    t.notok (n.skipN (123),              "trivial: skipN");
    t.notok (n.skip ('x'),               "trivial: skip");
    t.notok (n.skipAll ('x'),            "trivial: skipAll");
    t.notok (n.skipAllOneOf ("abc"),     "trivial: skipAllOneOf");
    t.notok (n.backN (1),                "trivial: backN");
    t.notok (n.getQuoted ('"', s),       "trivial: getQuoted");
    t.notok (n.getDigit (i),             "trivial: getDigit");
    t.notok (n.getInt (i),               "trivial: getInt"); // 10
    t.notok (n.getUnsignedInt (i),       "trivial: getUnsignedInt");
    t.notok (n.getUntilEOL (s),          "trivial: getUntilEOL");
    t.notok (n.getUntilEOS (s),          "trivial: getUntilEOS");
    t.notok (n.getDateISO (ti),          "trivial: getDateISO");
#ifdef NIBBLER_FEATURE_DATE
    t.notok (n.getDate ("YYYYMMDD", ti), "trivial: getDate");
#endif
    t.notok (n.getOneOf (options, s),    "trivial: getOneOf");
    t.ok    (n.depleted (),              "trivial: depleted");

    // bool getUntil (char, std::string&);
    t.diag ("Nibbler::getUntil");
    n = Nibbler ("one two");
    t.ok    (n.getUntil (' ', s),        " 'one two' :       getUntil (' ')    -> true");
    t.is    (s, "one",                   " 'one two' :       getUntil (' ')    -> 'one'"); // 20
    t.ok    (n.getUntil (' ', s),        "    ' two' :       getUntil (' ')    -> true");
    t.is    (s, "",                      "    ' two' :       getUntil (' ')    -> ''");
    t.ok    (n.skip (' '),               "    ' two' :           skip (' ')    -> true");
    t.ok    (n.getUntil (' ', s),        "     'two' :       getUntil (' ')    -> 'two'");
    t.notok (n.getUntil (' ', s),        "        '' :       getUntil (' ')    -> false");
    t.ok    (n.depleted (),              "        '' :       depleted ()       -> true");

#ifdef NIBBLER_FEATURE_REGEX
    // bool getUntilRx (const std::string&, std::string&);
    t.diag ("Nibbler::getUntilRx");
    n = Nibbler ("one two");
    t.ok    (n.getUntilRx ("th", s),     " 'one two' :     getUntilRx ('th')   -> true");
    t.is    (s, "one two",               " 'one two' :     getUntilRx ('th')   -> 'one two'");

    n = Nibbler ("one two");
    t.ok    (n.getUntilRx ("e", s),      " 'one two' :     getUntilRx ('e')    -> true");
    t.is    (s, "on",                    " 'one two' :     getUntilRx ('e')    -> 'on'"); // 30
    t.ok    (n.getUntilRx ("tw", s),     "   'e two' :     getUntilRx ('tw')   -> true");
    t.is    (s, "e ",                    "   'e two' :     getUntilRx ('tw')   -> 'e '");
    t.ok    (n.getUntilRx ("$", s),      "     'two' :     getUntilRx ('$')    -> true");
    t.is    (s, "two",                   "     'two' :     getUntilRx ('$')    -> 'two'");
    t.ok    (n.depleted (),              "        '' :       depleted ()       -> true");
#endif

    // bool getUntilOneOf (const std::string&, std::string&);
    t.diag ("Nibbler::getUntilOneOf");
    n = Nibbler ("ab.cd");
    t.ok    (n.getUntilOneOf (".:", s),  "   'ab.cd' :  getUntilOneOf ('.:')   -> true");
    t.is    (s, "ab",                    "   'ab.cd' :  getUntilOneOf ('.:')   -> 'ab'");
    t.ok    (n.skipN (),                 "     '.cd' :          skipN ()       -> true");
    t.ok    (n.getUntilOneOf (".:", s),  "      'cd' :  getUntilOneOf ('.:')   -> true");
    t.notok (n.getUntilOneOf (".:", s),  "        '' :  getUntilOneOf ('.:')   -> false");
    t.ok    (n.depleted (),              "        '' :       depleted ()       -> true");

    // bool getUntil (const std::string&, std::string&);
    t.diag ("Nibbler::getUntil");
    n = Nibbler ("ab\r\ncd");
    t.ok (n.getUntil ("\r\n", s),     "'ab\\r\\ncd' :       getUntil ('\\r\\n') -> true");
    t.ok (n.skipN (2),                "  '\\r\\ncd' :          skipN (2)      -> true");
    t.ok (n.getUntil ("\r\n", s),     "      'cd' :       getUntil ('\\r\\n') -> true");
    t.ok (n.depleted (),              "        '' :       depleted ()       -> true");

    // bool getUntilWS (std::string&);
    t.diag ("Nibbler::getUntilWS");
    n = Nibbler ("ab \t\ncd");
    t.ok    (n.getUntilWS (s),        " 'ab \\t\\ncd' :     getUntilWS ()     -> true");
    t.is    (s, "ab",                 " 'ab \\t\\ncd' :     getUntilWS ()     -> 'ab'");
    t.ok    (n.getUntilWS (s),        "   ' \\t\\ncd' :     getUntilWS ()     -> true");
    t.is    (s, "",                   "   ' \\t\\ncd' :     getUntilWS ()     -> ''");
    t.ok    (n.skipWS (),             "        'cd' :         skipWS ()     -> true");
    t.ok    (n.getUntilWS (s),        "          '' :     getUntilWS ()     -> true");
    t.is    (s, "cd",                 "        'cd' :     getUntilWS ()     -> 'cd'");
    t.ok    (n.depleted (),           "          '' :       depleted ()     -> true");

    // bool skipN (const int quantity = 1);
    t.diag ("Nibbler::skipN");
    n = Nibbler ("abcde");
    t.ok    (n.skipN (),              "   'abcde' :          skipN ()       -> true");
    t.ok    (n.skipN (2),             "    'bcde' :          skipN (2       -> true");
    t.notok (n.skipN (3),             "      'de' :          skipN (3       -> false");
    t.notok (n.depleted (),           "      'de' :       depleted ()       -> true");

    // bool skip (char);
    t.diag ("Nibbler::skip");
    n = Nibbler ("  a");
    t.ok    (n.skip (' '),            "     '  a' :           skip (' ')    -> true");
    t.ok    (n.skip (' '),            "      ' a' :           skip (' ')    -> true");
    t.notok (n.skip (' '),            "       'a' :           skip (' ')    -> false");
    t.notok (n.depleted (),           "       'a' :       depleted ()       -> false");
    t.ok    (n.skip ('a'),            "       'a' :           skip ('a')    -> true");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool skipAll (char);
    t.diag ("Nibbler::skipAll");
    n = Nibbler ("aaaabb");
    t.ok    (n.skipAll ('a'),         "  'aaaabb' :        skipAll ('a')    -> true");
    t.notok (n.skipAll ('a'),         "      'bb' :        skipAll ('a')    -> false");
    t.ok    (n.skipAll ('b'),         "      'bb' :        skipAll ('b')    -> true");
    t.notok (n.skipAll ('b'),         "        '' :        skipAll ('b')    -> false");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool skipAllOneOf (const std::string&);
    t.diag ("Nibbler::skipAllOneOf");
    n = Nibbler ("abababcc");
    t.ok    (n.skipAllOneOf ("ab"),   "'abababcc' :   skipAllOneOf ('ab')   -> true");
    t.notok (n.skipAllOneOf ("ab"),   "      'cc' :   skipAllOneOf ('ab')   -> false");
    t.ok    (n.skipAllOneOf ("c"),    "      'cc' :   skipAllOneOf ('ab')   -> false");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool skipWS ();
    t.diag ("Nibbler::skipWS");
    n = Nibbler (" \tfoo");
    t.ok    (n.skipWS (),             "  ' \\tfoo' :         skipWS ()       -> true");
    t.notok (n.skipWS (),             "     'foo' :         skipWS ()       -> false");
    t.ok    (n.getUntilEOS (s),       "     'foo' :    getUntilEOS ()       -> true");
    t.is    (s, "foo",                "     'foo' :    getUntilEOS ()       -> 'foo'");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

#ifdef NIBBLER_FEATURE_REGEX
    // bool skipRx (const std::string&);
    t.diag ("Nibbler::skipRx");
    n = Nibbler ("one two");
    t.ok    (n.skipRx ("o."),         " 'one two' :         skipRx ('o.')   -> true");
    t.notok (n.skipRx ("A+"),         "   'e two' :         skipRx ('A+')   -> false");
    t.ok    (n.skipRx ("e+"),         "   'e two' :         skipRx ('e+')   -> true");
    t.ok    (n.skipRx ("...."),       "    ' two' :         skipRx ('....') -> true");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");
#endif

    // bool backN (const int quantity = 1);
    t.diag ("Nibbler::backN");
    n = Nibbler ("/a/b/");
    t.ok (n.getQuoted ('/', s),       "   '/a/b/' :         getQuoted ('/') -> true");
    t.is (s, "a",                     "      'b/' :         getQuoted ('/') -> 'a'");
    t.ok (n.backN (),                 "      'b/' :         backN ()        -> true");
    t.ok (n.getQuoted ('/', s),       "     '/b/' :         getQuoted ('/') -> true");
    t.is (s, "b",                     "     '/b/' :         getQuoted ('/') -> 'b'");

    // bool getQuoted (char, std::string&);
    t.diag ("Nibbler::getQuoted");
    n = Nibbler ("''");
    t.ok    (n.getQuoted ('\'', s),   "      '''' :      getQuoted (''')    -> true");
    t.is    (s, "",                   "      '''' :      getQuoted (''')    -> ''");

    n = Nibbler ("'\"'");
    t.ok    (n.getQuoted ('\'', s),   "      ''\"'' :     getQuoted (''')    -> true");
    t.is    (s, "\"",                  "     ''\"'' :      getQuoted (''')    -> '\"'");

    n = Nibbler ("'x'");
    t.ok    (n.getQuoted ('\'', s),   "      ''x'' :     getQuoted (''')    -> true");
    t.is    (s, "x",                  "      ''x'' :     getQuoted (''')    -> ''");

    n = Nibbler ("'x");
    t.notok (n.getQuoted ('\'', s),   "      ''x' :      getQuoted (''')    -> false");

    n = Nibbler ("x");
    t.notok (n.getQuoted ('\'', s),   "       'x' :      getQuoted (''')    -> false"); // 90

    n = Nibbler ("\"one\\\"two\"");
    t.notok (n.getQuoted ('\'', s),   "\"one\\\"two\" :      getQuoted (''')    -> false");

    n = Nibbler ("\"one\\\"two\"");
    t.ok (n.getQuoted ('"', s, false), "\"one\\\"two\" :      getQuoted ('\"', false, false) -> true");
    t.is (s, "one\\\"two", "getQuoted ('\"', false) -> one\\\"two");

    n = Nibbler ("\"one\\\"two\"");
    t.ok (n.getQuoted ('"', s, true),  "\"one\\\"two\" :      getQuoted ('\"', false, true)  -> true");
    t.is (s, "\"one\\\"two\"", "getQuoted ('\"', true) -> \"one\\\"two\"");

    n = Nibbler ("\"one\\\"two\"");
    t.ok (n.getQuoted ('"', s, false), "\"one\\\"two\" :      getQuoted ('\"', true,  false) -> true");
    t.is (s, "one\\\"two", "getQuoted ('\"', false) -> one\\\"two");

    n = Nibbler ("\"one\\\"two\"");
    t.ok (n.getQuoted ('"', s, true),  "\"one\\\"two\" :      getQuoted ('\"', s,  true)  -> true");
    t.is (s, "\"one\\\"two\"", "getQuoted ('\"', s, true) -> \"one\\\"two\"");

    n = Nibbler ("\"one\\\\\"");
    t.ok (n.getQuoted ('\"', s, true), "\"one\\\" :           getQuoted ('\"', s, true)      -> true");
    t.is (s, "\"one\\\\\"",                                   "getQuoted ('\"', s, true)      -> \"one\\\\\"");

    n = Nibbler ("\"one\\\\\"");
    t.ok (n.getQuoted ('\"', s, false), "one\\ :              getQuoted ('\"', s, false)      -> true");
    t.is (s, "one\\\\",                                       "getQuoted ('\"', s, false)      -> \"one\\\\\"");

    // bool getDigit (int&);
    t.diag ("Nibbler::getDigit");
    n = Nibbler ("12x");
    t.ok    (n.getDigit (i),          "     '12x' :         getDigit ()     -> true");
    t.is    (i, 1,                    "     '12x' :         getDigit ()     -> 1");
    t.ok    (n.getDigit (i),          "      '2x' :         getDigit ()     -> true");
    t.is    (i, 2,                    "      '2x' :         getDigit ()     -> 2");
    t.notok (n.getDigit (i),          "       'x' :         getDigit ()     -> false");

    // bool getDigit6 (int&);
    t.diag ("Nibbler::getDigit6");
    n = Nibbler ("654321");
    t.ok    (n.getDigit6 (i),         "    654321 :         getDigit6 ()    -> true");
    t.is    (i, 654321,               "    654321 :         getDigit6 ()    -> 654321");

    // bool getDigit4 (int&);
    t.diag ("Nibbler::getDigit4");
    n = Nibbler ("4321");
    t.ok    (n.getDigit4 (i),         "      4321 :         getDigit4 ()    -> true");
    t.is    (i, 4321,                 "      4321 :         getDigit4 ()    -> 4321");

    // bool getDigit2 (int&);
    t.diag ("Nibbler::getDigit2");
    n = Nibbler ("21");
    t.ok    (n.getDigit2 (i),         "        21 :         getDigit2 ()    -> true");
    t.is    (i, 21,                   "        21 :         getDigit2 ()    -> 21");

    // bool getInt (int&);
    t.diag ("Nibbler::getInt");
    n = Nibbler ("123 -4");
    t.ok    (n.getInt (i),            "  '123 -4' :         getInt ()       -> true");
    t.is    (i, 123,                  "  '123 -4' :         getInt ()       -> '123'");
    t.ok    (n.skip (' '),            "     ' -4' :           skip (' ')    -> true");
    t.ok    (n.getInt (i),            "      '-4' :         getInt ()       -> true");
    t.is    (i, -4,                   "      '-4' :         getInt ()       -> '-4'");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool getUnsignedInt (int&i);
    t.diag ("Nibbler::getUnsignedInt");
    n = Nibbler ("123 4");
    t.ok    (n.getUnsignedInt (i),    "   '123 4' : getUnsignedInt ()       -> true");
    t.is    (i, 123,                  "   '123 4' : getUnsignedInt ()       -> '123'");
    t.ok    (n.skip (' '),            "      ' 4' :           skip (' ')    -> true");
    t.ok    (n.getUnsignedInt (i),    "       '4' : getUnsignedInt ()       -> true");
    t.is    (i, 4,                    "       '4' : getUnsignedInt ()       -> '4'");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool getNumber (double&);
    t.diag ("Nibbler::getNumber");
    n = Nibbler ("-1.234 2.3e4");
    t.ok    (n.getNumber (d),         "'-1.234 2.3e4' : getNumber ()       -> true");
    t.is    (d, -1.234, 0.000001,     "'-1.234 2.3e4' : getNumber ()       -> '-1.234'");
    t.ok    (n.skip (' '),            "      ' 2.3e4' : skip (' ')         -> true");
    t.ok    (n.getNumber (d),         "       '2.3e4' : getNumber ()       -> true");
    t.is    (d, 2.3e4,                "       '2.3e4' : getNumber ()       -> '2.3e4'");
    t.ok    (n.depleted (),           "            '' : depleted ()        -> true");

    n = Nibbler ("2.0");
    t.ok    (n.getNumber (d),         "'2.0' : getNumber ()                -> true");
    t.is    (d, 2.0, 0.000001,        "'2.0' : getNumber ()                -> '2.0'");
    t.ok    (n.depleted (),           "            '' : depleted ()        -> true");

    n = Nibbler ("-864000.00000");
    t.ok    (n.getNumber (d),         "'-864000.00000' : getNumber ()      -> true");
    t.is    (d, -864000.0,            "'-864000.00000' : getNumber ()      -> -864000.0");
    t.ok    (n.depleted (),           "             '' : depleted ()       -> true");

    // bool getLiteral (const std::string&);
    t.diag ("Nibbler::getLiteral");
    n = Nibbler ("foobar");
    t.ok    (n.getLiteral ("foo"),    "  'foobar' :     getLiteral ('foo')  -> true");
    t.notok (n.getLiteral ("foo"),    "     'bar' :     getLiteral ('foo')  -> false");
    t.ok    (n.getLiteral ("bar"),    "     'bar' :     getLiteral ('bar')  -> true");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

#ifdef NIBBLER_FEATURE_REGEX
    // bool getRx (const std::string&, std::string&);
    t.diag ("Nibbler::getRx");
    n = Nibbler ("one two three");
    t.ok    (n.getRx ("^(o..)", s),   "'one two three' :   getRx ('^(o..)')  -> true");
    t.is    (s, "one",                "'one two three' :   getRx ('^(o..)')  -> 'one'");
    t.ok    (n.skip (' '),            "   ' two three' :         skip (' ')  -> true");
    t.ok    (n.getRx ("t..", s),      "    'two three' :   getRx ('t..')     -> true");
    t.is    (s, "two",                "    'two three' :   getRx ('t..')     -> 'two'");
    t.notok (n.getRx ("th...", s),    "       ' three' :   getRx ('th...')   -> false");
    t.ok    (n.skip (' '),            "       ' three' :         skip (' ')  -> true");
    t.ok    (n.getRx ("th...", s),    "        'three' :   getRx ('th...')   -> true");
    t.is    (s, "three",              "        'three' :   getRx ('th...')   -> 'three'");
    t.ok    (n.depleted (),           "             '' :       depleted ()   -> true");
#endif

    // bool getUUID (std::string&);
    t.diag ("Nibbler::getUUID");
    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5");
    t.ok (n.getUUID (s),                             "uuid 1 found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "uuid 1 -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("00000000-0000-0000-0000-000000000000,a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5");
    t.ok (n.getUUID (s),                             "uuid 1 found");
    t.is (s, "00000000-0000-0000-0000-000000000000", "uuid 1 -> correct");
    t.ok (n.skip (','),                              "comma -> skipped");
    t.ok (n.getUUID (s),                             "uuid 2 -> found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "uuid 2 -> correct");
    t.ok (n.depleted (),                             "depleted");

    // bool getPartialUUID (std::string&);
    t.diag ("Nibbler::getPartialUUID");
    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5");
    t.ok (n.getPartialUUID (s),                      "partial uuid [36] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d5", "partial uuid [36] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d");
    t.ok (n.getPartialUUID (s),                      "partial uuid [35] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4d",  "partial uuid [35] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4");
    t.ok (n.getPartialUUID (s),                      "partial uuid [34] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c4",   "partial uuid [34] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c");
    t.ok (n.getPartialUUID (s),                      "partial uuid [33] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3c",    "partial uuid [33] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3");
    t.ok (n.getPartialUUID (s),                      "partial uuid [32] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b3",     "partial uuid [32] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b");
    t.ok (n.getPartialUUID (s),                      "partial uuid [31] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2b",      "partial uuid [31] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2");
    t.ok (n.getPartialUUID (s),                      "partial uuid [30] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a2",       "partial uuid [30] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1a");
    t.ok (n.getPartialUUID (s),                      "partial uuid [29] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1a",        "partial uuid [29] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F1");
    t.ok (n.getPartialUUID (s),                      "partial uuid [28] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F1",         "partial uuid [28] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0F");
    t.ok (n.getPartialUUID (s),                      "partial uuid [27] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0F",          "partial uuid [27] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E0");
    t.ok (n.getPartialUUID (s),                      "partial uuid [26] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E0",           "partial uuid [26] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-E");
    t.ok (n.getPartialUUID (s),                      "partial uuid [25] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-E",            "partial uuid [25] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9-");
    t.ok (n.getPartialUUID (s),                      "partial uuid [24] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9-",             "partial uuid [24] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D9");
    t.ok (n.getPartialUUID (s),                      "partial uuid [23] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D9",              "partial uuid [23] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8D");
    t.ok (n.getPartialUUID (s),                      "partial uuid [22] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8D",               "partial uuid [22] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C8");
    t.ok (n.getPartialUUID (s),                      "partial uuid [21] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C8",                "partial uuid [21] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-C");
    t.ok (n.getPartialUUID (s),                      "partial uuid [20] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-C",                 "partial uuid [20] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7-");
    t.ok (n.getPartialUUID (s),                      "partial uuid [19] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7-",                  "partial uuid [19] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B7");
    t.ok (n.getPartialUUID (s),                      "partial uuid [18] found");
    t.is (s, "a0b1c2d3-e4f5-A6B7",                   "partial uuid [18] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6B");
    t.ok (n.getPartialUUID (s),                      "partial uuid [17] found");
    t.is (s, "a0b1c2d3-e4f5-A6B",                    "partial uuid [17] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A6");
    t.ok (n.getPartialUUID (s),                      "partial uuid [16] found");
    t.is (s, "a0b1c2d3-e4f5-A6",                     "partial uuid [16] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-A");
    t.ok (n.getPartialUUID (s),                      "partial uuid [15] found");
    t.is (s, "a0b1c2d3-e4f5-A",                      "partial uuid [15] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5-");
    t.ok (n.getPartialUUID (s),                      "partial uuid [14] found");
    t.is (s, "a0b1c2d3-e4f5-",                       "partial uuid [14] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f5");
    t.ok (n.getPartialUUID (s),                      "partial uuid [13] found");
    t.is (s, "a0b1c2d3-e4f5",                        "partial uuid [13] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4f");
    t.ok (n.getPartialUUID (s),                      "partial uuid [12] found");
    t.is (s, "a0b1c2d3-e4f",                         "partial uuid [12] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e4");
    t.ok (n.getPartialUUID (s),                      "partial uuid [11] found");
    t.is (s, "a0b1c2d3-e4",                          "partial uuid [11] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-e");
    t.ok (n.getPartialUUID (s),                      "partial uuid [10] found");
    t.is (s, "a0b1c2d3-e",                           "partial uuid [10] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3-");
    t.ok (n.getPartialUUID (s),                      "partial uuid [9] found");
    t.is (s, "a0b1c2d3-",                            "partial uuid [9] -> correct");
    t.ok (n.depleted (),                             "depleted");

    n = Nibbler ("a0b1c2d3");
    t.ok (n.getPartialUUID (s),                      "partial uuid [8] found");
    t.is (s, "a0b1c2d3",                             "partial uuid [8] -> correct");
    t.ok (n.depleted (),                             "not depleted");

    // bool getDateISO (time_t&);
    t.diag ("Nibbler::getDateISO");
    n = Nibbler ("19980119T070000Z");
    t.ok    (n.getDateISO (ti),       "'19980119T070000Z': getDateISO ()  -> true");
    t.is    (ti, 885193200,           "'19980119T070000Z': getDateISO ()  -> 885193200");
    t.ok    (n.depleted (),           "depleted");

    n = Nibbler ("20090213T233130Z");
    t.ok    (n.getDateISO (ti),       "'20090213T233130Z': getDateISO ()  -> true");
    t.is    (ti, 1234567890,          "'20090213T233130Z': getDateISO ()  -> 1234567890");
    t.ok    (n.depleted (),           "depleted");

#ifdef NIBBLER_FEATURE_DATE
    // bool getDate (time_t&, const std::string&);
    t.diag ("Nibbler::getDate");
    n = Nibbler ("1/1/2008");
    t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
    dt = Date (ti);
    t.is (dt.month (),   1, "ctor (std::string) -> m");
    t.is (dt.day (),     1, "ctor (std::string) -> d");
    t.is (dt.year (), 2008, "ctor (std::string) -> y");

    n = Nibbler ("20080101");
    t.ok (n.getDate ("YMD", ti), "YMD ok");
    dt = Date (ti);
    t.is (dt.month (),   1, "ctor (std::string) -> m");
    t.is (dt.day (),     1, "ctor (std::string) -> d");
    t.is (dt.year (), 2008, "ctor (std::string) -> y");

    n = Nibbler ("12/31/2007");
    t.ok (n.getDate ("m/d/Y", ti), "m/d/Y ok");
    dt = Date (ti);
    t.is (dt.month (),  12, "ctor (std::string) -> m");
    t.is (dt.day (),    31, "ctor (std::string) -> d");
    t.is (dt.year (), 2007, "ctor (std::string) -> y");

    n = Nibbler ("20071231");
    t.ok (n.getDate ("YMD", ti), "YMD ok");
    dt = Date (ti);
    t.is (dt.month (),  12, "ctor (std::string) -> m");
    t.is (dt.day (),    31, "ctor (std::string) -> d");
    t.is (dt.year (), 2007, "ctor (std::string) -> y");

    n = Nibbler ("Tue 01 Jan 2008 (01)");
    t.ok (n.getDate ("a D b Y (V)", ti), "a D b Y (V)");
    dt = Date (ti);
    t.is (dt.month (),   1, "ctor (std::string) -> m");
    t.is (dt.day (),     1, "ctor (std::string) -> d");
    t.is (dt.year (), 2008, "ctor (std::string) -> y");

    n = Nibbler ("Tuesday, January 1, 2008");
    t.ok (n.getDate ("A, B d, Y", ti), "A, B d, Y ok");
    dt = Date (ti);
    t.is (dt.month (),   1, "ctor (std::string) -> m");
    t.is (dt.day (),     1, "ctor (std::string) -> d");
    t.is (dt.year (), 2008, "ctor (std::string) -> y");

    n = Nibbler ("w01 Tue 2008-01-01");
    t.ok (n.getDate ("wV a Y-M-D", ti), "wV a Y-M-D ok");
    dt = Date (ti);
    t.is (dt.month (),   1, "ctor (std::string) -> m");
    t.is (dt.day (),     1, "ctor (std::string) -> d");
    t.is (dt.year (), 2008, "ctor (std::string) -> y");

    n = Nibbler ("6/7/2010 1:23:45");
    t.ok (n.getDate ("m/d/Y h:N:S", ti), "m/d/Y h:N:S ok");
    dt = Date (ti);
    t.is (dt.month (),     6, "ctor (std::string) -> m");
    t.is (dt.day (),       7, "ctor (std::string) -> d");
    t.is (dt.year (),   2010, "ctor (std::string) -> Y");
    t.is (dt.hour (),      1, "ctor (std::string) -> h");
    t.is (dt.minute (),   23, "ctor (std::string) -> N");
    t.is (dt.second (),   45, "ctor (std::string) -> S");

    n = Nibbler ("6/7/2010 01:23:45");
    t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
    dt = Date (ti);
    t.is (dt.month (),     6, "ctor (std::string) -> m");
    t.is (dt.day (),       7, "ctor (std::string) -> d");
    t.is (dt.year (),   2010, "ctor (std::string) -> Y");
    t.is (dt.hour (),      1, "ctor (std::string) -> h");
    t.is (dt.minute (),   23, "ctor (std::string) -> N");
    t.is (dt.second (),   45, "ctor (std::string) -> S");

    n = Nibbler ("6/7/2010 12:34:56");
    t.ok (n.getDate ("m/d/Y H:N:S", ti), "m/d/Y H:N:S ok");
    dt = Date (ti);
    t.is (dt.month (),     6, "ctor (std::string) -> m");
    t.is (dt.day (),       7, "ctor (std::string) -> d");
    t.is (dt.year (),   2010, "ctor (std::string) -> Y");
    t.is (dt.hour (),     12, "ctor (std::string) -> h");
    t.is (dt.minute (),   34, "ctor (std::string) -> N");
    t.is (dt.second (),   56, "ctor (std::string) -> S");

    n = Nibbler ("2010");
    t.ok (n.getDate ("Y", ti), "Y ok");
    dt = Date (ti);
    t.is (dt.month (),     1, "ctor (std::string) -> m");
    t.is (dt.day (),       1, "ctor (std::string) -> d");
    t.is (dt.year (),   2010, "ctor (std::string) -> Y");
    t.is (dt.hour (),      0, "ctor (std::string) -> h");
    t.is (dt.minute (),    0, "ctor (std::string) -> N");
    t.is (dt.second (),    0, "ctor (std::string) -> S");

    n = Nibbler ("17:18:19");
    t.ok (n.getDate ("H:N:S", ti), "H:N:S ok");
    dt = Date (ti);
    Date now = Date ();
    t.is (dt.month (), now.month(), "ctor (std::string) -> m");
    t.is (dt.day (),     now.day(), "ctor (std::string) -> d");
    t.is (dt.year (),   now.year(), "ctor (std::string) -> Y");
    t.is (dt.hour (),           17, "ctor (std::string) -> h");
    t.is (dt.minute (),         18, "ctor (std::string) -> N");
    t.is (dt.second (),         19, "ctor (std::string) -> S");
#endif

    // bool getOneOf (const std::vector <std::string>&, std::string&);
    t.diag ("Nibbler::getOneOf");
    options.push_back ("one");
    options.push_back ("two");
    options.push_back ("three");
    n = Nibbler ("onetwothreefour");
    t.ok    (n.getOneOf (options, s),         "'onetwothreefour':   getOneOf () -> true");
    t.is    (s, "one",                        "'onetwothreefour':   getOneOf () -> one");
    t.ok    (n.getOneOf (options, s),         "   'twothreefour':   getOneOf () -> true");
    t.is    (s, "two",                        "   'twothreefour':   getOneOf () -> two");
    t.ok    (n.getOneOf (options, s),         "      'threefour':   getOneOf () -> true");
    t.is    (s, "three",                      "      'threefour':   getOneOf () -> three");
    t.notok (n.getOneOf (options, s),         "           'four':   getOneOf () -> false");

    // bool getName (std::string&);
    t.diag ("Nibbler::getName");
    n = Nibbler ("a1 one one.two 9 foo_bar");
    t.ok    (n.getName (s),       "'a1 one one.two 9 foo_bar' getName -> ok");
    t.is    (s, "a1",             "  ' one one.two 9 foo_bar' getName -> 'a1'");
    t.ok    (n.skipWS (),         "   'one one.two 9 foo_bar' skipWS  -> ok");

    t.ok    (n.getName (s),       "   'one one.two 9 foo_bar' getName -> ok");
    t.is    (s, "one",            "      ' one.two 9 foo_bar' getName -> 'one'");
    t.ok    (n.skipWS (),         "       'one.two 9 foo_bar' skipWS  -> ok");

    t.ok    (n.getName (s),       "       'one.two 9 foo_bar' getName -> ok");
    t.is    (s, "one",            "          '.two 9 foo_bar' getName -> 'one'");
    t.ok    (n.skip ('.'),        "           'two 9 foo_bar' skip .  -> ok");

    t.ok    (n.getName (s),       "           'two 9 foo_bar' getName -> ok");
    t.is    (s, "two",            "              ' 9 foo_bar' getName -> 'two'");
    t.ok    (n.skipWS (),         "               '9 foo_bar' skipWS  -> ok");

    t.notok (n.getName (s),       "               '9 foo_bar' getName -> not ok");
    t.ok    (n.skip ('9'),        "                ' foo_bar' skip 9  -> ok");
    t.ok    (n.skipWS (),         "                 'foo_bar' skipWS  -> ok");

    t.ok    (n.getName (s),       "                 'foo_bar' getName -> ok");
    t.is    (s, "foo_bar",        "                        '' getName -> 'foo_bar'");
    t.ok    (n.depleted (),       "depleted");

    n = Nibbler ("entrée");
    t.ok (n.getName (s), "'entrée' -> ok");
    t.is (s, "entrée",   "'entrée' -> 'entrée'");

    // bool getWord (std::string&);
    t.diag ("Nibbler::getWord");
    n = Nibbler ("one two th3ee");
    t.ok (n.getWord (s),       "'one'              getWord -> ok");
    t.is (s, "one",            "'one'              getWord -> 'one'");
    t.ok (n.skipWS (),         "skipWS");
    t.ok (n.getWord (s),       "'two'              getWord -> ok");
    t.is (s, "two",            "'two'              getWord -> 'two'");
    t.ok (n.skipWS (),         "skipWS");
    t.ok (n.getWord (s),       "'th'               getWord -> ok");
    t.is (s, "th",             "'th'               getWord -> 'th'");
    t.ok (n.skip ('3'),        "skip(3)");
    t.ok (n.getWord (s),       "'ee'               getWord -> ok");
    t.is (s, "ee",             "'ee'               getWord -> 'ee'");
    t.ok (n.depleted (),       "depleted");

    t.diag ("Nibbler::getWord");
    n = Nibbler ("one TWO,three,f ");
    t.ok (n.getWord (s),              "'one TWO,three,f '   getWord  -> ok");
    t.is (s, "one",                   "   ' TWO,three,f '   getWord  -> one");
    t.ok (n.skipWS (),                "    'TWO,three,f '   skipWS   -> ok");

    t.ok (n.getWord (s),              "    'TWO,three,f '   getWord  -> ok");
    t.is (s, "TWO",                   "       ',three,f '   getWord  -> TWO");
    t.ok (n.skip (','),               "        'three,f '   skip ,   -> ok");

    t.ok (n.getWord (s),              "        'three,f '   getWord  -> ok");
    t.is (s, "three",                 "             ',f '   getWord  -> three");
    t.ok (n.skip (','),               "              'f '   skip ,   -> ok");

    t.ok (n.getWord (s),              "              'f '   getWord  -> ok");
    t.is (s, "f",                     "               ' '   getWord  -> f");
    t.ok (n.skipWS (),                "                ''   skip ,   -> ok");
    t.ok (n.depleted (),              "                ''   depleted -> true");

    // bool getN (int, std::string&);
    t.diag ("Nibbler::getN");
    n = Nibbler ("111223");
    t.ok (n.getN (3, s),              "  '111223' : getN (3)         -> true");
    t.is (s, "111",                   "  '111223' : getN (3)         -> '111'");
    t.ok (n.getN (2, s),              "     '223' : getN (2)         -> true");
    t.is (s, "22",                    "     '223' : getN (2)         -> '22'");
    t.ok (n.getN (1, s),              "       '3' : getN (1)         -> true");
    t.is (s, "3",                     "       '3' : getN (1)         -> '1'");
    t.ok    (n.depleted (),           "        '' : depleted ()      -> true");

    // bool getUntilEOL (std::string&);
    t.diag ("Nibbler::getUntilEOL");
    n = Nibbler ("one\ntwo");
    t.ok    (n.getUntilEOL (s),       "'one\\ntwo' :   getUntilEOL ()       -> true");
    t.is    (s, "one",                "'one\\ntwo' :   getUntilEOL ()       -> 'one'");
    t.ok    (n.skip ('\n'),           "   '\\ntwo' :          skip ('\\n')   -> true");
    t.ok    (n.getUntilEOL (s),       "     'two' :    getUntilEOL ()       -> true");
    t.is    (s, "two",                "     'two' :    getUntilEOL ()       -> 'two'");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // bool getUntilEOS (std::string&);
    t.diag ("Nibbler::getUntilEOS");
    n = Nibbler ("one two");
    t.ok    (n.getUntilEOS (s),       " 'one two' :    getUntilEOS ()       -> 'one two'");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // char next ();
    t.diag ("Nibbler::next");
    n = Nibbler ("hello");
    t.is    (n.next (), 'h',          "   'hello' :           next ()       -> 'h'");
    t.is    (n.next (), 'h',          "   'hello' :           next ()       -> 'h'");
    t.ok    (n.skipN (4),             "   'hello' :          skipN (4)      -> true");
    t.is    (n.next (), 'o',          "       'o' :           next ()       -> 'o'");
    t.ok    (n.skipN (1),             "       'o' :          skipN ()       -> true");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // std::string next (const int quantity);
    t.diag ("Nibbler::next");
    n = Nibbler ("hello");
    t.is    (n.next (1), "h",         "   'hello' :          next (1)       -> 'h'");
    t.is    (n.next (1), "h",         "   'hello' :          next (1)       -> 'h'");
    t.is    (n.next (2), "he",        "   'hello' :          next (2)       -> 'he'");
    t.is    (n.next (3), "hel",       "   'hello' :          next (3)       -> 'hel'");
    t.is    (n.next (4), "hell",      "   'hello' :          next (4)       -> 'hell'");
    t.is    (n.next (5), "hello",     "   'hello' :          next (5)       -> 'hello'");
    t.is    (n.next (6), "",          "   'hello' :          next (6)       -> ''");

    // bool depleted ();
    t.diag ("Nibbler::depleted");
    n = Nibbler (" ");
    t.notok (n.depleted (),           "       ' ' :       depleted ()       -> false");
    t.ok    (n.skipN (),              "        '' :           skip ()       -> true");
    t.ok    (n.depleted (),           "        '' :       depleted ()       -> true");

    // void save ();
    // void restore ();
    n = Nibbler ("abcde");
    t.ok (n.skipN (),                 "   'abcde' :           skip ()       -> true");
    n.save ();
    t.ok (n.skipN (),                 "    'bcde' :           skip ()       -> true");
    t.ok (n.skipN (),                 "     'cde' :           skip ()       -> true");
    t.ok (n.skipN (),                 "      'de' :           skip ()       -> true");
    n.restore ();
    t.is (n.next (1), "b",            "    'bcde' :           skip ()       -> 'b'");
  }

  catch (const std::string& e) {t.diag (e);}

  return 0;
}
예제 #13
0
파일: CmdEdit.cpp 프로젝트: gerarldlee/task
void CmdEdit::parseTask (Task& task, const std::string& after, const std::string& dateformat)
{
  // project
  std::string value = findValue (after, "\n  Project:");
  if (task.get ("project") != value)
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_PROJECT_MOD);
      task.set ("project", value);
    }
    else
    {
      context.footnote (STRING_EDIT_PROJECT_DEL);
      task.remove ("project");
    }
  }

  // tags
  value = findValue (after, "\n  Tags:");
  std::vector <std::string> tags;
  split (tags, value, ' ');
  task.remove ("tags");
  task.addTags (tags);

  // description.
  value = findMultilineValue (after, "\n  Description:", "\n  Created:");
  if (task.get ("description") != value)
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_DESC_MOD);
      task.set ("description", value);
    }
    else
      throw std::string (STRING_EDIT_DESC_REMOVE_ERR);
  }

  // entry
  value = findValue (after, "\n  Created:");
  if (value != "")
  {
    std::string formatted = formatDate (task, "entry", dateformat);

    if (formatted != value)
    {
      context.footnote (STRING_EDIT_ENTRY_MOD);
      task.set ("entry", Date(value, dateformat).toEpochString ());
    }
  }
  else
    throw std::string (STRING_EDIT_ENTRY_REMOVE_ERR);

  // start
  value = findValue (after, "\n  Started:");
  if (value != "")
  {
    if (task.get ("start") != "")
    {
      std::string formatted = formatDate (task, "start", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_START_MOD);
        task.set ("start", Date(value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_START_MOD);
      task.set ("start", Date(value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("start") != "")
    {
      context.footnote (STRING_EDIT_START_DEL);
      task.remove ("start");
    }
  }

  // end
  value = findValue (after, "\n  Ended:");
  if (value != "")
  {
    if (task.get ("end") != "")
    {
      std::string formatted = formatDate (task, "end", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_END_MOD);
        task.set ("end", Date(value, dateformat).toEpochString ());
      }
    }
    else if (task.getStatus () != Task::deleted)
      throw std::string (STRING_EDIT_END_SET_ERR);
  }
  else
  {
    if (task.get ("end") != "")
    {
      context.footnote (STRING_EDIT_END_DEL);
      task.setStatus (Task::pending);
      task.remove ("end");
    }
  }

  // scheduled
  value = findValue (after, "\n  Scheduled:");
  if (value != "")
  {
    if (task.get ("scheduled") != "")
    {
      std::string formatted = formatDate (task, "scheduled", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_SCHED_MOD);
        task.set ("scheduled", Date(value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_SCHED_MOD);
      task.set ("scheduled", Date(value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("scheduled") != "")
    {
      context.footnote (STRING_EDIT_SCHED_DEL);
      task.setStatus (Task::pending);
      task.remove ("scheduled");
    }
  }

  // due
  value = findValue (after, "\n  Due:");
  if (value != "")
  {
    if (task.get ("due") != "")
    {
      std::string formatted = formatDate (task, "due", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_DUE_MOD);
        task.set ("due", Date(value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_DUE_MOD);
      task.set ("due", Date(value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("due") != "")
    {
      if (task.getStatus () == Task::recurring ||
          task.get ("parent") != "")
      {
        context.footnote (STRING_EDIT_DUE_DEL_ERR);
      }
      else
      {
        context.footnote (STRING_EDIT_DUE_DEL);
        task.remove ("due");
      }
    }
  }

  // until
  value = findValue (after, "\n  Until:");
  if (value != "")
  {
    if (task.get ("until") != "")
    {
      std::string formatted = formatDate (task, "until", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_UNTIL_MOD);
        task.set ("until", Date(value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_UNTIL_MOD);
      task.set ("until", Date(value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("until") != "")
    {
      context.footnote (STRING_EDIT_UNTIL_DEL);
      task.remove ("until");
    }
  }

  // recur
  value = findValue (after, "\n  Recur:");
  if (value != task.get ("recur"))
  {
    if (value != "")
    {
      Duration d;
      std::string::size_type idx = 0;
      if (d.parse (value, idx))
      {
        context.footnote (STRING_EDIT_RECUR_MOD);
        if (task.get ("due") != "")
        {
          task.set ("recur", value);
          task.setStatus (Task::recurring);
        }
        else
          throw std::string (STRING_EDIT_RECUR_DUE_ERR);
      }
      else
        throw std::string (STRING_EDIT_RECUR_ERR);
    }
    else
    {
      context.footnote (STRING_EDIT_RECUR_DEL);
      task.setStatus (Task::pending);
      task.remove ("recur");
      task.remove ("until");
      task.remove ("mask");
      task.remove ("imask");
    }
  }

  // wait
  value = findValue (after, "\n  Wait until:");
  if (value != "")
  {
    if (task.get ("wait") != "")
    {
      std::string formatted = formatDate (task, "wait", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_WAIT_MOD);
        task.set ("wait", Date(value, dateformat).toEpochString ());
        task.setStatus (Task::waiting);
      }
    }
    else
    {
      context.footnote (STRING_EDIT_WAIT_MOD);
      task.set ("wait", Date(value, dateformat).toEpochString ());
      task.setStatus (Task::waiting);
    }
  }
  else
  {
    if (task.get ("wait") != "")
    {
      context.footnote (STRING_EDIT_WAIT_DEL);
      task.remove ("wait");
      task.setStatus (Task::pending);
    }
  }

  // parent
  value = findValue (after, "\n  Parent:");
  if (value != task.get ("parent"))
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_PARENT_MOD);
      task.set ("parent", value);
    }
    else
    {
      context.footnote (STRING_EDIT_PARENT_DEL);
      task.remove ("parent");
    }
  }

  // Annotations
  std::map <std::string, std::string> annotations;
  std::string::size_type found = 0;
  while ((found = after.find ("\n  Annotation:", found)) != std::string::npos)
  {
    found += 14;  // Length of "\n  Annotation:".

    std::string::size_type eol = after.find ("\n", found + 1);
    if (eol != std::string::npos)
    {
      std::string value = trim (after.substr (
        found,
        eol - found), "\t ");

      std::string::size_type gap = value.find (" -- ");
      if (gap != std::string::npos)
      {
        // TODO keeping the initial dates even if dateformat approximates them
        // is complex as finding the correspondence between each original line
        // and edited line may be impossible (bug #705). It would be simpler if
        // each annotation was put on a line with a distinguishable id (then
        // for each line: if the annotation is the same, then it is copied; if
        // the annotation is modified, then its original date may be kept; and
        // if there is no corresponding id, then a new unique date is created).
        Date when (value.substr (0, gap), dateformat);

        // This guarantees that if more than one annotation has the same date,
        // that the seconds will be different, thus unique, thus not squashed.
        // Bug #249
        when += (const int) annotations.size ();

        std::stringstream name;
        name << "annotation_" << when.toEpoch ();
        std::string text = trim (value.substr (gap + 4), "\t ");
        annotations.insert (std::make_pair (name.str (), text));
      }
    }
  }

  task.setAnnotations (annotations);

  // Dependencies
  value = findValue (after, "\n  Dependencies:");
  std::vector <std::string> dependencies;
  split (dependencies, value, ",");

  task.remove ("depends");
  std::vector <std::string>::iterator dep;
  for (dep = dependencies.begin (); dep != dependencies.end (); ++dep)
  {
    if (dep->length () >= 7)
      task.addDependency (*dep);
    else
      task.addDependency ((int) strtol (dep->c_str (), NULL, 10));
  }

  // UDAs
  std::map <std::string, Column*>::iterator col;
  for (col = context.columns.begin (); col != context.columns.end (); ++col)
  {
    std::string type = context.config.get ("uda." + col->first + ".type");
    if (type != "")
    {
      std::string value = findValue (after, "\n  UDA " + col->first + ":");
      if ((task.get (col->first) != value) && (type != "date" ||
           (task.get (col->first) != Date (value, dateformat).toEpochString ())) &&
           (type != "duration" ||
           (task.get (col->first) != (std::string) Duration (value) )))
      {
        if (value != "")
        {
          context.footnote (format (STRING_EDIT_UDA_MOD, col->first));

          if (type == "string")
          {
            task.set (col->first, value);
          }
          else if (type == "numeric")
          {
            Nibbler n (value);
            double d;
            if (n.getNumber (d) &&
                n.depleted ())
              task.set (col->first, value);
            else
              throw format (STRING_UDA_NUMERIC, value);
          }
          else if (type == "date")
          {
            Date d (value, dateformat);
            task.set (col->first, d.toEpochString ());
          }
          else if (type == "duration")
          {
            Duration d (value);
            task.set (col->first, (time_t) d);
          }
        }
        else
        {
          context.footnote (format (STRING_EDIT_UDA_DEL, col->first));
          task.remove (col->first);
        }
      }
    }
  }

  // UDA orphans
  std::vector <std::string> orphanValues = findValues (after, "\n  UDA Orphan ");
  std::vector <std::string>::iterator orphan;
  for (orphan = orphanValues.begin (); orphan != orphanValues.end (); ++orphan)
  {
    std::string::size_type colon = orphan->find (':');
    if (colon != std::string::npos)
    {
      std::string name  = trim (orphan->substr (0, colon),  "\t ");
      std::string value = trim (orphan->substr (colon + 1), "\t ");

      if (value != "")
        task.set (name, value);
      else
        task.remove (name);
    }
  }
}
예제 #14
0
void CmdEdit::parseTask (Task& task, const std::string& after, const std::string& dateformat)
{
  // project
  std::string value = findValue (after, "\n  Project:");
  if (task.get ("project") != value)
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_PROJECT_MOD);
      task.set ("project", value);
    }
    else
    {
      context.footnote (STRING_EDIT_PROJECT_DEL);
      task.remove ("project");
    }
  }

  // tags
  value = findValue (after, "\n  Tags:");
  std::vector <std::string> tags;
  split (tags, value, ' ');
  task.remove ("tags");
  task.addTags (tags);

  // description.
  value = findMultilineValue (after, "\n  Description:", "\n  Created:");
  if (task.get ("description") != value)
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_DESC_MOD);
      task.set ("description", value);
    }
    else
      throw std::string (STRING_EDIT_DESC_REMOVE_ERR);
  }

  // entry
  value = findValue (after, "\n  Created:");
  if (value != "")
  {
    std::string formatted = formatDate (task, "entry", dateformat);

    if (formatted != value)
    {
      context.footnote (STRING_EDIT_ENTRY_MOD);
      task.set ("entry", ISO8601d (value, dateformat).toEpochString ());
    }
  }
  else
    throw std::string (STRING_EDIT_ENTRY_REMOVE_ERR);

  // start
  value = findValue (after, "\n  Started:");
  if (value != "")
  {
    if (task.get ("start") != "")
    {
      std::string formatted = formatDate (task, "start", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_START_MOD);
        task.set ("start", ISO8601d (value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_START_MOD);
      task.set ("start", ISO8601d (value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("start") != "")
    {
      context.footnote (STRING_EDIT_START_DEL);
      task.remove ("start");
    }
  }

  // end
  value = findValue (after, "\n  Ended:");
  if (value != "")
  {
    if (task.get ("end") != "")
    {
      std::string formatted = formatDate (task, "end", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_END_MOD);
        task.set ("end", ISO8601d (value, dateformat).toEpochString ());
      }
    }
    else if (task.getStatus () != Task::deleted)
      throw std::string (STRING_EDIT_END_SET_ERR);
  }
  else
  {
    if (task.get ("end") != "")
    {
      context.footnote (STRING_EDIT_END_DEL);
      task.setStatus (Task::pending);
      task.remove ("end");
    }
  }

  // scheduled
  value = findValue (after, "\n  Scheduled:");
  if (value != "")
  {
    if (task.get ("scheduled") != "")
    {
      std::string formatted = formatDate (task, "scheduled", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_SCHED_MOD);
        task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_SCHED_MOD);
      task.set ("scheduled", ISO8601d (value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("scheduled") != "")
    {
      context.footnote (STRING_EDIT_SCHED_DEL);
      task.setStatus (Task::pending);
      task.remove ("scheduled");
    }
  }

  // due
  value = findValue (after, "\n  Due:");
  if (value != "")
  {
    if (task.get ("due") != "")
    {
      std::string formatted = formatDate (task, "due", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_DUE_MOD);
        task.set ("due", ISO8601d (value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_DUE_MOD);
      task.set ("due", ISO8601d (value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("due") != "")
    {
      if (task.getStatus () == Task::recurring ||
          task.get ("parent") != "")
      {
        context.footnote (STRING_EDIT_DUE_DEL_ERR);
      }
      else
      {
        context.footnote (STRING_EDIT_DUE_DEL);
        task.remove ("due");
      }
    }
  }

  // until
  value = findValue (after, "\n  Until:");
  if (value != "")
  {
    if (task.get ("until") != "")
    {
      std::string formatted = formatDate (task, "until", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_UNTIL_MOD);
        task.set ("until", ISO8601d (value, dateformat).toEpochString ());
      }
    }
    else
    {
      context.footnote (STRING_EDIT_UNTIL_MOD);
      task.set ("until", ISO8601d (value, dateformat).toEpochString ());
    }
  }
  else
  {
    if (task.get ("until") != "")
    {
      context.footnote (STRING_EDIT_UNTIL_DEL);
      task.remove ("until");
    }
  }

  // recur
  value = findValue (after, "\n  Recur:");
  if (value != task.get ("recur"))
  {
    if (value != "")
    {
      ISO8601p p;
      std::string::size_type idx = 0;
      if (p.parse (value, idx))
      {
        context.footnote (STRING_EDIT_RECUR_MOD);
        if (task.get ("due") != "")
        {
          task.set ("recur", value);
          task.setStatus (Task::recurring);
        }
        else
          throw std::string (STRING_EDIT_RECUR_DUE_ERR);
      }
      else
        throw std::string (STRING_EDIT_RECUR_ERR);
    }
    else
    {
      context.footnote (STRING_EDIT_RECUR_DEL);
      task.setStatus (Task::pending);
      task.remove ("recur");
      task.remove ("until");
      task.remove ("mask");
      task.remove ("imask");
    }
  }

  // wait
  value = findValue (after, "\n  Wait until:");
  if (value != "")
  {
    if (task.get ("wait") != "")
    {
      std::string formatted = formatDate (task, "wait", dateformat);

      if (formatted != value)
      {
        context.footnote (STRING_EDIT_WAIT_MOD);
        task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
        task.setStatus (Task::waiting);
      }
    }
    else
    {
      context.footnote (STRING_EDIT_WAIT_MOD);
      task.set ("wait", ISO8601d (value, dateformat).toEpochString ());
      task.setStatus (Task::waiting);
    }
  }
  else
  {
    if (task.get ("wait") != "")
    {
      context.footnote (STRING_EDIT_WAIT_DEL);
      task.remove ("wait");
      task.setStatus (Task::pending);
    }
  }

  // parent
  value = findValue (after, "\n  Parent:");
  if (value != task.get ("parent"))
  {
    if (value != "")
    {
      context.footnote (STRING_EDIT_PARENT_MOD);
      task.set ("parent", value);
    }
    else
    {
      context.footnote (STRING_EDIT_PARENT_DEL);
      task.remove ("parent");
    }
  }

  // Annotations
  std::map <std::string, std::string> annotations;
  std::string::size_type found = 0;
  while ((found = after.find ("\n  Annotation:", found)) != std::string::npos)
  {
    found += 14;  // Length of "\n  Annotation:".

    auto eol = after.find ("\n", found + 1);
    if (eol != std::string::npos)
    {
      std::string value = trim (after.substr (
        found,
        eol - found), "\t ");

      auto gap = value.find (" -- ");
      if (gap != std::string::npos)
      {
        // TODO keeping the initial dates even if dateformat approximates them
        // is complex as finding the correspondence between each original line
        // and edited line may be impossible (bug #705). It would be simpler if
        // each annotation was put on a line with a distinguishable id (then
        // for each line: if the annotation is the same, then it is copied; if
        // the annotation is modified, then its original date may be kept; and
        // if there is no corresponding id, then a new unique date is created).
        ISO8601d when (value.substr (0, gap), dateformat);

        // If the map already contains a annotation for a given timestamp
        // we need to increment until we find an unused key
        int timestamp = (int) when.toEpoch ();

        std::stringstream name;

        do
        {
          name.str ("");  // Clear
          name << "annotation_" << timestamp;
          timestamp++;
        }
        while (annotations.find (name.str ()) != annotations.end ());

        std::string text = trim (value.substr (gap + 4), "\t ");
        annotations.insert (std::make_pair (name.str (), json::decode (text)));
      }
    }
  }

  task.setAnnotations (annotations);

  // Dependencies
  value = findValue (after, "\n  Dependencies:");
  std::vector <std::string> dependencies;
  split (dependencies, value, ",");

  task.remove ("depends");
  for (auto& dep : dependencies)
  {
    if (dep.length () >= 7)
      task.addDependency (dep);
    else
      task.addDependency ((int) strtol (dep.c_str (), NULL, 10));
  }

  // UDAs
  for (auto& col : context.columns)
  {
    std::string type = context.config.get ("uda." + col.first + ".type");
    if (type != "")
    {
      std::string value = findValue (after, "\n  UDA " + col.first + ":");
      if ((task.get (col.first) != value) && (type != "date" ||
           (task.get (col.first) != ISO8601d (value, dateformat).toEpochString ())) &&
           (type != "duration" ||
           (task.get (col.first) != (std::string) ISO8601p (value))))
      {
        if (value != "")
        {
          context.footnote (format (STRING_EDIT_UDA_MOD, col.first));

          if (type == "string")
          {
            task.set (col.first, value);
          }
          else if (type == "numeric")
          {
            Nibbler n (value);
            double d;
            if (n.getNumber (d) &&
                n.depleted ())
              task.set (col.first, value);
            else
              throw format (STRING_UDA_NUMERIC, value);
          }
          else if (type == "date")
          {
            task.set (col.first, ISO8601d (value, dateformat).toEpochString ());
          }
          else if (type == "duration")
          {
            task.set (col.first, (time_t) ISO8601p (value));
          }
        }
        else
        {
          context.footnote (format (STRING_EDIT_UDA_DEL, col.first));
          task.remove (col.first);
        }
      }
    }
  }

  // UDA orphans
  std::vector <std::string> orphanValues = findValues (after, "\n  UDA Orphan ");
  for (auto& orphan : orphanValues)
  {
    auto colon = orphan.find (':');
    if (colon != std::string::npos)
    {
      std::string name  = trim (orphan.substr (0, colon),  "\t ");
      std::string value = trim (orphan.substr (colon + 1), "\t ");

      if (value != "")
        task.set (name, value);
      else
        task.remove (name);
    }
  }
}
예제 #15
0
파일: Duration.cpp 프로젝트: SEJeff/task
void Duration::parse (const std::string& input)
{
  std::string lower_input = lowerCase (input);

  // Assume the ordinal is 1, but look for an integer, just in case.
  double value = 1;
  Nibbler n (lower_input);
  n.getNumber (value);

  if (value < 0.0)
  {
    _negative = true;
    value = -value;
  }
  else
    _negative = false;

  // If no units are provided, assume seconds.
  if (n.depleted ())
  {
    _secs = (long) value;
    return;
  }

  std::string units;
  n.getUntilEOS (units);

  // Auto complete against all supported durations.
  std::vector <std::string> supported;
  for (unsigned int i = 0; i < NUM_DURATIONS; ++i)
    supported.push_back (durations[i]);

  _secs = 0;
  std::vector <std::string> matches;
  if (autoComplete (units,
                    supported,
                    matches,
                    context.config.getInteger ("abbreviation.minimum")) == 1)
  {
    std::string match = matches[0];

         if (match == "biannual")                         _secs = (int) (value * 86400 * 730);
    else if (match == "biyearly")                         _secs = (int) (value * 86400 * 730);

    else if (match == "yearly")                           _secs = (int) (value * 86400 * 365);
    else if (match == "annual")                           _secs = (int) (value * 86400 * 365);
    else if (match == "years")                            _secs = (int) (value * 86400 * 365);
    else if (match == "year")                             _secs = (int) (value * 86400 * 365);
    else if (match == "yrs")                              _secs = (int) (value * 86400 * 365);
    else if (match == "yr")                               _secs = (int) (value * 86400 * 365);
    else if (match == "y")                                _secs = (int) (value * 86400 * 365);

    else if (match == "semiannual")                       _secs = (int) (value * 86400 * 183);

    else if (match == "bimonthly")                        _secs = (int) (value * 86400 * 61);
    else if (match == "quarterly")                        _secs = (int) (value * 86400 * 91);
    else if (match == "quarters")                         _secs = (int) (value * 86400 * 91);
    else if (match == "qrtrs")                            _secs = (int) (value * 86400 * 91);
    else if (match == "qtrs")                             _secs = (int) (value * 86400 * 91);
    else if (match == "qtr")                              _secs = (int) (value * 86400 * 91);
    else if (match == "q")                                _secs = (int) (value * 86400 * 91);

    else if (match == "monthly")                          _secs = (int) (value * 86400 * 30);
    else if (match == "month")                            _secs = (int) (value * 86400 * 30);
    else if (match == "months")                           _secs = (int) (value * 86400 * 30);
    else if (match == "mnths")                            _secs = (int) (value * 86400 * 30);
    else if (match == "mos")                              _secs = (int) (value * 86400 * 30);
    else if (match == "mo")                               _secs = (int) (value * 86400 * 30);
    else if (match == "mths")                             _secs = (int) (value * 86400 * 30);
    else if (match == "mth")                              _secs = (int) (value * 86400 * 30);
    else if (match == "m")                                _secs = (int) (value * 86400 * 30);

    else if (match == "biweekly")                         _secs = (int) (value * 86400 * 14);
    else if (match == "fortnight")                        _secs = (int) (value * 86400 * 14);

    else if (match == "weekly")                           _secs = (int) (value * 86400 * 7);
    else if (match == "sennight")                         _secs = (int) (value * 86400 * 7);
    else if (match == "weeks")                            _secs = (int) (value * 86400 * 7);
    else if (match == "week")                             _secs = (int) (value * 86400 * 7);
    else if (match == "wks")                              _secs = (int) (value * 86400 * 7);
    else if (match == "wk")                               _secs = (int) (value * 86400 * 7);
    else if (match == "w")                                _secs = (int) (value * 86400 * 7);

    else if (match == "daily")                            _secs = (int) (value * 86400 * 1);
    else if (match == "day")                              _secs = (int) (value * 86400 * 1);
    else if (match == "weekdays")                         _secs = (int) (value * 86400 * 1);
    else if (match == "days")                             _secs = (int) (value * 86400 * 1);
    else if (match == "d")                                _secs = (int) (value * 86400 * 1);

    else if (match == "hours")                            _secs = (int) (value * 3600);
    else if (match == "hour")                             _secs = (int) (value * 3600);
    else if (match == "hrs")                              _secs = (int) (value * 3600);
    else if (match == "hr")                               _secs = (int) (value * 3600);
    else if (match == "h")                                _secs = (int) (value * 3600);

    else if (match == "minutes")                          _secs = (int) (value * 60);
    else if (match == "mins")                             _secs = (int) (value * 60);
    else if (match == "min")                              _secs = (int) (value * 60);

    else if (match == "seconds")                          _secs = (int) value;
    else if (match == "secs")                             _secs = (int) value;
    else if (match == "sec")                              _secs = (int) value;
    else if (match == "s")                                _secs = (int) value;

    else if (match == "-")                                _secs = 0;
  }

  if (_secs == 0)
    throw ::format (STRING_DURATION_UNRECOGNIZED, input);
}
예제 #16
0
파일: Task.cpp 프로젝트: nigeil/task
////////////////////////////////////////////////////////////////////////////////
// Attempt an FF4 parse first, using Task::parse, and in the event of an error
// try a legacy parse (F3, FF2).  Note that FF1 is no longer supported.
//
// start --> [ --> Att --> ] --> end
//              ^       |
//              +-------+
//
void Task::parse (const std::string& input)
{
  std::string copy;
  if (input[input.length () - 1] == '\n')
    copy = input.substr (0, input.length () - 1);
  else
    copy = input;

  try
  {
    clear ();

    Nibbler n (copy);
    std::string line;
    if (n.skip     ('[')       &&
        n.getUntil (']', line) &&
        n.skip     (']')       &&
        n.depleted ())
    {
      if (line.length () == 0)
        throw std::string (STRING_RECORD_EMPTY);

      Nibbler nl (line);
      std::string name;
      std::string value;
      while (!nl.depleted ())
      {
        if (nl.getUntil (':', name) &&
            nl.skip (':')           &&
            nl.getQuoted ('"', value))
        {
          // Experimental legacy value translation of 'recur:m' --> 'recur:mo'.
          if (name == "recur" &&
              digitsOnly (value.substr (0, value.length () - 1)) &&
              value[value.length () - 1] == 'm')
            value += 'o';

          if (name.substr (0, 11) == "annotation_")
            ++annotation_count;

          (*this)[name] = decode (json::decode (value));
        }

        nl.skip (' ');
      }

      std::string remainder;
      nl.getUntilEOS (remainder);
      if (remainder.length ())
        throw std::string (STRING_RECORD_JUNK_AT_EOL);
    }
    else
      throw std::string (STRING_RECORD_NOT_FF4);
  }

  catch (const std::string&)
  {
    legacyParse (copy);
  }

  recalc_urgency = true;
}
예제 #17
0
파일: CmdShow.cpp 프로젝트: SEJeff/task
int CmdShow::execute (std::string& output)
{
  int rc = 0;
  std::stringstream out;

  // Obtain the arguments from the description.  That way, things like '--'
  // have already been handled.
  std::vector <std::string> words = context.a3.extract_words ();
  if (words.size () > 2)
    throw std::string (STRING_CMD_SHOW_ARGS);

  int width = context.getWidth ();

  // Complain about configuration variables that are not recognized.
  // These are the regular configuration variables.
  // Note that there is a leading and trailing space, to make it easier to
  // search for whole words.
  std::string recognized =
    " abbreviation.minimum"
    " active.indicator"
    " avoidlastcolumn"
    " bulk"
    " burndown.bias"
    " calendar.details"
    " calendar.details.report"
    " calendar.holidays"
    " calendar.legend"
    " calendar.offset"
    " calendar.offset.value"
    " color"
    " color.active"
    " color.alternate"
    " color.blocked"
    " color.burndown.done"
    " color.burndown.pending"
    " color.burndown.started"
    " color.calendar.due"
    " color.calendar.due.today"
    " color.calendar.holiday"
    " color.calendar.overdue"
    " color.calendar.today"
    " color.calendar.weekend"
    " color.calendar.weeknumber"
    " color.completed"
    " color.debug"
    " color.deleted"
    " color.due"
    " color.due.today"
    " color.footnote"
    " color.header"
    " color.history.add"
    " color.history.delete"
    " color.history.done"
    " color.label"
    " color.overdue"
    " color.pri.H"
    " color.pri.L"
    " color.pri.M"
    " color.pri.none"
    " color.recurring"
    " color.summary.background"
    " color.summary.bar"
    " color.sync.added"
    " color.sync.changed"
    " color.sync.rejected"
    " color.tagged"
    " color.undo.after"
    " color.undo.before"
    " column.padding"
    " complete.all.projects"
    " complete.all.tags"
    " confirmation"
    " data.location"
    " dateformat"
    " dateformat.annotation"
    " dateformat.holiday"
    " dateformat.report"
    " debug"
    " default.command"
    " default.due"
    " default.priority"
    " default.project"
    " defaultheight"
    " defaultwidth"
    " dependency.confirmation"
    " dependency.indicator"
    " dependency.reminder"
    " detection"
    " displayweeknumber"
    " dom"
    " due"
    " echo.command"                      // Deprecated 2.0
    " edit.verbose"                      // Deprecated 2.0
    " editor"
    " exit.on.missing.db"
    " expressions"
    " extensions"
    " fontunderline"
    " gc"
    " hyphenate"
    " indent.annotation"
    " indent.report"
    " journal.info"
    " journal.time"
    " journal.time.start.annotation"
    " journal.time.stop.annotation"
    " json.array"
    " list.all.projects"
    " list.all.tags"
    " locale"
    " locking"
    " merge.autopush"
    " merge.default.uri"
    " monthsperline"
    " nag"
    " patterns"
    " pull.default.uri"
    " push.default.uri"
    " recurrence.indicator"
    " recurrence.limit"
    " regex"
    " row.padding"
    " rule.precedence.color"
    " search.case.sensitive"
    " shadow.command"
    " shadow.file"
    " shadow.notify"
    " shell.prompt"
    " tag.indicator"
    " taskd.server"
    " taskd.credentials"
    " undo.style"
    " urgency.active.coefficient"
    " urgency.annotations.coefficient"
    " urgency.blocked.coefficient"
    " urgency.blocking.coefficient"
    " urgency.due.coefficient"
    " urgency.next.coefficient"
    " urgency.priority.coefficient"
    " urgency.project.coefficient"
    " urgency.tags.coefficient"
    " urgency.waiting.coefficient"
    " urgency.age.coefficient"
    " urgency.age.max"
    " verbose"
    " weekstart"
    " xterm.title"
    " ";

  // This configuration variable is supported, but not documented.  It exists
  // so that unit tests can force color to be on even when the output from task
  // is redirected to a file, or stdout is not a tty.
  recognized += "_forcecolor ";

  std::vector <std::string> all;
  context.config.all (all);

  std::vector <std::string> unrecognized;
  std::vector <std::string>::iterator i;
  for (i = all.begin (); i != all.end (); ++i)
  {
    // Disallow partial matches by tacking a leading and trailing space on each
    // variable name.
    std::string pattern = " " + *i + " ";
    if (recognized.find (pattern) == std::string::npos)
    {
      // These are special configuration variables, because their name is
      // dynamic.
      if (i->substr (0, 14) != "color.keyword."        &&
          i->substr (0, 14) != "color.project."        &&
          i->substr (0, 10) != "color.tag."            &&
          i->substr (0,  8) != "holiday."              &&
          i->substr (0,  7) != "report."               &&
          i->substr (0,  6) != "alias."                &&
          i->substr (0,  5) != "hook."                 &&
          i->substr (0,  5) != "push."                 &&
          i->substr (0,  5) != "pull."                 &&
          i->substr (0,  6) != "merge."                &&
          i->substr (0,  4) != "uda."                  &&
          i->substr (0, 21) != "urgency.user.project." &&
          i->substr (0, 17) != "urgency.user.tag.")
      {
        unrecognized.push_back (*i);
      }
    }
  }

  // Find all the values that match the defaults, for highlighting.
  std::vector <std::string> default_values;
  Config default_config;
  default_config.setDefaults ();

  for (i = all.begin (); i != all.end (); ++i)
    if (context.config.get (*i) != default_config.get (*i))
      default_values.push_back (*i);

  // Create output view.
  ViewText view;
  view.width (width);
  view.add (Column::factory ("string", STRING_CMD_SHOW_CONF_VAR));
  view.add (Column::factory ("string", STRING_CMD_SHOW_CONF_VALUE));

  Color error ("bold white on red");
  Color warning ("black on yellow");

  std::string section;

  // Look for the first plausible argument which could be a pattern 
  if (words.size ())
    section = words[0];

  if (section == "all")
    section = "";

  for (i = all.begin (); i != all.end (); ++i)
  {
    std::string::size_type loc = i->find (section, 0);
    if (loc != std::string::npos)
    {
      // Look for unrecognized.
      Color color;
      if (std::find (unrecognized.begin (), unrecognized.end (), *i) != unrecognized.end ())
        color = error;
      else if (std::find (default_values.begin (), default_values.end (), *i) != default_values.end ())
        color = warning;

      std::string value = context.config.get (*i);
      // hide sensible information
      if ( (i->substr (0, 5) == "push."   ||
            i->substr (0, 5) == "pull."   ||
            i->substr (0, 6) == "merge.") && (i->find (".uri") != std::string::npos) ) {

        Uri uri (value);
        uri.parse ();
        value = uri.ToString ();
      }

      int row = view.addRow ();
      view.set (row, 0, *i, color);
      view.set (row, 1, value, color);
    }
  }

  out << "\n"
      << view.render ()
      << (view.rows () == 0 ? STRING_CMD_SHOW_NONE : "")
      << (view.rows () == 0 ? "\n\n" : "\n");

  if (default_values.size ())
  {
    out << STRING_CMD_SHOW_DIFFER;

    if (context.color ())
      out << "  "
          << format (STRING_CMD_SHOW_DIFFER_COLOR, warning.colorize ("color"))
          << "\n\n";
  }

  // Display the unrecognized variables.
  if (unrecognized.size ())
  {
    out << STRING_CMD_SHOW_UNREC << "\n";

    for (i = unrecognized.begin (); i != unrecognized.end (); ++i)
      out << "  " << *i << "\n";

    if (context.color ())
      out << "\n  " << format (STRING_CMD_SHOW_DIFFER_COLOR, error.colorize ("color"));

    out << "\n\n";
  }

  out << legacyCheckForDeprecatedVariables ();
  out << legacyCheckForDeprecatedColor ();
  out << legacyCheckForDeprecatedColumns ();

  // TODO Check for referenced but missing theme files.
  // TODO Check for referenced but missing string files.
  // TODO Check for referenced but missing tips files.

  // Check for referenced but missing hook scripts.
#ifdef HAVE_LIBLUA
  std::vector <std::string> missing_scripts;
  for (i = all.begin (); i != all.end (); ++i)
  {
    if (i->substr (0, 5) == "hook.")
    {
      std::string value = context.config.get (*i);
      Nibbler n (value);

      // <path>:<function> [, ...]
      while (!n.depleted ())
      {
        std::string file;
        std::string function;
        if (n.getUntil (':', file) &&
            n.skip (':')           &&
            n.getUntil (',', function))
        {
          Path script (file);
          if (!script.exists () || !script.readable ())
            missing_scripts.push_back (file);

          (void) n.skip (',');
        }
      }
    }
  }

  if (missing_scripts.size ())
  {
    out << STRING_CMD_SHOW_HOOKS << "\n";

    for (i = missing_scripts.begin (); i != missing_scripts.end (); ++i)
      out << "  " << *i << "\n";

    out << "\n";
  }
#endif

  // Check for bad values in rc.annotations.
  // TODO Deprecated.
  std::string annotations = context.config.get ("annotations");
  if (annotations != "full"   &&
      annotations != "sparse" &&
      annotations != "none")
    out << format (STRING_CMD_SHOW_CONFIG_ERROR, "annotations", annotations)
        << "\n";

  // Check for bad values in rc.calendar.details.
  std::string calendardetails = context.config.get ("calendar.details");
  if (calendardetails != "full"   &&
      calendardetails != "sparse" &&
      calendardetails != "none")
    out << format (STRING_CMD_SHOW_CONFIG_ERROR, "calendar.details", calendardetails)
        << "\n";

  // Check for bad values in rc.calendar.holidays.
  std::string calendarholidays = context.config.get ("calendar.holidays");
  if (calendarholidays != "full"   &&
      calendarholidays != "sparse" &&
      calendarholidays != "none")
    out << format (STRING_CMD_SHOW_CONFIG_ERROR, "calendar.holidays", calendarholidays)
        << "\n";

  // Check for bad values in rc.default.priority.
  std::string defaultPriority = context.config.get ("default.priority");
  if (defaultPriority != "H" &&
      defaultPriority != "M" &&
      defaultPriority != "L" &&
      defaultPriority != "")
    out << format (STRING_CMD_SHOW_CONFIG_ERROR, "default.priority", defaultPriority)
        << "\n";

  // Verify installation.  This is mentioned in the documentation as the way
  // to ensure everything is properly installed.

  if (all.size () == 0)
  {
    out << STRING_CMD_SHOW_EMPTY << "\n";
    rc = 1;
  }
  else
  {
    Directory location (context.config.get ("data.location"));

    if (location._data == "")
      out << STRING_CMD_SHOW_NO_LOCATION << "\n";

    if (! location.exists ())
      out << STRING_CMD_SHOW_LOC_EXIST << "\n";
  }

  output = out.str ();
  return rc;
}
예제 #18
0
bool Duration::parse (const std::string& input, std::string::size_type& start)
{
  std::string::size_type original_start = start;
  Nibbler n (input.substr (start));

  // Static and so preserved between calls.
  static std::vector <std::string> units;
  if (units.size () == 0)
    for (unsigned int i = 0; i < NUM_DURATIONS; i++)
      units.push_back (durations[i].unit);

  std::string number;
  std::string unit;

  if (n.getOneOf (units, unit))
  {
    if (n.depleted () ||
        Lexer::isWhitespace (n.next ()))
    {
      start = original_start + n.cursor ();

      // Linear lookup - should be logarithmic.
      for (unsigned int i = 0; i < NUM_DURATIONS; i++)
      {
        if (durations[i].unit == unit &&
            durations[i].standalone == true)
        {
          _secs = static_cast <int> (durations[i].seconds);
          return true;
        }
      }
    }
  }

  else if (n.getNumber (number))
  {
    n.skipWS ();
    if (n.getOneOf (units, unit))
    {
      if (n.depleted () ||
          Lexer::isWhitespace (n.next ()))
      {
        start = original_start + n.cursor ();
        double quantity = strtod (number.c_str (), NULL);

        // Linear lookup - should be logarithmic.
        double seconds = 1;
        for (unsigned int i = 0; i < NUM_DURATIONS; i++)
        {
          if (durations[i].unit == unit)
          {
            seconds = durations[i].seconds;
            _secs = static_cast <int> (quantity * static_cast <double> (seconds));
            return true;
          }
        }
      }
    }
  }

  return false;
}