spiegel-keyman/core/src/option.cpp
Marc Durdin 7ec4832edc fix(core): memory management of options in action struct
Fixes #10067.

Management of memory for persisted options was wrong in the action
struct, as the members key and value would be freed immediately after
being added to the temporary vector (because the vector was of the
struct rather than of the class).

Given the struct is a C struct, we need the memory management to be
explicit, so we now release() each option into the vector as we create
it, which means that its member values will not be freed when the option
is then immediately deleted. (This allows us to use the initial copy of
the members of option that option() constructor does.)

Added the release() function as that was a relatively clear way of
indicating that the contents of the structure are now owned by the
caller, following the pattern from std::unique_ptr.

Finally, the unit test for persisted options was in the action_api.cpp
test module, but it was never called, so this was not being tested. Now
it is.
2023-11-24 07:52:31 +10:00

84 lines
1.8 KiB
C++

/*
Copyright: © 2018 SIL International.
Description: Internal option key value map class and adaptor class for
the API.
Create Date: 7 Oct 2018
Authors: Tim Eves (TSE)
History: 7 Nov 2018 - TSE - Refactored into option.hpp & option.cpp.
*/
#include <algorithm>
#include "option.hpp"
#include "processor.hpp"
using namespace km::core;
namespace
{
constexpr char const * const scope_names_lut[] = {
u8"keyboard",
u8"environment"
};
}
// Forward declarations
option::option(km_core_option_scope s, char16_t const *k, char16_t const *v)
: option()
{
if (k && v)
{
auto n_k = std::char_traits<char16_t>::length(k)+1,
n_v = std::char_traits<char16_t>::length(v)+1;
auto _key = new km_core_cp[n_k],
_val = new km_core_cp[n_v];
std::copy_n(k, n_k, _key);
std::copy_n(v, n_v, _val);
key = _key;
value = _val;
scope = s;
}
}
km_core_option_item
option::release() {
km_core_option_item opt = *this;
key = nullptr;
value = nullptr;
return opt;
}
// TODO: Relocate this and fix it
json & km::core::operator << (json &j, abstract_processor const &)
{
j << json::object;
// auto n = 0;
// for (auto scope: opts._scopes)
// {
// j << scope_names_lut[n++] << json::object;
// for (auto opt = scope; opt->key; ++opt)
// {
// j << opt->key << opt->value;
// }
// j << json::close;
// }
j << "saved" << json::object;
for (auto scope: {KM_CORE_OPT_KEYBOARD, KM_CORE_OPT_ENVIRONMENT})
{
j << scope_names_lut[scope-1] << json::object;
// for (auto & opt: opts._saved)
// {
// if (opt.scope != scope) continue;
// j << opt.key << opt.value;
// }
j << json::close;
}
j << json::close;
j << json::close;
return j;
}