Merge pull request #288 from GorgonMeducer/shell-filter-impl

implement shell filter
This commit is contained in:
Lyon 2023-02-13 08:08:12 +08:00 committed by GitHub
commit d61767d09e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 584 additions and 7 deletions

View File

@ -5,6 +5,7 @@
* MIT License
*
* Copyright (c) 2021 lyon liang6516@outlook.com
* Copyright (c) 2023 Gorgon Meducer embedded_zhuroan@hotmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -34,6 +35,7 @@
#include "dataMemory.h"
#include "dataString.h"
#include "dataStrs.h"
#include "dataQueue.h"
static volatile Arg* _help_modules_cmodule = NULL;
static volatile PIKA_BOOL in_root_obj = PIKA_FALSE;
@ -982,11 +984,221 @@ enum shellCTRL _inner_do_obj_runChar( PikaObj* self,
char inputChar,
ShellConfig* shell);
typedef enum {
__FILTER_NO_RESULT,
__FILTER_FAIL_DROP_ONE,
__FILTER_SUCCESS_GET_ALL_PEEKED,
__FILTER_SUCCESS_DROP_ALL_PEEKED
} FilterReturn;
PIKA_BOOL _filter_msg_hi_pika_handler( FilterItem *msg,
PikaObj* self,
ShellConfig* shell)
{
#if !(defined(__linux) || defined(_WIN32))
pika_platform_printf("Yes, I am here\r\n");
#endif
return PIKA_TRUE;
}
PIKA_BOOL _filter_msg_bye_pika_handler( FilterItem *msg,
PikaObj* self,
ShellConfig* shell)
{
#if !(defined(__linux) || defined(_WIN32))
pika_platform_printf("OK, see you\r\n");
#endif
return PIKA_TRUE;
}
#define __MSG_DECLARE
#include "__default_filter_msg_table.cfg"
static const FilterItem c_default_filter_messages[] = {
#define __MSG_TABLE
#include "__default_filter_msg_table.cfg"
};
static FilterReturn _do_message_filter( PikaObj* self,
ShellConfig* shell,
FilterItem *msg,
uint_fast16_t count)
{
pika_assert(NULL != messages);
pika_assert(count > 0);
ByteQueue *queue = &shell->filter_fifo.queue;
FilterReturn result = __FILTER_FAIL_DROP_ONE;
do {
do {
if (msg->ignore_mask & shell->filter_fifo.ignore_mask) {
/* this message should be ignored */
break;
}
if (NULL == msg->message){
break;
}
uint_fast16_t message_size = msg->size;
if (!message_size) {
break;
}
byte_queue_reset_peek(queue);
/* do message comparison */
uint8_t *src = (uint8_t *)msg->message;
if (msg->is_case_insensitive) {
do {
uint8_t byte;
if (!byte_queue_peek_one(queue, &byte)) {
result = __FILTER_NO_RESULT;
break;
}
char letter = *src++;
if (letter >= 'A' && letter <= 'Z') {
letter += 'a' - 'A';
}
if (byte >= 'A' && byte <= 'Z') {
byte += 'a' - 'A';
}
if (letter != byte) {
break;
}
} while(--message_size);
} else {
do {
uint8_t byte;
if (!byte_queue_peek_one(queue, &byte)) {
result = __FILTER_NO_RESULT;
break;
}
if (*src++ != byte) {
break;
}
} while(--message_size);
}
if (0 == message_size) {
/* message match */
if (NULL != msg->handler) {
if (!msg->handler(msg, self, shell)) {
break;
}
}
/* message is handled */
if (msg->is_visible) {
return __FILTER_SUCCESS_GET_ALL_PEEKED;
}
return __FILTER_SUCCESS_DROP_ALL_PEEKED;
}
} while(0);
msg++;
} while(--count);
return result;
}
#ifndef dimof
#define dimof(__array) (sizeof(__array) / sizeof(__array[0]))
#endif
int16_t _do_stream_filter(PikaObj* self, ShellConfig* shell){
ByteQueue *queue = &shell->filter_fifo.queue;
FilterReturn result = _do_message_filter(self,
shell,
(FilterItem *)c_default_filter_messages,
dimof(c_default_filter_messages));
int16_t drop_count = 0;
switch (result) {
case __FILTER_NO_RESULT:
break;
case __FILTER_FAIL_DROP_ONE:
drop_count = 1;
break;
case __FILTER_SUCCESS_DROP_ALL_PEEKED:
byte_queue_drop_all_peeked(queue);
return 0;
case __FILTER_SUCCESS_GET_ALL_PEEKED:
drop_count = byte_queue_get_peeked_number(queue);
return drop_count;
}
/* user registered message filter */
if (NULL != shell->messages && shell->message_count) {
result = _do_message_filter(self,
shell,
shell->messages,
shell->message_count);
switch (result) {
case __FILTER_NO_RESULT:
break;
case __FILTER_FAIL_DROP_ONE:
drop_count = 1;
break;
case __FILTER_SUCCESS_DROP_ALL_PEEKED:
byte_queue_drop_all_peeked(&shell->filter_fifo.queue);
return 0;
case __FILTER_SUCCESS_GET_ALL_PEEKED:
drop_count = byte_queue_get_peeked_number(&shell->filter_fifo.queue);
return drop_count;
}
}
return drop_count;
}
PIKA_WEAK
enum shellCTRL _do_obj_runChar(PikaObj* self,
char inputChar,
ShellConfig* shell) {
return _inner_do_obj_runChar(self, inputChar, shell);
ByteQueue *queue = &(shell->filter_fifo.queue);
/* validation */
if (NULL == queue->buffer) {
/* need initialize first */
byte_queue_init(queue,
&shell->filter_fifo.buffer,
sizeof(shell->filter_fifo.buffer),
PIKA_FALSE);
}
PIKA_BOOL result = byte_queue_write_one(queue, inputChar);
pika_assert(result != PIKA_FALSE);
int16_t byte_count;
do {
if (0 == byte_queue_peek_available_count(queue)) {
break;
}
byte_count = _do_stream_filter(self, shell);
int16_t n = byte_count;
while(n--) {
PIKA_BOOL result = byte_queue_read_one(queue, (uint8_t *)&inputChar);
pika_assert(result != PIKA_FALSE);
if (SHELL_CTRL_EXIT == _inner_do_obj_runChar(self, inputChar, shell)) {
return SHELL_CTRL_EXIT;
}
}
} while(byte_count);
return SHELL_CTRL_CONTINUE;
}
static

