22/* *
33 * @file minbasecli.cpp
44 * @author Jose Miguel Rios Rubio <[email protected] > 5- * @date 10-02 -2022
6- * @version 1.1.0
5+ * @date 02-04 -2022
6+ * @version 1.1.1
77 *
88 * @section DESCRIPTION
99 *
3838
3939// Standard Libraries
4040#include < string.h>
41+ #include < stdarg.h>
4142
4243/* ****************************************************************************/
4344
4445/* Constants & Defines */
4546
47+ // Maximum string length to store a 64 bit signed/unsigned number
48+ static const uint8_t MAX_64_BIT_NUM_STR_LENGTH = 21 ;
49+
4650/* ****************************************************************************/
4751
4852/* In-Scope Function Prototypes */
@@ -103,8 +107,7 @@ bool MINBASECLI::manage(t_cli_result* cli_result)
103107 cli_result->cmd , MINBASECLI_MAX_CMD_LEN);
104108
105109 // Shows the received command
106- print (" # " );
107- println (this ->rx_read );
110+ this ->printf (" # %s\n " , this ->rx_read );
108111
109112 // Check number of command arguments
110113 cli_result->argc = str_count_words (this ->rx_read , received_bytes);
@@ -129,8 +132,6 @@ bool MINBASECLI::manage(t_cli_result* cli_result)
129132 if (ptr_argv == NULL )
130133 {
131134 // No ' ' character found, so it is last command, lets get it
132- // hal_snprintf(cli_result->argv[i], MINBASECLI_MAX_ARGV_LEN,
133- // "%s", ptr_data);
134135 strncpy (cli_result->argv [i], ptr_data, strlen (ptr_data));
135136 cli_result->argv [i][MINBASECLI_MAX_ARGV_LEN-1 ] = ' \0 ' ;
136137 break ;
@@ -147,31 +148,255 @@ bool MINBASECLI::manage(t_cli_result* cli_result)
147148}
148149
149150/* *
150- * @brief Print a given string through the CLI.
151- * @param str String to print.
151+ * @brief Print a format string through the CLI.
152+ * @param fstr String format to print.
152153 */
153- void MINBASECLI::print (const char * str)
154+ void MINBASECLI::printf (const char * fstr, ...)
155+ {
156+ va_list lst;
157+
158+ va_start (lst, fstr);
159+
160+ while (*fstr != ' \0 ' )
161+ {
162+ // Just print the string if start format symbol has not been reach
163+ if (*fstr != ' %' )
164+ {
165+ hal_iface_print ((uint8_t )(*fstr));
166+ fstr = fstr + 1 ;
167+ continue ;
168+ }
169+
170+ // Increase format string pointer to next char, and check end of string
171+ fstr = fstr + 1 ;
172+ if (*fstr == ' \0 ' )
173+ break ;
174+
175+ /* Check for format to apply */
176+
177+ // Format String
178+ if (*fstr == ' s' )
179+ printstr (va_arg (lst, char *));
180+
181+ // Format Character
182+ else if (*fstr == ' c' )
183+ hal_iface_print ((uint8_t )(va_arg (lst, int )));
184+
185+ // Format Unsigned integer
186+ else if (*fstr == ' u' )
187+ {
188+ // Convert unsigned type argument of variadic list into string
189+ if (u64toa ((uint64_t )(va_arg (lst, unsigned )), print_array,
190+ MINBASECLI_MAX_PRINT_SIZE, 10 ) == false )
191+ {
192+ // Increase format string pointer to next character
193+ fstr = fstr + 1 ;
194+ continue ;
195+ }
196+
197+ // Print the converted value string
198+ printstr (print_array);
199+ }
200+
201+ // Format Signed Integer
202+ else if ((*fstr == ' i' ) || (*fstr == ' d' ))
203+ {
204+ // Convert integer type argument of variadic list into string
205+ if (i64toa ((int64_t )(va_arg (lst, int )), print_array,
206+ MINBASECLI_MAX_PRINT_SIZE, 10 ) == false )
207+ {
208+ // Increase format string pointer to next character
209+ fstr = fstr + 1 ;
210+ continue ;
211+ }
212+
213+ // Print the converted value string
214+ printstr (print_array);
215+ }
216+
217+ // Format Hexadecimal
218+ // Note: specify leading zeroes is not supported
219+ else if ((*fstr == ' x' ) || (*fstr == ' X' ))
220+ {
221+ // Convert unsigned type argument of variadic list into string
222+ if (u64toa ((uint64_t )(va_arg (lst, unsigned )), print_array,
223+ MINBASECLI_MAX_PRINT_SIZE, 16 ) == false )
224+ {
225+ // Increase format string pointer to next character
226+ fstr = fstr + 1 ;
227+ continue ;
228+ }
229+
230+ // Print a leading zero if hexadecimal string length is odd
231+ if ((strlen (print_array) % 2 ) != 0 )
232+ this ->hal_iface_print (' 0' );
233+
234+ // Print the converted value string
235+ printstr (print_array);
236+ }
237+
238+ // Unssuported format
239+ else
240+ {
241+ // Do nothing
242+ }
243+
244+ // Increase format string pointer to next character
245+ fstr = fstr + 1 ;
246+ }
247+
248+ va_end (lst);
249+ }
250+
251+ /* ****************************************************************************/
252+
253+ /* Private Methods */
254+
255+ /* *
256+ * @brief Print a string.
257+ * @param str The string to print.
258+ */
259+ void MINBASECLI::printstr (const char * str)
154260{
155261 while (*str != ' \0 ' )
156262 {
157- hal_iface_print ((const uint8_t )(*str));
263+ hal_iface_print ((uint8_t )(*str));
158264 str = str + 1 ;
159265 }
160266}
161267
162268/* *
163- * @brief Print line a given string through the CLI.
164- * @param str String to print.
269+ * @brief Reverse string characters ("ABCD" -> "DCBA").
270+ * @param str Pointer to string to reverse (also reversed string result).
271+ * @param length Number of characters of the string.
272+ * @return Operation result success/fail (true/false).
273+ */
274+ bool MINBASECLI::str_reverse (char * str, uint8_t length)
275+ {
276+ char tmp[MAX_64_BIT_NUM_STR_LENGTH];
277+ int8_t start = 0 ;
278+ int8_t end = length - 1 ;
279+
280+ if (length == 0 )
281+ return false ;
282+
283+ memcpy (tmp, str, length);
284+ while (start < end)
285+ {
286+ *(str + start) = *(tmp + end);
287+ *(str + end) = *(tmp + start);
288+ start = start + 1 ;
289+ end = end - 1 ;
290+ }
291+
292+ return true ;
293+ }
294+
295+ /* *
296+ * @brief Convert a unsigned integer of 64 bits (uint64_t) into a string.
297+ * @param num Unsigned integer to be converted.
298+ * @param str Pointer to array that gonna store the converted result string.
299+ * @param str_size Size of converted string array.
300+ * @param base Provided number base (binary, decimal, hexadecimal, etc.).
301+ * @return Conversion result (false - fail; true - success).
165302 */
166- void MINBASECLI::println (const char * str)
303+ bool MINBASECLI::u64toa (uint64_t num, char * str,
304+ const uint8_t str_size, const uint8_t base)
167305{
168- print (str);
169- print (" \n " );
306+ uint64_t tmp;
307+ uint8_t i = 0 ;
308+
309+ // Check if string buffer max size is large enough for 64 bits num
310+ if (str_size < MAX_64_BIT_NUM_STR_LENGTH)
311+ return false ;
312+
313+ // Check for number 0
314+ if (num == 0 )
315+ {
316+ str[0 ] = ' 0' ;
317+ str[1 ] = ' \0 ' ;
318+ return true ;
319+ }
320+
321+ // Process individual digits
322+ while (num != 0 )
323+ {
324+ tmp = num % base;
325+ if (tmp > 9 )
326+ str[i] = (tmp - 10 ) + ' a' ;
327+ else
328+ str[i] = tmp + ' 0' ;
329+ num = num / base;
330+ i = i + 1 ;
331+ }
332+
333+ // Null terminate string
334+ str[i] = ' \0 ' ;
335+
336+ // Reverse the string
337+ str_reverse (str, i);
338+
339+ return true ;
170340}
171341
172- /* ****************************************************************************/
342+ /* *
343+ * @brief Convert a signed integer of 64 bits (int64_t) into a string.
344+ * @param num Signed integer to be converted.
345+ * @param str Pointer to array that gonna store the converted result string.
346+ * @param str_size Size of converted string array.
347+ * @param base Provided number base (binary, decimal, hexadecimal, etc.).
348+ * @return Conversion result (false - fail; true - success).
349+ */
350+ bool MINBASECLI::i64toa (int64_t num, char * str,
351+ const uint8_t str_size, const uint8_t base)
352+ {
353+ uint64_t tmp;
354+ uint8_t i = 0 ;
355+ bool negative_num = false ;
173356
174- /* Private Methods */
357+ // Check if string buffer max size is large enough for 64 bits num
358+ if (str_size < MAX_64_BIT_NUM_STR_LENGTH)
359+ return false ;
360+
361+ // Check for number 0
362+ if (num == 0 )
363+ {
364+ str[0 ] = ' 0' ;
365+ str[1 ] = ' \0 ' ;
366+ return true ;
367+ }
368+
369+ // Check for negative number when decimal base
370+ if (num < 0 && base == 10 )
371+ {
372+ negative_num = true ;
373+ num = (-num);
374+ }
375+
376+ // Process individual digits
377+ while (num != 0 )
378+ {
379+ tmp = num % base;
380+ if (tmp > 9 )
381+ str[i] = (tmp - 10 ) + ' a' ;
382+ else
383+ str[i] = tmp + ' 0' ;
384+ num = num / base;
385+ i = i + 1 ;
386+ }
387+
388+ // If number is negative, append '-'
389+ if (negative_num)
390+ str[i++] = ' -' ;
391+
392+ // Null terminate string
393+ str[i] = ' \0 ' ;
394+
395+ // Reverse the string
396+ str_reverse (str, i);
397+
398+ return true ;
399+ }
175400
176401/* *
177402 * @brief Set attributes of a t_cli_result element to default null values.
0 commit comments