/**************************************************************************** ** OrangeBot Project ***************************************************************************** ** / ** / ** / ** ______ \ ** \ ** \ ***************************************************************************** ** UNIVERSAL PARSER ***************************************************************************** ** Author: Orso Eric ** Creation Date: 2019-06-17 ** Last Edit Date: 2020-01-15 ** Revision: 2 ** Version: 5.0 ****************************************************************************/ /**************************************************************************** ** DESCRIPTION ***************************************************************************** ** Do a universal parser that does not require malloc/free and do not use explicit dictionary ** I create a special register command function in which the message and an handler is provided ****************************************************************************/ /**************************************************************************** ** COMMAND RULES ***************************************************************************** ** ADD COMMAND TO PARSER ** A command is composed by fixed alphanumeric chars and argument descriptors ** Each command is associated with a unique function callback ** A command can only start with letters ** ** EXAMPLE ADD COMMAND TO PARSER ** myparser.add_cmd("P", (void *)&my_ping_handler ); ** Add a new command that is triggered when the string P\0 is received. ** function my_ping_handler will be automatically executed when the \0 is processed ** myparser.parse( 'P' ); ** myparser.parse( '\0' ); ** send manually bytes to the parser to test the system ***************************************************************************** ** Command restriction: ** >Can only start with a letter ** >Valid arguments are %u %s %U %S %d %D ** >There can be no commands with same start but two different argument type. Only the first one will be considered in case ** PWM%d... ** PWM%u... ** The parser has no way of knowing if the incoming input (example 10) is meant for one command or the other ** >After valid ID access parameters using Parser Macros ****************************************************************************/ /**************************************************************************** ** KNOWN BUG ***************************************************************************** ** ****************************************************************************/ /**************************************************************************** ** INCLUDES ****************************************************************************/ //#include #include #include #define ENABLE_DEBUG #include "debug.h" //Class Header #include "uniparser.h" /**************************************************************************** ** NAMESPACES ****************************************************************************/ namespace Orangebot { /**************************************************************************** ** GLOBAL VARIABILES ****************************************************************************/ /**************************************************************************** ***************************************************************************** ** CONSTRUCTORS ***************************************************************************** ****************************************************************************/ /***************************************************************************/ //! @brief Empty Constructor //! Uniparser | void /***************************************************************************/ // @param //! @return no return //! @details //! Empty constructor /***************************************************************************/ Uniparser::Uniparser( void ) { //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! @details algorithm: //Initialize structure to safe values this -> init(); //Pass a terminator to the parser to have it initialize itself this -> parse( '\0' ); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- return; } //end constructor: /**************************************************************************** ***************************************************************************** ** DESTRUCTORS ***************************************************************************** ****************************************************************************/ /***************************************************************************/ //! @brief Empty Destructor //! Uniparser | void /***************************************************************************/ // @param //! @return no return //! @details //! Empty destructor /***************************************************************************/ Uniparser::~Uniparser( void ) { //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! @details algorithm: //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- return; } //end destructor: /**************************************************************************** ***************************************************************************** ** OPERATORS ***************************************************************************** ****************************************************************************/ /**************************************************************************** ***************************************************************************** ** SETTERS ***************************************************************************** ****************************************************************************/ /**************************************************************************** ***************************************************************************** ** GETTERS ***************************************************************************** ****************************************************************************/ /***************************************************************************/ //! @brief Public Getter //! get_error | void /***************************************************************************/ //! @return Err_codes | error code //! @details //! Get current error code of the parser /***************************************************************************/ Err_codes Uniparser::get_error( void ) { //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- return this -> g_err; } //end destructor: get_error | void /**************************************************************************** ***************************************************************************** ** TESTERS ***************************************************************************** ****************************************************************************/ /**************************************************************************** ***************************************************************************** ** PUBLIC METHODS ***************************************************************************** ****************************************************************************/ /***************************************************************************/ //! @brief Public Method //! add_command | const char *, void * /***************************************************************************/ //! @param cmd | const char * Text that will trigger the command //! @param handler | void * Pointer to callback function for this command //! @return bool | false: OK | true: fail //! @details //! Add a string and a function pointer to the parser //! @todo check that command is valid /***************************************************************************/ bool Uniparser::add_cmd( const char *cmd, void *handler ) { DENTER_ARG("cmd: %p >%s<\n", (void *)cmd, cmd ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //index uint8_t t; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //if: input is invalid if ((cmd == nullptr) || (handler == nullptr)) { this -> g_err = ERR_INVALID_CMD; DRETURN_ARG("ERR%d: ERR_INVALID_CMD\n", this -> g_err); return true; //fail } //If: num command is invalid if ((UNIPARSER_PENDANTIC_CHECKS) && ((this -> g_num_cmd < 0) || (this->g_num_cmd >= UNIPARSER_MAX_CMD)) ) { this -> g_err = ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //if: maximum number of command has been reached if (this -> g_num_cmd >= (UNIPARSER_MAX_CMD-1)) { this -> g_err = ERR_ADD_MAX_CMD; DRETURN_ARG("ERR%d: ERR_ADD_MAX_CMD in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } // check the validity of the string bool f_ret = this -> chk_cmd((const uint8_t *)cmd); //If: command had a syntax error if (f_ret == true) { DRETURN_ARG("command didnt get past argument descriptor check\n"); return true; //FAIL } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Fetch currently used command t = this -> g_num_cmd; //Link command handler and command text this -> g_cmd_txt[t] = (uint8_t *)cmd; this -> g_cmd_handler[t] = handler; DPRINT("Command >%s< with handler >%p< has been added with index: %d\n", cmd, (void *)handler, t); //A command has been added this -> g_num_cmd = t +1; DPRINT("Total number of commands: %d\n", this -> g_num_cmd); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN(); return false; } //end method: add_command | const char *, void * /***************************************************************************/ //! @brief Public Method //! parse | char /***************************************************************************/ //! @param data | uint8_t | incoming character to be processed through the universal parser //! @return bool | false = OK | true = A runtime error occurred //! @details //! Intricate FSM. The objective is to check the incoming character against //! charaters inside the various commands and decode a command when a \0 is detected /***************************************************************************/ bool Uniparser::parse( uint8_t data ) { if ((data < '0') || (data > 'z')) { DENTER_ARG("exe: >0x%x<\n", data ); } else { DENTER_ARG("exe: >0x%x< >%c<\n", data, data ); } //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //when true, reset the FMS bool f_rst_fsm = false; //Index of the handler to be executer int8_t exe_index = -1; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // CLEAR ERROR //---------------------------------------------------------------- // User was notified of the error during previous call // Errors should have triggered an FSM reset to return in working condition // I can clear the error and keep churning bytes //If: an error was reported if (this -> g_err != Err_codes::NO_ERR) { //Clear the error DPRINT("%d | Clear Error: %d\n", __LINE__, this -> g_err); this -> g_err = Err_codes::NO_ERR; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //---------------------------------------------------------------- // TERMINATOR //---------------------------------------------------------------- //! @details when terminator is detected, close the command. //! I either have a full match, or the command is invalid and I have to reset the FSM //If: input terminator from user if (data == '\0') { DPRINT("%d | Terminator detected | Number of partial matches: %d\n", __LINE__, this -> g_num_match); //counter uint8_t t; //If: i was decoding an argument if (this -> g_status == Orangebot::Parser_status::PARSER_ARG) { //I'm done decoding DPRINT("%d | Terminator after ARG\n", __LINE__); //Close current argument and update the argument detector FSM. bool f_ret = this -> close_arg(); //if could not close argument if (f_ret == true) { //I can recover from this. //no matches and reset the FSM. this -> g_num_match = 0; } } //Index inside the command uint8_t cmd_index; //if: I have at least one parser_tmp.id_index entry if (this -> g_num_match > 0) { DPRINT("%d | Scanning partially matched commands for terminators\n", __LINE__); //For: scan all commands for (t = 0;t g_num_cmd;t++) { //Fetch command index cmd_index = this -> g_cmd_index[t]; //If: this command is a partial match if (cmd_index > 0) { //If: i was decoding an argument if (this -> g_status == Parser_status::PARSER_ARG) { //If: index is not pointing to an argument descriptor inside the command if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t][cmd_index] != '%')) { DPRINT("ERR: This command should have an argument descriptor in this position. | cmd: %d | cmd_index: %d | actual content: >0x%x<\n", t, cmd_index, this -> g_cmd_txt[t][cmd_index]); this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //The argument has been closed. I need to skip the argument descriptor "%?" cmd_index += 2; //With argument closed I'm now doing an ID matching for terminator. Can be skipped since it's the last char this -> g_status = Parser_status::PARSER_ID; //I should write back the index. Can be skipped since it's the last char this -> g_cmd_index[t] = cmd_index; } //Check match against the character after the one already matched. //If: the next command data would be the terminator '\0' if ( this -> g_cmd_txt[t][ cmd_index ] == '\0') { //If there is a pending execution already if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index != -1)) { //this should never happen this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //Issue execution of the callback function linked exe_index = t; DPRINT("Valid command ID%d decoded\n", t); //I can stop the search t = this -> g_num_cmd; } //If: command would keep on going else { DPRINT("%d | no match in %x cmd %x | ", __LINE__ ,data , this -> g_cmd_txt[t][ cmd_index ] ); } } //End If: this command is a partial match } //End For: scan all commands } //end if: I have at least one parser_tmp.id_index entry //If I have just one match. g_num_match now holds the index of the match shifted by one else if (this -> g_num_match < 0) { //decode command index | BUGFIX: -1 means only one match of command ID 0 t = -this -> g_num_match -1; DPRINT("just one partial match: %d\n", t); //Fetch command index cmd_index = this -> g_cmd_index[t]; //If: i was decoding an argument if (this -> g_status == Parser_status::PARSER_ARG) { //If: index is not pointing to an argument descriptor inside the command if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t][cmd_index] != '%')) { DPRINT("ERR: This command should have an argument descriptor in this position. | cmd: %d | cmd_index: %d | actual content: >0x%x<\n", t, cmd_index, this -> g_cmd_txt[t][cmd_index]); this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //The argument has been closed. I need to skip the argument descriptor "%?" cmd_index += 2; //With argument closed I'm now doing an ID matching for terminator. Can be skipped since it's the last char //this -> g_status == Parser_status::PARSER_ID; } //BUGFIX: this branch can now be executed with null pointer if dictionary is yet to be initialized. This is not a pedantic check //Check match against the character after the one already matched. //If: the next command data would be the terminator '\0' if ((this -> g_cmd_txt[t] != nullptr) && (this -> g_cmd_txt[t][ cmd_index ] == '\0')) { //If there is a pending execution already if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index != -1)) { //this should never happen this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //Issue execution of the callback function linked exe_index = t; DPRINT("%d | Valid command ID%d decoded\n", __LINE__, t); //I can stop the search t = this -> g_num_cmd; } //BUGFIX: this branch can now be executed with null pointer if dictionary is yet to be initialized. This is not a pedantic check //if: I'm given a terminator but dictionary does not contain a terminator else { if (this -> g_cmd_txt[t] != nullptr) { //This happen if user gives a command that lack one char DPRINT("%d | no match. given: >0x%x< expected: >0x%x<\n" ,__LINE__, data , this -> g_cmd_txt[t][ cmd_index ] ); } else { //This happen if user gives a command that lack one char DPRINT("%d | Dictionary entry is nullptr. Maybe dictionary is yet to be initialized? Dictionary entry: %d\n",__LINE__, t ); } //Issue a FSM reset f_rst_fsm = true; } //End if: I'm given a terminator but dictionary does not contain a terminator } //End If: I have just one match g_num_match now holds the index of the match shifted by one //If: exactly zero matches. else { DPRINT("%d | No partial matches\n", __LINE__ ); } //Issue a FSM reset f_rst_fsm = true; } //End If: input terminator from user //-------------------------------------------------------------------------- // PARSER_IDLE //-------------------------------------------------------------------------- // Only letters can be used as first character in a command // This section matches the first character in each command // This section takes care of initializing g_cmd_index[] to valid partial match values //If: PARSER_IDLE else if (this -> g_status == Parser_status::PARSER_IDLE) { DPRINT("%d | PARSER_IDLE\n", __LINE__); //If: letter First character in a command can only be a letter if (IS_LETTER( data )) { //counter uint8_t t; //for each command for (t = 0; t < this -> g_num_cmd;t++) { //if: dictionary is unlinked if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[t] == nullptr)) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("%d | ERR%d: ERR_GENERIC\n", __LINE__, this -> g_err ); return true; //fail } //If: partial match if (this -> g_cmd_txt[t][0] == data) { //A partial match has been found this -> g_num_match++; //Match has been found up to first character. Point to the next unmatched char this -> g_cmd_index[t] = 1; //Next, I'm matching ID entries this -> g_status = Parser_status::PARSER_ID; //TIP: I can't speculatively detect % here because two commands may have the same first section and diverge later. DPRINT("%d | Match command %d, total partial matches: %d\n", __LINE__, t, this -> g_num_match); } //if: no match else { //special code for no match found this -> g_cmd_index[t] = 0; } } //end for: each command } //End If: letter //Non letter can never be a first character else { //Issue a FSM reset f_rst_fsm = true; } } //End If: PARSER_IDLE //-------------------------------------------------------------------------- // ID matching //-------------------------------------------------------------------------- //if: I'm ID matching else if (this -> g_status == Parser_status::PARSER_ID) { DPRINT("%d | PARSER_ID ", __LINE__); //! @todo only go ARG if a command has an arg descriptor if there are number or sign. allow number or sign to be used as command ID //if: I'm being fed an argument if (IS_NUMBER( data ) || IS_SIGN( data )) { DPRINT_NOTAB("- ARG | num_match %d\n", this -> g_num_match); //if: I have at least one partial match if (this -> g_num_match > 0) { //for each dictionary command for (uint8_t t = 0;t < this -> g_num_cmd;t++) { //if: the command is a partial match if (this -> g_cmd_index[t] > 0) { //Search in the dictionary for a % entry. An argument descriptor if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == '%') { //Do not increment index but go in ARG parsing mode this -> g_status = Parser_status::PARSER_ARG; //Do not advance index until argument decoding is complete DPRINT("%d | ARG begins | command: %d\n", __LINE__, t); //Add an argument using current partial match as template bool f_ret = this -> add_arg( t ); //if: adding argument failed if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) { this -> error_handler( Err_codes::ERR_ADD_ARG ); DPRINT("%d | ERR Failed to add an argument\n", __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } //initialize agrument this -> accumulate_arg( data ); //argument detection make the detection unique. Remove all other partial matches | BUGFIX: now negative index is shifted by one this -> g_num_match = -t -1; //Single match has been found. Break the cycle t = UNIPARSER_MAX_CMD; } //If: this dictionary entry does not contain an argument descriptor else { //Prune away the partial match this -> g_cmd_index[t] = 0; DPRINT("%d | Prune away partial match: %d | ", __LINE__, t); //if: I still have partial matches after pruning if (this -> g_num_match >= 2) { //One fewer partial match this -> g_num_match--; DPRINT_NOTAB(" num_match: %d\n", this -> g_num_match ); } //if: all partial matches have been pruned away else { //No more commands. Reset the machine f_rst_fsm = true; //No more matches. Can breack cycle early t = UNIPARSER_MAX_CMD; DPRINT_NOTAB("%d | Last partial match has been pruned away... RESET\n", __LINE__); //! @todo command refeed function. Safe and refeed last char to detect other partial commands } } //End If: this dictionary entry does not contain an argument descriptor } //End if: the command is a partial match //If: this commnd did not match to begin with else { //do nothing } } //end for each dictionary command } //end if: I have at least one partial match //If I only have one match | BUGFIX: single match is now shifted by one else if (this -> g_num_match < 0) { //decode command index uint8_t t = -this -> g_num_match -1; //Search in the dictionary for a % entry. An argument descriptor if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == '%') { //! This is the first char of an argument //Do not increment index but go in ARG parsing mode this -> g_status = Parser_status::PARSER_ARG; //Do not advance index until argument decoding is complete DPRINT("%d | ARG begins | command: %d\n", __LINE__, t); //Add an argument using current partial match as template bool f_ret = this -> add_arg( t ); //if: adding argument failed if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) { this -> g_err = Err_codes::ERR_GENERIC; DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } //! accumulate argument character inside argument. f_ret = this -> accumulate_arg( data ); //if: adding argument failed if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) { this -> g_err = Err_codes::ERR_GENERIC; DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } } } //If I only have one match //If: I had no matches to begin with else { //DO nothing } } //end if: I'm being fed an argument //if: I'm matching a non argument non terminator else { DPRINT_NOTAB("- ID\n"); //if: I have at least one partial match if (this -> g_num_match > 0) { //If I have just one match, I can upgrade num_match to skip for next time bool f_match = (this -> g_num_match == 1); //for each dictionary command for (uint8_t t = 0;t < this -> g_num_cmd;t++) { //if: the command is a partial match if (this -> g_cmd_index[t] > 0) { //check that the dictionary holds the same value as data if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == data) { //Advance to the next dictionary entry for this command this -> g_cmd_index[t]++; //if: This is the sole partial match surviving if (f_match == true) { //Save the index inside num match to skip the for next time | BUGFIX: Now single match is shifted by one this -> g_num_match = -t -1; //Single match has been found. Break the cycle t = UNIPARSER_MAX_CMD; DPRINT("%d | Only one partial match remains. Num_match: %d\n", __LINE__, this -> g_num_match); } } //Else: this dictionary entry does not contain an argument descriptor else { //Prune away the partial match this -> g_cmd_index[t] = 0; DPRINT("%d | Prune away partial match: %d | ", __LINE__, t); //if: I still have partial matches after pruning if (this -> g_num_match >= 2) { //One fewer partial match this -> g_num_match--; DPRINT_NOTAB(" num_match: %d\n", this -> g_num_match ); } //if: all partial matches have been pruned away else { //No more commands. Reset the machine f_rst_fsm = true; //No more matches. Can breack cycle early t = UNIPARSER_MAX_CMD; DPRINT_NOTAB("Last partial match has been pruned away... RESET\n"); //! @todo replay system. Safe and refeed last char to detect other partial commands } } } //End if: the command is a partial match //if: the command was pruned away long ago else { //do nothing } } //end for each dictionary command } //end if: I have at least one partial match //BUGFIX: If the only match is also entry 0 //If I only have one match else //if (this -> g_num_match <= 0) { //decode command index | BUGFIX: Now single match is shifted by one uint8_t t = -this -> g_num_match -1; //check that the dictionary holds the same value as data if (this -> g_cmd_txt[t][ this -> g_cmd_index[t] ] == data) { //Match! Scan next entry this -> g_cmd_index[t]++; DPRINT("%d | Match still valid...\n", __LINE__); } //no match else { //Last partial match has been pruned away. Issue a FSM reset f_rst_fsm = true; DPRINT("%d | Last match was pruned away. Expected >0x%x< got >0x%x< instead\n", __LINE__, this -> g_cmd_txt[t][ this -> g_cmd_index[t] ], data); } } //If I only have one match } //end if: I'm matching a non argument non terminator } //end if: I'm ID matching //-------------------------------------------------------------------------- // ARG decoder //-------------------------------------------------------------------------- //if: I'm decoding arguments else if (this -> g_status == Parser_status::PARSER_ARG) { DPRINT("%d | PARSER_ARG\n", __LINE__); //If: I'm fed a number if (IS_NUMBER(data)) { //! accumulate argument character inside argument. bool f_ret = this -> accumulate_arg( data ); //if: adding argument failed if ((UNIPARSER_PENDANTIC_CHECKS) && (f_ret == true)) { this -> g_err = Err_codes::ERR_GENERIC; DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } //Do not advance to next dictionary entry } //If: I'm fed a number //if: I'm fed a non number else { DPRINT("Closing argument\n"); //! Exit argument mode //Close current argument and update argument FSM this -> close_arg(); //BUGFIX: If the only match is also entry 0 //if: I have multiple matches. I should have just one match by this point. if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_num_match > 0)) { this -> g_err = Err_codes::ERR_GENERIC; DPRINT("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } else { //After argument, I can only have one match. | BUGFIX: Now single match is shifted by one uint8_t cmd_id = -this -> g_num_match -1; //Update the parser index by skipping % and the argument descriptor this -> g_cmd_index[ cmd_id ] += 2; uint8_t u8_index = this -> g_cmd_index[ cmd_id ]; //Get the next cmd match uint8_t u8_next_cmd_id = this -> g_cmd_txt[ cmd_id ][ u8_index ]; DPRINT("%d | Expected CMD ID %d | Got CMD ID %d\n", __LINE__, this -> g_cmd_txt[ cmd_id ][ u8_index ], data); //check that the dictionary holds the same value as data if (u8_next_cmd_id == data) { //Advance to the next dictionary entry for this command this -> g_cmd_index[ cmd_id ]++; } //No match else { DPRINT("%d | Pruning away last match\n", __LINE__ ); //I can recover from this by resetting the FSM f_rst_fsm = true; } this -> g_status = Parser_status::PARSER_ID; } } //if: I'm fed a non number } //if: I'm decoding arguments //---------------------------------------------------------------- // FSM RESET //---------------------------------------------------------------- //! @detail //! FSM reset. Clear up the machine for the next clean execution //If: a reset was issued if (f_rst_fsm == true) { DPRINT("%d | FSM RESET\n", __LINE__); //Clear reset flag f_rst_fsm = false; //Status becomes IDLE this -> g_status = Orangebot::Parser_status::PARSER_IDLE; //I have no partial matches anymore this -> g_num_match = 0; //If I don't have a pending execution if (exe_index == -1) { //Reset the argument decoder and prepare for a new command this -> init_arg_decoder(); } } //If: a reset was issued //---------------------------------------------------------------- // HANDLER EXECUTION //---------------------------------------------------------------- //! @detail //! FSM reset. Clear up the machine for the next clean execution //If: an execution event has been launched if (exe_index > -1) { //if execution index is out of range. if ((UNIPARSER_PENDANTIC_CHECKS) && (exe_index == this -> g_num_cmd)) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } DPRINT("%d | Executing handler of command %d | num arguments: %d\n", __LINE__, exe_index, this -> g_arg_fsm_status.num_arg); //Execute handler of given function. Automatically deduce arguments from argument vector this -> execute_callback( this ->g_cmd_handler[exe_index] ); //Reset the argument decoder and prepare for a new command this -> init_arg_decoder(); } //If: a reset was issued //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return from main DRETURN_ARG("Err_code: %d\n", this -> g_err); //Inform the caller that an error occurred return (this -> g_err != Err_codes::NO_ERR); } //end method: parse | char /**************************************************************************** ***************************************************************************** ** PUBLIC STATIC METHODS ***************************************************************************** ****************************************************************************/ /**************************************************************************** ***************************************************************************** ** PRIVATE METHODS ***************************************************************************** ****************************************************************************/ /***************************************************************************/ //! @brief Private Method //! init | void /***************************************************************************/ //! @return no return //! @details //! initialize structure /***************************************************************************/ inline void Uniparser::init( void ) { DENTER(); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //counter uint8_t t; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! @details initialize structure //No commands are currently loaded inside the parser this -> g_num_cmd = 0; //for: each possible command for (t = 0;t < UNIPARSER_MAX_CMD;t++) { //command has no txt identifier linked this -> g_cmd_txt[t] = nullptr; //command has no function handler linked this -> g_cmd_handler[t] = nullptr; } //I have no partial matches this -> g_num_match = 0; //FSM begins in idle this -> g_status = Orangebot::Parser_status::PARSER_IDLE; //No error this -> g_err = Orangebot::Err_codes::NO_ERR; //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return from main DRETURN(); return; //OK } //end method: init | void /***************************************************************************/ //! @brief Private Method //! init_arg_decoder | void /***************************************************************************/ //! @details //! initialize argument decoder for a new command /***************************************************************************/ inline void Uniparser::init_arg_decoder( void ) { //Trace Enter with arguments DENTER(); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! @details algorithm: //Prepare the argument descriptor. zero arguments are in store this -> g_arg_fsm_status.num_arg = 0; //First free slot in the argument vector is the first byte this -> g_arg_fsm_status.arg_index = 0; //if sign is not specified, default argument sign is plus this -> g_arg_fsm_status.arg_sign = false; //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return vith return value DRETURN(); return; //OK } //end method: init_arg_decoder | void /***************************************************************************/ //! @brief Private Method //! chk_cmd | const uint8_t * /***************************************************************************/ //! @param cmd | //! @return syntax error | bool | false: OK | true: error detected. Code handled by the error handler //! @details //! Check command syntax to prevent bad commands from being loaded in the dictionary //! Saves runtime check for bad dictionary entries /***************************************************************************/ bool Uniparser::chk_cmd( const uint8_t *cmd ) { //Trace Enter with arguments DENTER_ARG("cmd: %p\n", (void *)cmd); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //Counter uint8_t t; //Total argument size used uint8_t arg_cnt = 0; //Number of arguments uint8_t arg_type_cnt = 0; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If a null pointer function handler was given if (cmd == nullptr) { this -> error_handler( Err_codes::SYNTAX_BAD_POINTER ); DRETURN_ARG("ERR%d: | Bad handler function pointer\n", Err_codes::SYNTAX_BAD_POINTER); return true; //FAIL } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //if: first char is not a letter if (!IS_LETTER( cmd[0] )) { this -> error_handler( Err_codes::SYNTAX_FIRST_NOLETTER ); DRETURN_ARG("ERR%d | First character of a command must be a letter\n", Err_codes::SYNTAX_FIRST_NOLETTER); return true; //FAIL } //Initialize counter t = 1; //While: parsing is not done while ((cmd[t] != '\0') && (t < UNIPARSER_MAX_CMD_LENGTH)) { //if: argument descriptor if (cmd[t] == '%') { //!Check number of arguments //i have an argument descriptor arg_type_cnt++; //if: exceed number of arguments if (arg_type_cnt > UNIPARSER_MAX_ARGS) { this -> error_handler( Err_codes::SYNTAX_TOO_MANY_ARGS ); DRETURN_ARG("ERR%d in line %d | too many arguments in this command %d\n", Err_codes::SYNTAX_TOO_MANY_ARGS, __LINE__, arg_type_cnt); return true; //FAIL } //!Check back to back arguments //if: two arguments back to back if ( (t >= 2) && (cmd[t -2] == '%') ) { this -> error_handler( Err_codes::SYNTAX_ARG_BACKTOBACK ); DRETURN_ARG("ERR%d in line %d | Two back to back arguments were given. Add a character in between them\n", Err_codes::SYNTAX_ARG_BACKTOBACK, __LINE__); return true; //FAIL } //!Check total size of arguments //Skip the argument descriptor t++; //Switch: argument type switch( cmd[t] ) { //Decode type case Arg_type::ARG_U8: { //Accumulate arg_cnt += Arg_size::ARG_U8_SIZE; break; } //Decode type case Arg_type::ARG_S8: { //Accumulate arg_cnt += Arg_size::ARG_S8_SIZE; break; } //Decode type case Arg_type::ARG_U16: { //Accumulate arg_cnt += Arg_size::ARG_U16_SIZE; break; } //Decode type case Arg_type::ARG_S16: { //Accumulate arg_cnt += Arg_size::ARG_S16_SIZE; break; } //Decode type case Arg_type::ARG_U32: { //Accumulate arg_cnt += Arg_size::ARG_U32_SIZE; break; } //Decode type case Arg_type::ARG_S32: { //Accumulate arg_cnt += Arg_size::ARG_S32_SIZE; break; } default: { this -> error_handler( Err_codes::SYNTAX_ARG_TYPE_INVALID ); DRETURN_ARG("ERR%d in line %d | Invalid argument descriptor %x\n", Err_codes::SYNTAX_ARG_TYPE_INVALID , __LINE__, cmd[t]); return true; //FAIL } } //End Switch: argument type //Check size if (arg_cnt > UNIPARSER_ARG_VECTOR_SIZE) { this -> error_handler( Err_codes::SYNTAX_ARG_LENGTH ); DRETURN_ARG("ERR%d in line %d | Invalid argument descriptor %x\n", Err_codes::SYNTAX_ARG_LENGTH , __LINE__, cmd[t]); return true; //FAIL } } //End if: argument descriptor //Parse next byte t++; } //End While: parsing is not done //If command size has been exceeded if (t >= UNIPARSER_MAX_CMD_LENGTH) { this -> error_handler( Err_codes::SYNTAX_LENGTH ); DRETURN_ARG("ERR%d in line %d | Given command was too long %d\n", Err_codes::SYNTAX_LENGTH , __LINE__, t); return true; //FAIL } //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN(); return false; //OK } //end method: chk_cmd | const uint8_t * /***************************************************************************/ //! @brief Private Method //! set_arg | uint8_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, uint8_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U8_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Save the numeric value of the argument this -> g_arg[ arg_index ] = (uint8_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0] ); return false; //OK } //end method: set_arg | uint8_t /***************************************************************************/ //! @brief Public Method //! set_arg | uint8_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, int8_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S8_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Link pointer to the correct data type int8_t *arg_ptr = ARG_CAST( arg_index, int8_t ); //Save the numeric value of the argument *arg_ptr = (int8_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0] ); return false; //OK } //end method: set_arg | int8_t /***************************************************************************/ //! @brief Public Method //! set_arg | uint16_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, uint16_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U16_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Link pointer to the correct data type uint16_t *arg_ptr = ARG_CAST( arg_index, uint16_t ); //Save the numeric value of the argument *arg_ptr = (uint16_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1] ); return false; //OK } //end method: set_arg | uint16_t /***************************************************************************/ //! @brief Public Method //! set_arg | int16_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based add_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, int16_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: set_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S16_SIZE)) { //Trace Return DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Link pointer to the correct data type int16_t *arg_ptr = ARG_CAST( arg_index, int16_t ); //Save the numeric value of the argument *arg_ptr = (int16_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1] ); return false; //OK } //end method: set_arg | int16_t /***************************************************************************/ //! @brief Public Method //! set_arg | uint32_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, uint32_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U32_SIZE)) { //Trace Return DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Link pointer to the correct data type uint32_t *arg_ptr = ARG_CAST( arg_index, uint32_t ); //Save the numeric value of the argument *arg_ptr = (uint32_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x %3x %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1], (uint8_t)this -> g_arg[arg_index +2], (uint8_t)this -> g_arg[arg_index +3] ); return false; //OK } //end method: set_arg | int32_t /***************************************************************************/ //! @brief Public Method //! set_arg | int32_t /***************************************************************************/ //! @param arg | T | numeric value of the argument to be recorded inside the general argument vector //! @return bool | false: OK | true: argument exceed the alloted arg vector space //! @details //! Template based set_arg method to add the numeric value of the argument to be recorded inside the general argument vector \n //! Each method is specialized for each supported type, while leaving space for standard or custom types to be added \n //! It is much cleaner than encoding the type inside the name of the function and takes advantage of C++ constructs /***************************************************************************/ template <> inline bool Uniparser::set_arg( uint8_t arg_index, int32_t arg ) { //Trace Enter DENTER_ARG( "argument: %d\n", arg ); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S32_SIZE)) { //Trace Return DRETURN_ARG("ERR: set_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return true; } ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //Link pointer to the correct data type int32_t *arg_ptr = ARG_CAST( arg_index, int32_t ); //Save the numeric value of the argument *arg_ptr = (int32_t)arg; ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN_ARG("Index: %d | Binary: %3x %3x %3x %3x\n", arg_index, (uint8_t)this -> g_arg[arg_index +0], (uint8_t)this -> g_arg[arg_index +1], (uint8_t)this -> g_arg[arg_index +2], (uint8_t)this -> g_arg[arg_index +3] ); return false; //OK } //end method: set_arg | int32_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline uint8_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U8_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content uint8_t *arg_ptr = &this -> g_arg[arg_index]; //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline int8_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S8_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content int8_t *arg_ptr = ARG_CAST( arg_index, int8_t); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline uint16_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U16_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content uint16_t *arg_ptr = ARG_CAST( arg_index, uint16_t); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline int16_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S16_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content int16_t *arg_ptr = ARG_CAST( arg_index, int16_t); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline uint32_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_U32_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content uint32_t *arg_ptr = ARG_CAST( arg_index, uint32_t); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! get_arg | uint8_t /***************************************************************************/ //! @param arg_index | point to an argument inside the argument vector //! @return decoded content of argument vector at given position //! @details //! fetch the numeric value of an argument from the argument vector /***************************************************************************/ template <> inline int32_t Uniparser::get_arg( uint8_t arg_index ) { DENTER_ARG("arg_index: %d\n", arg_index ); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If: add_arg would exceed the maximum allowed argument vector size if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_index > UNIPARSER_ARG_VECTOR_SIZE -ARG_S32_SIZE)) { //Trace Return DRETURN_ARG("ERR: add_arg would exceed the maximum allowed argument vector size | max: %d | current: %d\n", UNIPARSER_ARG_VECTOR_SIZE, arg_index); this -> error_handler( Err_codes::ERR_ARG_SIZE ); return (uint8_t)0xff; } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Link the pointer to the actual content int32_t *arg_ptr = ARG_CAST( arg_index, int32_t); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- DRETURN_ARG("Decoded: %d\n", *arg_ptr); return *arg_ptr; //OK } //end method: get_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! add_arg | uint8_t /***************************************************************************/ //! @param cmd_id | index of the command the argument is inferred from //! @return false: ok | true: fail //! @details //! Add an argument to the parser argument storage. //! It expect the command to be a partial match and the index to be pointing to '%' //! The command is added to the class argument storage string in the format //! 'u' data0 ... data 1 /***************************************************************************/ bool Uniparser::add_arg( uint8_t cmd_id ) { //Trace Enter with arguments DENTER_ARG("command index: %d\n", cmd_id); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //return bool f_ret = false; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //If input index is out of range if ((UNIPARSER_PENDANTIC_CHECKS) && (cmd_id > this -> g_num_cmd) ) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //Fetch index inside the command uint8_t cmd_index = this -> g_cmd_index[ cmd_id ]; //if: the command is not an argument if ((UNIPARSER_PENDANTIC_CHECKS) && (this -> g_cmd_txt[cmd_id][ cmd_index ] != '%')) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //Point to the argument type cmd_index++; //if: the command is not an argument descriptor. PEDANTIC because dictionary should have been checked before hand if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(this -> g_cmd_txt[cmd_id][ cmd_index ])) ) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! @details algorithm: //! Compute index to argument vector and number of arguments //! Compute //! ARG Index points to first free slot in the argument vector //! I save argument type and initialize the content //! Initialize argument identifier //argument descriptor is held in the dictionary Arg_type arg_type = (Arg_type)this -> g_cmd_txt[cmd_id][cmd_index]; //Fetch index to the next free argument slot uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; //Store argument type in the argument type vector this -> g_arg_type[ arg_type_index ] = arg_type; //A new argument is being added. Reset the argument sign (@TODO: do this earlier) this -> g_arg_fsm_status.arg_sign = false; //fetch argument index uint8_t arg_index = this -> g_arg_fsm_status.arg_index; DPRINT("argument of type >%c< added | Num arguments: %d | Arg index: %d | Arg sign %c \n", arg_type, this -> g_arg_fsm_status.num_arg, arg_index, (this -> g_arg_fsm_status.arg_sign)?('-'):('+') ); //! Initialize argument content //switch: decode argument desriptor switch (arg_type) { case Arg_type::ARG_U8: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (uint8_t)0 ); break; } case Arg_type::ARG_S8: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (int8_t)0 ); break; } case Arg_type::ARG_U16: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (uint16_t)0 ); break; } case Arg_type::ARG_S16: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (int16_t)0 ); break; } case Arg_type::ARG_U32: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (uint32_t)0 ); break; } case Arg_type::ARG_S32: { //Write zero inside the argument f_ret = this -> set_arg( arg_index, (int32_t)0 ); break; } //if: type is not handled default: { this -> error_handler( Err_codes::ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d\n", __LINE__, arg_type_index); return true; //FAIL } } //end switch: decode argument desriptor //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return vith return value DRETURN_ARG("Success: %x\n", f_ret); return f_ret; //OK } //end method: add_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! accumulate_arg | uint8_t /***************************************************************************/ //! @param data | input character to be decoded. It should be a number or a sign //! @return false: ok | true: fail //! @details //! decode an input character and accumulate it into the argument vector /***************************************************************************/ bool Uniparser::accumulate_arg( uint8_t data ) { //Trace Enter with arguments DENTER_ARG("data >%c<\n", data); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //detect failure state bool f_ret; //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //Fetch argument index uint8_t arg_index = this -> g_arg_fsm_status.arg_index; //Fetch argument type index uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; //If argument descriptor is bad if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_type_index >= UNIPARSER_MAX_ARGS)) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Num args: %x\n", this -> g_err, __LINE__, arg_type_index ); return true; //fail } //Fetch argument type Arg_type arg_type = (Arg_type)this->g_arg_type[arg_type_index]; //If argument descriptor is bad if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(arg_type))) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Arg_type: %x\n", this -> g_err, __LINE__, arg_type ); return true; //fail } //If: input char is bad if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_SIGN(data)) && (!IS_NUMBER(data))) { DPRINT("ERR: bad input char. Expecting number or sign and got >0x%x< instead\n", data); this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //!Detect sign //if sign if (IS_SIGN(data)) { //If sign is minus, argument sign is true which means minus this -> g_arg_fsm_status.arg_sign = (data == '-'); DRETURN(); //I'm done updating argument for now. Next round will come actual numbers. return false; } //!Decode numeric value //decode the argument descriptor switch (arg_type) { //if: the command expects a uint8_t data case (Arg_type::ARG_U8): { //Fetch old argument uint8_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //if: the command expects a uint8_t data case (Arg_type::ARG_S8): { //Fetch old argument int8_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //if: the command expects a uint8_t data case (Arg_type::ARG_U16): { //Fetch old argument uint16_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //if: the command expects a uint8_t data case (Arg_type::ARG_S16): { //Fetch old argument int16_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //if: the command expects a uint8_t data case (Arg_type::ARG_U32): { //Fetch old argument uint32_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //if: the command expects a uint8_t data case (Arg_type::ARG_S32): { //Fetch old argument int32_t old = this -> get_arg( arg_index ); //Shift by one digit left old *= 10; //If number is positive if (this -> g_arg_fsm_status.arg_sign == false) { //Accumulate new digit old += data -'0'; } //if: number is negative else { //Accumulate new digit old -= data -'0'; } //Write back argument inside argument vector f_ret = this -> set_arg( arg_index, old ); //If set arg failed if (f_ret == true) { return true; } DPRINT("Updated argument with value: %d | index: %d\n", old, arg_index); break; } //Unrecognized argument descriptor in the dictionary default: { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } } //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return vith return value DRETURN(); return false; //OK } //end method: accumulate_arg | uint8_t /***************************************************************************/ //! @brief Private Method //! close_arg | void /***************************************************************************/ //! @return false: OK | true: fail //! @details //! Argument has been fully decoded into argument string. Update argument descriptor FSM. /***************************************************************************/ bool Uniparser::close_arg( void ) { //Trace Enter with arguments DENTER(); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //Fetch argument index uint8_t arg_index = this -> g_arg_fsm_status.arg_index; //Fetch argument type index uint8_t arg_type_index = this -> g_arg_fsm_status.num_arg; //If argument descriptor is bad if ((UNIPARSER_PENDANTIC_CHECKS) && (arg_type_index >= UNIPARSER_MAX_ARGS)) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Num args: %x\n", this -> g_err, __LINE__, arg_type_index ); return true; //fail } //Fetch argument type Arg_type arg_type = (Arg_type)this->g_arg_type[arg_type_index]; //If argument descriptor is bad if ((UNIPARSER_PENDANTIC_CHECKS) && (!IS_ARG_DESCRIPTOR(arg_type))) { this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d | Arg_type: %x\n", this -> g_err, __LINE__, arg_type ); return true; //fail } //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //! Advance the argument index to the first free byte in the argument vector //If: one byte argument if ((arg_type == Arg_type::ARG_U8) || (arg_type == Arg_type::ARG_S8)) { //Skip the argument descriptor and the argument itself arg_index += Arg_size::ARG_S8_SIZE; } //If: two bytes argument else if ((arg_type == Arg_type::ARG_U16) || (arg_type == Arg_type::ARG_S16)) { //Skip the argument descriptor and the argument itself arg_index += Arg_size::ARG_S16_SIZE; } //If: four bytes argument else if ((arg_type == Arg_type::ARG_U32) || (arg_type == Arg_type::ARG_S32)) { //Skip the argument descriptor and the argument itself arg_index += Arg_size::ARG_S32_SIZE; } //pedantic because the ditionary should have been checked before hand for bad argument descriptors else if (UNIPARSER_PENDANTIC_CHECKS) { //This error means the argument descriptor was unrecognized this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; } else { //failure return true; } //! Check that index is valid //if: index is above bit width or exceed the argument vector size if ((arg_index > UNIPARSER_MAX_ARG_INDEX) || (arg_index > UNIPARSER_ARG_VECTOR_SIZE)) { //Restart the argument decoder this -> init_arg_decoder(); // DPRINT("ERR: Exceeded alloted argument vector size with index: %d\n", arg_index); this -> g_err = Err_codes::ERR_GENERIC; DRETURN_ARG("ERR%d: ERR_GENERIC in line: %d\n", this -> g_err, __LINE__ ); return true; //fail } //Write back index this -> g_arg_fsm_status.arg_index = arg_index; //Update number of decoded arguments this -> g_arg_fsm_status.num_arg++; DPRINT("Argument closed | num arg: %d | arg index: %d\n", this -> g_arg_fsm_status.num_arg, this -> g_arg_fsm_status.arg_index); //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return vith return value DRETURN(); return false; //OK } //end method: close_arg | void /***************************************************************************/ //! @brief Public Method //! execute_callback | void /***************************************************************************/ // @param //! @return no return //! @details //! Execute callback by passing a vector of U8 inside which are codified the bytes of the arguments //! @algorithm //! It's an execution tree that execute a branch based on the argument types //! Tree is limited by the maximum number of types and the maximum number of bytes //! ARG0 ARG0,ARG1 ARG0,ARG1,ARG2 ARG0,ARG1,ARG2,ARG3 //! void //! 8 8 8 8 8 8 8 8 8 8 (arg number limit) //! ... ... //! 8 16 //! 8 32 //! 16 16 8 //! 16 16 //! ... //! 32 32 8 32 8 8 8 (arg number limit) //! 32 16 8 8 (arg number and size limit) //! 32 16 16 (arg number limit) //! 32 32 (arg size limit) //! (arg type limit) //! Calls work equally with signed or unsiged arguments /***************************************************************************/ bool Uniparser::execute_callback( void *callback_ptr ) { //Trace Enter DENTER(); ///-------------------------------------------------------------------------- /// VARS ///-------------------------------------------------------------------------- //Argument index counter uint8_t arg_cnt = 0; //Number of arguments uint8_t arg_num_types = this -> g_arg_fsm_status.num_arg; //Count the index of the current argument type being decoded uint8_t arg_type_cnt = 0; //Link argument type vector Arg_type *arg_type = this -> g_arg_type; ///-------------------------------------------------------------------------- /// INIT ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- /// BODY ///-------------------------------------------------------------------------- //if: no arguments if (arg_num_types == 0) { ///-------------------------------------------------------------------------- /// void ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, void ) = FUNCTION_PTR_CAST(void)callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE_VOID( f_ptr ); DPRINT("Executing void -> void: %p | Args: NONE \n", (void *)f_ptr ); } //if: first argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode first argument uint8_t *arg_a_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 - 1 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t ) = FUNCTION_PTR_CAST( uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); DPRINT("Executing uint8_t -> void: %p | Args: %d \n", (void *)f_ptr, (*arg_a_ptr) ); } //End If: it's the only argument //if: second argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 - 2 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint8_t, uint8_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U8 - 3 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U8 U8 - 4 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U8 U16 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U8 U32 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U16 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U16 U8 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U16 U16 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U16 U32 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint16_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U32 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U32 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U8 U32 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint8_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint8_t, uint32_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint8_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U8 or S8 //if: second argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 - 3 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint8_t, uint16_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U8 - 4 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U8 U8 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U8 U16 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode fourth argument uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U8 U32 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U16 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U16 U8 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U16 U16 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U32 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U16 U32 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint16_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint16_t, uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint16_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U16 or S16 //if: second argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint8_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if: third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 U8 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 U8 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 U8 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint32_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 U16 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint8_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U8 U32 U16 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint8_t, uint32_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint8_t, uint32_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint8_t, uint32_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 or U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 or U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } } //if: second argument is U32 or S32 //If: second argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: second argument is unhandled } //end if: first argument is U8 or S8 //if: first argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode first argument uint16_t *arg_a_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 - 2 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t ) = FUNCTION_PTR_CAST( uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); DPRINT("Executing uint16_t -> void: %p | Args: %d \n", (void *)f_ptr, (*arg_a_ptr) ); } //if: second argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 - 3 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint16_t, uint8_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U8 - 4 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U8 U8 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U8 U16 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode fourth argument uint32_t *arg_d_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U8 U32 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U16 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U16 U8 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U16 U16 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U32 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint8_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U8 U32 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint8_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint8_t, uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint8_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 or U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U8 or S8 //if: second argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 - 4 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint16_t, uint16_t -> void: %p | Args: %d %d\n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U8 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U8 U8 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U8 U16 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint16_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U16 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U16 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint16_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U16 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint16_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument //if: fifth argument else { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fifth argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_c_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U16 U32 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint16_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint16_t, uint32_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if: fourth argument else { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U16 or S16 //if: second argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U32 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint16_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U32 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint32_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U32 U8 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint16_t, uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 or U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U16 or S16 or U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U16 U32 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint16_t, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint16_t, uint32_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint16_t, uint32_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if: fourth argument else { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U32 or S32 //If: second argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: second argument is unhandled } //end if: first argument is U16 or S16 //if: first argument is S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode first argument uint32_t *arg_a_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_S32_SIZE; //I decoded an argument arg_type_cnt++; DPRINT("Decoded argument | arg_type_cnt: %d | arg_cnt: %d | arg: %d\n", arg_type_cnt, arg_cnt, (*arg_a_ptr)); //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 - 4 ///-------------------------------------------------------------------------- //Passing an unsigned 32 bit pointer is decoded successfully as signed of same size FUNCTION_PTR_VAR( f_ptr, uint32_t ) = FUNCTION_PTR_CAST( uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr) ); DPRINT("Executing int32_t -> void: %p | Args: %d\n", (void *)f_ptr, (*arg_a_ptr) ); } //if: second argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_b_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 - 5 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint16_t, uint8_t -> void: %p | Args: %d %d\n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 U8 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint32_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 U8 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint32_t, uint8_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode fourth argument uint16_t *arg_d_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 U8 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint32_t, uint8_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U16 or S16 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 U16 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint32_t, uint8_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U8 U16 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint8_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint8_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint32_t, uint8_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U8 or S8 //if: second argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_b_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U16 - 6 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint16_t, uint16_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //if third argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode second argument uint8_t *arg_c_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U16 U8 - 7 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint32_t, uint16_t, uint8_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument is U8 or S8 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U8) || (arg_type[arg_type_cnt] == Arg_type::ARG_S8)) { //Decode fourth argument uint8_t *arg_d_ptr = ARG_CAST( arg_cnt, uint8_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U8_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U16 U8 U8 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint8_t, uint8_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint8_t, uint8_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr)); DPRINT("Executing uint32_t, uint16_t, uint8_t, uint8_t -> void: %p | Args: %d %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr), (*arg_d_ptr) ); } //End If: it's the only argument } //end if fourth argument is U8 or S8 //if fourth argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16) || (arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument is U32 or S32 //if: more than four arguments are forbidden! else { this -> error_handler( ERR_TOO_MANY_ARGS ); DRETURN_ARG("ERR_TOO_MANY_ARGS in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if: more than four arguments are forbidden! } //if: third argument is U8 or S8 //if third argument is U16 or S16 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U16) || (arg_type[arg_type_cnt] == Arg_type::ARG_S16)) { //Decode second argument uint16_t *arg_c_ptr = ARG_CAST( arg_cnt, uint16_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U16_SIZE; //I decoded an argument arg_type_cnt++; //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U16 U16 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint16_t, uint16_t ) = FUNCTION_PTR_CAST( uint32_t, uint16_t, uint16_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr)); DPRINT("Executing uint32_t, uint16_t, uint16_t -> void: %p | Args: %d %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr), (*arg_c_ptr) ); } //End If: it's the only argument //if fourth argument else { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //end if fourth argument } //if: third argument is U16 or S16 //if third argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //if: third argument is U32 or S32 //If: third argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: third argument is unhandled } //if: second argument is U16 or S16 //if: second argument is U32 or S32 else if ((arg_type[arg_type_cnt] == Arg_type::ARG_U32) || (arg_type[arg_type_cnt] == Arg_type::ARG_S32)) { //Decode second argument uint32_t *arg_b_ptr = ARG_CAST( arg_cnt, uint32_t ); //Accumulate argument size arg_cnt += Arg_size::ARG_U32_SIZE; //I decoded an argument arg_type_cnt++; DPRINT("Decoded argument | arg_type_cnt: %d | arg_cnt: %d | arg: %d\n", arg_type_cnt, arg_cnt, (*arg_b_ptr)); //If: it's the only argument if (arg_num_types == arg_type_cnt) { ///-------------------------------------------------------------------------- /// U32 U32 - 8 ///-------------------------------------------------------------------------- //Declare specialized function pointer and link it to the general registered function callback address FUNCTION_PTR_VAR( f_ptr, uint32_t, uint32_t ) = FUNCTION_PTR_CAST( uint32_t, uint32_t )callback_ptr; //Execute function from its specialized pointer FUNCTION_PTR_EXE( f_ptr, (*arg_a_ptr), (*arg_b_ptr)); DPRINT("Executing uint32_t, uint32_t -> void: %p | Args: %d %d \n", (void *)f_ptr, (*arg_a_ptr), (*arg_b_ptr) ); } //End If: it's the only argument //If: I CANNOT have a third argument after this because it would exceed the argument size limit else { this -> error_handler( ERR_ARG_SIZE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: argument is unhandled } //if: second argument is U32 or S32 //If: second argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_ARG_SIZE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: second argument is unhandled } //end if: first argument is S32 //If: argument is unhandled else { this -> error_handler( ERR_UNHANDLED_ARG_TYPE ); DRETURN_ARG("ERR_UNHANDLED_ARG_TYPE in line: %d | num arg: %d | arg_index: %d\n", __LINE__, arg_type_cnt, arg_cnt); return true; //FAIL } //End If: argument is unhandled ///-------------------------------------------------------------------------- /// RETURN ///-------------------------------------------------------------------------- //Trace Return DRETURN(); return false; //OK } //end method: execute_callback /***************************************************************************/ //! @brief Private Method //! error_handler | Err_codes /***************************************************************************/ //! @param err_code | Err_codes | internal uniparser error code //! @return void //! @details //! Handles an internal parser error /***************************************************************************/ void Uniparser::error_handler( Err_codes err_code ) { //Trace Enter with arguments DENTER_ARG( "Error code: %d\n", err_code); //---------------------------------------------------------------- // VARS //---------------------------------------------------------------- //---------------------------------------------------------------- // INIT //---------------------------------------------------------------- //---------------------------------------------------------------- // BODY //---------------------------------------------------------------- //Save the error code this -> g_err = err_code; //---------------------------------------------------------------- // RETURN //---------------------------------------------------------------- //Trace Return vith return value DRETURN(); return; } //end method: error_handler | Err_codes /**************************************************************************** ** NAMESPACES ****************************************************************************/ } //End Namespace: Orangebot