View File

@ -1,10 +1,11 @@
/*
/*
* This file is part of the PikaScript project.
* http://github.com/pikastech/pikascript
*
* MIT License
*
* Copyright (c) 2021 lyon liang6516@outlook.com
* Copyright (c) 2023 Gorgon Meducer embedded_zhuroan@hotmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -32,6 +33,7 @@
#include "dataLink.h"
#include "dataMemory.h"
#include "dataStrs.h"
#include "dataQueue.h"
typedef struct InstructUnit InstructUnit;
struct InstructUnit {
@ -277,7 +279,40 @@ typedef struct ShellConfig ShellConfig;
typedef enum shellCTRL (*sh_handler)(PikaObj*, char*, ShellConfig*);
typedef char (*sh_getchar)(void);
#if PIKA_SHELL_FILTER_ENABLE
typedef struct FilterFIFO {
ByteQueue queue;
uint8_t ignore_mask;
uint8_t buffer[PIKA_SHELL_FILTER_FIFO_SIZE];
} FilterFIFO;
typedef struct FilterItem FilterItem;
typedef PIKA_BOOL FilterMessageHandler( FilterItem *msg,
PikaObj* self,
ShellConfig* shell);
struct FilterItem {
FilterMessageHandler *handler;
const uint8_t *message;
uint16_t size;
uint8_t is_visible : 1;
uint8_t is_case_insensitive : 1;
uint8_t : 6;
uint8_t ignore_mask;
uintptr_t target;
};
#endif
struct ShellConfig {
#if PIKA_SHELL_FILTER_ENABLE
FilterFIFO filter_fifo;
FilterItem *messages;
uint16_t message_count;
uint16_t : 16; /* padding to suppress warning*/
#endif
char* prefix;
sh_handler handler;
void* context;

View File

