Skip to content

Commit

Permalink
feat(core): infrastructure for normalization of output
Browse files Browse the repository at this point in the history
Relates to #9999.

Establishes functions, unit test sources, normalization entry point and
an effectively no-op unit test for normalization support.
  • Loading branch information
mcdurdin committed Jan 16, 2024
1 parent ba1f592 commit e39affe
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 9 deletions.
4 changes: 2 additions & 2 deletions core/include/keyman/keyman_core_api_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ km_core_context_items_dispose(km_core_context_item *context_items);
*/
KMN_API
km_core_context *
km_core_state_context(km_core_state *state);
km_core_state_context(km_core_state const *state);

/**
* Get access to the state object's application context.
Expand All @@ -127,7 +127,7 @@ km_core_state_context(km_core_state *state);
*/
KMN_API
km_core_context *
km_core_state_app_context(km_core_state *state);
km_core_state_app_context(km_core_state const *state);

/*
```
Expand Down
2 changes: 1 addition & 1 deletion core/src/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "state.hpp"
#include "option.hpp"

km_core_actions const * km::core::action_item_list_to_actions_object(
km_core_actions * km::core::action_item_list_to_actions_object(
km_core_action_item const *action_items
) {
assert(action_items != nullptr);
Expand Down
8 changes: 7 additions & 1 deletion core/src/action.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@
namespace km {
namespace core
{
km_core_actions const *action_item_list_to_actions_object(
km_core_actions *action_item_list_to_actions_object(
km_core_action_item const *action_items
);

bool actions_normalize(
km_core_context const *cached_context,
km_core_context const *app_context,
km_core_actions *actions
);
} // namespace core
} // namespace km
34 changes: 34 additions & 0 deletions core/src/actions_normalize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright: © 2024 SIL International.
Description: Implementation of the action output normalization.
Create Date: 16 Jan 2024
Authors: Marc Durdin (MCD)
History: 16 Jan 2024 - MCD - Initial implementation from #9999
*/
#include <cassert>
#include <algorithm>
#include <sstream>
#include <memory>

#include "action.hpp"
#include "state.hpp"
#include "option.hpp"

bool km::core::actions_normalize(
km_core_context const *cached_context,
km_core_context const *app_context,
km_core_actions *actions
) {
assert(actions != nullptr);
assert(cached_context != nullptr);
assert(app_context != nullptr);
if(actions == nullptr || cached_context == nullptr || app_context == nullptr) {
return false;
}

// Normalize output to NFC
//TODO
// actions->code_points_to_delete++;

return true;
}
11 changes: 10 additions & 1 deletion core/src/km_core_action_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,16 @@ km_core_actions const * km_core_state_get_actions(
return nullptr;
}

return action_item_list_to_actions_object(action_items);
km_core_actions * result = action_item_list_to_actions_object(action_items);

if(state->processor().supports_normalization()) {
// Normalize to NFC for those keyboard processors that support it
if(!actions_normalize(km_core_state_context(state), km_core_state_app_context(state), result)) {
km_core_actions_dispose(result);
return nullptr;
}
}
return result;
}

km_core_status km_core_actions_dispose(
Expand Down
8 changes: 4 additions & 4 deletions core/src/km_core_state_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,20 @@ void km_core_state_dispose(km_core_state *state)
}


km_core_context *km_core_state_context(km_core_state *state)
km_core_context *km_core_state_context(km_core_state const *state)
{
assert(state);
if (!state) return nullptr;

return static_cast<km_core_context *>(&state->context());
return static_cast<km_core_context *>(&(const_cast<km_core_state *>(state)->context()));
}

km_core_context *km_core_state_app_context(km_core_state *state)
km_core_context *km_core_state_app_context(km_core_state const *state)
{
assert(state);
if (!state) return nullptr;

return static_cast<km_core_context *>(&state->app_context());
return static_cast<km_core_context *>(&(const_cast<km_core_state *>(state)->app_context()));
}

