blob: 122276d4b339d29bb68d13da0f7a6ba04bc0566e [file] [log] [blame]
//*****************************************************************************
//
//! @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) 2017, 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.
//
// 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 v1.2.10-2-gea660ad-hotfix2 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;
}