5.2 KB · raw
#include <stdlib.h>
#include "string.h"
#include "util.h"
bool is_special(char c) {
//ctype takes an int that must be representable as unsigned char or EOF. Passing a
//plain (signed) char hands it a negative value for every byte above 0x7f, which is
//undefined - and these protocols carry binary payloads full of them.
unsigned char u = (unsigned char)c;
return (isspace(u) || u == '\r' || u == '\n');
}
char * strip_whitespace(char * cmd) {
for (; strlen(cmd) > 0 && is_special(*cmd); cmd++);
//a string that is empty, or entirely whitespace, leaves strlen at 0 here and the old
//"strlen - 1" wrapped to SIZE_MAX, so the loop read cmd[SIZE_MAX] on its first test.
size_t len = strlen(cmd);
if (len == 0) {
return cmd;
}
for (size_t idx = len - 1; idx > 0 && is_special(cmd[idx]) ; idx--) {
char c = cmd[idx];
if (!isprint(c)) {
cmd[idx] = ' ';
}
if (isspace(c)) {
cmd[idx] = ' ';
}
if (c == '\r' || c == '\n') {
cmd[idx] = 0;
}
}
return cmd;
}
int parse_int(char * str, size_t count) {
if (count >= 32) {
return 0;
}
if (0 == str) {
return 0;
}
for (size_t i = 0; i < count && is_special(*str); i++) {
str++;
}
unsigned char tmp[32];
memset(tmp, 0, 32);
memcpy(tmp, str, min(count, strlen(str)));
return atoi((const char *)tmp);
}
float parse_float(char * string) {
float num = 0, divisor = 10;;
char ch;
bool neg = false;
if (0 == string) {
return num;
}
size_t count = strlen(string);
for (size_t i = 0; i < count && is_special(*string); i++) {
string++;
}
if (*string == '-') {
neg = true;
string++;
}
while (isdigit((unsigned char)(ch = *string)) && ch != 0) {
num = 10 * num + ch - '0';
string++;
}
//the integer loop above used to consume the byte that stopped it. When that byte was
//the terminator the fractional loop started one past the end of the string and read
//whatever followed it in memory.
if (*string == '.' || *string == ',') {
string++;
while (isdigit((unsigned char)(ch = *string)) && ch != 0) {
num = num + (ch - '0') / divisor;
divisor *= 10;
string++;
}
}
return neg ? -num : num;
}
int idx(char * string, char c) {
char * e = strchr(string, c);
if (e == NULL) {
return 0;
}
return (int)(e - string);
}
/*
* Where c first appears in the first len bytes of buf, or -1 when it does not.
*
* The framing code used idx(), which answers 0 both for "not there" and for "at the very
* start", and searches with strchr - past read_count, through whatever an earlier message
* left in the buffer. A frame that was nothing but its terminator ("#" on its own) therefore
* looked like no frame at all, was never consumed, and every message behind it waited for
* ever. memchr over the bytes actually received, and a distinct answer for "not found".
*/
long find_byte(const unsigned char * buf, size_t len, unsigned char c) {
const unsigned char * at = buf ? memchr(buf, c, len) : NULL;
return at ? (long)(at - buf) : -1;
}
/*
* Six hex octets out of a scan entry, in whichever layout the protocol uses ("%x:%x:..." or
* "%2x%2x..."). True only when all six converted, each fits a byte, and the address is not
* all zeros or all ones - neither of which is an access point. mac is written only then, so
* a field that does not parse can never hand the lookup whatever was on the stack.
*/
bool parse_mac(const char * text, const char * format, unsigned char mac[6]) {
unsigned int v[6] = {0};
if (text == 0 || format == 0 || sscanf(text, format, &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]) != 6) {
return false;
}
bool all_zero = true;
bool all_ones = true;
for (int b = 0; b < 6; b++) {
if (v[b] > 0xff) {
return false;
}
all_zero = all_zero && v[b] == 0;
all_ones = all_ones && v[b] == 0xff;
}
if (all_zero || all_ones) {
return false;
}
for (int b = 0; b < 6; b++) {
mac[b] = (unsigned char)v[b];
}
return true;
}
void rep(unsigned char * in, unsigned char from, unsigned char with, size_t len) {
for (size_t i = 0; i < len; i++)if (in[i] == from) {
in[i] = with;
}
}
size_t split_to(unsigned char delim, unsigned char * src, size_t len, unsigned char ** dest, size_t dest_count) {
size_t prev_idx = 0;
size_t str_count = 0;
len = min(len, strlen(src));
for (size_t i = 0; i <= len && str_count < dest_count; i++) {
if (src[i] == delim || src[i] == '\0' || i == len) {
size_t cur_len = i - prev_idx;
dest[str_count] = src + prev_idx;
for (; cur_len > 0 && isspace(dest[str_count][0]) && dest[str_count] < (src + len) ;) {
dest[str_count]++;
cur_len--;
}
str_count++;
if ( src[i] == '\0' || i == len) {
return str_count;
}
prev_idx = i + 1;
src[i] = 0;
}
}
return str_count;
}