km_core_status km_core_state_get_intermediate_context(
Expand Down
1 change: 1 addition & 0 deletions core/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ endif


kmx_files = files(
'actions_normalize.cpp',
'action.cpp',
'option.cpp',
'keyboard.cpp',
Expand Down
1 change: 1 addition & 0 deletions core/tests/unit/kmnkbd/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ tests = [
['debug-api', 'debug_api.cpp'],
['kmx_xstring', 'test_kmx_xstring.cpp'],
['kmx_context', 'test_kmx_context.cpp'],
['test_actions_normalize', 'test_actions_normalize.cpp'],
]

test_path = join_paths(meson.current_build_dir(), '..', 'kmx')
Expand Down
112 changes: 112 additions & 0 deletions core/tests/unit/kmnkbd/test_actions_normalize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
Copyright: © 2018 SIL International.
Description: Tests for the context API family of functions.
Create Date: 23 Oct 2023
Authors: Marc Durdin
History: 23 Oct 2023 - MCD - Initial implementation.
*/
#include <string>
#include "keyman_core.h"

#include "path.hpp"
#include "action.hpp"

#include <test_assert.h>
#include "../emscripten_filesystem.h"

km_core_option_item test_env_opts[] =
{
KM_CORE_OPTIONS_END
};

km_core_keyboard * test_kb = nullptr;
km_core_state * test_state = nullptr;
km_core_actions * test_actions = nullptr;
std::string arg_path;

void teardown() {
if(test_state) {
km_core_state_dispose(test_state);
test_state = nullptr;
}
if(test_kb) {
km_core_keyboard_dispose(test_kb);
test_kb = nullptr;
}
if(test_actions) {
delete [] test_actions->output;
delete test_actions;
test_actions = nullptr;
}
}

void setup(const km_core_cp *context, int actions_code_points_to_delete, const std::u32string actions_output) {
teardown();

km::core::path path = km::core::path::join(arg_path, "..", "ldml", "keyboards", "k_001_tiny.kmx");
try_status(km_core_keyboard_load(path.native().c_str(), &test_kb));
try_status(km_core_state_create(test_kb, test_env_opts, &test_state));

assert(km_core_state_context_set_if_needed(test_state, context) == KM_CORE_CONTEXT_STATUS_UPDATED);

test_actions = new km_core_actions;
test_actions->code_points_to_delete = actions_code_points_to_delete;
test_actions->output = new km_core_usv[actions_output.length() + 1];
actions_output.copy(test_actions->output, actions_output.length());
test_actions->output[actions_output.length()] = 0;
}

//-------------------------------------------------------------------------------------

void test_no_normalization() {
setup(u"abc", 0, U"def");
const int expected_delete = 0;
const std::u32string expected_output = U"def";

assert(km::core::actions_normalize(km_core_state_context(test_state), km_core_state_app_context(test_state), test_actions));

assert(expected_delete == test_actions->code_points_to_delete);
assert(expected_output == test_actions->output);

teardown();
}

//-------------------------------------------------------------------------------------
// Launcher
//-------------------------------------------------------------------------------------

constexpr const auto help_str = "\
test_actions_normalize [--color] <BUILD_PATH>\n\
\n\
--color Force color output\n\
BUILD_PATH Path where test_actions_normalize.exe is found; kmx files are\n\
located relative to this path.\n";

int error_args() {
std::cerr << "test_actions_normalize: Invalid arguments." << std::endl;
std::cout << help_str;
return 1;
}

int main(int argc, char *argv []) {

if(argc < 2) {
return error_args();
}

auto arg_color = std::string(argv[1]) == "--color";
if(arg_color && argc < 3) {
return error_args();
}
console_color::enabled = console_color::isaterminal() || arg_color;

#ifdef __EMSCRIPTEN__
arg_path = get_wasm_file_path(argv[arg_color ? 2 : 1]);
#else
arg_path = argv[arg_color ? 2 : 1];
#endif

// actions
test_no_normalization();
}

0 comments on commit e39affe

Please sign in to comment.