Taskolib  1.3.3
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 <chrono>
30 #include <filesystem>
31 #include <functional>
32 #include <limits>
33 #include <string>
34 #include <utility>
35 #include <vector>
36 
37 #include <gul14/cat.h>
38 #include <gul14/finalizer.h>
39 #include <gul14/optional.h>
40 #include <gul14/string_view.h>
41 #include <gul14/traits.h>
42 
43 #include "taskolib/CommChannel.h"
44 #include "taskolib/Context.h"
45 #include "taskolib/exceptions.h"
46 #include "taskolib/SequenceName.h"
47 #include "taskolib/Step.h"
48 #include "taskolib/StepIndex.h"
49 #include "taskolib/Tag.h"
51 #include "taskolib/UniqueId.h"
52 
53 namespace task {
54 
159 class Sequence
160 {
161 public:
165  using Iterator = std::vector<Step>::iterator;
167  using ConstIterator = std::vector<Step>::const_iterator;
169  using ConstReverseIterator = std::vector<Step>::const_reverse_iterator;
170 
172  static constexpr std::size_t max_label_length = 128;
173 
187  Sequence(gul14::string_view label = "", SequenceName name = SequenceName{},
188  UniqueId uid = UniqueId{});
189 
198  void assign(ConstIterator iter, const Step& step);
199 
208  void assign(ConstIterator iter, Step&& step);
209 
216  ConstIterator begin() const noexcept { return steps_.cbegin(); }
217 
224  ConstIterator cbegin() const noexcept { return steps_.cbegin(); }
225 
232  ConstIterator cend() const noexcept { return steps_.cend(); }
233 
240  ConstReverseIterator crbegin() const noexcept { return steps_.crbegin(); }
241 
248  ConstReverseIterator crend() const noexcept { return steps_.crend(); }
249 
267  void check_syntax() const;
268 
270  bool empty() const noexcept { return steps_.empty(); }
271 
278  ConstIterator end() const noexcept { return steps_.cend(); }
279 
293 
325 
363  [[nodiscard]]
364  gul14::optional<Error> execute(Context& context, CommChannel* comm_channel,
365  OptionalStepIndex opt_step_index = gul14::nullopt);
366 
372  gul14::optional<Error> get_error() const { return error_; }
373 
381  std::filesystem::path get_folder() const;
382 
387  const std::string& get_indentation_error() const noexcept { return indentation_error_; }
388 
390  const std::string& get_label() const noexcept { return label_; }
391 
393  const std::string& get_maintainers() const noexcept { return maintainers_; }
394 
396  const SequenceName& get_name() const noexcept { return name_; }
397 
399  const std::string& get_step_setup_script() const noexcept { return step_setup_script_; }
400 
402  const std::vector<Tag>& get_tags() const noexcept { return tags_; }
403 
405  bool get_autorun() const noexcept { return autorun_; }
406 
408  bool is_disabled() const noexcept { return is_disabled_; }
409 
416  {
418  }
419 
422 
424  UniqueId get_unique_id() const noexcept { return unique_id_; }
425 
439  template <typename StepType, std::enable_if_t<
440  std::is_same<gul14::remove_cvref_t<StepType>, Step>::value, bool> = true>
441  ConstIterator insert(ConstIterator iter, StepType step)
442  {
444  throw_if_full();
445 
446  auto return_iter = steps_.insert(iter, std::forward<StepType>(step));
447 
449  [insert_idx = return_iter - cbegin()](StepIndex error_idx) -> OptionalStepIndex
450  {
451  if (insert_idx <= error_idx)
452  return error_idx + 1;
453  else
454  return error_idx;
455  });
456 
458  return return_iter;
459  }
460 
466  bool is_running() const noexcept { return is_running_; }
467 
469  bool is_timeout_elapsed() const { return timeout_trigger_.is_elapsed(); }
470 
472  static SizeType max_size() noexcept { return std::numeric_limits<StepIndex>::max(); }
473 
503  template <typename Closure>
504  void modify(ConstIterator iter, Closure modification_fct)
505  {
507 
508  // Construct a mutable iterator from the given ConstIterator
509  const auto it = steps_.begin() + (iter - steps_.cbegin());
510 
511  // Reindent at the end of the function, even if an exception is thrown
512  auto indent_if_necessary = gul14::finally(
513  [this,
514  it,
515  old_indentation_level = it->get_indentation_level(),
516  old_type = it->get_type(),
517  old_disabled = it->is_disabled()]()
518  {
519  if (it->get_type() != old_type
520  || it->get_indentation_level() != old_indentation_level)
521  {
522  indent();
523  }
524 
525  // Special treatment for re-enabling an entire block-with-continuation
526  // if its head step is re-enabled
527  if (it->is_disabled() == false && old_disabled == true)
528  {
529  if (it->get_type() == Step::type_if
530  || it->get_type() == Step::type_while
531  || it->get_type() == Step::type_try)
532  {
533  auto it_end = find_end_of_continuation(it);
534  std::for_each(it, it_end, [](Step& st) { st.set_disabled(false); });
535  }
536  }
537 
539  });
540 
541  modification_fct(*it);
542  }
543 
551  const Step& operator[](SizeType idx) const noexcept { return steps_[idx]; }
552 
561  void pop_back();
562 
571  void push_back(const Step& step);
572 
581  void push_back(Step&& step);
582 
589  ConstReverseIterator rbegin() const noexcept { return steps_.crbegin(); }
590 
597  ConstReverseIterator rend() const noexcept { return steps_.crend(); }
598 
613  void set_error(gul14::optional<Error> opt_error);
614 
627  void set_label(gul14::string_view label);
628 
640  void set_maintainers(gul14::string_view maintainers);
641 
647  void set_name(SequenceName name) { name_ = std::move(name); }
648 
656  void set_running(bool running) noexcept { is_running_ = running; }
657 
667  void set_step_setup_script(gul14::string_view step_setup_script);
668 
674  void set_tags(const std::vector<Tag>& tags);
675 
682  void set_autorun(bool autorun);
683 
685  void set_disabled(bool disabled = true);
686 
688  void set_timeout(Timeout timeout) { timeout_trigger_.set_timeout(timeout); }
689 
696  void set_unique_id(UniqueId uid) { unique_id_ = uid; }
697 
699  SizeType size() const noexcept { return static_cast<SizeType>(steps_.size()); }
700 
701 private:
706  gul14::optional<Error> error_;
707 
709  std::string indentation_error_;
710 
713  std::string label_;
714  std::string maintainers_;
715  std::string step_setup_script_;
716  std::vector<Tag> tags_;
717  bool autorun_{ false } ;
718  bool is_disabled_{ false };
719  std::vector<Step> steps_;
720 
721  bool is_running_{ false };
722 
724 
739  void check_syntax(ConstIterator begin, ConstIterator end) const;
740 
751  ConstIterator check_syntax_for_if(ConstIterator begin, ConstIterator end) const;
752 
762  ConstIterator check_syntax_for_try(ConstIterator begin, ConstIterator end) const;
763 
773  ConstIterator check_syntax_for_while(ConstIterator begin, ConstIterator end) const;
774 
784  void correct_error_index(
785  std::function<OptionalStepIndex(StepIndex err_idx)> get_new_index);
786 
799  void enforce_consistency_of_disabled_flags() noexcept;
800 
807  void enforce_invariants();
808 
821  Iterator
822  execute_else_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
823 
838  Iterator
839  execute_if_or_elseif_block(Iterator begin, Iterator end, Context& context,
840  CommChannel* comm);
841 
852  Iterator
853  execute_range(Iterator step_begin, Iterator step_end, Context& context,
854  CommChannel* comm);
855 
868  Iterator
869  execute_try_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
870 
883  Iterator
884  execute_while_block(Iterator begin, Iterator end, Context& context, CommChannel* comm);
885 
900  Iterator find_end_of_continuation(Iterator block_start);
901  ConstIterator find_end_of_continuation(ConstIterator block_start) const;
902 
917  [[nodiscard]]
918  gul14::optional<Error>
919  handle_execution(Context& context, CommChannel* comm_channel,
920  gul14::string_view exec_block_name,
921  std::function<void(Context&, CommChannel*)> runner);
922 
932  void indent();
933 
935  void throw_if_full() const;
936 
938  void throw_if_running() const;
939 
941  void throw_if_disabled() const;
942 
947  void throw_syntax_error_for_step(ConstIterator it, gul14::string_view msg) const;
948 };
949 
950 } // namespace task
951 
952 #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:44
A sequence of steps that can be modified and executed.
Definition: Sequence.h:160
gul14::optional< Error > execute(Context &context, CommChannel *comm_channel, OptionalStepIndex opt_step_index=gul14::nullopt)
Execute the sequence (or just one of its steps) within a given context.
Definition: Sequence.cc:338
const SequenceName & get_name() const noexcept
Return the machine-friendly name of the sequence.
Definition: Sequence.h:396
std::string step_setup_script_
Step setup script.
Definition: Sequence.h:715
ConstReverseIterator rbegin() const noexcept
Return a constant reverse iterator to the last Step in the container.
Definition: Sequence.h:589
const Step & operator[](SizeType idx) const noexcept
Access the step at a given index.
Definition: Sequence.h:551
Timeout get_timeout() const
Return the timeout duration for executing the sequence.
Definition: Sequence.h:421
void enforce_invariants()
Make sure that all class invariants are upheld.
Definition: Sequence.cc:283
std::string maintainers_
One or more maintainers.
Definition: Sequence.h:714
gul14::optional< Error > get_error() const
Return an optional Error object explaining why the sequence stopped prematurely.
Definition: Sequence.h:372
bool is_disabled() const noexcept
Return the disable flag. When set to true it will prohibit any execution.
Definition: Sequence.h:408
std::string indentation_error_
Empty if indentation is correct and complete, error message otherwise.
Definition: Sequence.h:709
void throw_if_full() const
Throw an Error if no further steps can be inserted into the sequence.
Definition: Sequence.cc:772
ConstReverseIterator rend() const noexcept
Return a constant reverse iterator pointing before the first Step in the container.
Definition: Sequence.h:597
UniqueId get_unique_id() const noexcept
Return the unique ID of the sequence.
Definition: Sequence.h:424
void set_running(bool running) noexcept
Set the sequence into the state "is running" (true) or "is not running" (false).
Definition: Sequence.h:656
void throw_if_running() const
When the sequence is executed it rejects with an Error exception.
Definition: Sequence.cc:778
bool is_running() const noexcept
Retrieve if the sequence is executed.
Definition: Sequence.h:466
ConstReverseIterator crbegin() const noexcept
Return a constant reverse iterator to the last Step in the container.
Definition: Sequence.h:240
TimeoutTrigger timeout_trigger_
Logic to check for elapsed sequence timeout.
Definition: Sequence.h:723
bool is_disabled_
Disabled sequence. Used for execution control.
Definition: Sequence.h:718
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:387
TimePoint get_time_of_last_execution() const
Determine when the sequence was last executed.
Definition: Sequence.h:415
SequenceName name_
Machine-readable name.
Definition: Sequence.h:712
StepIndex SizeType
Alias for step type.
Definition: Sequence.h:163
void modify(ConstIterator iter, Closure modification_fct)
Modify a step inside the sequence.
Definition: Sequence.h:504
const std::string & get_maintainers() const noexcept
Return a string listing the maintainer(s) of the sequence.
Definition: Sequence.h:393
bool autorun_
Flag for automatic execution.
Definition: Sequence.h:717
void set_timeout(Timeout timeout)
Set the timeout duration for executing the sequence.
Definition: Sequence.h:688
const std::string & get_step_setup_script() const noexcept
Return the step setup script.
Definition: Sequence.h:399
void set_unique_id(UniqueId uid)
Set the unique ID of the sequence.
Definition: Sequence.h:696
ConstReverseIterator crend() const noexcept
Return a constant reverse iterator pointing before the first Step in the container.
Definition: Sequence.h:248
const std::vector< Tag > & get_tags() const noexcept
Return the tags associated with this sequence in alphabetical order.
Definition: Sequence.h:402
bool empty() const noexcept
Determine whether the sequence contains no steps.
Definition: Sequence.h:270
std::vector< Tag > tags_
Tags for categorizing the sequence.
Definition: Sequence.h:716
static constexpr std::size_t max_label_length
Maximum number of bytes of a Sequence label.
Definition: Sequence.h:172
std::vector< Step >::const_reverse_iterator ConstReverseIterator
Alias for a constant reverse vector iterator.
Definition: Sequence.h:169
static SizeType max_size() noexcept
Return the maximum number of steps that a sequence can hold.
Definition: Sequence.h:472
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:223
std::vector< Step > steps_
Collection of steps.
Definition: Sequence.h:719
gul14::optional< Error > error_
An optional Error object describing why the Sequence stopped prematurely (if it has a value) or that ...
Definition: Sequence.h:706
ConstIterator end() const noexcept
Return a constant iterator pointing past the last Step in the container.
Definition: Sequence.h:278
UniqueId unique_id_
Unique ID.
Definition: Sequence.h:711
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:236
bool is_timeout_elapsed() const
Return true if the timeout is elapsed otherwise false.
Definition: Sequence.h:469
std::filesystem::path get_folder() const
Return the (relative) folder name associated with this sequence.
Definition: Sequence.cc:369
std::string label_
Human-readable sequence label.
Definition: Sequence.h:713
ConstIterator begin() const noexcept
Return a constant iterator to the first Step in the container.
Definition: Sequence.h:216
ConstIterator cend() const noexcept
Return a constant iterator pointing past the last Step in the container.
Definition: Sequence.h:232
Sequence(gul14::string_view label="", SequenceName name=SequenceName{}, UniqueId uid=UniqueId{})
Construct an empty sequence.
Definition: Sequence.cc:67
void set_name(SequenceName name)
Set the machine-friendly sequence name.
Definition: Sequence.h:647
const std::string & get_label() const noexcept
Return the human-readable sequence label.
Definition: Sequence.h:390
std::vector< Step >::iterator Iterator
Alias for a vector iterator.
Definition: Sequence.h:165
bool is_running_
Flag to determine if the sequence is running.
Definition: Sequence.h:721
ConstIterator cbegin() const noexcept
Return a constant iterator to the first Step in the container.
Definition: Sequence.h:224
void check_syntax() const
Validates if the Step 's token are correctly enclosed in a proper way.
Definition: Sequence.cc:92
ConstIterator erase(ConstIterator iter)
Remove a step from the sequence.
Definition: Sequence.cc:289
void assign(ConstIterator iter, const Step &step)
Assign a Step to the sequence entry at the given position.
Definition: Sequence.cc:76
SizeType size() const noexcept
Return the number of steps contained in this sequence.
Definition: Sequence.h:699
bool get_autorun() const noexcept
Return true if an automatic execution can be performed otherwise false.
Definition: Sequence.h:405
std::vector< Step >::const_iterator ConstIterator
Alias for a constant vector iterator.
Definition: Sequence.h:167
ConstIterator insert(ConstIterator iter, StepType step)
Insert the given Step into the sequence just before the specified iterator.
Definition: Sequence.h:441
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:40
Definition of the Error exception class.
Definition: VariableName.h:154
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
gul14::optional< StepIndex > OptionalStepIndex
An optional step index (gul14::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