Taskolib  1.4.4
Sequence.h
Go to the documentation of this file.
1 
23 // SPDX-License-Identifier: LGPL-2.1-or-later
24 
25 #ifndef TASKOLIB_SEQUENCE_H_
26 #define TASKOLIB_SEQUENCE_H_
27 
28 #include <algorithm>
29 #include <filesystem>
30 #include <functional>
31 #include <limits>
32 #include <optional>
33 #include <string_view>
34 #include <string>
35 #include <utility>
36 #include <vector>
37 
38 #include <gul17/cat.h>
39 #include <gul17/finalizer.h>
40 #include <gul17/traits.h>
41 
42 #include "taskolib/CommChannel.h"
43 #include "taskolib/Context.h"
44 #include "taskolib/exceptions.h"
45 #include "taskolib/SequenceName.h"
46 #include "taskolib/Step.h"
47 #include "taskolib/StepIndex.h"
48 #include "taskolib/Tag.h"
50 #include "taskolib/UniqueId.h"
51 
52 namespace task {
53 
158 class Sequence
159 {
160 public:
164  using Iterator = std::vector<Step>::iterator;
166  using ConstIterator = std::vector<Step>::const_iterator;
168  using ConstReverseIterator = std::vector<Step>::const_reverse_iterator;
169 
171  static constexpr std::size_t max_label_length = 128;
172 
186  Sequence(std::string_view label = "", SequenceName name = SequenceName{},
187  UniqueId uid = UniqueId{});
188 
197  void assign(ConstIterator iter, const Step& step);
198 
207  void assign(ConstIterator iter, Step&& step);
208 
215  ConstIterator begin() const noexcept { return steps_.cbegin(); }
216 
223  ConstIterator cbegin() const noexcept { return steps_.cbegin(); }
224 
231  ConstIterator cend() const noexcept { return steps_.cend(); }
232 
239  ConstReverseIterator crbegin() const noexcept { return steps_.crbegin(); }
240 
247  ConstReverseIterator crend() const noexcept { return steps_.crend(); }
248 
266  void check_syntax() const;
267 
269  bool empty() const noexcept { return steps_.empty(); }
270 
277  ConstIterator end() const noexcept { return steps_.cend(); }
278 
292 
324 
362  [[nodiscard]]
363  std::optional<Error> execute(Context& context, CommChannel* comm_channel,
364  OptionalStepIndex opt_step_index = std::nullopt);
365 
371  std::optional<Error> get_error() const { return error_; }
372 
380  std::filesystem::path get_folder() const;
381 
386  const std::string& get_indentation_error() const noexcept { return indentation_error_; }
387 
389  const std::string& get_label() const noexcept { return label_; }
390 
392  const std::string& get_maintainers() const noexcept { return maintainers_; }
393 
395  const SequenceName& get_name() const noexcept { return name_; }
396 
398  const std::string& get_step_setup_script() const noexcept { return step_setup_script_; }
399 
401  const std::vector<Tag>& get_tags() const noexcept { return tags_; }
402 
404  bool get_autorun() const noexcept { return autorun_; }
405 
407  bool is_disabled() const noexcept { return is_disabled_; }
408 
415  {
417  }
418 
421 
423  UniqueId get_unique_id() const noexcept { return unique_id_; }
424 
438  template <typename StepType, std::enable_if_t<
439  std::is_same<gul17::remove_cvref_t<StepType>, Step>::value, bool> = true>
440  ConstIterator insert(ConstIterator iter, StepType step)
441  {
443  throw_if_full();
444 
445  auto return_iter = steps_.insert(iter, std::forward<StepType>(step));
446 
448  [insert_idx = return_iter - cbegin()](StepIndex error_idx) -> OptionalStepIndex
449  {
450  if (insert_idx <= error_idx)
451  return error_idx + 1;
452  else
453  return error_idx;
454  });
455 
457  return return_iter;
458  }
459 
465  bool is_running() const noexcept { return is_running_; }
466 
468  bool is_timeout_elapsed() const { return timeout_trigger_.is_elapsed(); }
469 
471  static SizeType max_size() noexcept { return std::numeric_limits<StepIndex>::max(); }
472 
502  template <typename Closure>
503  void modify(ConstIterator iter, Closure modification_fct)
504  {
506 
507  // Construct a mutable iterator from the given ConstIterator
508  const auto it = steps_.begin() + (iter - steps_.cbegin());
509 
510  // Reindent at the end of the function, even if an exception is thrown
511  auto indent_if_necessary = gul17::finally(
512  [this,
513  it,
514  old_indentation_level = it->get_indentation_level(),
515  old_type = it->get_type(),
516  old_disabled = it->is_disabled()]()
517  {
518  if (it->get_type() != old_type
519  || it->get_indentation_level() != old_indentation_level)
520  {
521  indent();
522  }
523 
524  // Special treatment for re-enabling an entire block-with-continuation
525  // if its head step is re-enabled
526  if (it->is_disabled() == false && old_disabled == true)
527  {
528  if (it->get_type() == Step::type_if
529  || it->get_type() == Step::type_while
530  || it->get_type() == Step::type_try)
531  {
532  auto it_end = find_end_of_continuation(it);
533  std::for_each(it, it_end, [](Step& st) { st.set_disabled(false); });
534  }
535  }
536 
538  });
539 
540  modification_fct(*it);
541  }
542 
550  const Step& operator[](SizeType idx) const noexcept { return steps_[idx]; }
551 
560  void pop_back();
561 
570  void push_back(const Step& step);
571 
580  void push_back(Step&& step);
581 
588  ConstReverseIterator rbegin() const noexcept { return steps_.crbegin(); }
589 
596  ConstReverseIterator rend() const noexcept { return steps_.crend(); }
597 
612  void set_error(std::optional<Error> opt_error);
613 
626  void set_label(std::string_view label);
627 
639  void set_maintainers(std::string_view maintainers);
640 
646  void set_name(SequenceName name) { name_ = std::move(name); }
647 
655  void set_running(bool running) noexcept { is_running_ = running; }
656 
666  void set_step_setup_script(std::string_view step_setup_script);
667 
673  void set_tags(const std::vector<Tag>& tags);
674 
681  void set_autorun(bool autorun);
682 
684  void set_disabled(bool disabled = true);
685 
687  void set_timeout(Timeout timeout) { timeout_trigger_.set_timeout(timeout); }
688 
695  void set_unique_id(UniqueId uid) { unique_id_ = uid; }
696 
698  SizeType size() const noexcept { return static_cast<SizeType>(steps_.size()); }
699 
700 private:
705  std::optional<Error> error_;
706 
708  std::string indentation_error_;
709 
712  std::string label_;
713  std::string maintainers_;
714  std::string step_setup_script_;
715  std::vector<Tag> tags_;
716  bool autorun_{ false } ;
717  bool is_disabled_{ false };
718  std::vector<Step> steps_;
719 
720  bool is_running_{ false };
721 
723 
738  void check_syntax(ConstIterator begin, ConstIterator end) const;
739 
750  ConstIterator check_syntax_for_if(ConstIterator begin, ConstIterator end) const;
751 
761  ConstIterator check_syntax_for_try(ConstIterator begin, ConstIterator end) const;
762 
772  ConstIterator check_syntax_for_while(ConstIterator begin, ConstIterator end) const;
773 
783  void correct_error_index(
784  std::function<OptionalStepIndex(StepIndex err_idx)> get_new_index);
785 
798  void enforce_consistency_of_disabled_flags() noexcept;
799 
806  void enforce_invariants();
807 
820  Iterator
821  execute_else_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
822 
837  Iterator
838  execute_if_or_elseif_block(Iterator begin, Iterator end, Context& context,
839  CommChannel* comm);
840 
851  Iterator
852  execute_range(Iterator step_begin, Iterator step_end, Context& context,
853  CommChannel* comm);
854 
867  Iterator
868  execute_try_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
869 
882  Iterator
883  execute_while_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
884 
899  Iterator find_end_of_continuation(Iterator block_start);
900  ConstIterator find_end_of_continuation(ConstIterator block_start) const;
901 
916  [[nodiscard]]
917  std::optional<Error>
918  handle_execution(Context& context, CommChannel* comm_channel,
919  std::string_view exec_block_name,
920  std::function<void(Context&, CommChannel*)> runner);
921 
931  void indent();
932 
934  void throw_if_full() const;
935 
937  void throw_if_running() const;
938 
940  void throw_if_disabled() const;
941 
946  void throw_syntax_error_for_step(ConstIterator it, std::string_view msg) const;
947 };
948 
949 } // namespace task
950 
951 #endif
Declaration of the CommChannel struct.
Declaration of the Context and VariableValue types.
Declaration of the SequenceName class.
Declaration of the StepIndex type.
Declaration of the Step class.
Declaration of the Tag class.
Logic to check if a timeout elapsed.
Declaration of the UniqueId class.
An exception class carrying an error message and, optionally, the index of the step in which the erro...
Definition: exceptions.h:73
The machine-readable name of a Sequence.
Definition: SequenceName.h:43
A sequence of steps that can be modified and executed.
Definition: Sequence.h:159
const SequenceName & get_name() const noexcept
Return the machine-friendly name of the sequence.
Definition: Sequence.h:395
std::string step_setup_script_
Step setup script.
Definition: Sequence.h:714
ConstReverseIterator rbegin() const noexcept
Return a constant reverse iterator to the last Step in the container.
Definition: Sequence.h:588
std::optional< Error > get_error() const
Return an optional Error object explaining why the sequence stopped prematurely.
Definition: Sequence.h:371
const Step & operator[](SizeType idx) const noexcept
Access the step at a given index.
Definition: Sequence.h:550
Timeout get_timeout() const
Return the timeout duration for executing the sequence.
Definition: Sequence.h:420
void enforce_invariants()
Make sure that all class invariants are upheld.
Definition: Sequence.cc:282
std::string maintainers_
One or more maintainers.
Definition: Sequence.h:713
bool is_disabled() const noexcept
Return the disable flag. When set to true it will prohibit any execution.
Definition: Sequence.h:407
std::string indentation_error_
Empty if indentation is correct and complete, error message otherwise.
Definition: Sequence.h:708
std::optional< Error > execute(Context &context, CommChannel *comm_channel, OptionalStepIndex opt_step_index=std::nullopt)
Execute the sequence (or just one of its steps) within a given context.
Definition: Sequence.cc:337
void throw_if_full() const
Throw an Error if no further steps can be inserted into the sequence.
Definition: Sequence.cc:771
ConstReverseIterator rend() const noexcept
Return a constant reverse iterator pointing before the first Step in the container.
Definition: Sequence.h:596
UniqueId get_unique_id() const noexcept
Return the unique ID of the sequence.
Definition: Sequence.h:423
void set_running(bool running) noexcept
Set the sequence into the state "is running" (true) or "is not running" (false).
Definition: Sequence.h:655
void throw_if_running() const
When the sequence is executed it rejects with an Error exception.
Definition: Sequence.cc:777
Sequence(std::string_view label="", SequenceName name=SequenceName{}, UniqueId uid=UniqueId{})
Construct an empty sequence.
Definition: Sequence.cc:68
bool is_running() const noexcept
Retrieve if the sequence is executed.
Definition: Sequence.h:465
ConstReverseIterator crbegin() const noexcept
Return a constant reverse iterator to the last Step in the container.
Definition: Sequence.h:239
TimeoutTrigger timeout_trigger_
Logic to check for elapsed sequence timeout.
Definition: Sequence.h:722
bool is_disabled_
Disabled sequence. Used for execution control.
Definition: Sequence.h:717
const std::string & get_indentation_error() const noexcept
Return an error string if the sequence is not consistently nested, or an empty string if the nesting ...
Definition: Sequence.h:386
TimePoint get_time_of_last_execution() const
Determine when the sequence was last executed.
Definition: Sequence.h:414
SequenceName name_
Machine-readable name.
Definition: Sequence.h:711
StepIndex SizeType
Alias for step type.
Definition: Sequence.h:162
void modify(ConstIterator iter, Closure modification_fct)
Modify a step inside the sequence.
Definition: Sequence.h:503
const std::string & get_maintainers() const noexcept
Return a string listing the maintainer(s) of the sequence.
Definition: Sequence.h:392
bool autorun_
Flag for automatic execution.
Definition: Sequence.h:716
void set_timeout(Timeout timeout)
Set the timeout duration for executing the sequence.
Definition: Sequence.h:687
const std::string & get_step_setup_script() const noexcept
Return the step setup script.
Definition: Sequence.h:398
void set_unique_id(UniqueId uid)
Set the unique ID of the sequence.
Definition: Sequence.h:695
ConstReverseIterator crend() const noexcept
Return a constant reverse iterator pointing before the first Step in the container.
Definition: Sequence.h:247
const std::vector< Tag > & get_tags() const noexcept
Return the tags associated with this sequence in alphabetical order.
Definition: Sequence.h:401
bool empty() const noexcept
Determine whether the sequence contains no steps.
Definition: Sequence.h:269
std::vector< Tag > tags_
Tags for categorizing the sequence.
Definition: Sequence.h:715
static constexpr std::size_t max_label_length
Maximum number of bytes of a Sequence label.
Definition: Sequence.h:171
std::vector< Step >::const_reverse_iterator ConstReverseIterator
Alias for a constant reverse vector iterator.
Definition: Sequence.h:168
static SizeType max_size() noexcept
Return the maximum number of steps that a sequence can hold.
Definition: Sequence.h:471
void correct_error_index(std::function< OptionalStepIndex(StepIndex err_idx)> get_new_index)
If the sequence has a stored error with step index information, call the given function and replace t...
Definition: Sequence.cc:222
std::vector< Step > steps_
Collection of steps.
Definition: Sequence.h:718
ConstIterator end() const noexcept
Return a constant iterator pointing past the last Step in the container.
Definition: Sequence.h:277
UniqueId unique_id_
Unique ID.
Definition: Sequence.h:710
void enforce_consistency_of_disabled_flags() noexcept
Update the disabled flag of all steps to ensure that control structures are not partially disabled.
Definition: Sequence.cc:235
bool is_timeout_elapsed() const
Return true if the timeout is elapsed otherwise false.
Definition: Sequence.h:468
std::filesystem::path get_folder() const
Return the (relative) folder name associated with this sequence.
Definition: Sequence.cc:368
std::string label_
Human-readable sequence label.
Definition: Sequence.h:712
ConstIterator begin() const noexcept
Return a constant iterator to the first Step in the container.
Definition: Sequence.h:215
ConstIterator cend() const noexcept
Return a constant iterator pointing past the last Step in the container.
Definition: Sequence.h:231
void set_name(SequenceName name)
Set the machine-friendly sequence name.
Definition: Sequence.h:646
const std::string & get_label() const noexcept
Return the human-readable sequence label.
Definition: Sequence.h:389
std::vector< Step >::iterator Iterator
Alias for a vector iterator.
Definition: Sequence.h:164
bool is_running_
Flag to determine if the sequence is running.
Definition: Sequence.h:720
ConstIterator cbegin() const noexcept
Return a constant iterator to the first Step in the container.
Definition: Sequence.h:223
void check_syntax() const
Validates if the Step 's token are correctly enclosed in a proper way.
Definition: Sequence.cc:91
ConstIterator erase(ConstIterator iter)
Remove a step from the sequence.
Definition: Sequence.cc:288
void assign(ConstIterator iter, const Step &step)
Assign a Step to the sequence entry at the given position.
Definition: Sequence.cc:75
SizeType size() const noexcept
Return the number of steps contained in this sequence.
Definition: Sequence.h:698
bool get_autorun() const noexcept
Return true if an automatic execution can be performed otherwise false.
Definition: Sequence.h:404
std::optional< Error > error_
An optional Error object describing why the Sequence stopped prematurely (if it has a value) or that ...
Definition: Sequence.h:705
std::vector< Step >::const_iterator ConstIterator
Alias for a constant vector iterator.
Definition: Sequence.h:166
ConstIterator insert(ConstIterator iter, StepType step)
Insert the given Step into the sequence just before the specified iterator.
Definition: Sequence.h:440
A step is the main building block of a sequence.
Definition: Step.h:53
Evaluates when the clock is elapsed.
Definition: TimeoutTrigger.h:49
const Timeout get_timeout() const
Get the timeout duration.
Definition: TimeoutTrigger.h:68
bool is_elapsed() const
Evaluates if a timeout elapsed.
Definition: TimeoutTrigger.h:92
TimePoint get_start_time() const
Get start time.
Definition: TimeoutTrigger.h:83
A type for storing a timeout duration.
Definition: Timeout.h:72
An unsigned 64-bit integer for use as a unique ID.
Definition: UniqueId.h:39
Definition of the Error exception class.
Definition: VariableName.h:156
Namespace task contains all Taskolib functions and classes.
Definition: CommChannel.h:33
std::uint16_t StepIndex
A type for storing the index of a Step in a Sequence.
Definition: StepIndex.h:34
std::optional< StepIndex > OptionalStepIndex
An optional step index (std::optional<StepIndex>).
Definition: StepIndex.h:37
std::chrono::time_point< Clock > TimePoint
Definition: time_types.h:34
A struct combining a message queue and several atomic flags.
Definition: CommChannel.h:43
A context stores information that influences the execution of steps and sequences,...
Definition: Context.h:128