HAN-FUN API  1.5.3
This project provides the common implementation of ULE Alliance's HAN-FUN application protocol.
common.cpp
Go to the documentation of this file.
1 // =============================================================================
16 // =============================================================================
17 
18 #include <iostream>
19 #include <iomanip>
20 #include <vector>
21 #include <string>
22 #include <sstream>
23 #include <iterator>
24 
25 #include <cstdint>
26 
27 #include "common.h"
28 #include "application.h"
29 
34 // =============================================================================
35 // Commands API
36 // =============================================================================
37 
38 std::map<std::string, ICommand *> ICommand::registry;
39 
40 // =============================================================================
41 // ICommand::add
42 // =============================================================================
46 // =============================================================================
47 void ICommand::add(ICommand *command)
48 {
49  registry.insert(std::pair<std::string, ICommand *>(command->key(), command));
50 }
51 
52 // =============================================================================
53 // ICommand::remove
54 // =============================================================================
58 // =============================================================================
59 void ICommand::remove(ICommand *command)
60 {
61  registry.erase(command->key());
62 }
63 
64 // =============================================================================
65 // ICommand::help
66 // =============================================================================
70 // =============================================================================
71 std::ostream &ICommand::help(std::ostream &_stream)
72 {
73  struct entry
74  {
75  std::string cmd;
76  std::string help;
77  };
78 
79  static std::string cache = "";
80  static uint8_t cache_count = 0;
81 
82  if (cache_count == ICommand::registry.size())
83  {
84  _stream << cache;
85  return _stream;
86  }
87 
88  std::stringstream stream;
89 
90  uint16_t size = 0;
91  std::vector<entry> entries;
92 
93  /* *INDENT-OFF* */
94  std::for_each (ICommand::registry.begin (), ICommand::registry.end (),
95  [&entries, &size](std::pair <std::string, ICommand *> e)
96  {
97  // LOG (TRACE) << "E F : " << e.first << NL;
98  // LOG (TRACE) << "E S : " << e.second << NL;
99 
100  const std::string &raw = e.second->usage ();
101 
102  char *temp = new char[raw.size ()+1];
103 
104  strncpy (temp, raw.c_str (), raw.size ())[raw.size ()] = 0;
105 
106  std::vector <char *> lines;
107 
108  char *saveptr = NULL;
109  for (char *p = strtok_r (temp, "\n", &saveptr); p != NULL; p = strtok_r (NULL, "\n", &saveptr))
110  {
111  lines.push_back (p);
112  }
113 
114  std::for_each (lines.begin (), lines.end (), [&entries, &size](char *line)
115  {
116  entry e;
117 
118  char *saveptr = NULL;
119  char *p = strtok_r (line, ":", &saveptr);
120  e.cmd = std::string (p);
121 
122  p = strtok_r (NULL, ":", &saveptr);
123  e.help = std::string (p);
124 
125  entries.push_back (e);
126 
127  if (size < e.cmd.size ())
128  {
129  size = e.cmd.size ();
130  }
131  });
132 
133  delete[] temp;
134  });
135  /* *INDENT-ON* */
136 
137  size++;
138 
139  stream << std::endl;
140 
141  stream << "================================================" << std::endl;
142  stream << "HAN-FUN Example Application : v" << HF_VERSION << std::endl;
143  stream << "================================================" << std::endl << std::endl;
144 
145  stream << std::setfill(' ');
146  /* *INDENT-OFF* */
147  std::for_each (entries.begin (), entries.end (), [&stream, size](entry &e)
148  {
149  stream << std::left << std::setw (size) << e.cmd << "\t: " << e.help << std::endl;
150  });
151  /* *INDENT-ON* */
152 
153  stream << std::left << std::setw(size) << "h/?" << "\t: " << "this help menu."
154  << std::endl << std::endl;
155  stream << "Select an Option (Q/q to exit): " << std::endl;
156 
157  cache = stream.str();
158 
159  _stream << cache;
160 
161  return _stream;
162 }
163 
164 // =============================================================================
165 // ICommand::run
166 // =============================================================================
170 // =============================================================================
171 void ICommand::run(std::string &key, std::vector<std::string> &args)
172 {
173  auto it = registry.find(key);
174 
175  if (it == registry.end())
176  {
177  LOG(ERROR) << "Command '" << key << "' not found !" << NL;
178  ICommand::help(std::cout);
179  }
180  else
181  {
182  it->second->run(args);
183  }
184 }
185 
186 // =============================================================================
187 // API
188 // =============================================================================
189 
190 // =============================================================================
191 // HF::Application::Handle
192 // =============================================================================
196 // =============================================================================
197 bool HF::Application::Handle(std::string command)
198 {
199  LOG(TRACE) << __PRETTY_FUNCTION__ << NL;
200 
201  if (command.empty() || (command.size() == 1 && command[0] == '\n'))
202  {
203  ICommand::help(std::cout);
204  return false;
205  }
206 
207  std::istringstream buf(command);
208  std::istream_iterator<std::string> beg(buf), end;
209 
210  std::vector<std::string> tokens(beg, end);
211 
212  std::string cmd = *tokens.begin();
213 
214  std::vector<std::string> args(tokens.begin() + 1, tokens.end());
215 
216  if (cmd == "q" || cmd == "Q")
217  {
218  return true;
219  }
220  else if (cmd == "h" || cmd == "?")
221  {
222  LOG(APP) << "";
223  ICommand::help(std::cout);
224  }
225  else
226  {
227  ICommand::run(cmd, args);
228  }
229 
230  LOG(APP) << "> " << std::flush;
231 
232  return false;
233 }
234 
bool Handle(std::string command)
Handle the command.
Definition: common.cpp:197
This file contains the definitions for the HAN-FUN example applications.
static void add(ICommand *command)
Add a command to the registry.
Definition: common.cpp:47
Example application menu entry API.
Definition: apps/common.h:37
static std::map< std::string, ICommand * > registry
Command registry.
Definition: apps/common.h:42
virtual void run(std::vector< std::string > &args)=0
Execute the command code.
#define NL
Helper define for new-line and stream clear.
Definition: debug.h:34
static void remove(ICommand *command)
Remove a command to the registry.
Definition: common.cpp:59
virtual const std::string & key() const =0
Get the command key.
This file contains the definitions for the common functionality in the HAN-FUN example applications...
#define LOG(X)
Log messages with the level given by X.
Definition: debug.h:81
static std::ostream & help(std::ostream &stream)
Generate the help screen, based on the commands in the registry.
Definition: common.cpp:71