@ -0,0 +1,69 @@
/*
* This file is part of the PikaScript project.
* http://github.com/pikastech/pikascript
*
* MIT License
*
* Copyright (c) 2023 GorgonMeducer ?? embedded_zhuoran@hotmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#undef add_filter_msg
#undef add_filter_item
#undef __add_filter_msg
#undef __add_filter_item
#undef __NO_FILTER_HANLDER__
#if defined(__MSG_TABLE)
#define __add_filter_msg(__name, __msg, ...) \
{ \
.message = (const uint8_t []){__msg}, \
.size = sizeof((const uint8_t []){__msg}) - 1, \
.handler = _filter_msg_##__name##_handler, \
__VA_ARGS__ \
},
#define __add_filter_item(__name, ...) \
{ \
.handler = _filter_msg_##__name##_handler, \
__VA_ARGS__ \
},
#endif
#if defined(__MSG_DECLARE)
#define __add_filter_msg(__name, __msg, ...) \
PIKA_BOOL _filter_msg_##__name##_handler( FilterItem *msg, \
PikaObj* self, \
ShellConfig* shell);
#define __add_filter_item(__name, ...) \
PIKA_BOOL _filter_msg_##__name##_handler( FilterItem *msg, \
PikaObj* self, \
ShellConfig* shell);
#endif
#undef __MSG_TABLE
#undef __MSG_DECLARE
#define add_filter_msg(__name, __msg, ...) \
__add_filter_msg(__name, __msg, ##__VA_ARGS__)
#define add_filter_item(__name, ...) \
__add_filter_item(__name, ##__VA_ARGS__)
#define __NO_FILTER_HANLDER__ .handler = NULL

View File

@ -0,0 +1,74 @@
/*
* This file is part of the PikaScript project.
* http://github.com/pikastech/pikascript
*
* MIT License
*
* Copyright (c) 2023 GorgonMeducer ?? embedded_zhuoran@hotmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "__default_filter_msg_def.h"
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunknown-warning-option"
# pragma clang diagnostic ignored "-Winitializer-overrides"
#endif
/* add your own message filter here with syntax:
*
* add_filter_msg(
* <name>,
* <string>,
* [.is_visible = PIKA_TRUE,]
* [.is_case_insensitive = PIKA_TRUE,]
* [.ignore_mask = mask value,]
* [.target = your own object address/value,]
* )
*/
add_filter_msg(hi_pika, "Hi Pika")
add_filter_msg(bye_pika, "bye pika", .is_case_insensitive = PIKA_TRUE)
/* add your own message item here with syntax:
*
* add_filter_item(
* <name>,
* .message = (const uint8_t []){< num0, num1, ... >},
* .size = <array size>,
* [.is_visible = PIKA_TRUE,]
* [.is_case_insensitive = PIKA_TRUE,]
* [.ignore_mask = mask value,]
* [.target = your own object address/value,]
* )
*
* for example:
*
* add_filter_item(
* example_array,
* .message = (const uint8_t []){'a','b','c'},
* .size = 3,
* __NO_FILTER_HANLDER__,
* )
*/
#if defined(__clang__)
# pragma clang diagnostic pop
#endif

View File

@ -26,11 +26,16 @@
* SOFTWARE.
*/
#ifndef __PIKA_OOC_H__
#define __PIKA_OOC_H__
#if PIKA_PLOOC_ENABLE
#include "../pikascript-lib/PLOOC/plooc_class.h"
#else
/* non-reentrant part */
#if !defined(PIKA_PLOOC_ENABLE) || !PIKA_PLOOC_ENABLE
#define private_member(...) __VA_ARGS__
#endif
#endif
/* plooc_class.h should support reentrant */
#if PIKA_PLOOC_ENABLE
#include "../pikascript-lib/PLOOC/plooc_class.h"
#endif

View File

@ -31,7 +31,7 @@
#include "PikaPlatform.h"
#include "PikaVersion.h"
/*! \NOTE: Make sure #include "plooc_class.h" is close to the class definition
/*! \NOTE: Make sure #include "__pika_ooc.h" is close to the class definition
*/
#if defined(__DATA_MEMORY_CLASS_IMPLEMENT__)
#define __PLOOC_CLASS_IMPLEMENT__

View File

