17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 21:29:19 +02:00

Fix/sonar maintainability rebased (#209)

* refactor(sonar): use override instead of redundant virtual (cpp:S3471)

* refactor(sonar): remove empty statements, one declaration per statement (cpp:S1116, cpp:S1659)

* refactor(sonar): drop redundant lambda return types (cpp:S3574)

* refactor(sonar): prefer using over typedef (cpp:S5416)

* refactor(sonar): use =default for trivial special members (cpp:S3490)

* refactor(sonar): use nullptr literal (cpp:S4962)

* refactor(sonar): remove redundant access specifiers (cpp:S3539)

* refactor(sonar): remove redundant casts (cpp:S1905)

* refactor(sonar): use std::scoped_lock instead of std::lock_guard (cpp:S5997)

* refactor(sonar): construct elements in place with emplace_back (cpp:S6003)

* refactor(sonar): make narrowing conversions explicit (cpp:S5276)

* refactor(sonar): mark unused parameters (cpp:S1172)

Unused names are commented out; parameters used only on some platforms
are marked [[maybe_unused]].

* refactor(sonar): declare non-mutating member functions const (cpp:S5817)

Virtual functions are left untouched so overrides keep matching.

* refactor(sonar): merge collapsible nested if statements (cpp:S1066)

Comments that preceded the inner if are kept above the merged statement.

* refactor(sonar): scope single-use variables in if init-statements (cpp:S6004)

* fix(sonar): give polymorphic base classes virtual destructors (cpp:S1235)

* refactor(sonar): use try_emplace for map insertion (cpp:S6030)

* refactor(sonar): use auto where the type is spelled out on the right (cpp:S5827)

* refactor(sonar): remove redundant parentheses (cpp:S1110)

* refactor(sonar): document intentionally empty functions (cpp:S1186)

* refactor(sonar): remove dead stores (cpp:S1854)

Side effects (e.g. LISTLINE++) are kept.

* refactor(sonar): remove unused variables, captures and private fields (cpp:S1481, cpp:S1068)

* refactor(sonar): use structured bindings for pair access (cpp:S6005)

* refactor(sonar): use range-based loops and ranges algorithms (cpp:S5566)

* refactor(sonar): split chained assignments (cpp:S1121)

* refactor(sonar): add default cases to switch statements (cpp:S3562)

* refactor(sonar): use std::size for array lengths (cpp:S7127)

* refactor(sonar): use std::ranges algorithms and std::erase(_if) (cpp:S6197)

* refactor(sonar): access static members through the class (cpp:S2209)

* refactor(sonar): add braces around nested if-else (cpp:S5261)

* refactor(sonar): avoid side effects inside typeid operands (cpp:S5279)

* refactor(sonar): drop top-level const from by-value return types (cpp:S5951)

* refactor(sonar): declare variables separately from their type definitions (cpp:S3646)

* refactor(sonar): declare loop counters in the for statement (cpp:S5955)

* refactor(sonar): rely on class template argument deduction (cpp:S6012)

* refactor(sonar): inherit base constructors instead of forwarding them (cpp:S5952)

* refactor(sonar): rename locals that shadow outer declarations (cpp:S1117)

Only local variables and definition parameters are renamed; shadowing
struct fields and enumerators in headers are left for a separate change.

* refactor(sonar): reduce enum qualification with using enum (cpp:S6177)

Applied only where no unqualified name in the block could be captured by
the introduced enumerators.

* refactor(sonar): mark converting constructors explicit (cpp:S1709)

sound_source and the gl::object conversion operators stay implicit; they
are relied upon by copy-list-initialisation and GL calls.

* refactor(sonar): initialise members in initialiser lists or declarations (cpp:S3230)

* refactor(sonar): make read-only local references and pointers const (cpp:S5350)

* refactor(sonar): take read-only pointer and reference parameters as const (cpp:S995)

TTrain command handlers keep their signature, it is fixed by the handler table.

* refactor(sonar): pass expensive-to-copy parameters by const reference (cpp:S1238)

Signatures declared in files touched by PR 206 (Driver.h, EU07.cpp) and
virtual overrides are left unchanged.

* refactor(sonar): use transparent comparators for string-keyed maps (cpp:S6045)

std::unordered_map instances and map types exposed in headers used by
other modules are left as they are.

* fix(sonar): do not use UI text as a printf format string (cpp:S5281)

Text lines containing '%' would otherwise be interpreted as format
specifiers by ImGui::TextColored.

* refactor(sonar): use std::bind_front for callbacks (cpp:S5995)

* refactor(sonar): drop const_cast on string literals passed to the Python C API (cpp:S859)

* refactor(sonar): take read-only string parameters as std::string_view (cpp:S6009)

The Windows messaging helpers keep std::string, they need c_str().

* refactor(sonar): make read-only global tables const (cpp:S5421)

Mutable global state (flags, timers, singletons) is left as is.

* refactor(sonar): replace single-case switch statements with if (cpp:S1301)

* refactor(sonar): format UUIDs and log timestamps with std::format (cpp:S6494, cpp:S5945)

* refactor(sonar): use std::array for local fixed-size arrays (cpp:S5945)

Arrays that are class members or part of headers are left unchanged.

* fix(sonar): test the bearing damage bit, not bit 0 (cpp:S872)

'DamageFlag & dtrain_bearing > 0' parsed as 'DamageFlag & (dtrain_bearing > 0)',
i.e. DamageFlag & 1, so bearing friction reacted to the wrong damage flag.

* refactor(sonar): assorted small fixes

- empty() instead of size() comparisons (cpp:S1155)
- member initialisers in declaration order (cpp:S3229)
- no redundant c_str() when a std::string is accepted (cpp:S7121)
- contains() on associative containers (cpp:S6171)
- const reference instead of a copying range-for (cpp:S6032)
- starts_with() for prefix checks (cpp:S6178)
- no std::move on temporaries (cpp:S5274)
- has_value() on std::optional (cpp:S7172)
- bool literals for bool members (cpp:S5820)
- inline only on the definition (cpp:S3548)
- explicit base access specifier (cpp:S5965)
- explicit element access instead of dereferencing an array (cpp:S7116)
- rely on the C++20 rewritten operator!= (cpp:S6186)

* refactor(sonar): more small fixes

- std::format instead of iostream manipulators in to_string/to_hex_str (cpp:S6495);
  output verified identical, negative hex values keep the unsigned form
- remove an empty compound statement (cpp:S108)
- drop an always-false unsigned < 0 branch (cpp:S1768)
- explicit lambda capture (cpp:S3608)
- std::make_unique (cpp:S5950)

* chore: strip stray carriage returns left in TTrain constructor comments

* fix: keep quantize() in its own value type

The S5276 change cast the result of the generic quantize<Type_>() to
unsigned int, which truncated float/double callers (shadow angle slider,
editor rotation snapping, AI speed control steps) and broke negative values.

* fix(sonar): use integer loop counters in segment sampling (cpp:S2193)

* refactor(sonar): clean up issues reported on PR 209

- remove locals left unused after the dead-store cleanup (cpp:S1481, cpp:S1854)
- unnamed unused parameter (cpp:S1172)
- single-use declarations moved into if init-statements (cpp:S6004)
- auto for casted initialisers (cpp:S5827)
- const references and pointers where nothing is modified (cpp:S5350)
- rename structured bindings shadowed by inner declarations (cpp:S1117)
This commit is contained in:
jerrrrycho
2026-10-11 13:22:33 +02:00
committed by GitHub
parent c26041f2e7
commit 6263fe539b
162 changed files with 4220 additions and 4598 deletions

View File

@@ -30,36 +30,36 @@ void render_task::run()
cancel();
return;
}
for (auto const &datapair : m_input->floats)
for (auto const &[dataname, datavalue] : m_input->floats)
{
auto *value{PyGetFloat(datapair.second)};
auto *value{PyGetFloat(datavalue)};
if (value == nullptr)
{
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->integers)
for (auto const &[dataname, datavalue] : m_input->integers)
{
auto *value{PyLong_FromLong(datapair.second)};
auto *value{PyLong_FromLong(datavalue)};
if (value == nullptr)
{
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->bools)
for (auto const &[dataname, datavalue] : m_input->bools)
{
// Py_True / Py_False sa niesmiertelne, ale PyDict_SetItemString i tak
// pobiera wlasna referencje - nie zwalniamy
auto *value{PyGetBool(datapair.second)};
PyDict_SetItemString(input, datapair.first.c_str(), value);
auto *value{PyGetBool(datavalue)};
PyDict_SetItemString(input, dataname.c_str(), value);
}
for (auto const &datapair : m_input->strings)
for (auto const &[dataname, datavalue] : m_input->strings)
{
// Nazwy scenerii/wagonow (asName, SceneryFile, asCarName, cCode...) moga
// byc albo w UTF-8, albo w starym kodowaniu Windows-1250. PyUnicode_FromString
@@ -68,8 +68,8 @@ void render_task::run()
//
// Strategia: najpierw probujemy UTF-8 (strict). Jesli sie nie uda - probujemy
// cp1250. Jesli oba zawioda - pomijamy klucz, ale nie wywracamy symulatora.
char const *const str{datapair.second.c_str()};
Py_ssize_t const len{static_cast<Py_ssize_t>(datapair.second.size())};
char const *const str{datavalue.c_str()};
Py_ssize_t const len{static_cast<Py_ssize_t>(datavalue.size())};
auto *value{PyUnicode_DecodeUTF8(str, len, "strict")};
if (value == nullptr)
@@ -82,16 +82,16 @@ void render_task::run()
PyErr_Clear();
continue;
}
PyDict_SetItemString(input, datapair.first.c_str(), value);
PyDict_SetItemString(input, dataname.c_str(), value);
Py_DECREF(value);
}
for (auto const &datapair : m_input->vec2_lists)
for (auto const &[dataname, datavalue] : m_input->vec2_lists)
{
PyObject *list = PyList_New(datapair.second.size());
PyObject *list = PyList_New(datavalue.size());
for (size_t i = 0; i < datapair.second.size(); i++)
for (size_t i = 0; i < datavalue.size(); i++)
{
auto const &vec = datapair.second[i];
auto const &vec = datavalue[i];
WriteLog("passing " + glm::to_string(vec));
PyObject *tuple = PyTuple_New(2);
@@ -101,24 +101,24 @@ void render_task::run()
PyList_SetItem(list, i, tuple); // steals ref
}
PyDict_SetItemString(input, datapair.first.c_str(), list);
PyDict_SetItemString(input, dataname.c_str(), list);
Py_DECREF(list);
}
m_input = nullptr;
// call the renderer
auto *output{PyObject_CallMethod(m_renderer, const_cast<char *>("render"), const_cast<char *>("O"), input)};
auto *output{PyObject_CallMethod(m_renderer, "render", "O", input)};
Py_DECREF(input);
if (output != nullptr)
{
auto *outputWidth = PyObject_CallMethod(m_renderer, const_cast<char *>("get_width"), nullptr);
auto *outputHeight = PyObject_CallMethod(m_renderer, const_cast<char *>("get_height"), nullptr);
auto *outputWidth = PyObject_CallMethod(m_renderer, "get_width", nullptr);
auto *outputHeight = PyObject_CallMethod(m_renderer, "get_height", nullptr);
if (outputWidth != nullptr && outputHeight != nullptr && m_target != nullptr)
{
const int screenWidth = static_cast<int>(PyLong_AsLong(outputWidth));
const int screenHeight = static_cast<int>(PyLong_AsLong(outputHeight));
const auto screenWidth = static_cast<int>(PyLong_AsLong(outputWidth));
const auto screenHeight = static_cast<int>(PyLong_AsLong(outputHeight));
const bool useRgb = false && !Global.gfx_usegles;
@@ -166,7 +166,7 @@ void render_task::run()
}
// get commands from renderer
auto *commandsPO = PyObject_CallMethod(m_renderer, const_cast<char *>("getCommands"), nullptr);
auto *commandsPO = PyObject_CallMethod(m_renderer, "getCommands", nullptr);
if (commandsPO != nullptr)
{
std::vector<std::string> commands = python_external_utils::PyObjectToStringArray(commandsPO);
@@ -178,10 +178,10 @@ void render_task::run()
for (const auto &cmd : commands)
{
std::string baseCmd;
int p1 = 0, p2 = 0;
int p1 = 0;
int p2 = 0;
size_t pos1 = cmd.find(';');
if (pos1 == std::string::npos)
if (size_t pos1 = cmd.find(';'); pos1 == std::string::npos)
{
baseCmd = cmd;
}
@@ -224,7 +224,7 @@ void render_task::run()
}
}
void render_task::upload()
void render_task::upload() const
{
if (Global.python_uploadmain && m_target && m_target->shared_tex)
{
@@ -232,7 +232,7 @@ void render_task::upload()
}
}
void render_task::cancel() {}
void render_task::cancel() const { /* nothing to do */ }
// initializes the module. returns true on success
auto python_taskqueue::init() -> bool
@@ -310,7 +310,7 @@ auto python_taskqueue::init() -> bool
stringiomodule = PyImport_ImportModule("io");
stringioclassname = stringiomodule != nullptr ? PyObject_GetAttrString(stringiomodule, "StringIO") : nullptr;
stringioobject = stringioclassname != nullptr ? PyObject_CallObject(stringioclassname, nullptr) : nullptr;
m_stderr = {(stringioobject == nullptr ? nullptr : PySys_SetObject(const_cast<char *>("stderr"), stringioobject) != 0 ? nullptr : stringioobject)};
m_stderr = {(stringioobject == nullptr ? nullptr : PySys_SetObject("stderr", stringioobject) != 0 ? nullptr : stringioobject)};
if (false == run_file("abstractscreenrenderer"))
{
@@ -362,23 +362,23 @@ void python_taskqueue::exit()
// document intent. clearing the deque also actually releases the tasks,
// which the previous code did not do (cancel() is a no-op stub).
{
std::lock_guard<std::mutex> lock(m_tasks.mutex);
for (auto &task : m_tasks.data)
std::scoped_lock lock(m_tasks.mutex);
for (auto const &task : m_tasks.data)
{
task->cancel();
}
m_tasks.data.clear();
}
{
std::lock_guard<std::mutex> lock(m_uploadtasks.mutex);
std::scoped_lock lock(m_uploadtasks.mutex);
m_uploadtasks.data.clear();
}
// reclaim cached python objects while the interpreter is still alive,
// so no Py_DECREF lands on a finalized interpreter during later teardown
acquire_lock();
for (auto &entry : m_renderers)
for (auto const &[renderername, rendererobject] : m_renderers)
{
Py_XDECREF(entry.second);
Py_XDECREF(rendererobject);
}
m_renderers.clear();
Py_XDECREF(m_stderr);
@@ -394,7 +394,7 @@ void python_taskqueue::exit()
auto python_taskqueue::insert(task_request const &Task) -> bool
{
if (!m_initialized || false == Global.python_enabled || Task.renderer.empty() || Task.input == nullptr || Task.target == 0)
if (!m_initialized || false == Global.python_enabled || Task.renderer.empty() || Task.input == nullptr || Task.target == nullptr)
{
return false;
}
@@ -409,7 +409,7 @@ auto python_taskqueue::insert(task_request const &Task) -> bool
bool newtaskinserted{false};
// acquire a lock on the task queue and add the new task
{
std::lock_guard<std::mutex> lock(m_tasks.mutex);
std::scoped_lock lock(m_tasks.mutex);
// check the task list for a pending request with the same target
for (auto &task : m_tasks.data)
{
@@ -437,13 +437,13 @@ auto python_taskqueue::insert(task_request const &Task) -> bool
auto python_taskqueue::run_file(std::string const &File, std::string const &Path) -> bool
{
auto const lookup{FileExists({Path + File, "python/local/" + File}, {".py"})};
if (lookup.first.empty())
auto const [filepath, fileextension]{FileExists({Path + File, "python/local/" + File}, {".py"})};
if (filepath.empty())
{
return false;
}
std::ifstream inputfile{lookup.first + lookup.second};
std::ifstream inputfile{filepath + fileextension};
std::string input;
input.assign(std::istreambuf_iterator<char>(inputfile), std::istreambuf_iterator<char>());
@@ -464,17 +464,16 @@ void python_taskqueue::acquire_lock()
}
// releases the python gil and swaps the main thread out
void python_taskqueue::release_lock()
void python_taskqueue::release_lock() const
{
PyEval_SaveThread();
}
auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
auto python_taskqueue::fetch_renderer(std::string const &Renderer) -> PyObject *
{
auto const lookup{m_renderers.find(Renderer)};
if (lookup != std::end(m_renderers))
if (auto const lookup{m_renderers.find(Renderer)}; lookup != std::end(m_renderers))
{
return lookup->second;
}
@@ -510,7 +509,7 @@ auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
}
renderer = PyObject_CallObject(renderername, rendererarguments);
PyObject_CallMethod(renderer, const_cast<char *>("manul_set_format"), const_cast<char *>("(s)"), "RGBA");
PyObject_CallMethod(renderer, "manul_set_format", "(s)", "RGBA");
if (PyErr_Occurred() != nullptr)
{
@@ -527,11 +526,11 @@ auto python_taskqueue::fetch_renderer(std::string const Renderer) -> PyObject *
}
release_lock();
// cache the failures as well so we don't try again on subsequent requests
m_renderers.emplace(Renderer, renderer);
m_renderers.try_emplace(Renderer, renderer);
return renderer;
}
void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit)
void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> const &Exit)
{
if (Context)
@@ -554,7 +553,7 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
task = nullptr;
// acquire a lock on the task queue and potentially grab a task from it
{
std::lock_guard<std::mutex> lock(Tasks.mutex);
std::scoped_lock lock(Tasks.mutex);
if (false == Tasks.data.empty())
{
// fifo
@@ -573,7 +572,7 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
task->upload();
else
{
std::lock_guard<std::mutex> lock(Upload_Tasks.mutex);
std::scoped_lock lock(Upload_Tasks.mutex);
Upload_Tasks.data.push_back(task);
}
if (PyErr_Occurred() != nullptr)
@@ -608,9 +607,9 @@ void python_taskqueue::run(GLFWwindow *Context, rendertask_sequence &Tasks, uplo
void python_taskqueue::update()
{
std::lock_guard<std::mutex> lock(m_uploadtasks.mutex);
std::scoped_lock lock(m_uploadtasks.mutex);
for (auto &task : m_uploadtasks.data)
for (auto const &task : m_uploadtasks.data)
task->upload();
m_uploadtasks.data.clear();
@@ -622,21 +621,21 @@ void python_taskqueue::error()
{
// std err pythona jest buforowane
PyErr_Print();
auto *errortext{PyObject_CallMethod(m_stderr, const_cast<char *>("getvalue"), nullptr)};
if (errortext != nullptr)
if (auto *errortext{PyObject_CallMethod(m_stderr, "getvalue", nullptr)}; errortext != nullptr)
{
const char *errstr = PyUnicode_AsUTF8(errortext);
if (errstr != nullptr)
if (const char *errstr = PyUnicode_AsUTF8(errortext); errstr != nullptr)
ErrorLog(errstr);
Py_DECREF(errortext);
}
PyObject_CallMethod(m_stderr, const_cast<char *>("truncate"), const_cast<char *>("L"), (long long)0);
PyObject_CallMethod(m_stderr, const_cast<char *>("seek"), const_cast<char *>("L"), (long long)0);
PyObject_CallMethod(m_stderr, "truncate", "L", (long long)0);
PyObject_CallMethod(m_stderr, "seek", "L", (long long)0);
}
else
{
// nie dziala buffor pythona
PyObject *type, *value, *traceback;
PyObject *type;
PyObject *value;
PyObject *traceback;
PyErr_Fetch(&type, &value, &traceback);
if (type == nullptr)
{
@@ -647,11 +646,9 @@ void python_taskqueue::error()
{
ErrorLog("Python Interpreter: don't know how to handle null exception");
}
auto *typetext{PyObject_Str(type)};
if (typetext != nullptr)
if (auto *typetext{PyObject_Str(type)}; typetext != nullptr)
{
const char *s = PyUnicode_AsUTF8(typetext);
if (s)
if (const char *s = PyUnicode_AsUTF8(typetext); s)
ErrorLog(s);
Py_DECREF(typetext);
}
@@ -660,8 +657,7 @@ void python_taskqueue::error()
auto *valuetext{PyObject_Str(value)};
if (valuetext != nullptr)
{
const char *s = PyUnicode_AsUTF8(valuetext);
if (s)
if (const char *s = PyUnicode_AsUTF8(valuetext); s)
ErrorLog(s);
Py_DECREF(valuetext);
}
@@ -669,8 +665,7 @@ void python_taskqueue::error()
auto *tracebacktext{PyObject_Str(traceback)};
if (tracebacktext != nullptr)
{
const char *s = PyUnicode_AsUTF8(tracebacktext);
if (s)
if (const char *s = PyUnicode_AsUTF8(tracebacktext); s)
ErrorLog(s);
Py_DECREF(tracebacktext);
}
@@ -709,7 +704,7 @@ std::vector<std::string> python_external_utils::PyObjectToStringArray(PyObject *
return emptyIfError;
}
result.push_back(std::string(str));
result.emplace_back(str);
Py_DECREF(item); // Decrease reference count for the item
}

View File

@@ -80,8 +80,8 @@ class render_task
render_task(PyObject *Renderer, std::shared_ptr<dictionary_source> Input, std::shared_ptr<python_rt> Target) : m_renderer(Renderer), m_input(Input), m_target(Target) {}
// methods
void run();
void upload();
void cancel();
void upload() const;
void cancel() const;
auto target() const -> std::shared_ptr<python_rt>
{
return m_target;
@@ -120,7 +120,7 @@ class python_taskqueue
// acquires the python gil and sets the main thread as current
void acquire_lock();
// releases the python gil and swaps the main thread out
void release_lock();
void release_lock() const;
void update();
@@ -131,8 +131,8 @@ class python_taskqueue
using rendertask_sequence = threading::lockable<std::deque<std::shared_ptr<render_task>>>;
using uploadtask_sequence = threading::lockable<std::deque<std::shared_ptr<render_task>>>;
// methods
auto fetch_renderer(std::string const Renderer) -> PyObject *;
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit);
auto fetch_renderer(std::string const &Renderer) -> PyObject *;
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> const &Exit);
void error();
// members

View File

@@ -67,7 +67,7 @@ basic_controller::output( element_handle const Element ) const -> int {
}
auto
basic_controller::load( std::string const &Filename ) -> bool {
basic_controller::load( std::string_view Filename) -> bool {
m_program.clear();
m_updateaccumulator = 0.0;
@@ -111,7 +111,7 @@ basic_controller::update( double const Timestep ) -> int {
return run();
}
std::map<std::string, basic_controller::opcode_e> const basic_controller::m_operationcodemap = {
std::map<std::string, basic_controller::opcode_e, std::less<>> const basic_controller::m_operationcodemap = {
{ "ld", opcode_e::op_ld }, { "ldi", opcode_e::op_ldi },
{ "and", opcode_e::op_and }, { "ani", opcode_e::op_ani }, { "anb", opcode_e::op_anb },
{ "or", opcode_e::op_or }, { "ori", opcode_e::op_ori }, { "orb", opcode_e::op_orb },
@@ -130,10 +130,9 @@ basic_controller::deserialize_operation( cParser &Input ) -> bool {
cParser operationparser( operationdata, cParser::buffer_TEXT );
// HACK: operation potentially contains 1-2 parameters so we try to grab the whole set
operationparser.getTokens( 3, "\t " );
std::string
operationname,
operationelement,
operationparameter;
std::string operationname;
std::string operationelement;
std::string operationparameter;
operationparser
>> operationname
>> operationelement
@@ -142,7 +141,7 @@ basic_controller::deserialize_operation( cParser &Input ) -> bool {
auto const lookup { m_operationcodemap.find( operationname ) };
operation.code = lookup != m_operationcodemap.end() ? lookup->second : opcode_e::op_nop;
if( lookup == m_operationcodemap.end() ) {
log_error( "contains unknown command \"" + operationname + "\"", Input.Line() - 1 );
log_error( "contains unknown command \"" + operationname + "\"", static_cast<int>(Input.Line() - 1) );
}
if( operation.code == opcode_e::op_nop ) { return true; }
@@ -155,8 +154,8 @@ basic_controller::deserialize_operation( cParser &Input ) -> bool {
}
if( false == operationparameter.empty() ) {
auto const parameter{ split_string_and_number( operationparameter ) };
operation.parameter1 = static_cast<short>( parameter.second );
auto const [parametertype, parameterindex]{ split_string_and_number( operationparameter ) };
operation.parameter1 = static_cast<short>( parameterindex );
}
m_program.emplace_back( operation );
@@ -165,7 +164,7 @@ basic_controller::deserialize_operation( cParser &Input ) -> bool {
}
auto
basic_controller::insert( std::string const Name, basic_element Element ) -> element_handle {
basic_controller::insert( std::string const &Name, basic_element Element ) -> element_handle {
m_elements.push_back( Element );
m_elementnames.push_back( Name );
@@ -301,6 +300,8 @@ basic_controller::run() -> int {
}
break;
}
default:
break;
}
// accumulator was published at least once, next ld(i) operation will start a new rung
m_popstack = true;
@@ -316,7 +317,6 @@ basic_controller::run() -> int {
break;
}
auto &target { element( operation.element ) };
auto const initialstate { target.input() };
target.input() = m_accumulator.back();
// additional operations for advanced element types
switch( (basic_element::type_e)target.data.index() ) {
@@ -334,6 +334,8 @@ basic_controller::run() -> int {
*/
break;
}
default:
break;
}
// accumulator was published at least once, next ld(i) operation will start a new rung
m_popstack = true;
@@ -356,11 +358,16 @@ basic_controller::run() -> int {
std::get<basic_element::counter>(target.data).count_value = 0;
break;
}
default:
break;
}
// accumulator was published at least once, next ld(i) operation will start a new rung
m_popstack = true;
break;
}
default: {
break;
}
}
++programline;
}
@@ -381,17 +388,18 @@ basic_controller::log_error( std::string const &Error, int const Line ) const {
auto
basic_controller::guess_element_type_from_name( std::string const &Name ) const -> basic_element::type_e {
using enum plc::basic_element::type_e;
auto const name { split_string_and_number( Name ) };
auto const [nametype, nameindex]{ split_string_and_number( Name ) };
if( name.first == "t" || name.first == "ton" || name.first.find("timer.") == 0 ) {
return basic_element::type_e::timer;
if( nametype == "t" || nametype == "ton" || nametype.find("timer.") == 0 ) {
return timer;
}
if( name.first == "c" || name.first.find("counter.") == 0 ) {
return basic_element::type_e::counter;
if( nametype == "c" || nametype.find("counter.") == 0 ) {
return counter;
}
return basic_element::type_e::variable;
return variable;
}
} // plc

View File

@@ -27,7 +27,7 @@ public:
};
// constructors
template<typename ...Args_>
basic_element( basic_element::type_e Type = basic_element::type_e::variable, Args_ ...Args );
explicit basic_element( basic_element::type_e Type = basic_element::type_e::variable, Args_ ...Args );
// methods
// data access
auto input() -> int &;
@@ -60,7 +60,7 @@ class basic_controller {
public:
// methods
auto load( std::string const &Filename ) -> bool;
auto load( std::string_view Filename) -> bool;
auto update( double const Timestep ) -> int;
// finds element with specified name, potentially creating new element of specified type initialized with provided arguments. returns: handle to the element
template<typename ...Args_>
@@ -100,7 +100,7 @@ private:
// methods
auto deserialize_operation( cParser &Input ) -> bool;
// adds provided item to the collection. returns: true if there's no duplicate with the same name, false otherwise
auto insert( std::string const Name, basic_element Element ) -> element_handle;
auto insert( std::string const &Name, basic_element Element ) -> element_handle;
// runs one cycle of current program. returns: error code or 0 if there's no error
auto run() -> int;
void log_error( std::string const &Error, int const Line = -1 ) const;
@@ -110,13 +110,13 @@ private:
return Value == 0 ? 1 : 0; }
// element access
inline
auto element( element_handle const Element ) const -> basic_element const {
auto element( element_handle const Element ) const -> basic_element {
return m_elements[ Element - 1 ]; }
inline
auto element( element_handle const Element ) -> basic_element & {
return m_elements[ Element - 1 ]; }
// members
static std::map<std::string, basic_controller::opcode_e> const m_operationcodemap;
static std::map<std::string, basic_controller::opcode_e, std::less<>> const m_operationcodemap;
element_sequence m_elements; // collection of elements accessed by the plc program
name_sequence m_elementnames;
handle_sequence m_timerhandles; // indices of timer elements, timer update optimization helper
@@ -158,7 +158,7 @@ auto basic_controller::find_or_insert( std::string const &Name, basic_element::t
auto index { 1 };
for( auto const &name : m_elementnames ) {
if( name == Name ) {
return index;
return static_cast<element_handle>(index);
}
++index;
}

View File

@@ -145,10 +145,10 @@ int lua::scriptapi_event_create(lua_State *L)
int lua::scriptapi_event_find(lua_State *L)
{
std::string name = lua_tostring(L, 1);
basic_event *event = simulation::Events.FindEvent(name);
if (event)
basic_event *foundevent = simulation::Events.FindEvent(name);
if (foundevent)
{
lua_pushlightuserdata(L, event);
lua_pushlightuserdata(L, foundevent);
return 1;
}
ErrorLog("lua: missing event: " + name);
@@ -158,8 +158,8 @@ int lua::scriptapi_event_find(lua_State *L)
int lua::scriptapi_event_exists(lua_State *L)
{
std::string name = lua_tostring(L, 1);
basic_event *event = simulation::Events.FindEvent(name);
lua_pushboolean(L, event != nullptr);
basic_event *foundevent = simulation::Events.FindEvent(name);
lua_pushboolean(L, foundevent != nullptr);
return 1;
}
@@ -189,9 +189,9 @@ int lua::scriptapi_event_dispatch_n(lua_State *L)
std::string name = lua_tostring(L, 1);
auto *activator = static_cast<TDynamicObject *>(lua_touserdata(L, 2));
double delay = lua_tonumber(L, 3);
basic_event *event = simulation::Events.FindEvent(name);
if (event)
simulation::Events.AddToQuery(event, activator, delay);
basic_event *foundevent = simulation::Events.FindEvent(name);
if (foundevent)
simulation::Events.AddToQuery(foundevent, activator, delay);
else
ErrorLog("lua: missing event: " + name);
return 0;

View File

@@ -7,32 +7,31 @@
void texture_window_resize(GLFWwindow *win, int w, int h)
{
python_screen_viewer *texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
auto texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
texwindow->notify_window_size(win, w, h);
}
void texture_window_fb_resize(GLFWwindow *win, int w, int h)
{
python_screen_viewer *texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
auto texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
texwindow->notify_window_fb_size(win, w, h);
}
void texture_window_mouse_button(GLFWwindow *win, int button, int action, int mods)
void texture_window_mouse_button(GLFWwindow *win, int button, int action, int /*mods*/)
{
python_screen_viewer *texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
auto texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
texwindow->notify_click(win, button, action);
}
void texture_window_cursor_pos(GLFWwindow *win, double x, double y)
{
python_screen_viewer *texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
auto texwindow = (python_screen_viewer*)glfwGetWindowUserPointer(win);
texwindow->notify_cursor_pos(win, x, y);
}
python_screen_viewer::python_screen_viewer(std::shared_ptr<python_rt> rt, std::shared_ptr<std::vector<glm::vec2>> touchlist, std::string surfacename)
python_screen_viewer::python_screen_viewer(std::shared_ptr<python_rt> rt, std::shared_ptr<std::vector<glm::vec2>> touchlist, std::string const &surfacename)
: m_rt(rt), m_touchlist(touchlist)
{
m_rt = rt;
m_touchlist = touchlist;
for (const auto &viewport : Global.python_viewports) {
if (viewport.surface == surfacename) {
@@ -49,7 +48,8 @@ python_screen_viewer::python_screen_viewer(std::shared_ptr<python_rt> rt, std::s
monitor, false, Global.python_sharectx);
{
int w, h;
int w;
int h;
glfwGetWindowSize(conf->window, &w, &h);
conf->window_size = glm::ivec2(w, h);
glfwGetFramebufferSize(conf->window, &w, &h);
@@ -79,7 +79,7 @@ python_screen_viewer::~python_screen_viewer()
void python_screen_viewer::threadfunc()
{
for (auto &window : m_windows) {
for (auto const &window : m_windows) {
glfwMakeContextCurrent(window->window);
glfwSwapInterval(Global.python_vsync ? 1 : 0);
@@ -90,7 +90,7 @@ void python_screen_viewer::threadfunc()
glActiveTexture(GL_TEXTURE0);
if (Global.python_sharectx) {
glBindTexture(GL_TEXTURE_2D, m_rt->shared_tex->get_id());
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(m_rt->shared_tex->get_id()));
}
else {
GLuint tex;
@@ -115,13 +115,16 @@ void python_screen_viewer::threadfunc()
{
auto start_time = std::chrono::high_resolution_clock::now();
for (auto &window : m_windows) {
for (auto const &window : m_windows) {
unsigned char *image = nullptr;
int format, components, width, height;
int format;
int components;
int width;
int height;
if (!Global.python_sharectx) {
std::lock_guard<std::mutex> guard(m_rt->mutex);
std::scoped_lock guard(m_rt->mutex);
if (window->timestamp == m_rt->timestamp)
continue;
@@ -185,9 +188,9 @@ void python_screen_viewer::threadfunc()
}
}
void python_screen_viewer::notify_window_fb_size(GLFWwindow *window, int w, int h)
void python_screen_viewer::notify_window_fb_size(GLFWwindow const *window, int w, int h) const
{
for (auto &conf : m_windows) {
for (auto const &conf : m_windows) {
if (conf->window == window) {
conf->fb_size.x = w;
conf->fb_size.y = h;
@@ -196,9 +199,9 @@ void python_screen_viewer::notify_window_fb_size(GLFWwindow *window, int w, int
}
}
void python_screen_viewer::notify_window_size(GLFWwindow *window, int w, int h)
void python_screen_viewer::notify_window_size(GLFWwindow const *window, int w, int h) const
{
for (auto &conf : m_windows) {
for (auto const &conf : m_windows) {
if (conf->window == window) {
conf->window_size.x = w;
conf->window_size.y = h;
@@ -207,23 +210,23 @@ void python_screen_viewer::notify_window_size(GLFWwindow *window, int w, int h)
}
}
void python_screen_viewer::notify_cursor_pos(GLFWwindow *window, double x, double y)
void python_screen_viewer::notify_cursor_pos(GLFWwindow const *window, double x, double y) const
{
for (auto &conf : m_windows) {
for (auto const &conf : m_windows) {
if (conf->window == window) {
conf->cursor_pos.x = x;
conf->cursor_pos.y = y;
conf->cursor_pos.x = static_cast<int>(x);
conf->cursor_pos.y = static_cast<int>(y);
return;
}
}
}
void python_screen_viewer::notify_click(GLFWwindow *window, int button, int action)
void python_screen_viewer::notify_click(GLFWwindow const *window, int button, int action) const
{
if (button != GLFW_MOUSE_BUTTON_LEFT || action != GLFW_PRESS)
return;
for (auto &conf : m_windows) {
for (auto const &conf : m_windows) {
if (conf->window == window) {
auto pos = glm::vec2(conf->cursor_pos) / glm::vec2(conf->window_size);
pos.y = 1.0f - pos.y;

View File

@@ -35,11 +35,11 @@ class python_screen_viewer
void threadfunc();
public:
python_screen_viewer(std::shared_ptr<python_rt> rt, std::shared_ptr<std::vector<glm::vec2>> touchlist, std::string name);
python_screen_viewer(std::shared_ptr<python_rt> rt, std::shared_ptr<std::vector<glm::vec2>> touchlist, std::string const &name);
~python_screen_viewer();
void notify_window_size(GLFWwindow *window, int w, int h);
void notify_window_fb_size(GLFWwindow *window, int w, int h);
void notify_cursor_pos(GLFWwindow *window, double x, double y);
void notify_click(GLFWwindow *window, int button, int action);
void notify_window_size(GLFWwindow const *window, int w, int h) const;
void notify_window_fb_size(GLFWwindow const *window, int w, int h) const;
void notify_cursor_pos(GLFWwindow const *window, double x, double y) const;
void notify_click(GLFWwindow const *window, int button, int action) const;
};