blob: 924f7553d8edeb6cd72b44d7f274a89501766acc [file] [edit]
/*
*
* Copyright (c) 2016 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Description:
* This file defines utility functions for manipulating and comparing
* C-strings or other buffers.
*
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include "string-utils.h"
#include <ctype.h>
#include <inttypes.h>
#include <stdlib.h>
#ifndef __USE_GNU
#define __USE_GNU // Needed for `strcasestr`
#endif
#include <string.h>
// Declare function to avoid compile warning: comparison between pointer and integer.
extern char *strcasestr(const char *, const char *);
void
memcpyrev(void *dest_, const void *src_, size_t len)
{
uint8_t* const dest = dest_;
const uint8_t* const src = src_;
size_t i;
for (i = 0; i < len; i++) {
dest[i] = src[len - 1 - i];
}
}
int
memcmprev(const void *dest_, const void *src_, size_t len)
{
const uint8_t* const dest = dest_;
const uint8_t* const src = src_;
int ret = 0;
size_t i;
for (i = 0; i < len && !ret; i++) {
ret = dest[i] - src[len - 1 - i];
}
return ret;
}
void
reverse_bytes(uint8_t *bytes, size_t count)
{
size_t i;
for (i = 0; i < count / 2; i++) {
uint8_t x = bytes[i];
bytes[i] = bytes[count - i - 1];
bytes[count - i - 1] = x;
}
}
int
parse_string_into_data(uint8_t* buffer, size_t len, const char* c_str)
{
int ret = 0;
if (NULL == buffer) {
len = 0;
}
while ((*c_str != 0) && (len > 0)) {
int c = tolower(*c_str++);
if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) {
continue;
}
c = isdigit(c) ? (c - '0') : (c - 'a' + 10);
if (len > 0) {
*buffer = (c << 4);
len--;
}
ret++;
if (!*c_str) {
break;
}
c = tolower(*c_str++);
if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) {
continue;
}
c = isdigit(c) ? (c - '0') : (c - 'a' + 10);
*buffer++ |= c;
}
return ret;
}
int
encode_data_into_string(const uint8_t *buffer, size_t len, char *c_str, size_t c_str_max_len, int pad_to)
{
int ret = 0;
while (len && (c_str_max_len > 2)) {
uint8_t byte = *buffer++;
len--;
pad_to--;
*c_str++ = int_to_hex_digit(byte >> 4);
*c_str++ = int_to_hex_digit(byte & 0xF);
c_str_max_len -= 2;
ret += 2;
}
while (pad_to > 0 && (c_str_max_len > 2)) {
pad_to--;
*c_str++ = '0';
*c_str++ = '0';
c_str_max_len -= 2;
ret += 2;
}
c_str_max_len--;
*c_str++ = 0;
return ret;
}
bool
strtobool(const char* string)
{
bool ret = false;
switch(string[0]) {
case 'y':
case 'Y':
case 't':
case 'T':
ret = true;
break;
case 'n':
case 'N':
case 'f':
case 'F':
ret = false;
break;
default:
ret = (strtol(string, NULL, 0) != 0);
break;
}
return ret;
}
uint32_t
strtomask_uint32(const char* in_string)
{
char *tmp_string = strdup(in_string);
char *chan_ranges; // points to a channel num or a range of channels
char *dash_location; // points to location of the dash in a range of channels
int channel_start = 0;
int channel_stop = 0;
uint32_t mask = 0;
chan_ranges = strtok(tmp_string, ",");
while(chan_ranges != NULL) {
// loop to parse channels by comma (,)
// each fragment may include a range (-) of channels
dash_location = strchr(chan_ranges, '-');
if (dash_location != NULL) {
// process a range of channels
*dash_location = '\0';
dash_location++;
if (atoi(chan_ranges) < atoi(dash_location)) {
channel_start = atoi(chan_ranges);
channel_stop = atoi(dash_location);
} else {
channel_stop = atoi(chan_ranges);
channel_start = atoi(dash_location);
}
while (channel_start <= channel_stop) {
mask |= (1 << channel_start);
channel_start++;
}
} else {
// no range, just add channel to the scan mask
mask |= (1 << strtol(chan_ranges, NULL, 0));
}
chan_ranges = strtok(NULL, ",");
}
free(tmp_string);
return mask;
}
#include <syslog.h>
int
strtologmask(const char* value, int prev_mask)
{
int mask = (int)strtol(value, NULL, 0);
if (mask == 0) {
mask = prev_mask;
if(strcasestr(value, "all") != NULL) {
if (strcasestr(value, "-all") != NULL) {
mask &= 0;
} else {
mask |= ~0;
}
}
if (strcasestr(value, "emerg") != NULL) {
if (strcasestr(value, "-emerg") != NULL) {
mask &= ~LOG_MASK(LOG_EMERG);
} else {
mask |= LOG_MASK(LOG_EMERG);
}
}
if (strcasestr(value, "alert") != NULL) {
if (strcasestr(value, "-alert") != NULL) {
mask &= ~LOG_MASK(LOG_ALERT);
} else {
mask |= LOG_MASK(LOG_ALERT);
}
}
if (strcasestr(value, "crit") != NULL) {
if (strcasestr(value, "-crit") != NULL) {
mask &= ~LOG_MASK(LOG_CRIT);
} else {
mask |= LOG_MASK(LOG_CRIT);
}
}
if (strcasestr(value, "err") != NULL) {
if (strcasestr(value, "-err") != NULL) {
mask &= ~LOG_MASK(LOG_ERR);
} else {
mask |= LOG_MASK(LOG_ERR);
}
}
if (strcasestr(value, "warn") != NULL) {
if (strcasestr(value, "-warn") != NULL) {
mask &= ~LOG_MASK(LOG_WARNING);
} else {
mask |= LOG_MASK(LOG_WARNING);
}
}
if (strcasestr(value, "notice") != NULL) {
if (strcasestr(value, "-notice") != NULL) {
mask &= ~LOG_MASK(LOG_NOTICE);
} else {
mask |= LOG_MASK(LOG_NOTICE);
}
}
if (strcasestr(value, "info") != NULL) {
if (strcasestr(value, "-info") != NULL) {
mask &= ~LOG_MASK(LOG_INFO);
} else {
mask |= LOG_MASK(LOG_INFO);
}
}
if (strcasestr(value, "debug") != NULL) {
if (strcasestr(value, "-debug") != NULL) {
mask &= ~LOG_MASK(LOG_DEBUG);
} else {
mask |= LOG_MASK(LOG_DEBUG);
}
}
}
return mask;
}
bool
buffer_is_nonzero(const uint8_t* buffer, size_t len)
{
while (len--) {
if (*buffer++ != 0) {
return true;
}
}
return false;
}
bool
is_hex(const uint8_t* buff, size_t len)
{
while (len--) {
if (!isxdigit(*buff++)) {
return false;
}
}
return true;
}
bool
is_uppercase_or_digit(const uint8_t* buff, size_t len)
{
while (len--) {
if (!(isupper(*buff) || isdigit(*buff))) {
return false;
}
buff++;
}
return true;
}