lnav/src/relative_time.hh

264 lines
6.3 KiB
C++
Raw Normal View History

2015-09-14 17:56:42 +02:00
/**
* Copyright (c) 2015, Timothy Stack
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of Timothy Stack nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2022-03-16 23:38:08 +01:00
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2015-09-14 17:56:42 +02:00
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LNAV_RELATIVE_TIME_HH
#define LNAV_RELATIVE_TIME_HH
#include <sys/time.h>
2015-12-19 15:13:12 +01:00
#define __STDC_FORMAT_MACROS
2020-09-12 08:10:11 +02:00
#include <array>
#include <chrono>
2022-03-16 23:38:08 +01:00
#include <set>
2015-09-14 17:56:42 +02:00
#include <string>
2022-03-16 23:38:08 +01:00
#include <inttypes.h>
#include "base/intern_string.hh"
#include "base/result.h"
2022-03-16 23:38:08 +01:00
#include "ptimec.hh"
2015-09-14 17:56:42 +02:00
class relative_time {
public:
enum token_t {
RTT_INVALID = -1,
RTT_WHITE,
RTT_AM,
RTT_PM,
RTT_A,
RTT_AN,
RTT_AT,
2015-09-14 17:56:42 +02:00
RTT_TIME,
RTT_NUMBER,
RTT_SUNDAY,
RTT_MONDAY,
RTT_TUESDAY,
RTT_WEDNESDAY,
RTT_THURSDAY,
RTT_FRIDAY,
RTT_SATURDAY,
2015-09-14 17:56:42 +02:00
RTT_MICROS,
RTT_MILLIS,
RTT_SECONDS,
RTT_MINUTES,
RTT_HOURS,
RTT_DAYS,
RTT_WEEKS,
RTT_MONTHS,
RTT_YEARS,
RTT_TODAY,
RTT_YESTERDAY,
RTT_TOMORROW,
RTT_NOON,
RTT_AND,
2018-08-12 17:37:16 +02:00
RTT_THE,
2015-09-14 17:56:42 +02:00
RTT_AGO,
RTT_LATER,
RTT_BEFORE,
2018-08-12 17:37:16 +02:00
RTT_AFTER,
2015-12-06 05:38:21 +01:00
RTT_NOW,
RTT_HERE,
2018-08-12 17:37:16 +02:00
RTT_NEXT,
RTT_PREVIOUS,
2015-09-14 17:56:42 +02:00
RTT__MAX
};
enum rt_field_type {
RTF_MICROSECONDS,
RTF_SECONDS,
RTF_MINUTES,
RTF_HOURS,
RTF_DAYS,
RTF_MONTHS,
RTF_YEARS,
RTF__MAX
};
struct parse_error {
int pe_column;
std::string pe_msg;
};
static Result<relative_time, parse_error> from_str(string_fragment str);
static relative_time from_timeval(const struct timeval& tv);
static relative_time from_usecs(std::chrono::microseconds usecs);
relative_time() { this->clear(); }
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
void clear()
{
2020-09-12 08:10:11 +02:00
this->rt_field.fill({});
2018-08-12 17:37:16 +02:00
this->rt_next = false;
this->rt_previous = false;
this->rt_absolute_field_end = 0;
}
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
void negate()
{
if (this->is_absolute()) {
2018-08-12 17:37:16 +02:00
if (this->rt_next) {
this->rt_next = false;
this->rt_previous = true;
} else if (this->rt_previous) {
this->rt_next = true;
this->rt_previous = false;
}
return;
}
2015-09-14 17:56:42 +02:00
for (int lpc = 0; lpc < RTF__MAX; lpc++) {
2018-08-12 17:37:16 +02:00
if (this->rt_field[lpc].value != 0) {
this->rt_field[lpc].value = -this->rt_field[lpc].value;
2015-09-14 17:56:42 +02:00
}
}
}
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
bool is_negative() const
{
2018-08-12 17:37:16 +02:00
if (this->rt_previous) {
return true;
}
for (const auto& rtf : this->rt_field) {
2018-08-12 17:37:16 +02:00
if (rtf.value < 0) {
2015-09-14 17:56:42 +02:00
return true;
}
}
return false;
}
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
bool is_absolute() const
{
return !this->rt_included_days.empty()
|| this->rt_absolute_field_end > 0;
}
2022-03-16 23:38:08 +01:00
bool is_absolute(rt_field_type rft) const
{
return rft < this->rt_absolute_field_end;
}
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
bool is_relative() const
{
return !this->is_absolute() || this->rt_next || this->rt_previous;
2018-08-12 17:37:16 +02:00
}
2022-03-16 23:38:08 +01:00
bool empty() const
{
if (!this->rt_included_days.empty()) {
return false;
}
for (const auto& rtf : this->rt_field) {
2018-08-12 17:37:16 +02:00
if (rtf.is_set) {
2015-09-14 17:56:42 +02:00
return false;
}
}
return true;
}
2015-09-14 17:56:42 +02:00
2022-03-16 23:38:08 +01:00
struct exttm adjust_now() const
{
struct exttm tm;
time_t now;
time(&now);
tm.et_tm = *gmtime(&now);
return this->adjust(tm);
}
2022-03-16 23:38:08 +01:00
struct exttm adjust(const struct timeval& tv) const
{
struct exttm tm;
tm.et_tm = *gmtime(&tv.tv_sec);
tm.et_nsec = tv.tv_usec * 1000;
return this->adjust(tm);
}
2022-03-16 23:38:08 +01:00
struct exttm adjust(const struct exttm& tm) const;
2022-03-16 23:38:08 +01:00
nonstd::optional<exttm> window_start(const struct exttm& tm) const;
2015-09-14 17:56:42 +02:00
int64_t to_microseconds() const;
2015-10-03 23:58:01 +02:00
2022-03-16 23:38:08 +01:00
void to_timeval(struct timeval& tv_out) const
{
2015-10-03 23:58:01 +02:00
int64_t us = this->to_microseconds();
tv_out.tv_sec = us / (1000 * 1000);
tv_out.tv_usec = us % (1000 * 1000);
}
2015-10-03 23:58:01 +02:00
2022-03-16 23:38:08 +01:00
struct timeval to_timeval() const
{
int64_t us = this->to_microseconds();
struct timeval retval;
retval.tv_sec = us / (1000 * 1000);
retval.tv_usec = us % (1000 * 1000);
return retval;
}
std::string to_string() const;
2015-09-14 17:56:42 +02:00
void rollover();
2018-08-12 17:37:16 +02:00
static const char FIELD_CHARS[RTF__MAX];
struct _rt_field {
_rt_field(int64_t value) : value(value), is_set(true) {}
2018-08-12 17:37:16 +02:00
_rt_field() : value(0), is_set(false) {}
2018-08-12 17:37:16 +02:00
2022-03-16 23:38:08 +01:00
void clear()
{
this->value = 0;
this->is_set = false;
}
2018-08-12 17:37:16 +02:00
int64_t value;
bool is_set;
2020-09-12 08:10:11 +02:00
};
std::array<_rt_field, RTF__MAX> rt_field;
std::set<token_t> rt_included_days;
std::chrono::microseconds rt_duration{0};
2018-08-12 17:37:16 +02:00
bool rt_next;
bool rt_previous;
int rt_absolute_field_end;
2015-09-14 17:56:42 +02:00
};
2022-03-16 23:38:08 +01:00
#endif // LNAV_RELATIVE_TIME_HH