diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4a544127..76c2d912 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ set (timew_SRCS CLI.cpp CLI.h Exclusion.cpp Exclusion.h Extensions.cpp Extensions.h Interval.cpp Interval.h + IntervalFactory.cpp IntervalFactory.h Range.cpp Range.h Rules.cpp Rules.h TagInfo.cpp TagInfo.h diff --git a/src/Interval.cpp b/src/Interval.cpp index 66f034d5..9a2de943 100644 --- a/src/Interval.cpp +++ b/src/Interval.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2015 - 2016, Paul Beckingham, Federico Hernandez. +// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -32,56 +32,6 @@ #include #include -//////////////////////////////////////////////////////////////////////////////// -// Syntax: -// 'inc' [ [ '-' ]] [ '#' [ ... ]] -void Interval::initialize (const std::string& line) -{ - Lexer lexer (line); - std::vector tokens; - std::string token; - Lexer::Type type; - while (lexer.token (token, type)) - tokens.push_back (Lexer::dequote (token)); - - // Minimal requirement 'inc'. - if (!tokens.empty () && - tokens[0] == "inc") - { - unsigned int offset = 0; - - // Optional - if (tokens.size () > 1 && - tokens[1].length () == 16) - { - start = Datetime (tokens[1]); - offset = 1; - - // Optional '-' - if (tokens.size () > 3 && - tokens[2] == "-" && - tokens[3].length () == 16) - { - end = Datetime (tokens[3]); - offset = 3; - } - } - - // Optional '#' - if (tokens.size () > 2 + offset && - tokens[1 + offset] == "#") - { - // Optional ... - for (unsigned int i = 2 + offset; i < tokens.size (); ++i) - _tags.insert (tokens[i]); - } - - return; - } - - throw format ("Unrecognizable line '{1}'.", line); -} - //////////////////////////////////////////////////////////////////////////////// bool Interval::empty () const { @@ -218,32 +168,5 @@ void Interval::setRange (const Datetime& start, const Datetime& end) this->end = end; } -Interval Interval::fromJson (std::string jsonString) -{ - Interval interval = Interval (); - - if (!jsonString.empty ()) - { - auto* json = (json::object*) json::parse (jsonString); - - json::array* tags = (json::array*) json->_data["tags"]; - - if (tags != nullptr) - { - for (auto& tag : tags->_data) - { - auto* value = (json::string*) tag; - interval.tag(value->_data); - } - } - - json::string* start = (json::string*) json->_data["start"]; - interval.start = Datetime(start->_data); - json::string* end = (json::string*) json->_data["end"]; - interval.end = (end != nullptr) ? Datetime(end->_data) : 0; - } - - return interval; -} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Interval.h b/src/Interval.h index ed5c499c..4218129d 100644 --- a/src/Interval.h +++ b/src/Interval.h @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2015 - 2016, Paul Beckingham, Federico Hernandez. +// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,6 @@ class Interval : public Range { public: Interval () = default; - void initialize (const std::string&); bool empty () const; bool hasTag (const std::string&) const; @@ -50,8 +49,6 @@ public: std::string json () const; std::string dump () const; - static Interval fromJson (std::string json); - public: int id {0}; bool synthetic {false}; diff --git a/src/IntervalFactory.cpp b/src/IntervalFactory.cpp new file mode 100644 index 00000000..d85a3df9 --- /dev/null +++ b/src/IntervalFactory.cpp @@ -0,0 +1,116 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// https://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////// +// Syntax: +// 'inc' [ [ '-' ]] [ '#' [ ... ]] +Interval IntervalFactory::fromSerialization (const std::string &line) +{ + Lexer lexer (line); + std::vector tokens; + std::string token; + Lexer::Type type; + + while (lexer.token (token, type)) + { + tokens.push_back (Lexer::dequote (token)); + } + + // Minimal requirement 'inc'. + if (!tokens.empty () && + tokens[0] == "inc") + { + Interval interval = Interval (); + + unsigned int offset = 0; + + // Optional + if (tokens.size () > 1 && + tokens[1].length () == 16) + { + interval.start = Datetime (tokens[1]); + offset = 1; + + // Optional '-' + if (tokens.size () > 3 && + tokens[2] == "-" && + tokens[3].length () == 16) + { + interval.end = Datetime (tokens[3]); + offset = 3; + } + } + + // Optional '#' + if (tokens.size () > 2 + offset && + tokens[1 + offset] == "#") + { + // Optional ... + for (unsigned int i = 2 + offset; i < tokens.size (); ++i) + interval.tag (tokens[i]); + } + + return interval; + } + + throw format ("Unrecognizable line '{1}'.", line); +} + +//////////////////////////////////////////////////////////////////////////////// +Interval IntervalFactory::fromJson (std::string jsonString) +{ + Interval interval = Interval (); + + if (!jsonString.empty ()) + { + auto* json = (json::object*) json::parse (jsonString); + + json::array* tags = (json::array*) json->_data["tags"]; + + if (tags != nullptr) + { + for (auto& tag : tags->_data) + { + auto* value = (json::string*) tag; + interval.tag(value->_data); + } + } + + json::string* start = (json::string*) json->_data["start"]; + interval.start = Datetime(start->_data); + json::string* end = (json::string*) json->_data["end"]; + interval.end = (end != nullptr) ? Datetime(end->_data) : 0; + } + + return interval; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/IntervalFactory.h b/src/IntervalFactory.h new file mode 100644 index 00000000..efa2e231 --- /dev/null +++ b/src/IntervalFactory.h @@ -0,0 +1,40 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// https://www.opensource.org/licenses/mit-license.php +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDED_INTERVALFACTORY +#define INCLUDED_INTERVALFACTORY + +#include +#include + +class IntervalFactory +{ +public: + static Interval fromSerialization (const std::string &line); + static Interval fromJson (std::string jsonString); +}; + +#endif diff --git a/src/commands/CmdUndo.cpp b/src/commands/CmdUndo.cpp index 07634c86..f99130a1 100644 --- a/src/commands/CmdUndo.cpp +++ b/src/commands/CmdUndo.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. +// Copyright 2016, 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,11 +28,12 @@ #include #include #include +#include static void undoIntervalAction(UndoAction& action, Database& database) { - Interval before = Interval::fromJson (action.getBefore ()); - Interval after = Interval::fromJson (action.getAfter ()); + Interval before = IntervalFactory::fromJson (action.getBefore ()); + Interval after = IntervalFactory::fromJson (action.getAfter ()); database.modifyInterval (after, before, false); } diff --git a/src/data.cpp b/src/data.cpp index 223b1234..064e63bc 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2015 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. +// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -32,6 +32,7 @@ #include #include #include +#include "IntervalFactory.h" //////////////////////////////////////////////////////////////////////////////// // A filter is just another interval, containing start, end and tags. @@ -316,8 +317,7 @@ std::vector getAllInclusions (Database& database) std::vector all; for (auto& line : database.allLines ()) { - Interval i; - i.initialize (line); + Interval i = IntervalFactory::fromSerialization (line); all.push_back (i); } @@ -675,14 +675,14 @@ Interval getLatestInterval (Database& database) // ^ 20 if (line.find (" - ") != 20) { - i.initialize (line); + i = IntervalFactory::fromSerialization (line); return i; } } auto lastLine = database.lastLine (); if (! lastLine.empty ()) - i.initialize (lastLine); + i = IntervalFactory::fromSerialization (lastLine); return i; } diff --git a/test/data.t.cpp b/test/data.t.cpp index 4e007bc9..c3f531c2 100644 --- a/test/data.t.cpp +++ b/test/data.t.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2015 - 2018, Paul Beckingham, Federico Hernandez. +// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ #include #include +#include //////////////////////////////////////////////////////////////////////////////// void test_flatten ( @@ -36,7 +37,7 @@ void test_flatten ( const std::vector & output) { Interval i; - i.initialize (input); + i = IntervalFactory::fromSerialization (input); auto results = flatten (i, exclusions); @@ -44,7 +45,7 @@ void test_flatten ( for (unsigned int i = 0; i < std::min (output.size (), results.size ()); ++i) { Interval tmp; - tmp.initialize (output[i]); + tmp = IntervalFactory::fromSerialization (output[i]); t.is (tmp.start.toISO (), results[i].start.toISO (), "flatten: " + label + " start matches"); t.is (tmp.end.toISO (), results[i].end.toISO (), "flatten: " + label + " end matches"); diff --git a/test/interval.t.cpp b/test/interval.t.cpp index 77153dcc..e4b8d26f 100644 --- a/test/interval.t.cpp +++ b/test/interval.t.cpp @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// Copyright 2015 - 2018, Paul Beckingham, Federico Hernandez. +// Copyright 2016 - 2018, Thomas Lauf, Paul Beckingham, Federico Hernandez. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,7 @@ #include #include +#include #include //////////////////////////////////////////////////////////////////////////////// @@ -82,83 +83,83 @@ int main (int, char**) // Round-trip parsing. Interval i4; - i4.initialize ( "inc"); + i4 = IntervalFactory::fromSerialization ("inc"); t.is (i4.serialize (), "inc", "Round-trip 'inc'"); Interval i5; - i5.initialize ( "inc # foo"); + i5 = IntervalFactory::fromSerialization ("inc # foo"); t.is (i5.serialize (), "inc # foo", "Round-trip 'inc # foo'"); Interval i6; - i6.initialize ( "inc # bar foo"); + i6 = IntervalFactory::fromSerialization ("inc # bar foo"); t.is (i6.serialize (), "inc # bar foo", "Round-trip 'inc # bar foo'"); Interval i7; - i7.initialize ( "inc 19700101T000001Z"); + i7 = IntervalFactory::fromSerialization ("inc 19700101T000001Z"); t.is (i7.serialize (), "inc 19700101T000001Z", "Round-trip 'inc 19700101T000001Z'"); Interval i8; - i8.initialize ( "inc 19700101T000001Z - 19700101T000002Z"); + i8 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z"); t.is (i8.serialize (), "inc 19700101T000001Z - 19700101T000002Z", "Round-trip 'inc 19700101T000001Z - 19700101T000002Z'"); Interval i9; - i9.initialize ( "inc 19700101T000001Z # bar foo"); + i9 = IntervalFactory::fromSerialization ("inc 19700101T000001Z # bar foo"); t.is (i9.serialize (), "inc 19700101T000001Z # bar foo", "Round-trip 'inc 19700101T000001Z # bar foo'"); Interval i10; - i10.initialize ( "inc 19700101T000001Z - 19700101T000002Z # bar foo"); + i10 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo"); t.is (i10.serialize (), "inc 19700101T000001Z - 19700101T000002Z # bar foo", "Round-trip 'inc 19700101T000001Z - 19700101T000002Z # bar foo'"); Interval i11; - i11.initialize ( "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo"); + i11 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo"); t.is (i11.serialize (), "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo", "Round-trip 'inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo'"); // std::string json () const; Interval i12; - i12.initialize ( "inc"); + i12 = IntervalFactory::fromSerialization ("inc"); t.is (i12.json (), "{}", "JSON '{}'"); Interval i13; - i13.initialize ( "inc # foo"); + i13 = IntervalFactory::fromSerialization ("inc # foo"); t.is (i13.json (), "{\"tags\":[\"foo\"]}", "JSON '{\"tags\":[\"foo\"]}'"); Interval i14; - i14.initialize ( "inc # bar foo"); + i14 = IntervalFactory::fromSerialization ("inc # bar foo"); t.is (i14.json (), "{\"tags\":[\"bar\",\"foo\"]}", "JSON '{\"tags\":[\"bar\",\"foo\"]}'"); Interval i15; - i15.initialize ( "inc 19700101T000001Z"); + i15 = IntervalFactory::fromSerialization ("inc 19700101T000001Z"); t.is (i15.json (), "{\"start\":\"19700101T000001Z\"}", "JSON '{\"start\":\"19700101T000001Z\"}'"); Interval i16; - i16.initialize ( "inc 19700101T000001Z - 19700101T000002Z"); + i16 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z"); t.is (i16.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}", "JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}'"); Interval i17; - i17.initialize ( "inc 19700101T000001Z # bar foo"); + i17 = IntervalFactory::fromSerialization ("inc 19700101T000001Z # bar foo"); t.is (i17.json (), "{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}", "JSON '{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}'"); Interval i18; - i18.initialize ( "inc 19700101T000001Z - 19700101T000002Z # bar foo"); + i18 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo"); t.is (i18.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}", "JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}'"); Interval i19; - i19.initialize ( "inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo"); + i19 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo"); t.is (i19.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}", "JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}'");