mirror of https://github.com/ecmwf/eccodes.git
128 lines
4.0 KiB
C++
128 lines
4.0 KiB
C++
/*
|
|
* (C) Copyright 2005- ECMWF.
|
|
*
|
|
* This software is licensed under the terms of the Apache Licence Version 2.0
|
|
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
* In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
|
|
* virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <tuple>
|
|
#include <map>
|
|
#include <exception>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <unordered_map>
|
|
#include <cassert>
|
|
#include <sstream>
|
|
#include <optional>
|
|
|
|
#include "step_unit.h"
|
|
|
|
namespace eccodes {
|
|
class Step {
|
|
public:
|
|
// Constructors
|
|
Step() : internal_value_(0), internal_unit_(Unit::Value::SECOND) {}
|
|
|
|
Step(double value, const Unit& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);}
|
|
Step(double value, Unit::Value unit) {init_double(value, Unit{unit});}
|
|
Step(double value, long unit) {init_double(value, Unit{unit});}
|
|
Step(double value, const std::string& unit) {init_double(value, Unit{unit});}
|
|
|
|
Step(long value, const Unit& unit) { init_long(value, unit);}
|
|
Step(long value, Unit::Value unit) {init_long(value, Unit{unit});}
|
|
Step(long value, long unit) {init_long(value, Unit{unit});}
|
|
Step(long value, const std::string& unit) {init_long(value, Unit{unit});}
|
|
|
|
// Getters
|
|
template <typename T> T value() const;
|
|
template <typename T> T value(const Unit& unit) const;
|
|
template <typename T> T value(const std::string& format, bool show_hours) const;
|
|
Unit unit() const { return unit_; }
|
|
|
|
// Setters
|
|
Step& set_unit(const std::string& unit_name) {unit_ = Unit{unit_name}; return *this;}
|
|
Step& set_unit(long unit_code) {unit_ = Unit{unit_code}; return *this;}
|
|
Step& set_unit(const Unit& new_unit) {unit_ = new_unit; return *this;}
|
|
Step& set_unit(const Unit::Value new_unit) {unit_ = new_unit; return *this;}
|
|
|
|
// Operators
|
|
bool operator==(const Step& other) const;
|
|
bool operator!=(const Step& other) const;
|
|
Step operator+(const Step& step) const;
|
|
Step operator-(const Step& step) const;
|
|
bool operator>(const Step& step) const;
|
|
bool operator<(const Step& step) const;
|
|
Step copy() const {
|
|
Step ret{};
|
|
ret.internal_value_ = internal_value_;
|
|
ret.internal_unit_ = internal_unit_;
|
|
ret.unit_ = unit_;
|
|
return ret;
|
|
}
|
|
|
|
// Methods
|
|
Step& optimize_unit();
|
|
friend std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep);
|
|
|
|
|
|
private:
|
|
void init_long(long value, const Unit& unit);
|
|
void init_double(double value, const Unit& unit);
|
|
Step& recalculateValue() {
|
|
if (internal_value_ == 0) {
|
|
internal_unit_ = unit_;
|
|
return *this;
|
|
}
|
|
|
|
Seconds<long> seconds = to_seconds<long>(internal_value_, internal_unit_);
|
|
long multiplier = Unit::get_converter().unit_to_duration(unit_.value<Unit::Value>());
|
|
internal_value_ = seconds.count() / multiplier;
|
|
internal_unit_ = unit_;
|
|
|
|
return *this;
|
|
}
|
|
|
|
long internal_value_;
|
|
Unit internal_unit_;
|
|
Unit unit_;
|
|
};
|
|
|
|
|
|
Step step_from_string(const std::string& step, const Unit& force_unit);
|
|
std::vector<Step> parse_range(const std::string& range_str, const Unit& force_unit);
|
|
std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep);
|
|
|
|
|
|
template <typename T> T Step::value() const {
|
|
if (internal_value_ == 0) {
|
|
return 0;
|
|
}
|
|
if (internal_unit_ == unit_) {
|
|
return internal_value_;
|
|
}
|
|
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
|
|
T value = from_seconds<T>(seconds, unit_);
|
|
return value;
|
|
}
|
|
|
|
template <typename T> T Step::value(const Unit& unit) const {
|
|
if (internal_value_ == 0) {
|
|
return 0;
|
|
}
|
|
if (internal_unit_ == unit) {
|
|
return internal_value_;
|
|
}
|
|
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
|
|
T value = from_seconds<T>(seconds, unit);
|
|
return value;
|
|
}
|
|
|
|
} // namespace eccodes
|