Skip to content

Commit 9144d30

Browse files
committed
Basic printf support
1 parent 15e1b3e commit 9144d30

File tree

2 files changed

+272
-22
lines changed

2 files changed

+272
-22
lines changed

src/minbasecli.cpp

Lines changed: 242 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
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
*
@@ -38,11 +38,15 @@
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.

src/minbasecli.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
/**
33
* @file minbasecli.h
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
*
@@ -113,6 +113,11 @@
113113
#define MINBASECLI_MAX_ARGV 4
114114
#endif
115115

116+
// Maximum Print formated number array size
117+
#if !defined(MINBASECLI_MAX_PRINT_SIZE)
118+
#define MINBASECLI_MAX_PRINT_SIZE 22
119+
#endif
120+
116121
/*****************************************************************************/
117122

118123
/* Data Types */
@@ -125,6 +130,20 @@ typedef struct t_cli_result
125130
uint8_t argc;
126131
} t_cli_result;
127132

133+
//
134+
typedef enum t_var_type
135+
{
136+
T_UINT8,
137+
T_UINT16,
138+
T_UINT32,
139+
T_UINT64,
140+
T_INT8,
141+
T_INT16,
142+
T_INT32,
143+
T_INT64,
144+
T_FLOAT
145+
} t_var_type;
146+
128147
/*****************************************************************************/
129148

130149
/* MinBaseCLI Class Interface */
@@ -138,22 +157,28 @@ class MINBASECLI : public MINBASECLI_HAL
138157
bool setup(void* iface,
139158
const uint32_t baud_rate=MINBASECLI_DEFAULT_BAUDS);
140159
bool manage(t_cli_result* cli_result);
141-
uint32_t get_received_bytes();
142-
void print(const char* str);
143-
void println(const char* str);
160+
void printf(const char* str, ...);
144161

145162
private:
146163
bool initialized;
147164
uint32_t received_bytes;
148165
char rx_read[MINBASECLI_MAX_READ_SIZE];
166+
char print_array[MINBASECLI_MAX_PRINT_SIZE];
149167

150168
void set_default_result(t_cli_result* cli_result);
151169
bool iface_is_not_initialized();
170+
uint32_t get_received_bytes();
152171
bool iface_read_data(char* rx_read, const size_t rx_read_size);
153172
uint32_t str_count_words(const char* str_in, const size_t str_in_len);
154173
bool str_read_until_char(char* str, const size_t str_len,
155174
const char until_c, char* str_read,
156175
const size_t str_read_size);
176+
void printstr(const char* str);
177+
bool u64toa(uint64_t number, char* str, const uint8_t str_max_size,
178+
const uint8_t base);
179+
bool i64toa(int64_t number, char* str, const uint8_t str_max_size,
180+
const uint8_t base);
181+
bool str_reverse(char* str, uint8_t length);
157182
};
158183

159184
/*****************************************************************************/

0 commit comments

Comments
 (0)