/** * @file datarouter.c */ #include "datarouter.h" #include #if defined(__GNUC__) || defined(__clang__) #define DR_WEAK __attribute__((weak)) #else #define DR_WEAK #endif #ifndef DR_MAX_PORTS #define DR_MAX_PORTS 64 #endif typedef struct { int send_type; dr_send_handler_t handlers[DR_MAX_HANDLERS_PER_PORT]; int count; uint8_t in_use; } port_entry_t; static port_entry_t ports[DR_MAX_PORTS]; static uint8_t initialized; /* ---- 元数据 ---- */ static const char *send_names[] = { #define DR_SEND(id, desc) #id, DR_SEND_CAPABILITIES #undef DR_SEND }; static const char *send_descs[] = { #define DR_SEND(id, desc) desc, DR_SEND_CAPABILITIES #undef DR_SEND }; static const char *recv_names[] = { #define DR_RECV(id, desc) #id, DR_RECV_CAPABILITIES #undef DR_RECV }; static const char *recv_descs[] = { #define DR_RECV(id, desc) desc, DR_RECV_CAPABILITIES #undef DR_RECV }; /* ---- 弱符号接收回调 ---- */ #define DR_RECV(id, desc) \ DR_WEAK void dr_on_recv_##id( \ uint32_t port_id, const void *data, size_t len) \ { (void)port_id; (void)data; (void)len; } DR_RECV_CAPABILITIES #undef DR_RECV /* ---- 发送触发函数 ---- */ #define DR_SEND(id, desc) \ int dr_send_##id(const void *data, size_t len) \ { \ if (!initialized) return -1; \ int called = 0; \ for (uint32_t _p = 0; _p < DR_MAX_PORTS; _p++) { \ if (!ports[_p].in_use) continue; \ if (ports[_p].send_type != DR_SEND_##id) continue; \ for (int _h = 0; _h < ports[_p].count; _h++) { \ ports[_p].handlers[_h](_p, data, len); \ called = 1; \ } \ } \ return called ? 0 : -2; \ } DR_SEND_CAPABILITIES #undef DR_SEND /* ---- 端口管理 ---- */ void dr_init(void) { if (initialized) return; memset(ports, 0, sizeof(ports)); initialized = 1; } void dr_reset(void) { initialized = 0; memset(ports, 0, sizeof(ports)); } dr_port_t dr_port_create(void) { if (!initialized) return DR_INVALID_PORT; for (int i = 0; i < DR_MAX_PORTS; i++) { if (!ports[i].in_use) { ports[i].in_use = 1; ports[i].send_type = -1; ports[i].count = 0; return (dr_port_t)i; } } return DR_INVALID_PORT; } void dr_port_delete(dr_port_t port) { if (!initialized) return; if (port < 0 || port >= DR_MAX_PORTS) return; ports[port].in_use = 0; } void dr_port_set_send_type(dr_port_t port, int cap_id) { if (!initialized) return; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return; ports[port].send_type = cap_id; } int dr_port_get_send_type(dr_port_t port) { if (!initialized) return -1; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1; return ports[port].send_type; } int dr_port_add_handler(dr_port_t port, dr_send_handler_t handler) { if (!initialized) return -1; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1; if (ports[port].count >= DR_MAX_HANDLERS_PER_PORT) return -2; for (int i = 0; i < ports[port].count; i++) if (ports[port].handlers[i] == handler) return -3; ports[port].handlers[ports[port].count++] = handler; return 0; } int dr_port_remove_handler(dr_port_t port, dr_send_handler_t handler) { if (!initialized) return -1; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1; for (int i = 0; i < ports[port].count; i++) { if (ports[port].handlers[i] == handler) { ports[port].handlers[i] = ports[port].handlers[--ports[port].count]; return 0; } } return -2; } void dr_port_clear_handlers(dr_port_t port) { if (!initialized) return; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return; ports[port].count = 0; } int dr_port_handler_count(dr_port_t port) { if (!initialized) return -1; if (port < 0 || port >= DR_MAX_PORTS || !ports[port].in_use) return -1; return ports[port].count; } /* ---- 元数据查询 ---- */ int dr_send_cap_count(void) { return DR_SEND_CAP_COUNT; } const char *dr_send_cap_name(int c) { return (c<0||c>=DR_SEND_CAP_COUNT)?NULL:send_names[c]; } const char *dr_send_cap_desc(int c) { return (c<0||c>=DR_SEND_CAP_COUNT)?NULL:send_descs[c]; } int dr_recv_cap_count(void) { return DR_RECV_CAP_COUNT; } const char *dr_recv_cap_name(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_names[c]; } const char *dr_recv_cap_desc(int c) { return (c<0||c>=DR_RECV_CAP_COUNT)?NULL:recv_descs[c]; }