Host library for controlling a WiConnect enabled Wi-Fi module.

Dependents:   wiconnect-ota_example wiconnect-web_setup_example wiconnect-test-console wiconnect-tcp_server_example ... more

StringUtil.h

Committer:
dan_ackme
Date:
2014-08-11
Revision:
1:6ec9998427ad
Parent:
0:ea85c4bb5e1f
Child:
16:7f1d6d359787

File content as of revision 1:6ec9998427ad:

/*
 * Copyright 2014, ACKme Networks
 * All Rights Reserved.
 *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of ACKme Networks;
 * the contents of this file may not be disclosed to third parties, copied
 * or duplicated in any form, in whole or in part, without the prior
 * written permission of ACKme Networks.
 */

#pragma once


#include <string.h>
#include <ctype.h>
#include <stdint.h>
#include <limits.h>


#ifdef WICONNECT_USE_STRTOLL
// Necessary to get strtoll in C99 mode.
// http://sourceware.org/ml/newlib/2012/msg00425.html
extern long long strtoll(const char *__n, char **__end_PTR, int __base);
#endif


class StringUtil
{

public:
    /*************************************************************************************************/
    // Helper to find an occurrence of a delimiter string,
    // insert '\0' in its place and return string after
    // the delimiter e.g.
    //     if char s[] = "foo://bar";
    //     - strchop(s, "://") returns "bar"
    //     - s becomes "foo"
    static char *chop(char *haystack, const char *needle)
    {
        if (!haystack)
        {
            return NULL;
        }
        char *end = strstr(haystack, needle);
        if (end)
        {
            *end = '\0';
            return end + strlen(needle);
        }
        return NULL;
    }

    /*************************************************************************************************/
    // Check if string is non-null and non-empty.
    static bool empty(const char *s)
    {
        return !(s && *s);
    }

    /*************************************************************************************************/
    static bool isSpace(const char *s)
    {
        while(*s != 0)
        {
            if(!isspace((uint8_t)*s++))
                return false;
        }
        return true;
    }

    /*************************************************************************************************/
    // Convert null-terminated string to lower case.
    // ASCII charset only.
    static void toLower(char *s)
    {
        for (; *s; ++s)
        {
            *s = tolower((int) * s);
        }
    }

    /*************************************************************************************************/
    // Combination of strip left + right.
    static char *strip(char *s, const char *chars)
    {
        return rightStrip(leftStrip(s, chars), chars);
    }

    /*************************************************************************************************/
    // Strip string from the left.
    // Returns pointer into the input string.
    static char *leftStrip(char *s, const char *chars)
    {
        return s + strspn(s, chars);
    }

    /*************************************************************************************************/
    // Strip string from the right.
    // Modified in place.
    static char *rightStrip(char *s, const char *chars)
    {
        char *end = s + strlen(s) - 1;
        while (end > s && strstr(chars, end))
        {
            *end-- = '\0';
        }
        return s;
    }

    /*************************************************************************************************/
    // Parse decimal integer and check if it's in bounds [min, max].
    static bool parseInt(const char *s, intmax_t *result, intmax_t min, intmax_t max)
    {
        return parseBase(s, result, min, max, 10);
    }

    // Parse hexadecimal integer and check if it's in bounds [min, max].
    static bool parseHex(const char *s, intmax_t *result, intmax_t min, intmax_t max)
    {
        return parseBase(s, result, min, max, 16);
    }

    /*************************************************************************************************/
    static bool parseBase(const char *s, intmax_t *result, intmax_t min, intmax_t max, int base)
    {
        if (!s)
        {
            return false;
        }
        char *end;
#ifdef WICONNECT_USE_STRTOLL
        intmax_t value = strtoll(s, &end, base);
#else
        intmax_t value = strtol(s, &end, base);
#endif
        if (*end || value < min || value > max)
        {
            return false;
        }
        *result = value;
        return true;
    }

    /*************************************************************************************************/
    // Parse an long long integer.
    static bool parseBool(const char *onoff, bool *var)
    {
        const char* const on_vals[] =
        {
                "1",
                "on",
                "true",
                "yes",
        };

        for(uint8_t i = 0; i < ARRAY_COUNT(on_vals); ++i)
        {
            if(strcasecmp(on_vals[i], onoff) == 0)
            {
                *var = true;
                return true;
            }
        }

        const char* const off_vals[] =
        {
                "0",
                "false",
                "no",
                "off",
                NULL
        };
        for(uint8_t i = 0; i < ARRAY_COUNT(off_vals); ++i)
        {
            if(strcasecmp(off_vals[i], onoff) == 0)
            {
                *var = false;
                return true;
            }
        }

        return false;
    }

