614 lines
25 KiB
C
614 lines
25 KiB
C
//*****************************************************************************
|
|
//
|
|
//! @file am_util_string.c
|
|
//!
|
|
//! @brief A subset of the functions provided in the C standard string library.
|
|
//!
|
|
//! The functions here are reimplementation of some of the standard "string"
|
|
//! functions.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Copyright (c) 2020, Ambiq Micro
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// 1. Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
//
|
|
// 2. Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// 3. Neither the name of the copyright holder nor the names of its
|
|
// contributors may be used to endorse or promote products derived from this
|
|
// software without specific prior written permission.
|
|
//
|
|
// Third party software included in this distribution is subject to the
|
|
// additional license terms as defined in the /docs/licenses directory.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// This is part of revision 2.4.2 of the AmbiqSuite Development Package.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "am_util_string.h"
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Table for quick lookup of character attributes.
|
|
//
|
|
//*****************************************************************************
|
|
#if MINIMIZE_CATTR_TABLE
|
|
#define CATTR_TBL_SIZE 128
|
|
#else
|
|
#define CATTR_TBL_SIZE 256
|
|
#endif
|
|
|
|
const uint8_t am_cattr[CATTR_TBL_SIZE] =
|
|
{
|
|
AM_CATTR_NONE, /* 0x00 */
|
|
AM_CATTR_NONE, /* 0x01 */
|
|
AM_CATTR_NONE, /* 0x02 */
|
|
AM_CATTR_NONE, /* 0x03 */
|
|
AM_CATTR_NONE, /* 0x04 */
|
|
AM_CATTR_NONE, /* 0x05 */
|
|
AM_CATTR_NONE, /* 0x06 */
|
|
AM_CATTR_NONE, /* 0x07 */
|
|
AM_CATTR_NONE, /* 0x08 */
|
|
AM_CATTR_WHSPACE, /* 0x09 */
|
|
AM_CATTR_WHSPACE, /* 0x0A */
|
|
AM_CATTR_WHSPACE, /* 0x0B */
|
|
AM_CATTR_WHSPACE, /* 0x0C */
|
|
AM_CATTR_WHSPACE, /* 0x0D */
|
|
AM_CATTR_NONE, /* 0x0E */
|
|
AM_CATTR_NONE, /* 0x0F */
|
|
AM_CATTR_NONE, /* 0x00 */
|
|
AM_CATTR_NONE, /* 0x11 */
|
|
AM_CATTR_NONE, /* 0x12 */
|
|
AM_CATTR_NONE, /* 0x13 */
|
|
AM_CATTR_NONE, /* 0x14 */
|
|
AM_CATTR_NONE, /* 0x15 */
|
|
AM_CATTR_NONE, /* 0x16 */
|
|
AM_CATTR_NONE, /* 0x17 */
|
|
AM_CATTR_NONE, /* 0x18 */
|
|
AM_CATTR_NONE, /* 0x19 */
|
|
AM_CATTR_NONE, /* 0x1A */
|
|
AM_CATTR_NONE, /* 0x1B */
|
|
AM_CATTR_NONE, /* 0x1C */
|
|
AM_CATTR_NONE, /* 0x1D */
|
|
AM_CATTR_NONE, /* 0x1E */
|
|
AM_CATTR_NONE, /* 0x1F */
|
|
AM_CATTR_WHSPACE, /* 0x20, space */
|
|
AM_CATTR_FILENM83, /* 0x21, ! */
|
|
AM_CATTR_NONE, /* 0x22, " */
|
|
AM_CATTR_FILENM83, /* 0x23, # */
|
|
AM_CATTR_FILENM83, /* 0x24, $ */
|
|
AM_CATTR_FILENM83, /* 0x25, % */
|
|
AM_CATTR_FILENM83, /* 0x26, & */
|
|
AM_CATTR_FILENM83, /* 0x27, ' */
|
|
AM_CATTR_FILENM83, /* 0x28, ( */
|
|
AM_CATTR_FILENM83, /* 0x29, ) */
|
|
AM_CATTR_NONE, /* 0x2A, * */
|
|
AM_CATTR_NONE, /* 0x2B, + */
|
|
AM_CATTR_NONE, /* 0x2C, , */
|
|
AM_CATTR_FILENM83, /* 0x2D, - */
|
|
AM_CATTR_FILENM83, /* 0x2E, . */
|
|
AM_CATTR_NONE, /* 0x2F, / */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x30, 0 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x31, 1 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x32, 2 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x33, 3 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x34, 4 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x35, 5 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x36, 6 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x37, 7 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x38, 8 */
|
|
AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x39, 9 */
|
|
AM_CATTR_NONE, /* 0x3A, : */
|
|
AM_CATTR_NONE, /* 0x3B, ; */
|
|
AM_CATTR_NONE, /* 0x3C, < */
|
|
AM_CATTR_NONE, /* 0x3D, = */
|
|
AM_CATTR_NONE, /* 0x3E, > */
|
|
AM_CATTR_NONE, /* 0x3F, ? */
|
|
AM_CATTR_FILENM83, /* 0x40, @ */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x41, A */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x42, B */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x43, C */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x44, D */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x45, E */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x46, F */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x47, G */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x48, H */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x49, I */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4A, J */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4B, K */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4C, L */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4D, M */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4E, N */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x4F, O */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x50, P */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x51, Q */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x52, R */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x53, S */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x54, T */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x55, U */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x56, V */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x57, W */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x58, X */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x59, Y */
|
|
AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83, /* 0x5A, Z */
|
|
AM_CATTR_NONE, /* 0x5B, [ */
|
|
AM_CATTR_NONE, /* 0x5C, \ */
|
|
AM_CATTR_NONE, /* 0x5D, ] */
|
|
AM_CATTR_FILENM83, /* 0x5E, ^ */
|
|
AM_CATTR_FILENM83, /* 0x5F, _ */
|
|
AM_CATTR_FILENM83, /* 0x60, ` */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x61, a */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x62, b */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x63, c */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x64, d */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x65, e */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83, /* 0x66, f */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x67, g */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x68, h */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x69, i */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6A, j */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6B, k */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6C, l */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6D, m */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6E, n */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x6F, o */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x70, p */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x71, q */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x72, r */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x73, s */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x74, t */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x75, u */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x76, v */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x77, w */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x78, x */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x79, y */
|
|
AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83, /* 0x7A, z */
|
|
AM_CATTR_FILENM83, /* 0x7B, { */
|
|
AM_CATTR_NONE, /* 0x7C, | */
|
|
AM_CATTR_FILENM83, /* 0x7D, } */
|
|
AM_CATTR_FILENM83, /* 0x7E, ~ */
|
|
AM_CATTR_NONE /* 0x7F, delete */
|
|
|
|
//
|
|
// All bit7 chars are AM_CATTR_NONE.
|
|
//
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Character "is" functions
|
|
//!
|
|
//! This family of functions tests a given integer value in order to determine
|
|
//! whether the integer satisfies the test condition.
|
|
//! These functions are generally based on the C99 standard functions.
|
|
//!
|
|
//! By default all of the "is" functions are implemented as macros. To implement
|
|
//! as functions rather than macros, use a global compiler command line (-D)
|
|
//! option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
|
|
//!
|
|
//! Standard functions currently implemented include:
|
|
//! isalnum(), isalpha(), islower(), isupper(), isdigit(), isxdigit(),
|
|
//! isspace().
|
|
//!
|
|
//! Standard functions not currently implemented include:
|
|
//! iscntrl(), isgraph(), isprint(), ispunct(), isblank() (new for C99).
|
|
//!
|
|
//! Non-standard functions currently implemented include:
|
|
//! isfilenm83().
|
|
//!
|
|
//! @return Each function returns a nonzero value if the integer satisfies
|
|
//! the test condition and 0 if it does not.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
#ifdef AM_UTIL_STRING_CTYPE_DISABLE_MACROS
|
|
int
|
|
am_util_string_isalnum(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT)) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT)) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
am_util_string_isalpha(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_ALPHA) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_ALPHA) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
am_util_string_isdigit(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_DIGIT) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_DIGIT) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int am_util_string_islower(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_LOWER) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_LOWER) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
am_util_string_isspace(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_WHSPACE) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_WHSPACE) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
am_util_string_isupper(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_UPPER) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_UPPER) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
am_util_string_isxdigit(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_XDIGIT) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_XDIGIT) ? 1 : 0;
|
|
#endif
|
|
}
|
|
|
|
int am_util_string_tolower(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (am_cattr[c & 0x7f] & AM_CATTR_UPPER) ? c | 0x20 : c;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_UPPER) ? c | 0x20 : c;
|
|
#endif
|
|
}
|
|
|
|
int am_util_string_toupper(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (am_cattr[c & 0x7f] & AM_CATTR_LOWER) ? c & ~0x20 : c;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_LOWER) ? c & ~0x20 : c;
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// Non-standard "is" Functions
|
|
//
|
|
int
|
|
am_util_string_isfilenm83(int c)
|
|
{
|
|
#if MINIMIZE_CATTR_TABLE
|
|
return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_FILENM83) ? 1 : 0;
|
|
#else
|
|
return (am_cattr[c & 0xff] & AM_CATTR_FILENM83) ? 1 : 0;
|
|
#endif
|
|
}
|
|
#endif // AM_UTIL_STRING_CTYPE_DISABLE_MACROS
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Compare two strings.
|
|
//!
|
|
//! @param str1 is the first string to compare.
|
|
//! @param str2 is the second string to compare
|
|
//!
|
|
//! This function steps through a pair of strings, character by character, to
|
|
//! determine if the strings contain the same characters. If the strings match,
|
|
//! this function will return a zero. If str1 is alphabetically earlier than
|
|
//! str2, the return value will be negative. Otherwise, the return value will
|
|
//! be positive.
|
|
//!
|
|
//! @return 0 for a perfect match, negative value if str1<str2, positive value
|
|
//! if str1>str2.
|
|
//
|
|
//*****************************************************************************
|
|
int32_t
|
|
am_util_string_strcmp(const char *str1, const char *str2)
|
|
{
|
|
return am_util_string_strncmp(str1, str2, 0xffffffff);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Compare two strings with a specified count.
|
|
//!
|
|
//! @param str1 is the first string to compare.
|
|
//! @param str2 is the second string to compare
|
|
//! @param num is the maximum number of characters to compare.
|
|
//!
|
|
//! This function steps through a pair of strings, character by character, to
|
|
//! determine if the strings contain the same characters. If the strings match,
|
|
//! this function will return a zero. If str1 is alphabetically earlier than
|
|
//! str2, the return value will be negative. Otherwise, the return value will
|
|
//! be positive.
|
|
//!
|
|
//! @return 0 for a perfect match, negative value if str1<str2, positive value
|
|
//! if str1>str2.
|
|
//
|
|
//*****************************************************************************
|
|
int32_t
|
|
am_util_string_strncmp(const char *str1, const char *str2, uint32_t num)
|
|
{
|
|
while ( num-- )
|
|
{
|
|
// Check for inequality OR end of string
|
|
if ( *str1 != *str2 || *str1 == '\0' )
|
|
{
|
|
return *str1 - *str2;
|
|
}
|
|
|
|
str1++;
|
|
str2++;
|
|
}
|
|
|
|
//
|
|
// Since we made it here, the strings must be equal to n characters.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Compare two strings with a specified count and without regard to
|
|
//! letter case in the strings.
|
|
//!
|
|
//! @param str1 is the first string to compare.
|
|
//! @param str2 is the second string to compare
|
|
//! @param num is the maximum number of characters to compare.
|
|
//!
|
|
//! This function steps through a pair of strings, character by character, to
|
|
//! determine if the strings contain the same characters. If the strings match,
|
|
//! this function will return a zero. If str1 is alphabetically earlier than
|
|
//! str2, the return value will be negative. Otherwise, the return value will
|
|
//! be positive.
|
|
//!
|
|
//! @return 0 for a perfect match, negative value if str1<str2, positive value
|
|
//! if str1>str2.
|
|
//
|
|
//*****************************************************************************
|
|
int32_t
|
|
am_util_string_strnicmp(const char *str1, const char *str2, int num)
|
|
{
|
|
uint8_t cChar1, cChar2;
|
|
|
|
while ( *str1 && *str2 && num )
|
|
{
|
|
cChar1 = *str1;
|
|
cChar2 = *str2;
|
|
|
|
cChar1 |= ( am_cattr[cChar1] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
|
|
cChar2 |= ( am_cattr[cChar2] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
|
|
|
|
if ( cChar1 != cChar2 )
|
|
{
|
|
return cChar1 - cChar2;
|
|
}
|
|
|
|
str1++;
|
|
str2++;
|
|
num--;
|
|
}
|
|
|
|
//
|
|
// Since we made it here, the strings must be equal to n characters.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Compare two strings with case-insensitivity.
|
|
//!
|
|
//! @param str1 is the first string to compare.
|
|
//! @param str2 is the second string to compare
|
|
//!
|
|
//! This function compares each character in the 2 strings, converting all
|
|
//! alpha characters to lower-case to make the comparison.
|
|
//!
|
|
//! To illustrate a possible unexpected outcome due to comparing the strings
|
|
//! as lower case, consider the example strings "AMBIQ_MICRO" and "AMBIQMICRO".
|
|
//! For these strings, stricmp() will return a negative value (indicating the
|
|
//! first as before the second), whereas strcmp() will return a positive value.
|
|
//!
|
|
//! @return 0 for a case-insensitive match, negative value if str1<str2,
|
|
//! positive value if str1>str2.
|
|
//
|
|
//*****************************************************************************
|
|
int32_t
|
|
am_util_string_stricmp(const char *str1, const char *str2)
|
|
{
|
|
uint8_t cChar1, cChar2;
|
|
|
|
while ( *str1 && *str2 )
|
|
{
|
|
cChar1 = *str1++;
|
|
cChar2 = *str2++;
|
|
|
|
cChar1 |= ( am_cattr[cChar1] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
|
|
cChar2 |= ( am_cattr[cChar2] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
|
|
|
|
if ( cChar1 != cChar2 )
|
|
{
|
|
return cChar1 - cChar2;
|
|
}
|
|
}
|
|
|
|
return *str1 - *str2;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Return the length of a string.
|
|
//!
|
|
//! @param pcStr pointer to the string.
|
|
//!
|
|
//! This function returns the length of the string at pcStr.
|
|
//!
|
|
//! @return length of the string pcStr.
|
|
//
|
|
//*****************************************************************************
|
|
uint32_t
|
|
am_util_string_strlen(const char *pcStr)
|
|
{
|
|
const char *pcS;
|
|
|
|
//
|
|
// Loop through the string.
|
|
//
|
|
for (pcS = pcStr; *pcS; ++pcS);
|
|
|
|
//
|
|
// Return the length.
|
|
//
|
|
return(pcS - pcStr);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Copies a string.
|
|
//!
|
|
//! @param pcDst pointer to the destination string.
|
|
//! @param pcSrc pointer to the source string to be copied to pcDst.
|
|
//!
|
|
//! This function copies pcSrc to the location specified by pcDst.
|
|
//!
|
|
//! @return pcDst (the location of the destination string).
|
|
//
|
|
//*****************************************************************************
|
|
char *
|
|
am_util_string_strcpy(char *pcDst, const char *pcSrc)
|
|
{
|
|
char *pcRet = pcDst;
|
|
|
|
//
|
|
// Blindly copy the string until we hit a terminating NULL char.
|
|
//
|
|
do
|
|
{
|
|
*pcDst++ = *pcSrc;
|
|
} while ( *pcSrc++ );
|
|
|
|
return pcRet;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Copies a specified number of characters of a string.
|
|
//!
|
|
//! @param pcDst pointer to the destination string.
|
|
//! @param pcSrc pointer to the source string to be copied to pcDst.
|
|
//!
|
|
//! This function copies uNum characters of pcSrc to the location specified
|
|
//! by pcDst.
|
|
//! If uNum is less than the length of pcSrc, a NULL terminating character
|
|
//! is not appended to the copied string. Thus the resultant string will be
|
|
//! exactly uNum chars in length and not terminated.
|
|
//! If uNum is greater than the length of pcSrc, then pcDst is padded with
|
|
//! NULL characters up to the uNum length.
|
|
//! Behavior is undefined if the addresses ranges overlap.
|
|
//!
|
|
//! @return pcDst (the location of the destination string).
|
|
//
|
|
//*****************************************************************************
|
|
char *
|
|
am_util_string_strncpy(char *pcDst, const char *pcSrc, uint32_t uNum)
|
|
{
|
|
char *pcRet = pcDst;
|
|
|
|
while (uNum > 0)
|
|
{
|
|
if ( *pcSrc )
|
|
{
|
|
*pcDst++ = *pcSrc++;
|
|
}
|
|
else
|
|
{
|
|
*pcDst++ = 0x00;
|
|
}
|
|
uNum--;
|
|
}
|
|
|
|
return pcRet;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//! @brief Concatenate a string.
|
|
//!
|
|
//! @param pcDst pointer to the destination string.
|
|
//! @param pcSrc pointer to the source string to be copied to pcDst.
|
|
//!
|
|
//! This function concatenates the string at pcSrc to the existing string
|
|
//! at pcDst.
|
|
//!
|
|
//! Both strings, pcDst and pcSrc, must be NULL-terminated.
|
|
//! No overflow checking is performed.
|
|
//! pcDst and pcSrc shall not overlap.
|
|
//!
|
|
//! @return pcDst (the location of the destination string).
|
|
//
|
|
//*****************************************************************************
|
|
char *
|
|
am_util_string_strcat(char *pcDst, const char *pcSrc)
|
|
{
|
|
char *pcRet = pcDst;
|
|
|
|
//
|
|
// Find the end of the existing string.
|
|
//
|
|
while ( *pcDst++ );
|
|
pcDst--;
|
|
|
|
//
|
|
// Now, copy the new string.
|
|
//
|
|
am_util_string_strcpy(pcDst, pcSrc);
|
|
|
|
return pcRet;
|
|
}
|