mirror of
https://github.com/dexterbg/Twizy-Cfg.git
synced 2024-11-18 11:53:59 +00:00
318 lines
6.1 KiB
C++
318 lines
6.1 KiB
C++
/**
|
|
* ==========================================================================
|
|
* Twizy/SEVCON configuration shell
|
|
* ==========================================================================
|
|
*
|
|
* Utilities
|
|
*
|
|
* Based on the OVMS:
|
|
* https://github.com/openvehicles/Open-Vehicle-Monitoring-System
|
|
*
|
|
* License:
|
|
* This is free software.
|
|
* This is a modified copy of the OVMS general utils, so the OVMS license applies:
|
|
* https://github.com/openvehicles/Open-Vehicle-Monitoring-System/blob/master/LICENSE
|
|
*
|
|
*/
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
// hex string decode:
|
|
|
|
unsigned long axtoul(char *s)
|
|
{
|
|
unsigned long val = 0;
|
|
unsigned char c;
|
|
unsigned int dig = 0;
|
|
|
|
while (s && *s) {
|
|
c = *s | 0x20;
|
|
|
|
if (c == 'x') {
|
|
val = 0; // prefix 0x => reset val
|
|
}
|
|
else if (c >= '0' && c <= '9') {
|
|
dig = c - '0';
|
|
val = (val << 4) | dig;
|
|
}
|
|
else if (c >= 'a' && c <= 'f') {
|
|
dig = c - 'a' + 10;
|
|
val = (val << 4) | dig;
|
|
}
|
|
else {
|
|
break; // no hex char, stop
|
|
}
|
|
|
|
s++;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
// string prefix check:
|
|
|
|
bool starts_with(char *s, const char *pfx)
|
|
{
|
|
while ((*s == *pfx) && (*pfx != 0))
|
|
{
|
|
pfx++;
|
|
s++;
|
|
}
|
|
return (*pfx == 0);
|
|
}
|
|
|
|
|
|
// string-print string:
|
|
|
|
char *stp_rom(char *dst, const char *val)
|
|
{
|
|
while (*dst = *val++) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print ram string:
|
|
|
|
char *stp_ram(char *dst, const char *val)
|
|
{
|
|
while (*dst = *val++) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print ram string with optional prefix:
|
|
|
|
char *stp_s(char *dst, const char *prefix, char *val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
return stp_ram(dst, val);
|
|
}
|
|
|
|
// string-print string with optional prefix:
|
|
|
|
char *stp_rs(char *dst, const char *prefix, const char *val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
return stp_rom(dst, val);
|
|
}
|
|
|
|
// string-print integer with optional string prefix:
|
|
|
|
char *stp_i(char *dst, const char *prefix, int val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
itoa(val, dst, 10);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print long with optional string prefix:
|
|
|
|
char *stp_l(char *dst, const char *prefix, long val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
ltoa(val, dst, 10);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print unsigned long with optional string prefix:
|
|
|
|
char *stp_ul(char *dst, const char *prefix, unsigned long val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
ultoa(val, dst, 10);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// ltox
|
|
// (note: fills fixed len chars with '0' padding = sprintf %04x)
|
|
|
|
void ltox(unsigned long i, char *s, unsigned int len)
|
|
{
|
|
unsigned char n;
|
|
|
|
s += len;
|
|
*s = '\0';
|
|
|
|
for (n = len; n != 0; --n)
|
|
{
|
|
*--s = "0123456789ABCDEF"[i & 0x0F];
|
|
i >>= 4;
|
|
}
|
|
}
|
|
|
|
// string-print unsigned integer hexadecimal with optional string prefix:
|
|
// (note: fills fixed 4 chars with '0' padding = sprintf %04x)
|
|
|
|
char *stp_x(char *dst, const char *prefix, unsigned int val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
ltox(val, dst, 4);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print unsigned long hexadecimal with optional string prefix:
|
|
// (note: fills fixed 8 chars with '0' padding = sprintf %08lx)
|
|
|
|
char *stp_lx(char *dst, const char *prefix, unsigned long val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
ltox(val, dst, 8);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print unsigned integer hexadecimal with optional string prefix:
|
|
// (note: fills fixed 2 chars with '0' padding = sprintf %02x)
|
|
|
|
char *stp_sx(char *dst, const char *prefix, unsigned char val)
|
|
{
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
ltox(val, dst, 2);
|
|
while (*dst) dst++;
|
|
return dst;
|
|
}
|
|
|
|
// string-print unsigned long to fixed size with padding
|
|
|
|
char *stp_ulp(char *dst, const char *prefix, unsigned long val, int len, char pad)
|
|
{
|
|
char buf[11];
|
|
byte bl;
|
|
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
|
|
ultoa(val, buf, 10);
|
|
|
|
for (bl = strlen(buf); bl < len; bl++)
|
|
*dst++ = pad;
|
|
|
|
dst = stp_ram(dst, buf);
|
|
|
|
return dst;
|
|
}
|
|
|
|
|
|
// string-print fixed precision long as float
|
|
|
|
char *stp_l2f(char *dst, const char *prefix, long val, int prec)
|
|
{
|
|
long factor, lval;
|
|
char p;
|
|
|
|
for (factor = 1, p = prec; p > 0; p--)
|
|
factor *= 10;
|
|
lval = val / factor;
|
|
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
if (lval == 0 && val < 0) // handle "negative zero"
|
|
*dst++ = '-';
|
|
dst = stp_l(dst, NULL, lval);
|
|
*dst++ = '.';
|
|
dst = stp_ulp(dst, NULL, ABS(val) % factor, prec, '0');
|
|
|
|
return dst;
|
|
}
|
|
|
|
|
|
// string-print unsigned long as fixed point number with optional string prefix
|
|
|
|
#define chDecimal '.'
|
|
#define chSeparator ','
|
|
|
|
char *stp_l2f_h(char *dst, const char *prefix, unsigned long val, int cdecimal)
|
|
{
|
|
char *start, *end;
|
|
int cch;
|
|
|
|
if (prefix)
|
|
dst = stp_rom(dst, prefix);
|
|
|
|
start = dst;
|
|
cch = 0;
|
|
// decompose the number, writing out the digits backwards
|
|
while (val != 0 || cch <= cdecimal)
|
|
{
|
|
// write out the thousands separator when needed
|
|
if (((cch - cdecimal) % 3) == 0 && cch > cdecimal)
|
|
*dst++ = chSeparator;
|
|
|
|
// peel off the next digit
|
|
*dst++ = '0' + (val % 10);
|
|
val /= 10;
|
|
|
|
// write out the decimal point when needed
|
|
if (++cch == cdecimal)
|
|
*dst++ = chDecimal;
|
|
}
|
|
end = dst - 1;
|
|
// reverse the string in place
|
|
while (start < end)
|
|
{
|
|
char chT = *start;
|
|
*start++ = *end;
|
|
*end-- = chT;
|
|
}
|
|
// null terminate
|
|
*dst = 0;
|
|
return dst;
|
|
}
|
|
|
|
|
|
// Text command argument tokenizing:
|
|
|
|
char *net_sms_argend = NULL;
|
|
|
|
char* net_sms_initargs(char* arguments)
|
|
{
|
|
char *p;
|
|
|
|
if (arguments == NULL) return NULL;
|
|
|
|
net_sms_argend = arguments + strlen(arguments);
|
|
if (net_sms_argend == arguments) return NULL;
|
|
|
|
// Zero-terminate the first argument
|
|
for (p = arguments; (*p != ' ') && (*p != 0); p++) {}
|
|
if (*p == ' ') *p = 0;
|
|
|
|
return arguments;
|
|
}
|
|
|
|
char* net_sms_nextarg(char *lastarg)
|
|
{
|
|
char *p;
|
|
|
|
if (lastarg == NULL) return NULL;
|
|
|
|
// find end of previous argument:
|
|
for (p = lastarg; (*p != 0); p++) {}
|
|
if (p == net_sms_argend) return NULL;
|
|
|
|
// find start of next argument:
|
|
while (*++p == ' ') {}
|
|
if (p == net_sms_argend) return NULL;
|
|
lastarg = p;
|
|
|
|
// zero-terminate:
|
|
for (; (*p != ' ') && (*p != 0); p++) {}
|
|
if (*p == ' ') *p = 0;
|
|
|
|
return lastarg;
|
|
}
|
|
|
|
|
|
|