реклама на сайте
подробности

 
 
> Command line parser
Jenya7
сообщение Apr 13 2015, 07:03
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



До сих пор пользовался таким парсером
Код
void PARSER_ParseUart(char *str)
{
    str = ToLower(str);
    if(strlen(str) == 0)
        goto exit;
    char *command;
    char *argument1="";
    char *argument2="";
    char *argument3="";
    command = strtok(str," ");
    argument1 = strtok (NULL, " ");
    argument2 = strtok (NULL, " ");
    argument3 = strtok (NULL, " ");
    if(strcmp(command,"command1")==0)
    {
        if(argument1 == NULL)
        {
                  UART_SendInt(UART0,FunctionReadsValue());    
          }
        else
        {
            int val1 = atoi(argument1);
            FunctionWritesValue(val1);
        }
    }
    else if(strcmp(command,"command2")==0)
    {
        if(argument1 == NULL)
        {
                UART_SendInt(UART0,FunctionReadsValue());
        }
        else if (argument2 == NULL || argument3 == NULL)
        {
           FunctionDoSmething();
        }
             else
             {
                FunctionDoAnotherThing();
             }
       }
       //and so on………………        
}

В принципе я этим способом доволен, работает четко. Но сейчас количество команд перевалило за 100. Функция стала монструозной к тому же жрет много флэша.
Поэтому я решил замутить что то вроде этого
Код
struct command
{
    char *name;  //command name
    char mode;   //0-read, 1- read/write
    int minval;  
    int maxval;
    char val_changed;  
    void (*fp) (void);  //function pointer
};

struct command commands[10];

struct command commands[] = {
    {"imax", 1, 1000, 10000, 0, get_imax},
    {"inow", 0, 1000, 10000, 0, get_inow},
    {"top",  1, 100,  2500,  0, get_top},
    {"pos",  0, 100000, 100000, 0, get_pos},
};

void get_command(char *com)
{
     int I;
     for (i = 0; i < sizeof(commands); i++)
     {
         if(strcmp(commands[i].name, com) == 0)
         {
            //do something
         }
     }
}

Вопрос как сделать универсальный указатель на функцию чтоб могла возвращать значение и содержать любое количество аргументов.
А может у кого нибудь есть более интересное решение?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
CrimsonPig
сообщение Apr 13 2015, 07:52
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502



Цитата(Jenya7 @ Apr 13 2015, 08:03) *
Вопрос как сделать универсальный указатель на функцию чтоб могла возвращать значение и содержать любое количество аргументов.


Если чтоб еще и работало, то никак sm.gif
Можно сделать аналог функционального объекта (functor) (ну или сам функциональный объект если используем Ц++). Он инкапсулирует указатель на функцию и ее аргументы и в простейшем случае один метод, при вызове которого он вызывает функцию по указателю с данными аргументами.

Цитата(Jenya7 @ Apr 13 2015, 08:03) *
А может у кого нибудь есть более интересное решение?


Тупой перебор всех команд в цикле с strcmp это работает до какого-то предела, потом начинает тормозить.
Например, если таких команд больше 1000, то становится весело.
"Более интересное решение" это сделать парсер текстовых команд, которые представлены в виде дерева. Но это не сильно тривиально и могут возникнуть проблемы с добавлением\измненением этих команд в коде программы.

В качестве промежуточного варианта можно использовать хэширование - посчитать perfect hash команд заранее и построить hash table, в которой будут храниться указатели на функици - обработчики команд. Приходит команда, считаем ее хэш, вызываем функцию из хэш-таблицы, она парсит аргументы и делает другие полезные дела.





Go to the top of the page
 
+Quote Post
Jenya7
сообщение Apr 13 2015, 08:04
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 778
Регистрация: 29-03-12
Пользователь №: 71 075



Цитата(CrimsonPig @ Apr 13 2015, 13:52) *
Если чтоб еще и работало, то никак sm.gif
Можно сделать аналог функционального объекта (functor) (ну или сам функциональный объект если используем Ц++). Он инкапсулирует указатель на функцию и ее аргументы и в простейшем случае один метод, при вызове которого он вызывает функцию по указателю с данными аргументами.



Тупой перебор всех команд в цикле с strcmp это работает до какого-то предела, потом начинает тормозить.
Например, если таких команд больше 1000, то становится весело.
"Более интересное решение" это сделать парсер текстовых команд, которые представлены в виде дерева. Но это не сильно тривиально и могут возникнуть проблемы с добавлением\измненением этих команд в коде программы.

В качестве промежуточного варианта можно использовать хэширование - посчитать perfect hash команд заранее и построить hash table, в которой будут храниться указатели на функици - обработчики команд. Приходит команда, считаем ее хэш, вызываем функцию из хэш-таблицы, она парсит аргументы и делает другие полезные дела.

Перебор по скорости не так уж плох. Кроме того комманды можно разбить на группы тогда перебор будет еще быстрее. Меня больше беспокоит размер функции - она уже отжирает здоровый кусок флэша а он у меня заканчивается.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th August 2025 - 00:16
Рейтинг@Mail.ru


Страница сгенерированна за 0.01435 секунд с 7
ELECTRONIX ©2004-2016