/* ********************************************************************************************************* * uC/LIB * CUSTOM LIBRARY MODULES * * (c) Copyright 2004-2007; Micrium, Inc.; Weston, FL * * All rights reserved. Protected by international copyright laws. * * uC/LIB is provided in source form for FREE evaluation, for educational * use or peaceful research. If you plan on using uC/LIB in a commercial * product you need to contact Micrium to properly license its use in your * product. We provide ALL the source code for your convenience and to * help you experience uC/LIB. The fact that the source code is provided * does NOT mean that you can use it without paying a licensing fee. * * Knowledge of the source code may NOT be used to develop a similar product. * * Please help us continue to provide the Embedded community with the finest * software available. Your honesty is greatly appreciated. ********************************************************************************************************* */ /* ********************************************************************************************************* * * ASCII STRING MANAGEMENT * * Filename : lib_str.c * Version : V1.24 * Programmer(s) : ITJ * JDH ********************************************************************************************************* * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software. * * (a) ALL standard library functions are implemented in the custom library modules : * * (1) \\lib*.* * * (2) \\Ports\\\lib*_a.* * * where * directory path for custom library software * directory name for specific processor (CPU) * directory name for specific compiler * * (b) Product-specific library functions are implemented in individual products. ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define LIB_STR_MODULE #include /*$PAGE*/ /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * Str_Len() * * Description : Calculate length of a string. * * Argument(s) : pstr Pointer to string (see Note #1). * * Return(s) : Length of string; number of characters in string before terminating NULL character. * * Caller(s) : various. * * Note(s) : (1) String buffer NOT modified. * * (2) String length calculation terminates when : * * (a) String pointer points to NULL. * (1) String buffer overlaps with NULL address. * (2) String length calculated for string up to but NOT beyond or including * the NULL address. * * (b) Terminating NULL character found. * (1) String length calculated for string up to but NOT including * the NULL character. ********************************************************************************************************* */ CPU_SIZE_T Str_Len (CPU_CHAR *pstr) { CPU_SIZE_T len; len = 0; while (( pstr != (CPU_CHAR *)0) && /* Calc str len until NULL ptr (see Note #2a) ... */ (*pstr != (CPU_CHAR )0)) { /* ... or NULL char found (see Note #2b). */ len++; pstr++; } return (len); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Copy() * * Description : Copy source string to destination string buffer. * * Argument(s) : pdest Pointer to destination string buffer to receive source string copy (see Note #1). * * psrc Pointer to source string to copy into destination string buffer. * * Return(s) : Pointer to destination string, if NO errors (see Note #2). * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (a) Destination buffer size MUST be large enough to accommodate the entire source * string size including the terminating NULL character. * * (2) String copy terminates when : * * (a) Destination/Source string pointer(s) are passed NULL pointers. * (1) No string copy performed; NULL pointer returned. * * (b) Destination/Source string pointer(s) points to NULL. * (1) String buffer(s) overlap with NULL address. * (2) Source string copied into destination string buffer up to but NOT beyond or * including the NULL address; destination string buffer properly terminated * with NULL character. * * (c) Source string's terminating NULL character found. * (1) Entire source string copied into destination string buffer. ********************************************************************************************************* */ CPU_CHAR *Str_Copy (CPU_CHAR *pdest, CPU_CHAR *psrc) { CPU_CHAR *pstr; CPU_CHAR *pstr_next; /* Rtn NULL if str ptr(s) NULL (see Note #2a). */ if (pdest == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (psrc == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } pstr = pdest; pstr_next = pstr; pstr_next++; while (( pstr_next != (CPU_CHAR *)0) && /* Copy str until NULL ptr(s) (see Note #2b) ... */ ( psrc != (CPU_CHAR *)0) && (*psrc != (CPU_CHAR )0)) { /* ... or NULL char found (see Note #2c). */ *pstr = *psrc; pstr++; pstr_next++; psrc++; } *pstr = (CPU_CHAR)0; /* Append NULL char (see Note #2b2). */ return (pdest); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Copy_N() * * Description : Copy source string to destination string buffer, up to a maximum number of characters. * * Argument(s) : pdest Pointer to destination string buffer to receive source string copy (see Note #1). * * psrc Pointer to source string to copy into destination string buffer. * * len_max Maximum number of characters to copy (see Note #2d). * * Return(s) : Pointer to destination string, if NO errors (see Note #2). * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (a) Destination buffer size MUST be large enough to accommodate the entire source * string size including the terminating NULL character. * * (2) String copy terminates when : * * (a) Destination/Source string pointer(s) are passed NULL pointers. * (1) No string copy performed; NULL pointer returned. * * (b) Destination/Source string pointer(s) points to NULL. * (1) String buffer(s) overlap with NULL address. * (2) Source string copied into destination string buffer up to but NOT beyond or * including the NULL address; destination string buffer properly terminated * with NULL character. * * (c) Source string's terminating NULL character found. * (1) Entire source string copied into destination string buffer. * * (d) 'len_max' number of characters copied. * (1) 'len_max' number of characters does NOT include the terminating NULL character. * * See also Note #1a. ********************************************************************************************************* */ CPU_CHAR *Str_Copy_N (CPU_CHAR *pdest, CPU_CHAR *psrc, CPU_SIZE_T len_max) { CPU_CHAR *pstr; CPU_CHAR *pstr_next; CPU_SIZE_T len_copy; /* Rtn NULL if str ptr(s) NULL (see Note #2a). */ if (pdest == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (psrc == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if copy len equals zero (see Note #2d). */ return ((CPU_CHAR *)0); } pstr = pdest; pstr_next = pstr; pstr_next++; len_copy = 0; while (( pstr_next != (CPU_CHAR *)0) && /* Copy str until NULL ptr(s) (see Note #2b) ... */ ( psrc != (CPU_CHAR *)0) && (*psrc != (CPU_CHAR )0) && /* ... or NULL char found (see Note #2c); ... */ ( len_copy < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars copied (see Note #2d). */ *pstr = *psrc; pstr++; pstr_next++; psrc++; len_copy++; } *pstr = (CPU_CHAR)0; /* Append NULL char (see Note #2b2). */ return (pdest); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Cat() * * Description : Append concatenation string to destination string. * * Argument(s) : pdest Pointer to destination string to append concatenation string (see Note #1). * * pstr_cat Pointer to concatenation string to append to destination string. * * Return(s) : Pointer to destination string, if NO errors (see Note #2). * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) Destination string buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (a) Destination buffer size MUST be large enough to accommodate the entire concatenated * string size including the terminating NULL character. * * (2) String concatenation terminates when : * * (a) Destination/Concatenation string pointer(s) are passed NULL pointers. * (1) No string concatenation performed; NULL pointer returned. * * (b) Destination string overlaps with NULL address. * (1) No string concatenation performed; NULL pointer returned. * * (c) Destination/Concatenation string pointer(s) points to NULL. * (1) String buffer(s) overlap with NULL address. * (2) Concatenation string appended into destination string buffer up to but NOT * beyond or including the NULL address; destination string buffer properly * terminated with NULL character. * * (d) Concatenation string's terminating NULL character found. * (1) Entire concatenation string appended to destination string. ********************************************************************************************************* */ CPU_CHAR *Str_Cat (CPU_CHAR *pdest, CPU_CHAR *pstr_cat) { CPU_CHAR *pstr; CPU_CHAR *pstr_next; /* Rtn NULL if str ptr(s) NULL (see Note #2a). */ if (pdest == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (pstr_cat == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } pstr = pdest; while (( pstr != (CPU_CHAR *)0) && /* Adv to end of cur dest str until NULL ptr ... */ (*pstr != (CPU_CHAR )0)) { /* ... or NULL char found.. */ pstr++; } if (pstr == (CPU_CHAR *)0) { /* If NULL str overrun, rtn NULL (see Note #2b). */ return ((CPU_CHAR *)0); } pstr_next = pstr; pstr_next++; while (( pstr_next != (CPU_CHAR *)0) && /* Cat str until NULL ptr(s) (see Note #2c) ... */ ( pstr_cat != (CPU_CHAR *)0) && (*pstr_cat != (CPU_CHAR )0)) { /* ... or NULL char found (see Note #2d). */ *pstr = *pstr_cat; pstr++; pstr_next++; pstr_cat++; } *pstr = (CPU_CHAR)0; /* Append NULL char (see Note #2c2). */ return (pdest); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Cat_N() * * Description : Append concatenation string to destination string, up to a maximum number of characters. * * Argument(s) : pdest Pointer to destination string to append concatenation string (see Note #1). * * pstr_cat Pointer to concatenation string to append to destination string. * * len_max Maximum number of characters to concatenate (see Note #2e). * * Return(s) : Pointer to destination string, if NO errors (see Note #2). * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) Destination string buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (a) Destination buffer size MUST be large enough to accommodate the entire concatenated * string size including the terminating NULL character. * * (2) String concatenation terminates when : * * (a) Destination/Concatenation string pointer(s) are passed NULL pointers. * (1) No string concatenation performed; NULL pointer returned. * * (b) Destination string overlaps with NULL address. * (1) No string concatenation performed; NULL pointer returned. * * (c) Destination/Concatenation string pointer(s) points to NULL. * (1) String buffer(s) overlap with NULL address. * (2) Concatenation string appended into destination string buffer up to but NOT * beyond or including the NULL address; destination string buffer properly * terminated with NULL character. * * (d) Concatenation string's terminating NULL character found. * (1) Entire concatenation string appended to destination string. * * (e) 'len_max' number of characters concatenated. * (1) 'len_max' number of characters does NOT include the terminating NULL character. * * See also Note #1a. ********************************************************************************************************* */ /*$PAGE*/ CPU_CHAR *Str_Cat_N (CPU_CHAR *pdest, CPU_CHAR *pstr_cat, CPU_SIZE_T len_max) { CPU_CHAR *pstr; CPU_CHAR *pstr_next; CPU_SIZE_T len_cat; /* Rtn NULL if str ptr(s) NULL (see Note #2a). */ if (pdest == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (pstr_cat == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if cat len equals zero (see Note #2e). */ return ((CPU_CHAR *)0); } pstr = pdest; while (( pstr != (CPU_CHAR *)0) && /* Adv to end of cur dest str until NULL ptr ... */ (*pstr != (CPU_CHAR )0)) { /* ... or NULL char found.. */ pstr++; } if (pstr == (CPU_CHAR *)0) { /* If NULL str overrun, rtn NULL (see Note #2b). */ return ((CPU_CHAR *)0); } pstr_next = pstr; pstr_next++; len_cat = 0; while (( pstr_next != (CPU_CHAR *)0) && /* Cat str until NULL ptr(s) (see Note #2c) ... */ ( pstr_cat != (CPU_CHAR *)0) && (*pstr_cat != (CPU_CHAR )0) && /* ... or NULL char found (see Note #2d); ... */ ( len_cat < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars cat'd (see Note #2d). */ *pstr = *pstr_cat; pstr++; pstr_next++; pstr_cat++; len_cat++; } *pstr = (CPU_CHAR)0; /* Append NULL char (see Note #2c2). */ return (pdest); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Cmp() * * Description : Determine if two strings are identical. * * Argument(s) : p1_str Pointer to first string (see Note #1). * * p2_str Pointer to second string (see Note #1). * * Return(s) : 0, if strings are identical (see Notes #2a, #2e, & #2f). * * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #2b, #2g, & #2d). * * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #2c, #2h, & #2d). * * Caller(s) : various. * * Note(s) : (1) String buffers NOT modified. * * (2) String comparison terminates when : * * (a) BOTH string pointer(s) are passed NULL pointers. * (1) NULL strings identical; return 0. * * (b) 'p1_str' passed a NULL pointer. * (1) Return negative value of character pointed to by 'p2_str'. * * (c) 'p2_str' passed a NULL pointer. * (1) Return positive value of character pointed to by 'p1_str'. * * (d) Non-matching characters found. * (1) Return signed-integer difference of the character pointed to by 'p2_str' * from the character pointed to by 'p1_str'. * * (e) Terminating NULL character found in both strings. * (1) Strings identical; return 0. * (2) Only one NULL character test required in conditional since previous condition * tested character equality. * * (f) BOTH strings point to NULL. * (1) Strings overlap with NULL address. * (2) Strings identical up to but NOT beyond or including the NULL address; return 0. * * (g) 'p1_str_next' points to NULL. * (1) 'p1_str' overlaps with NULL address. * (2) Strings compared up to but NOT beyond or including the NULL address. * (3) Return negative value of character pointed to by 'p2_str_next'. * * (h) 'p2_str_next' points to NULL. * (1) 'p2_str' overlaps with NULL address. * (2) Strings compared up to but NOT beyond or including the NULL address. * (3) Return positive value of character pointed to by 'p1_str_next'. * * (3) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison * return value, 'CPU_CHAR' native data type size MUST be 8-bit. ********************************************************************************************************* */ /*$PAGE*/ CPU_INT16S Str_Cmp (CPU_CHAR *p1_str, CPU_CHAR *p2_str) { CPU_CHAR *p1_str_next; CPU_CHAR *p2_str_next; CPU_INT16S cmp_val; if (p1_str == (CPU_CHAR *)0) { if (p2_str == (CPU_CHAR *)0) { return ((CPU_INT16S)0); /* If BOTH str ptrs NULL, rtn 0 (see Note #2a). */ } cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str); return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #2b). */ } if (p2_str == (CPU_CHAR *)0) { cmp_val = (CPU_INT16S)(*p1_str); return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #2c). */ } p1_str_next = p1_str; p2_str_next = p2_str; p1_str_next++; p2_str_next++; while ((*p1_str == *p2_str) && /* Cmp strs until non-matching char (see Note #2d) .. */ (*p1_str != (CPU_CHAR )0) && /* .. or NULL char(s) (see Note #2e) .. */ ( p1_str_next != (CPU_CHAR *)0) && /* .. or NULL ptr(s) found (see Notes #2f, #2g, & #2h). */ ( p2_str_next != (CPU_CHAR *)0)) { p1_str_next++; p2_str_next++; p1_str++; p2_str++; } if (*p1_str != *p2_str) { /* If strs NOT identical, ... */ cmp_val = (CPU_INT16S)(*p1_str) - (CPU_INT16S)(*p2_str); /* ... calc & rtn char diff (see Note #2d1). */ } else if (*p1_str == (CPU_CHAR)0) { /* If NULL char(s) found, ... */ cmp_val = 0; /* ... strs identical; rtn 0 (see Note #2e). */ } else { if (p1_str_next == (CPU_CHAR *)0) { if (p2_str_next == (CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */ cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #2f). */ } else { /* If p1_str_next NULL, ... */ cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str_next); /* ... rtn neg p2_str_next val (see Note #2g). */ } } else { /* If p2_str_next NULL, ... */ cmp_val = (CPU_INT16S)(*p1_str_next); /* ... rtn pos p1_str_next val (see Note #2h). */ } } return (cmp_val); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Cmp_N() * * Description : Determine if two strings are identical for up to a maximum number of characters. * * Argument(s) : p1_str Pointer to first string (see Note #1). * * p2_str Pointer to second string (see Note #1). * * len_max Maximum number of characters to compare (see Notes #2i & #2j). * * Return(s) : 0, if strings are identical (see Notes #2a, #2e, #2f, #2i, & #2j). * * Negative value, if 'p1_str' is less than 'p2_str' (see Notes #2b, #2g, & #2d). * * Positive value, if 'p1_str' is greater than 'p2_str' (see Notes #2c, #2h, & #2d). * * Caller(s) : various. * * Note(s) : (1) String buffers NOT modified. * * (2) String comparison terminates when : * * (a) BOTH string pointer(s) are passed NULL pointers. * (1) NULL strings identical; return 0. * * (b) 'p1_str' passed a NULL pointer. * (1) Return negative value of character pointed to by 'p2_str'. * * (c) 'p2_str' passed a NULL pointer. * (1) Return positive value of character pointed to by 'p1_str'. * * (d) Non-matching characters found. * (1) Return signed-integer difference of the character pointed to by 'p2_str' * from the character pointed to by 'p1_str'. * * (e) Terminating NULL character found in both strings. * (1) Strings identical; return 0. * (2) Only one NULL character test required in conditional since previous condition * tested character equality. * * (f) BOTH strings point to NULL. * (1) Strings overlap with NULL address. * (2) Strings identical up to but NOT beyond or including the NULL address; return 0. * * (g) 'p1_str_next' points to NULL. * (1) 'p1_str' overlaps with NULL address. * (2) Strings compared up to but NOT beyond or including the NULL address. * (3) Return negative value of character pointed to by 'p2_str_next'. * * (h) 'p2_str_next' points to NULL. * (1) 'p2_str' overlaps with NULL address. * (2) Strings compared up to but NOT beyond or including the NULL address. * (3) Return positive value of character pointed to by 'p1_str_next'. * * (i) 'len_max' passed a zero length. * (1) Zero-length strings identical; return 0. * * (j) First 'len_max' number of characters identical. * (1) Strings identical; return 0. * * (3) Since 16-bit signed arithmetic is performed to calculate a non-identical comparison * return value, 'CPU_CHAR' native data type size MUST be 8-bit. ********************************************************************************************************* */ /*$PAGE*/ CPU_INT16S Str_Cmp_N (CPU_CHAR *p1_str, CPU_CHAR *p2_str, CPU_SIZE_T len_max) { CPU_CHAR *p1_str_next; CPU_CHAR *p2_str_next; CPU_INT16S cmp_val; CPU_SIZE_T cmp_len; if (len_max == 0) { /* If cmp len equals zero, rtn 0 (see Note #2i). */ return ((CPU_INT16S)0); } if (p1_str == (CPU_CHAR *)0) { if (p2_str == (CPU_CHAR *)0) { return ((CPU_INT16S)0); /* If BOTH str ptrs NULL, rtn 0 (see Note #2a). */ } cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str); return (cmp_val); /* If p1_str NULL, rtn neg p2_str val (see Note #2b). */ } if (p2_str == (CPU_CHAR *)0) { cmp_val = (CPU_INT16S)(*p1_str); return (cmp_val); /* If p2_str NULL, rtn pos p1_str val (see Note #2c). */ } p1_str_next = p1_str; p2_str_next = p2_str; p1_str_next++; p2_str_next++; cmp_len = 0; while ((*p1_str == *p2_str) && /* Cmp strs until non-matching char (see Note #2d) .. */ (*p1_str != (CPU_CHAR )0) && /* .. or NULL char(s) (see Note #2e) .. */ ( p1_str_next != (CPU_CHAR *)0) && /* .. or NULL ptr(s) found (see Notes #2f, #2g, & #2h); */ ( p2_str_next != (CPU_CHAR *)0) && ( cmp_len < (CPU_SIZE_T)len_max)) { /* .. or len nbr chars cmp'd (see Note #2j). */ p1_str_next++; p2_str_next++; p1_str++; p2_str++; cmp_len++; } if (cmp_len == len_max) { /* If strs identical for len nbr of chars, */ return ((CPU_INT16S)0); /* ... rtn 0 (see Note #2j). */ } if (*p1_str != *p2_str) { /* If strs NOT identical, ... */ cmp_val = (CPU_INT16S)(*p1_str) - (CPU_INT16S)(*p2_str); /* ... calc & rtn char diff (see Note #2d1). */ } else if (*p1_str == (CPU_CHAR)0) { /* If NULL char(s) found, ... */ cmp_val = 0; /* ... strs identical; rtn 0 (see Note #2e). */ } else { if (p1_str_next == (CPU_CHAR *)0) { if (p2_str_next == (CPU_CHAR *)0) { /* If BOTH next str ptrs NULL, ... */ cmp_val = (CPU_INT16S)0; /* ... rtn 0 (see Note #2f). */ } else { /* If p1_str_next NULL, ... */ cmp_val = (CPU_INT16S)0 - (CPU_INT16S)(*p2_str_next); /* ... rtn neg p2_str_next val (see Note #2g). */ } } else { /* If p2_str_next NULL, ... */ cmp_val = (CPU_INT16S)(*p1_str_next); /* ... rtn pos p1_str_next val (see Note #2h). */ } } return (cmp_val); } /*$PAGE*/ /* ********************************************************************************************************* * Str_Char() * * Description : Search string for first occurrence of specific character. * * Argument(s) : pstr Pointer to string (see Note #1). * * srch_char Search character. * * Return(s) : Pointer to first occurrence of search character in string, if any. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) String buffer NOT modified. * * (2) String search terminates when : * * (a) String pointer passed a NULL pointer. * (1) No string search performed; NULL pointer returned. * * (b) String pointer points to NULL. * (1) String overlaps with NULL address. * (2) String searched up to but NOT beyond or including the NULL address. * * (c) String's terminating NULL character found. * (1) Search character NOT found in search string; NULL pointer returned. * (2) Applicable ONLY IF search character is NOT the terminating NULL character. * * (d) Search character found. * (1) Return pointer to first occurrence of search character in search string. ********************************************************************************************************* */ CPU_CHAR *Str_Char (CPU_CHAR *pstr, CPU_CHAR srch_char) { CPU_CHAR *pstr_next; if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a). */ return ((CPU_CHAR *)0); } pstr_next = pstr; pstr_next++; while (( pstr_next != (CPU_CHAR *)0) && /* Srch str until NULL ptr(s) (see Note #2b) ... */ (*pstr != (CPU_CHAR )0) && /* ... or NULL char (see Note #2c) ... */ (*pstr != (CPU_CHAR )srch_char)) { /* ... or srch char found (see Note #2d). */ pstr++; pstr_next++; } if (*pstr != srch_char) { /* If srch char NOT found, str points to NULL; ... */ return ((CPU_CHAR *)0); /* ... rtn NULL (see Notes #2b & #2c). */ } return (pstr); /* Else rtn ptr to found srch char (see Note #2d). */ } /*$PAGE*/ /* ********************************************************************************************************* * Str_Char_N() * * Description : Search string for first occurrence of specific character, up to a maximum number of characters. * * Argument(s) : pstr Pointer to string (see Note #1). * * len_max Maximum number of characters to search (see Notes #2e & #3). * * srch_char Search character. * * Return(s) : Pointer to first occurrence of search character in string, if any. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) String buffer NOT modified. * * (2) String search terminates when : * * (a) String pointer passed a NULL pointer. * (1) No string search performed; NULL pointer returned. * * (b) String pointer points to NULL. * (1) String overlaps with NULL address. * (2) String searched up to but NOT beyond or including the NULL address. * * (c) String's terminating NULL character found. * (1) Search character NOT found in search string; NULL pointer returned. * (2) Applicable ONLY IF search character is NOT the terminating NULL character. * * (d) Search character found. * (1) Return pointer to first occurrence of search character in search string. * * (e) 'len_max' number of characters searched. * (1) 'len_max' number of characters does NOT include terminating NULL character. * * (3) Ideally, the 'len_max' parameter would be the last parameter in this function's * paramter list for consistency with all other custom string library functions. * However, the 'len_max' parameter is ordered to comply with the standard library * function's parameter list. ********************************************************************************************************* */ CPU_CHAR *Str_Char_N (CPU_CHAR *pstr, CPU_SIZE_T len_max, CPU_CHAR srch_char) { CPU_CHAR *pstr_next; CPU_SIZE_T len_srch; if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a). */ return ((CPU_CHAR *)0); } if (len_max == (CPU_SIZE_T)0) { /* Rtn NULL if srch len equals zero (see Note #2e). */ return ((CPU_CHAR *)0); } pstr_next = pstr; pstr_next++; len_srch = 0; while (( pstr_next != (CPU_CHAR *)0) && /* Srch str until NULL ptr(s) (see Note #2b) ... */ (*pstr != (CPU_CHAR )0) && /* ... or NULL char (see Note #2c) ... */ (*pstr != (CPU_CHAR )srch_char) && /* ... or srch char found (see Note #2d); ... */ ( len_srch < (CPU_SIZE_T)len_max)) { /* ... or max nbr chars srch'd (see Note #2e). */ pstr++; pstr_next++; len_srch++; } if (*pstr != srch_char) { /* If srch char NOT found, str points to NULL; ... */ return ((CPU_CHAR *)0); /* ... rtn NULL (see Notes #2b & #2c). */ } return (pstr); /* Else rtn ptr to found srch char (see Note #2d). */ } /*$PAGE*/ /* ********************************************************************************************************* * Str_Char_Last() * * Description : Search string for last occurrence of specific character. * * Argument(s) : pstr Pointer to string (see Note #1). * * srch_char Search character. * * Return(s) : Pointer to last occurrence of search character in string, if any. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) String buffer NOT modified. * * (2) String search terminates when : * * (a) String pointer passed a NULL pointer. * (1) No string search performed; NULL pointer returned. * * (b) String pointer points to NULL. * (1) String overlaps with NULL address. * (2) String searched up to but NOT beyond or including the NULL address. * (3) NULL address boundary handled in Str_Len(). * * (c) String searched from end to beginning. * (1) Search character NOT found in search string; NULL pointer returned. * (2) Applicable ONLY IF search character is NOT the terminating NULL character. * * (d) Search character found. * (1) Return pointer to first occurrence of search character in search string. ********************************************************************************************************* */ CPU_CHAR *Str_Char_Last (CPU_CHAR *pstr, CPU_CHAR srch_char) { CPU_CHAR *pstr_next; CPU_SIZE_T str_len; if (pstr == (CPU_CHAR *)0) { /* Rtn NULL if srch str ptr NULL (see Note #2a). */ return ((CPU_CHAR *)0); } pstr_next = pstr; str_len = Str_Len(pstr); pstr_next += str_len; while (( pstr_next != pstr) && /* Srch str from end until beg (see Note #2c) ... */ (*pstr_next != srch_char)) { /* ... until srch char found (see Note #2d). */ pstr_next--; } if (*pstr_next != srch_char) { /* If srch char NOT found, str points to NULL; ... */ return ((CPU_CHAR *)0); /* ... rtn NULL (see Notes #2b & #2c). */ } return (pstr_next); /* Else rtn ptr to found srch char (see Note #2d). */ } /*$PAGE*/ /* ********************************************************************************************************* * Str_Str() * * Description : Search string for first occurence of a specific search string. * * Argument(s) : pstr Pointer to string (see Note #1). * * psrch_str Pointer to search string (see Note #1). * * Return(s) : Pointer to first occurrence of search string in string, if any. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) String buffers NOT modified. * * (2) String search terminates when : * * (a) String pointer passed a NULL pointer. * (1) No string search performed; NULL pointer returned. * * (b) Search string length greater than string length. * (1) No string search performed; NULL pointer returned. * * (c) Search string length equal to zero. * (1) NULL search string at end of string returned. * * (d) Entire string has been searched. * (1) Maximum size of the search is defined as the subtraction of the * search string length from the string length. * (2) Search string not found; NULL pointer returned. * * (e) Search string found. * (1) Search string found according to Str_Cmp_N() return value. * (2) Return pointer to first occurrence of search string in string. ********************************************************************************************************* */ CPU_CHAR *Str_Str (CPU_CHAR *pstr, CPU_CHAR *psrch_str) { CPU_SIZE_T str_len; CPU_SIZE_T srch_str_len; CPU_SIZE_T srch_len; CPU_SIZE_T srch_ix; CPU_BOOLEAN srch_done; CPU_INT16S srch_cmp; CPU_CHAR *pstr_srch_ix; /* Rtn NULL if str ptr(s) NULL (see Note #2a). */ if (pstr == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } if (psrch_str == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } str_len = Str_Len(pstr); srch_str_len = Str_Len(psrch_str); if (srch_str_len > str_len) { /* If srch str len > str len, rtn NULL (see Note #2b). */ return ((CPU_CHAR *)0); } if (srch_str_len == 0) { /* If srch str len = 0, srch str equal NULL str; ... */ pstr_srch_ix = (CPU_CHAR *)(pstr + str_len); /* ... rtn ptr to NULL str found in str (see Note #2c). */ return (pstr_srch_ix); } srch_len = str_len - srch_str_len; /* Determine srch len (see Note #2d1). */ srch_ix = 0; srch_done = DEF_NO; while ((srch_done == DEF_NO) && (srch_ix <= srch_len)) { pstr_srch_ix = (CPU_CHAR *)(pstr + srch_ix); srch_cmp = Str_Cmp_N(pstr_srch_ix, psrch_str, srch_str_len); srch_done = (srch_cmp == 0) ? DEF_YES : DEF_NO; srch_ix++; } if (srch_cmp != 0) { /* If srch str NOT found, rtn NULL (see Note #2d). */ return ((CPU_CHAR *)0); } return (pstr_srch_ix); /* Rtn ptr to srch str found in str (see Note #2e). */ } /*$PAGE*/ /* ********************************************************************************************************* * Str_FmtNbr_32() * * Description : Format number into a multi-digit character string. * * Argument(s) : nbr Number to format (see Note #1). * * nbr_dig Number of integer digits to format (see Note #2). * * nbr_dp Number of decimal point digits to format. * * lead_zeros Prepend leading zeros option (DEF_YES/DEF_NO) [see Note #3]. * * nul NULL-character terminate option (DEF_YES/DEF_NO) [see Note #4]. * * pstr_fmt Pointer to character array to return formatted number string (see Note #5). * * Return(s) : Pointer to formatted string, if NO errors (see Note #6). * * Pointer to NULL, otherwise. * * Caller(s) : various. * * Note(s) : (1) (a) The maximum accuracy for 32-bit floating-point numbers : * * * Maximum Accuracy log [Internal-Base ^ (Number-Internal-Base-Digits)] * 32-bit Floating-point Number = ----------------------------------------------------- * log [External-Base] * * log [2 ^ 24] * = -------------- * log [10] * * < 7.225 Base-10 Digits * * where * Internal-Base Internal number base of floating- * point numbers (i.e. 2) * External-Base External number base of floating- * point numbers (i.e. 10) * Number-Internal-Base-Digits Number of internal number base * significant digits (i.e. 24) * * (b) Some compilers' floating-point routines MAY further reduce the maximum accuracy. * * (c) If the total number of digits to format ('nbr_dig + nbr_dp') is greater than the * maximum accuracy; digits following the first, significantly-accurate digits will * be inaccurate. * * (2) (a) If the number of digits to format ('nbr_dig') is less than the number of significant * integer digits of the number to format ('nbr'); then the most-significant digits of * the formatted number will be truncated. * * Example : * * nbr = 23456.789 * nbr_dig = 3 * nbr_dp = 2 * * pstr_fmt = "456.78" * * (b) If number to format ('nbr') is negative but the most-significant digits of the * formatted number are truncated (see Note #2a); the negative sign still prefixes * the truncated formatted number. * * Example : * * nbr = -23456.789 * nbr_dig = 3 * nbr_dp = 2 * * pstr_fmt = "-456.78" * * (3) (a) Leading zeros option prepends leading '0's prior to the first non-zero digit. * The number of leading zeros is such that the total number integer digits is * equal to the requested number of integer digits to format ('nbr_dig'). * * (b) (1) If leading zeros option DISABLED, ... * (2) ... number of digits to format is non-zero, ... * (3) ... & the integer value of the number to format is zero; ... * (4) ... then one digit of '0' value is formatted. * * This is NOT a leading zero; but a single integer digit of '0' value. * * (4) (a) NULL-character terminate option DISABLED prevents overwriting previous character * array formatting. * * (b) WARNING: Unless 'pstr_fmt' character array is pre-/post-terminated, NULL-character * terminate option DISABLED will cause character string run-on. *$PAGE* * (5) (a) Format buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (b) To prevent character buffer overrun : * * Character array size MUST be >= ('nbr_dig' + * 'nbr_dp' + * 1 negative sign + * 1 decimal point + * 1 'NUL' terminator) characters * * (6) String format terminates when : * * (a) Format string pointer is passed a NULL pointer. * (1) No string format performed; NULL pointer returned. * * (b) Number successfully formatted into character string array. ********************************************************************************************************* */ #if (LIB_STR_CFG_FP_EN == DEF_ENABLED) CPU_CHAR *Str_FmtNbr_32 (CPU_FP32 nbr, CPU_INT08U nbr_dig, CPU_INT08U nbr_dp, CPU_BOOLEAN lead_zeros, CPU_BOOLEAN nul, CPU_CHAR *pstr_fmt) { CPU_CHAR *pstr; CPU_INT08U i; CPU_INT32U dig_nbr; CPU_INT32U dig_val; CPU_FP32 dig_exp; CPU_FP32 dp_exp; /* Rtn NULL if str ptr NULL (see Note #6a). */ if (pstr_fmt == (CPU_CHAR *)0) { return ((CPU_CHAR *)0); } pstr = pstr_fmt; if (nbr < 0.0) { /* If nbr neg, ... */ if ((nbr_dig > 0) || /* ... & at least one dig ... */ (nbr_dp > 0)) { /* ... or at least one dp; ... */ nbr = -nbr; /* ... negate nbr & ... */ *pstr++ = '-'; /* ... prefix with neg sign (see Note #2b). */ } } if (nbr_dig > 0) { dig_exp = 1.0; for (i = 1; i < nbr_dig; i++) { dig_exp *= 10.0; } for (i = nbr_dig; i > 0; i--) { /* Fmt str for desired nbr digs. */ dig_nbr = (CPU_INT32U)(nbr / dig_exp); if ((dig_nbr > 0) || /* If dig nbr > 0, ... */ (nbr_dig == 1) || /* ... OR exactly 1 dig to fmt, ... */ (i == 1) || /* ... OR on one's dig to fmt, ... */ (lead_zeros == DEF_YES)) { /* ... OR lead zeros opt ENABLED (see Note #3), ... */ /* ... calc & fmt dig val. */ dig_val = (CPU_INT32U)(dig_nbr % 10 ); *pstr++ = (CPU_CHAR )(dig_val + '0'); } dig_exp /= 10.0; /* Shift to next least-significant dig. */ } } if (nbr_dp > 0) { *pstr++ = '.'; /* Append dp prior to dp conversion. */ dp_exp = 10.0; for (i = 0; i < nbr_dp; i++) { /* Fmt str for desired nbr dp. */ dig_nbr = (CPU_INT32U)(nbr * dp_exp ); dig_val = (CPU_INT32U)(dig_nbr % 10 ); *pstr++ = (CPU_CHAR )(dig_val + '0'); dp_exp *= 10.0; /* Shift to next least-significant dp. */ } } if (nul != DEF_NO) { /* If NOT DISABLED, append NULL char (see Note #4). */ *pstr = (CPU_CHAR)0; } return (pstr_fmt); } #endif