@ -5,6 +5,7 @@
* MIT License
*
* Copyright (c) 2021 lyon liang6516@outlook.com
* Copyright (c) 2023 Gorgon Meducer embedded_zhuroan@hotmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -24,7 +25,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define __DATA_QUEUE_CLASS_IMPLEMENT__
#include "dataQueue.h"
#include "PikaPlatform.h"
#include "dataArgs.h"
@ -94,3 +95,143 @@ int32_t queue_pushStr(Queue* queue, char* str) {
char* queue_popStr(Queue* queue) {
return arg_getStr(__queue_popArg_noRmoveArg(queue));
}
ByteQueue *byte_queue_init( ByteQueue *queue,
void *buffer,
uint_fast16_t size,
PIKA_BOOL is_queue_full)
{
pika_assert(NULL != queue);
pika_assert(NULL != buffer);
pika_assert(size > 0);
pika_platform_memset(queue, 0, sizeof(ByteQueue));
queue->buffer = buffer;
queue->buffer_size = size;
if (is_queue_full) {
queue->count = size;
queue->peek_count = size;
}
return queue;
}
PIKA_BOOL byte_queue_read_one(ByteQueue *queue, uint8_t *byte_ptr)
{
pika_assert(NULL != queue);
uint8_t byte;
PIKA_BOOL result = PIKA_FALSE;
/* ------------------atomicity sensitive start---------------- */
do {
if ((queue->head == queue->tail) && (0 == queue->count)) {
/* empty */
break;
}
byte = queue->buffer[queue->head++];
queue->count--;
if (queue->head >= queue->buffer_size) {
queue->head = 0;
}
/* reset peek */
queue->peek_count = queue->count;
queue->peek = queue->head;
if (NULL != byte_ptr) {
*byte_ptr = byte;
}
result = PIKA_TRUE;
} while(0);
/* ------------------atomicity sensitive end ---------------- */
return result;
}
PIKA_BOOL byte_queue_peek_one(ByteQueue *queue, uint8_t *byte_ptr)
{
pika_assert(NULL != queue);
uint8_t byte;
PIKA_BOOL result = PIKA_FALSE;
/* ------------------atomicity sensitive start---------------- */
do {
if ((queue->peek == queue->tail) && (0 == queue->peek_count)) {
/* empty */
break;
}
byte = queue->buffer[queue->peek++];
queue->peek_count--;
if (queue->peek >= queue->buffer_size) {
queue->peek = 0;
}
if (NULL != byte_ptr) {
*byte_ptr = byte;
}
result = PIKA_TRUE;
} while(0);
/* ------------------atomicity sensitive end ---------------- */
return result;
}
void byte_queue_reset_peek(ByteQueue *queue)
{
pika_assert(NULL != queue);
/* ------------------atomicity sensitive start---------------- */
queue->peek_count = queue->count;
queue->peek = queue->head;
/* ------------------atomicity sensitive end ---------------- */
}
uint_fast16_t byte_queue_get_peeked_number(ByteQueue *queue)
{
return queue->count - queue->peek_count;
}
uint_fast16_t byte_queue_peek_available_count(ByteQueue *queue)
{
return queue->peek_count;
}
void byte_queue_drop_all_peeked(ByteQueue *queue)
{
pika_assert(NULL != queue);
/* ------------------atomicity sensitive start---------------- */
queue->count = queue->peek_count;
queue->head = queue->peek;
/* ------------------atomicity sensitive end ---------------- */
}
PIKA_BOOL byte_queue_write_one(ByteQueue *queue, uint8_t byte)
{
pika_assert(NULL != queue);
PIKA_BOOL result = PIKA_FALSE;
/* ------------------atomicity sensitive start---------------- */
do {
if ((queue->head == queue->tail) && (0 != queue->count)) {
/* full */
break;
}
queue->buffer[queue->tail++] = byte;
queue->count++;
queue->peek_count++;
if (queue->tail >= queue->buffer_size) {
queue->tail = 0;
}
result = PIKA_TRUE;
} while(0);
/* ------------------atomicity sensitive end ---------------- */
return result;
}

View File

@ -5,6 +5,7 @@
* MIT License
*
* Copyright (c) 2021 lyon liang6516@outlook.com
* Copyright (c) 2023 Gorgon Meducer embedded_zhuroan@hotmail.comByte
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -29,6 +30,29 @@
#define __DATA_QUEUE__H
#include "dataArgs.h"
/*! \NOTE: Make sure #include "__pika_ooc.h" is close to the class definition
*/
#if defined(__DATA_QUEUE_CLASS_IMPLEMENT__)
#define __PLOOC_CLASS_IMPLEMENT__
#undef __DATA_QUEUE_CLASS_IMPLEMENT__
#endif
#include "__pika_ooc.h"
typedef struct ByteQueue ByteQueue;
struct ByteQueue {
private_member(
uint8_t *buffer;
uint16_t buffer_size;
uint16_t head;
uint16_t tail;
uint16_t peek;
uint16_t count;
uint16_t peek_count;
)
};
typedef Args Queue;
Queue* New_queue(void);
@ -46,4 +70,17 @@ Arg* queue_popArg(Queue* queue);
Arg* queue_popArg_notDeinitArg(Queue* queue);
int32_t queue_deinit_stack(Queue* queue);
void queue_init(Queue* queue);
ByteQueue *byte_queue_init( ByteQueue *queue,
void *buffer,
uint_fast16_t size,
PIKA_BOOL is_queue_full);
PIKA_BOOL byte_queue_read_one(ByteQueue *queue, uint8_t *byte_ptr);
PIKA_BOOL byte_queue_peek_one(ByteQueue *queue, uint8_t *byte_ptr);
void byte_queue_reset_peek(ByteQueue *queue);
void byte_queue_drop_all_peeked(ByteQueue *queue);
uint_fast16_t byte_queue_get_peeked_number(ByteQueue *queue);
uint_fast16_t byte_queue_peek_available_count(ByteQueue *queue);
PIKA_BOOL byte_queue_write_one(ByteQueue *queue, uint8_t byte);
#endif

View File

@ -352,6 +352,10 @@
#define PIKA_SHELL_FILTER_ENABLE 0
#endif
#ifndef PIKA_SHELL_FILTER_FIFO_SIZE
#define PIKA_SHELL_FILTER_FIFO_SIZE 32
#endif
#ifndef PIKA_EVENT_LIST_SIZE
#define PIKA_EVENT_LIST_SIZE 16
#endif