From 412db1f293cd8f997583a4a90202a6e030f0e66a Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Tue, 23 Dec 2025 12:07:55 +0100 Subject: [PATCH] remove c ascii parsing --- plugin.lua | 11 +++- src/ascii_cmd.c | 132 ----------------------------------------------- src/ascii_cmd.h | 12 ----- src/command.lua | 91 ++++++++++++++++---------------- src/lua_rds.c | 80 +++++++++++++++++++++++++++- src/udp_server.c | 1 - src/udp_server.h | 5 +- 7 files changed, 137 insertions(+), 195 deletions(-) delete mode 100644 src/ascii_cmd.c delete mode 100644 src/ascii_cmd.h diff --git a/plugin.lua b/plugin.lua index f6866e0..dd18952 100644 --- a/plugin.lua +++ b/plugin.lua @@ -226,4 +226,13 @@ function set_rds_eon(eon, enabled, pi, tp, ta, pty, ps, afs, data) end ---@return string ps ---@return table _ this is empty, getting afs is not supported yet ---@return integer data -function get_rds_eon(eon) end \ No newline at end of file +function get_rds_eon(eon) end + +---Sets the X/Y of the UDG +---@param xy boolean +---@param groups table Table of tables, this should be up to 8 tables containing 3 integers +function set_rds_udg(xy, groups) end +---Sets the X/Y of the UDG for RDS2 +---@param xy boolean +---@param groups table Table of tables, this should be up to 8 tables containing 4 integers +function set_rds_udg2(xy, groups) end \ No newline at end of file diff --git a/src/ascii_cmd.c b/src/ascii_cmd.c deleted file mode 100644 index 50c7021..0000000 --- a/src/ascii_cmd.c +++ /dev/null @@ -1,132 +0,0 @@ -#include "ascii_cmd.h" - -typedef struct { - const char *cmd; - void (*handler)(char *arg, RDSModulator* mod, char* output); - uint8_t cmd_length; -} command_handler_t; - -typedef struct { - const char *prefix; - const char *suffix; - void (*handler)(char *arg, char *pattern, RDSModulator* mod, char* output); -} pattern_command_handler_t; - -static void handle_udg(char *arg, char *pattern, RDSModulator* mod, char* output) { - uint8_t all_scanned = 1, bad_format = 0; - uint16_t blocks[8][3]; - int sets = 0; - char *ptr = arg; - - while (sets < 8) { - int count = sscanf(ptr, "%4hx%4hx%4hx", &blocks[sets][0], &blocks[sets][1], &blocks[sets][2]); - if (count != 3) { - all_scanned = 0; - break; - } - sets++; - while (*ptr && *ptr != ',') ptr++; - if (*ptr == ',') ptr++; - else { - bad_format = 1; - break; - } - } - - if (strcmp(pattern, "1") == 0) { - memcpy(&(mod->enc->data[mod->enc->program].udg1), &blocks, sets * sizeof(uint16_t[3])); - mod->enc->data[mod->enc->program].udg1_len = sets; - } else if(strcmp(pattern, "2") == 0) { - memcpy(&(mod->enc->data[mod->enc->program].udg2), &blocks, sets * sizeof(uint16_t[3])); - mod->enc->data[mod->enc->program].udg2_len = sets; - } else strcpy(output, "!"); - if(bad_format) strcpy(output, "-"); - else if(all_scanned) strcpy(output, "+"); - else strcpy(output, "/"); -} - -static void handle_udg2(char *arg, char *pattern, RDSModulator* mod, char* output) { - uint8_t all_scanned = 1, bad_format = 0; - uint16_t blocks[8][4]; - int sets = 0; - char *ptr = arg; - - while (sets < 8) { - int count = sscanf(ptr, "%4hx%4hx%4hx%4hx", &blocks[sets][0], &blocks[sets][1], &blocks[sets][2], &blocks[sets][3]); - if (count != 4) { - all_scanned = 0; - break; - } - sets++; - while (*ptr && *ptr != ',') ptr++; - if (*ptr == ',') ptr++; - else { - bad_format = 1; - break; - } - } - - if (strcmp(pattern, "1") == 0) { - memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), &blocks, sets * sizeof(uint16_t[4])); - mod->enc->data[mod->enc->program].udg1_len_rds2 = sets; - } else if(strcmp(pattern, "2") == 0) { - memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), &blocks, sets * sizeof(uint16_t[4])); - mod->enc->data[mod->enc->program].udg2_len_rds2 = sets; - } else strcpy(output, "!"); - if(bad_format) strcpy(output, "-"); - else if(all_scanned) strcpy(output, "+"); - else strcpy(output, "/"); -} - - -static const pattern_command_handler_t pattern_commands[] = { - {"UDG", "", handle_udg}, - {"2UDG", "", handle_udg2}, -}; - -static bool process_pattern_commands(char *cmd, char *arg, char *output, RDSModulator* mod) { - size_t cmd_len = strlen(cmd); - char pattern_buffer[16] = {0}; - for (size_t i = 0; i < sizeof(pattern_commands) / sizeof(pattern_command_handler_t); i++) { - const pattern_command_handler_t *handler = &pattern_commands[i]; - size_t prefix_len = strlen(handler->prefix); - size_t suffix_len = strlen(handler->suffix); - if (cmd_len > (prefix_len + suffix_len) && strncmp(cmd, handler->prefix, prefix_len) == 0 && strcmp(cmd + cmd_len - suffix_len, handler->suffix) == 0) { - size_t pattern_len = cmd_len - prefix_len - suffix_len; - if (pattern_len < sizeof(pattern_buffer)) { - strncpy(pattern_buffer, cmd + prefix_len, pattern_len); - pattern_buffer[pattern_len] = 0; - handler->handler(arg, pattern_buffer, mod, output); - return true; - } - } - } - return false; -} - -void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output) { - (void)cmd_output; - char *cmd, *arg; - - char output[255]; - memset(output, 0, sizeof(output)); - - char upper_str[CTL_BUFFER_SIZE]; - uint16_t cmd_len = _strnlen((const char*)str, CTL_BUFFER_SIZE); - for(uint16_t i = 0; i < cmd_len; i++) if(str[i] == '\t') str[i] = ' '; - - strncpy(upper_str, str, CTL_BUFFER_SIZE); - upper_str[CTL_BUFFER_SIZE-1] = 0; - - for(uint16_t i = 0; i < cmd_len && upper_str[i] != '='; i++) { - if(upper_str[i] >= 'a' && upper_str[i] <= 'z') upper_str[i] = upper_str[i] - 'a' + 'A'; - } - - char *equals_pos = strchr(upper_str, '='); - if (equals_pos != NULL) { - cmd = upper_str; - cmd[equals_pos - upper_str] = 0; - arg = equals_pos + 1; - process_pattern_commands(cmd, arg, output, mod); - } -} \ No newline at end of file diff --git a/src/ascii_cmd.h b/src/ascii_cmd.h deleted file mode 100644 index 7e6f912..0000000 --- a/src/ascii_cmd.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "common.h" -#include "rds.h" -#include "fs.h" -#include "modulator.h" -#include "lib.h" -#define CMD_BUFFER_SIZE 255 -#define CTL_BUFFER_SIZE (CMD_BUFFER_SIZE * 2) -#define READ_TIMEOUT_MS 225 - -void process_ascii_cmd(RDSModulator* mod, char *str, char *cmd_output); \ No newline at end of file diff --git a/src/command.lua b/src/command.lua index d2ac85c..417624e 100644 --- a/src/command.lua +++ b/src/command.lua @@ -2,8 +2,7 @@ if type(data) == "string" and data ~= nil then local cmd, value = data:match("([^=]+)=([^=]+)") if cmd == nil then data = data:lower() - if data == "ver" then - return string.format("rds95 v. %s - (C) 2025 radio95 - lua parser", core_version) + if data == "ver" then return string.format("rds95 v. %s - (C) 2025 radio95 - lua parser", core_version) elseif data == "init" then set_rds_program_defaults() return "+" @@ -48,28 +47,17 @@ if type(data) == "string" and data ~= nil then local eon_cmd, eon_num = data:match("^eon(%d+)([a-z]+)$") if eon_cmd then local eon_idx = tonumber(eon_cmd) - if not eon_idx or eon_idx < 1 or eon_idx > eon_count then - return "?" - end - + if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?" end eon_idx = eon_idx - 1 - local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx) - if eon_num == "en" then - return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0) - elseif eon_num == "pi" then - return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi) - elseif eon_num == "ps" then - return string.format("EON%dPS=%s\r\n", eon_idx + 1, ps) - elseif eon_num == "pty" then - return string.format("EON%dPTY=%d\r\n", eon_idx + 1, pty) - elseif eon_num == "ta" then - return string.format("EON%dTA=%d\r\n", eon_idx + 1, ta and 1 or 0) - elseif eon_num == "tp" then - return string.format("EON%dTP=%d\r\n", eon_idx + 1, tp and 1 or 0) - elseif eon_num == "dt" then - return string.format("EON%dDT=%x\r\n", eon_idx + 1, data_val) + if eon_num == "en" then return string.format("EON%dEN=%d\r\n", eon_idx + 1, enabled and 1 or 0) + elseif eon_num == "pi" then return string.format("EON%dPI=%x\r\n", eon_idx + 1, pi) + elseif eon_num == "ps" then return string.format("EON%dPS=%s\r\n", eon_idx + 1, ps) + elseif eon_num == "pty" then return string.format("EON%dPTY=%d\r\n", eon_idx + 1, pty) + elseif eon_num == "ta" then return string.format("EON%dTA=%d\r\n", eon_idx + 1, ta and 1 or 0) + elseif eon_num == "tp" then return string.format("EON%dTP=%d\r\n", eon_idx + 1, tp and 1 or 0) + elseif eon_num == "dt" then return string.format("EON%dDT=%x\r\n", eon_idx + 1, data_val) end end return "?" @@ -81,58 +69,44 @@ if type(data) == "string" and data ~= nil then local eon_num, eon_type = cmd:match("^eon(%d+)([a-z]+)$") if eon_num then local eon_idx = tonumber(eon_num) - if not eon_idx or eon_idx < 1 or eon_idx > eon_count then - return "?" - end - + if not eon_idx or eon_idx < 1 or eon_idx > eon_count then return "?" end eon_idx = eon_idx - 1 local enabled, pi, tp, ta, pty, ps, afs, data_val = get_rds_eon(eon_idx) - if eon_type == "en" then local en_val = tonumber(value) if not en_val then return "-" end enabled = (en_val ~= 0) set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) return "+" - elseif eon_type == "pi" then local pi_val = tonumber(value, 16) if not pi_val then return "-" end set_rds_eon(eon_idx, enabled, pi_val, tp, ta, pty, ps, afs, data_val) return "+" - elseif eon_type == "ps" then local ps_val = value:sub(1, 24) set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps_val, afs, data_val) return "+" - elseif eon_type == "pty" then local pty_val = tonumber(value) if not pty_val then return "-" end set_rds_eon(eon_idx, enabled, pi, tp, ta, pty_val, ps, afs, data_val) return "+" - elseif eon_type == "ta" then - if not enabled or not tp then - return "-" - end + if not enabled or not tp then return "-" end local ta_val = tonumber(value) if not ta_val then return "-" end ta = (ta_val ~= 0) set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) - if ta then - set_rds_ta(true) - end + if ta then set_rds_ta(true) end return "+" - elseif eon_type == "tp" then local tp_val = tonumber(value) if not tp_val then return "-" end tp = (tp_val ~= 0) set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, data_val) return "+" - elseif eon_type == "af" then local af_table = {} if value == "" or value == "0" then @@ -141,24 +115,49 @@ if type(data) == "string" and data ~= nil then end for freq_str in value:gmatch("([^,]+)") do local f = tonumber(freq_str) - if f then - table.insert(af_table, f) - else - return "-" - end + if f then table.insert(af_table, f) + else return "-" end end if #af_table > 25 then return "-" end set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, af_table, data_val) return "+" - elseif eon_type == "dt" then local dt_val = tonumber(value, 16) if not dt_val then return "-" end set_rds_eon(eon_idx, enabled, pi, tp, ta, pty, ps, afs, dt_val) return "+" - else - return "?" + else return "?" end + end + + local udg_num = cmd:match("^udg([12])$") + local udg2_num = cmd:match("^2udg([12])$") + if udg_num then + local xy = (udg_num == "1") + local groups = {} + + for segment in value:gmatch("([^,]+)") do + local b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$") + if not (b and c and d) then return "-" end + table.insert(groups, {tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)}) end + + if #groups > 8 or #groups == 0 then return "-" end + set_rds_udg(xy, groups) + return "+" + end + if udg2_num then + local xy = (udg2_num == "1") + local groups = {} + + for segment in value:gmatch("([^,]+)") do + local a, b, c, d = segment:match("^(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)(%x%x%x%x)$") + if not (a and b and c and d) then return "-" end + table.insert(groups, {tonumber(a, 16), tonumber(b, 16), tonumber(c, 16), tonumber(d, 16)}) + end + + if #groups > 8 or #groups == 0 then return "-" end + set_rds_udg2(xy, groups) + return "+" end if cmd == "pi" then diff --git a/src/lua_rds.c b/src/lua_rds.c index 4aef48e..3d794ea 100644 --- a/src/lua_rds.c +++ b/src/lua_rds.c @@ -61,6 +61,7 @@ int lua_set_rds_##name(lua_State *localL) { \ for (int i = 1; i <= n; i++) { \ lua_rawgeti(localL, 1, i); \ if (lua_isnumber(localL, -1)) add_func(&new_af, lua_tonumber(localL, -1)); \ + else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); \ lua_pop(localL, 1); \ } \ memcpy(&(mod->enc->data[mod->enc->program].af_field), &new_af, sizeof(new_af)); \ @@ -296,14 +297,15 @@ int lua_set_rds_eon(lua_State *localL) { memset(&(mod->enc->data[mod->enc->program].eon[eon].af), 0, sizeof(RDSAFs)); return 0; } - if(n > 25) return luaL_error(localL, "table length over 25"); \ + if(n > 25) return luaL_error(localL, "table length over 25"); RDSAFs new_af; memset(&new_af, 0, sizeof(RDSAFs)); for (int i = 1; i <= n; i++) { - lua_rawgeti(localL, 8, i); \ + lua_rawgeti(localL, 8, i); if (lua_isnumber(localL, -1)) add_rds_af(&new_af, lua_tonumber(localL, -1)); + else return luaL_error(localL, "number expected, got %s", luaL_typename(localL, -1)); lua_pop(localL, 1); } memcpy(&(mod->enc->data[mod->enc->program].eon[eon].af), &new_af, sizeof(new_af)); @@ -324,6 +326,77 @@ int lua_get_rds_eon(lua_State *localL) { return 8; } +int lua_set_rds_udg(lua_State *localL) { + if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1)); + int xy = lua_toboolean(localL, 1); + luaL_checktype(localL, 2, LUA_TTABLE); + int n = lua_rawlen(localL, 2); + if(n > 8) return luaL_error(localL, "table length over 8"); + + uint16_t blocks[8][3] = {0}; + + for (int i = 1; i <= n; i++) { + lua_rawgeti(localL, 2, i); + if(lua_istable(localL, -1)) { + int n2 = lua_rawlen(localL, -1); + if(n2 > 3) return luaL_error(localL, "table length over 3"); + for(int j = 1; j <= n2; j++) { + lua_rawgeti(localL, -1, j); + if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1); + else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1)); + lua_pop(localL, 1); + } + } + else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1)); + lua_pop(localL, 1); + } + + if(xy) { + memcpy(&(mod->enc->data[mod->enc->program].udg2), blocks, n * sizeof(uint16_t[3])); + mod->enc->data[mod->enc->program].udg2_len = n; + } else { + memcpy(&(mod->enc->data[mod->enc->program].udg1), blocks, n * sizeof(uint16_t[3])); + mod->enc->data[mod->enc->program].udg1_len = n; + } + + return 0; +} +int lua_set_rds_udg2(lua_State *localL) { + if (!lua_isboolean(localL, 1)) return luaL_error(localL, "boolean expected, got %s", luaL_typename(localL, 1)); + int xy = lua_toboolean(localL, 1); + luaL_checktype(localL, 2, LUA_TTABLE); + int n = lua_rawlen(localL, 2); + if(n > 8) return luaL_error(localL, "table length over 8"); + + uint16_t blocks[8][4] = {0}; + + for (int i = 1; i <= n; i++) { + lua_rawgeti(localL, 2, i); + if(lua_istable(localL, -1)) { + int n2 = lua_rawlen(localL, -1); + if(n2 > 4) return luaL_error(localL, "table length over 4"); + for(int j = 1; j <= n2; j++) { + lua_rawgeti(localL, -1, j); + if (lua_isinteger(localL, -1)) blocks[i-1][j-1] = lua_tointeger(localL, -1); + else return luaL_error(localL, "integer expected, got %s", luaL_typename(localL, -1)); + lua_pop(localL, 1); + } + } + else return luaL_error(localL, "table expected, got %s", luaL_typename(localL, -1)); + lua_pop(localL, 1); + } + + if(xy) { + memcpy(&(mod->enc->data[mod->enc->program].udg2_rds2), blocks, n * sizeof(uint16_t[4])); + mod->enc->data[mod->enc->program].udg2_len_rds2 = n; + } else { + memcpy(&(mod->enc->data[mod->enc->program].udg1_rds2), blocks, n * sizeof(uint16_t[4])); + mod->enc->data[mod->enc->program].udg1_len_rds2 = n; + } + + return 0; +} + void init_lua(RDSModulator* rds_mod) { mod = rds_mod; L = luaL_newstate(); @@ -436,6 +509,9 @@ void init_lua(RDSModulator* rds_mod) { lua_register(L, "set_rds_eon", lua_set_rds_eon); lua_register(L, "get_rds_eon", lua_get_rds_eon); + + lua_register(L, "set_rds_udg", lua_set_rds_udg); + lua_register(L, "set_rds_udg2", lua_set_rds_udg2); } void run_lua(char *str, char *cmd_output) { diff --git a/src/udp_server.c b/src/udp_server.c index 391c53a..3abeb9a 100644 --- a/src/udp_server.c +++ b/src/udp_server.c @@ -59,7 +59,6 @@ void poll_udp_server() { strncpy(cmd_buf, token, BUF_SIZE - 1); memset(cmd_output, 0, BUF_SIZE); - process_ascii_cmd(mod, cmd_buf, NULL); run_lua(cmd_buf, cmd_output); size_t out_len = strlen(cmd_output); diff --git a/src/udp_server.h b/src/udp_server.h index 009b09a..b09095a 100644 --- a/src/udp_server.h +++ b/src/udp_server.h @@ -11,9 +11,12 @@ #include #include #include "modulator.h" -#include "ascii_cmd.h" #include "lua_rds.h" +#define CMD_BUFFER_SIZE 255 +#define CTL_BUFFER_SIZE (CMD_BUFFER_SIZE * 2) +#define READ_TIMEOUT_MS 225 + int open_udp_server(int port, RDSModulator *rds_mod); void poll_udp_server(); void close_udp_server();