24 namespace image { 
class locator; }
 
   25 using namespace std::chrono_literals;
 
   27 template<
typename T, 
typename D>
 
   31     using data_t = std::vector<std::pair<D, std::chrono::milliseconds>>;
 
   38     virtual const T 
get_current_element(
const std::chrono::milliseconds& current_time, T default_val) 
const = 0;
 
   42         return data_.size() <= 1;
 
   47         std::chrono::milliseconds total{0};
 
   48         for(
const auto& entry : data_) {
 
   49             total += entry.second;
 
   81     progressive_pair(
const std::string& input = 
"", 
const std::chrono::milliseconds& duration = std::chrono::milliseconds{0})
 
   88         const std::vector<std::string> comma_split = 
utils::split(input, 
',', split_flag);
 
   89         const auto time_chunk = std::max(1ms, duration / std::max<int>(comma_split.size(), 1));
 
   91         for(
const auto& entry : comma_split) {
 
   92             std::vector<std::string> colon_split = 
utils::split(entry, 
':', split_flag);
 
   96                 time = (colon_split.size() > 1) ? std::chrono::milliseconds{
std::stoi(colon_split[1])} : time_chunk;
 
   97             } 
catch(
const std::invalid_argument&) {
 
  102                 std::vector<std::string> range = 
utils::split(colon_split[0],
'~',split_flag);
 
  103                 T range0 = lexical_cast<T>(range[0]);
 
  104                 T range1 = (range.size() > 1) ? lexical_cast<T>(range[1]) : range0;
 
  106                 base_data.push_back({{range0, range1}, time});
 
  111     virtual const T 
get_current_element(
const std::chrono::milliseconds& current_time, T default_val = T())
 const override 
  114         const std::chrono::milliseconds& base_duration = progressive_pair_base_type::duration();
 
  116         if(base_data.empty()) {
 
  122         const std::chrono::milliseconds searched_time = std::clamp(current_time, 0ms, base_duration);
 
  124         while(time < searched_time && 
i < base_data.size()) {
 
  125             time += base_data[
i].second;
 
  131             time -= base_data[
i].second;
 
  134         const auto [first, second] = base_data[
i].first;
 
  135         using fractional_milliseconds = std::chrono::duration<double, std::milli>;
 
  138             fractional_milliseconds{searched_time - time} /
 
  139             fractional_milliseconds{base_data[
i].second}
 
  140         ) * (second - first) + first);
 
  146         return base_data.empty() || (base_data.size() == 1 && base_data[0].first.first == base_data[0].first.second);
 
  157     progressive_single(
const std::string& input = 
"", 
const std::chrono::milliseconds& duration = std::chrono::milliseconds{0})
 
  163         auto time_chunk = std::max(duration, 1ms);
 
  165         if(duration > 1ms && !first_pass.empty()) {
 
  167             auto total_specified_time = 0ms;
 
  169             for(
const std::string& fp_string : first_pass) {
 
  170                 std::vector<std::string> second_pass = 
utils::split(fp_string, 
':');
 
  171                 if(second_pass.size() > 1) {
 
  173                         total_specified_time += std::chrono::milliseconds{
std::stoi(second_pass[1])};
 
  174                     } 
catch(
const std::invalid_argument&) {
 
  182             std::chrono::milliseconds new_time_chunk{(duration - total_specified_time) / first_pass.size()};
 
  183             time_chunk = std::max(new_time_chunk, 1ms);
 
  186         for(
const std::string& fp_string : first_pass) {
 
  187             std::vector<std::string> second_pass = 
utils::split(fp_string, 
':');
 
  188             if(second_pass.size() > 1) {
 
  190                     std::chrono::milliseconds time{
std::stoi(second_pass[1])};
 
  191                     base_data.emplace_back(std::move(second_pass[0]), time);
 
  192                 } 
catch(
const std::invalid_argument&) {
 
  196                 base_data.emplace_back(std::move(second_pass[0]), time_chunk);
 
  201     virtual const T 
get_current_element(
const std::chrono::milliseconds& current_time, T default_val = T())
 const override 
  205         if(base_data.empty()) {
 
  212         while(time < current_time && 
i < base_data.size()) {
 
  213             time += base_data[
i].second;
 
  224         return base_data[
i].first;
 
const data_t & data() const
virtual ~progressive_base()
std::vector< std::pair< D, std::chrono::milliseconds > > data_t
progressive_base(const std::string &input)
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val) const =0
std::string get_original() const
virtual bool does_not_change() const
std::chrono::milliseconds duration() const
progressive_pair(const std::string &input="", const std::chrono::milliseconds &duration=std::chrono::milliseconds{0})
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val=T()) const override
bool does_not_change() const override
progressive_single(const std::string &input="", const std::chrono::milliseconds &duration=std::chrono::milliseconds{0})
virtual const T get_current_element(const std::chrono::milliseconds ¤t_time, T default_val=T()) const override
New lexcical_cast header.
Functions to load and save images from/to disk.
int stoi(std::string_view str)
Same interface as std::stoi and meant as a drop in replacement, except:
std::vector< std::string > square_parenthetical_split(const std::string &val, const char separator, const std::string &left, const std::string &right, const int flags)
Similar to parenthetical_split, but also expands embedded square brackets.
std::vector< std::string > split(const config_attribute_value &val)
Thrown when a lexical_cast fails.