subsurface/core/event.cpp
Berthold Stoeger 27dbdd35c6 core: turn event-list of divecomputer into std::vector<>
This is a rather long commit, because it refactors lots of the event
code from pointer to value semantics: pointers to entries in an
std::vector<> are not stable, so better use indexes.

To step through the event-list at diven time stamps, add *_loop classes,
which encapsulate state that had to be manually handled before by
the caller. I'm not happy about the interface, but it tries to
mirror the one we had before.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2024-08-13 19:28:30 +02:00

113 lines
2.7 KiB
C++

// SPDX-License-Identifier: GPL-2.0
#include "event.h"
#include "divecomputer.h"
#include "eventtype.h"
#include "subsurface-string.h"
event::event() : type(SAMPLE_EVENT_NONE), flags(0), value(0),
divemode(OC), hidden(false)
{
/* That overwrites divemode. Is this a smart thing to do? */
gas.index = -1;
gas.mix = gasmix_air;
}
event::event(unsigned int time, int type, int flags, int value, const std::string &name) :
type(type), flags(flags), value(value), divemode(OC),
hidden(false), name(name)
{
int gas_index = -1;
fraction_t he;
this->time.seconds = time;
/*
* Expand the events into a sane format. Currently
* just gas switches
*/
switch (type) {
case SAMPLE_EVENT_GASCHANGE2:
/* High 16 bits are He percentage */
he.permille = (value >> 16) * 10;
/* Extension to the GASCHANGE2 format: cylinder index in 'flags' */
/* TODO: verify that gas_index < num_cylinders. */
if (flags > 0)
gas_index = flags-1;
/* Fallthrough */
case SAMPLE_EVENT_GASCHANGE:
/* Low 16 bits are O2 percentage */
gas.mix.he = he;
gas.mix.o2.permille = (value & 0xffff) * 10;
gas.index = gas_index;
break;
}
remember_event_type(this);
}
event::~event()
{
}
bool event_is_gaschange(const struct event &ev)
{
return ev.type == SAMPLE_EVENT_GASCHANGE ||
ev.type == SAMPLE_EVENT_GASCHANGE2;
}
bool event_is_divemodechange(const struct event &ev)
{
return ev.name == "modechange";
}
bool event::operator==(const event &b) const
{
return std::tie(time.seconds, type, flags, value, name) ==
std::tie(b.time.seconds, b.type, b.flags, b.value, b.name);
}
extern enum event_severity get_event_severity(const struct event &ev)
{
switch (ev.flags & SAMPLE_FLAGS_SEVERITY_MASK) {
case SAMPLE_FLAGS_SEVERITY_INFO:
return EVENT_SEVERITY_INFO;
case SAMPLE_FLAGS_SEVERITY_WARN:
return EVENT_SEVERITY_WARN;
case SAMPLE_FLAGS_SEVERITY_ALARM:
return EVENT_SEVERITY_ALARM;
default:
return EVENT_SEVERITY_NONE;
}
}
event_loop::event_loop(const char *name) : name(name), idx(0)
{
}
struct event *event_loop::next(struct divecomputer &dc)
{
if (name.empty())
return nullptr;
while (idx < dc.events.size()) {
struct event &ev = dc.events[idx++];
if (ev.name == name)
return &ev;
}
return nullptr;
}
const struct event *event_loop::next(const struct divecomputer &dc)
{
return next(const_cast<divecomputer &>(dc));
}
struct event *get_first_event(struct divecomputer &dc, const std::string &name)
{
auto it = std::find_if(dc.events.begin(), dc.events.end(), [name](auto &ev) { return ev.name == name; });
return it != dc.events.end() ? &*it : nullptr;
}
const struct event *get_first_event(const struct divecomputer &dc, const std::string &name)
{
return get_first_event(const_cast<divecomputer &>(dc), name);
}