Home | History | Annotate | Download | only in remote-processor
      1 /*
      2  * Copyright (c) 2011-2014, Intel Corporation
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without modification,
      6  * are permitted provided that the following conditions are met:
      7  *
      8  * 1. Redistributions of source code must retain the above copyright notice, this
      9  * list of conditions and the following disclaimer.
     10  *
     11  * 2. Redistributions in binary form must reproduce the above copyright notice,
     12  * this list of conditions and the following disclaimer in the documentation and/or
     13  * other materials provided with the distribution.
     14  *
     15  * 3. Neither the name of the copyright holder nor the names of its contributors
     16  * may be used to endorse or promote products derived from this software without
     17  * specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
     23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 #pragma once
     31 
     32 #include <vector>
     33 #include "RemoteCommandHandler.h"
     34 
     35 template <class CCommandParser>
     36 class TRemoteCommandHandlerTemplate : public IRemoteCommandHandler
     37 {
     38 public:
     39     /** Remote command parser execution return status */
     40     enum CommandStatus {
     41         EDone, /**< Command succeded, return "Done" */
     42         ESucceeded, /**< Command succeeded */
     43         EFailed, /**< Command failed */
     44         EShowUsage /**< Command failed, show usage */
     45     };
     46 
     47     /** Type of the remote command callbacks
     48      *
     49      * @param[in] remoteCommand contains the arguments of the received command.
     50      * @param[out] strResult a string containing the result of the command.
     51      *
     52      * @return the command execution status, @see CommandStatus
     53      */
     54     typedef CommandStatus (CCommandParser::*RemoteCommandParser)(const IRemoteCommand& remoteCommand, std::string& strResult);
     55 
     56 private:
     57     // Parser descriptions
     58     class CRemoteCommandParserItem
     59     {
     60     public:
     61         CRemoteCommandParserItem(const std::string& strCommandName,
     62                                  RemoteCommandParser pfnParser,
     63                                  uint32_t uiMinArgumentCount,
     64                                  const std::string& strHelp,
     65                                  const std::string& strDescription)
     66             : _strCommandName(strCommandName),
     67               _pfnParser(pfnParser),
     68               _uiMinArgumentCount(uiMinArgumentCount),
     69               _strHelp(strHelp),
     70               _strDescription(strDescription) {}
     71 
     72         const std::string& getCommandName() const
     73         {
     74             return _strCommandName;
     75         }
     76 
     77         const std::string& getDescription() const
     78         {
     79             return _strDescription;
     80         }
     81 
     82         // Usage
     83         std::string usage() const
     84         {
     85             return _strCommandName + " " + _strHelp;
     86         }
     87 
     88         bool parse(CCommandParser* pCommandParser, const IRemoteCommand& remoteCommand, std::string& strResult) const
     89         {
     90             // Check enough arguments supplied
     91             if (remoteCommand.getArgumentCount() < _uiMinArgumentCount) {
     92 
     93                 strResult = std::string("Not enough arguments supplied\nUsage:\n") + usage();
     94 
     95                 return false;
     96             }
     97 
     98             switch ((pCommandParser->*_pfnParser)(remoteCommand, strResult)) {
     99             case EDone:
    100                 strResult = "Done";
    101                 // Fall through intentionally
    102             case ESucceeded:
    103                 return true;
    104             case EShowUsage:
    105                 strResult = usage();
    106                 // Fall through intentionally
    107             case EFailed:
    108                 return false;
    109             }
    110 
    111             return false;
    112         }
    113 
    114     private:
    115         std::string _strCommandName;
    116         RemoteCommandParser _pfnParser;
    117         uint32_t _uiMinArgumentCount;
    118         std::string _strHelp;
    119         std::string _strDescription;
    120     };
    121 
    122 public:
    123     TRemoteCommandHandlerTemplate(CCommandParser* pCommandParser) : _pCommandParser(pCommandParser), _uiMaxCommandUsageLength(0)
    124     {
    125         // Help Command
    126         addCommandParser("help", NULL, 0, "", "Show commands description and usage");
    127     }
    128     ~TRemoteCommandHandlerTemplate()
    129     {
    130         uint32_t uiIndex;
    131 
    132         for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
    133 
    134             delete _remoteCommandParserVector[uiIndex];
    135         }
    136     }
    137 
    138     // Parsers
    139     bool addCommandParser(const std::string& strCommandName,
    140         RemoteCommandParser pfnParser,
    141         uint32_t uiMinArgumentCount,
    142         const std::string& strHelp,
    143         const std::string& strDescription)
    144     {
    145         if (findCommandParserItem(strCommandName)) {
    146 
    147             // Already exists
    148             return false;
    149         }
    150 
    151         // Add command
    152         _remoteCommandParserVector.push_back(new CRemoteCommandParserItem(strCommandName, pfnParser, uiMinArgumentCount, strHelp, strDescription));
    153 
    154         return true;
    155     }
    156 
    157 private:
    158     // Command processing
    159     bool remoteCommandProcess(const IRemoteCommand& remoteCommand, std::string& strResult)
    160     {
    161         // Dispatch
    162         const CRemoteCommandParserItem* pRemoteCommandParserItem = findCommandParserItem(remoteCommand.getCommand());
    163 
    164         if (!pRemoteCommandParserItem) {
    165 
    166             // Not found
    167             strResult = "Command not found!\nUse \"help\" to show available commands";
    168 
    169             return false;
    170         }
    171 
    172         if (remoteCommand.getCommand() == "help") {
    173 
    174             helpCommandProcess(strResult);
    175 
    176             return true;
    177         }
    178 
    179         return pRemoteCommandParserItem->parse(_pCommandParser, remoteCommand, strResult);
    180     }
    181 
    182     // Max command usage length, use for formatting
    183     void initMaxCommandUsageLength()
    184     {
    185         if (!_uiMaxCommandUsageLength) {
    186             // Show usages
    187             uint32_t uiIndex;
    188 
    189             for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
    190 
    191                 const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
    192 
    193                 uint32_t uiRemoteCommandUsageLength = (uint32_t)pRemoteCommandParserItem->usage().length();
    194 
    195                 if (uiRemoteCommandUsageLength > _uiMaxCommandUsageLength) {
    196 
    197                     _uiMaxCommandUsageLength = uiRemoteCommandUsageLength;
    198                 }
    199             }
    200         }
    201     }
    202 
    203     /////////////////// Remote command parsers
    204     /// Help
    205     void helpCommandProcess(std::string& strResult)
    206     {
    207         initMaxCommandUsageLength();
    208 
    209         strResult = "\n";
    210 
    211         // Show usages
    212         uint32_t uiIndex;
    213 
    214         for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
    215 
    216             const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
    217 
    218             std::string strUsage = pRemoteCommandParserItem->usage();
    219 
    220             strResult += strUsage;
    221 
    222             // Align
    223             uint32_t uiToSpacesAdd = _uiMaxCommandUsageLength + 5 - (uint32_t)strUsage.length();
    224 
    225             while (uiToSpacesAdd--) {
    226 
    227                 strResult += " ";
    228             }
    229 
    230             strResult += std::string("=> ") + std::string(pRemoteCommandParserItem->getDescription()) + "\n";
    231         }
    232     }
    233 
    234     const CRemoteCommandParserItem* findCommandParserItem(const std::string& strCommandName) const
    235     {
    236         uint32_t uiIndex;
    237 
    238         for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
    239 
    240             const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
    241 
    242             if (pRemoteCommandParserItem->getCommandName() == strCommandName) {
    243 
    244                 return pRemoteCommandParserItem;
    245             }
    246         }
    247         return NULL;
    248     }
    249 
    250 private:
    251     CCommandParser* _pCommandParser;
    252     std::vector<CRemoteCommandParserItem*> _remoteCommandParserVector;
    253     uint32_t _uiMaxCommandUsageLength;
    254 };
    255 
    256