    /*************************************************************************************************/
    // convert binary data to hex string
    static void binToHex(char *dst, int max_dst, const void *data, int data_len)
    {
        char *end = dst + max_dst - 1;
        for (int i = 0; i < data_len; ++i)
        {
            if (dst < end)
            {
                dst += sprintf(dst, "%2.2x", ((uint8_t *)data)[i]);
            }
        }
    }


    /*************************************************************************************************/
    // Parse binary data into hex string
    // the input buffer MUST be len*2  long
    // as the parsing is destructive and done in-place
    static void binToHex(void *h, int len)
    {
        char *dst = (char*)h;
        char *src= (char*)h+len;

        memmove(src, dst, len);

        while(len--)
        {
            sprintf(dst, "%2.2X", (unsigned int)(*src & 0xff));
            dst += 2;
            ++src;
        }
    }


    /*************************************************************************************************/
    // Parses hex representation of binary data destructively.
    // Returns number of bytes parsed or -1 on error.
    static int hexToBin(char *s)
    {
        int len, i, j;
        len = strlen(s);
        if (len % 2)
        {
            return -1;
        }
        for (i = j = 0; i < len; i += 2, j++)
        {
            const int num = hexToInt(&s[i]);
            if(num == -1)
                return -1;
            s[j] = (char)num;
        }
        return j;
    }

    /*************************************************************************************************/
    // hex string to integer, returns -1 on error
    static int hexToInt(const char *hex_str)
    {
        int hi = hexToNibble(*hex_str);
        int lo = hexToNibble(*(hex_str+1));
        if (hi == -1 || lo == -1)
        {
            return -1;
        }
        return (hi << 4) | lo;
    }

    /*************************************************************************************************/
    static int hexToNibble(char c)
    {
        if (c >= '0' && c <= '9')
        {
            return c - '0';
        }
        if (c >= 'a' && c <= 'f')
        {
            return 10 + (c - 'a');
        }
        if (c >= 'A' && c <= 'F')
        {
            return 10 + (c - 'A');
        }
        return -1;
    }

    /*************************************************************************************************/
    static const char* uint32ToStr(char* intStrBuffer, int integer)
    {
        sprintf(intStrBuffer, "%u", integer);
        return intStrBuffer;
    }

    /*************************************************************************************************/
    static bool strToUint32(const char *str, uint32_t *uint32Ptr)
    {
        intmax_t r;
        bool result = StringUtil::parseInt(str, &r, 0, UINT_MAX);
        *uint32Ptr = (uint32_t)r;
        return result;
    }

    /*************************************************************************************************/
    static bool strToInt32(const char *str, int32_t *int32Ptr)
    {
        intmax_t r;
        bool result = StringUtil::parseInt(str, &r, INT_MIN, INT_MAX);
        *int32Ptr = (int32_t)r;
        return result;
    }

    /*************************************************************************************************/
    // uint32 hex string to uint32
    static bool strHexToUint32(const char *strHex, uint32_t *uint32Ptr)
    {
        intmax_t r;
        bool result = StringUtil::parseHex(strHex, &r, 0, UINT_MAX);
        *uint32Ptr = (uint32_t)r;
        return result;
    }

    /*************************************************************************************************/
    static char *strtok_r(char *str, const char *delim, char **nextp)
    {
        char *ret;

        if (str == NULL)
        {
            str = *nextp;
        }

        str += strspn(str, delim);

        if (*str == '\0')
        {
            return NULL;
        }

        ret = str;

        str += strcspn(str, delim);

        if (*str)
        {
            *str++ = '\0';
        }

        *nextp = str;

        return ret;
    }

    /*************************************************************************************************/
    static int strncasecmp(const char *s1, const char *s2, int n)
    {
        if (n == 0)
            return 0;

        while (n-- != 0 && tolower(*s1) == tolower(*s2))
        {
            if (n == 0 || *s1 == '\0' || *s2 == '\0')
                break;
            s1++;
            s2++;
        }

        return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
    }

    /*************************************************************************************************/
    static int strcasecmp(const char *s1, const char *s2)
    {
        register const unsigned char *p1 = (const unsigned char *) s1;
        register const unsigned char *p2 = (const unsigned char *) s2;
        unsigned char c1, c2;

        if (p1 == p2)
            return 0;

        do
        {
            c1 = tolower (*p1);
            c2 = tolower (*p2);

            if (c1 == '\0')
                break;

            ++p1;
            ++p2;
        }
        while (c1 == c2);

        if (UCHAR_MAX <= INT_MAX)
            return c1 - c2;
        else
            /* On machines where 'char' and 'int' are types of the same size, the
               difference of two 'unsigned char' values - including the sign bit -
               doesn't fit in an 'int'.  */
            return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
    }
};