1 //*****************************************************************************
2 //
3 //! @file am_util_string.c
4 //!
5 //! @brief A subset of the functions provided in the C standard string library.
6 //!
7 //! The functions here are reimplementation of some of the standard "string"
8 //! functions.
9 //!
10 //! @addtogroup string String - Ambiq subset of C String Library
11 //! @ingroup utils
12 //! @{
13 //
14 //*****************************************************************************
15 
16 //*****************************************************************************
17 //
18 // Copyright (c) 2023, Ambiq Micro, Inc.
19 // All rights reserved.
20 //
21 // Redistribution and use in source and binary forms, with or without
22 // modification, are permitted provided that the following conditions are met:
23 //
24 // 1. Redistributions of source code must retain the above copyright notice,
25 // this list of conditions and the following disclaimer.
26 //
27 // 2. Redistributions in binary form must reproduce the above copyright
28 // notice, this list of conditions and the following disclaimer in the
29 // documentation and/or other materials provided with the distribution.
30 //
31 // 3. Neither the name of the copyright holder nor the names of its
32 // contributors may be used to endorse or promote products derived from this
33 // software without specific prior written permission.
34 //
35 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
39 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
40 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
43 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
44 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
45 // POSSIBILITY OF SUCH DAMAGE.
46 //
47 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
48 //
49 //*****************************************************************************
50 
51 #include <stdint.h>
52 #include <stdbool.h>
53 #include "am_util_string.h"
54 
55 #if MINIMIZE_CATTR_TABLE
56 #define CATTR_TBL_SIZE  128
57 #else
58 #define CATTR_TBL_SIZE  256
59 #endif
60 
61 //*****************************************************************************
62 //
63 //! @brief Table for quick lookup of character attributes.
64 //
65 //*****************************************************************************
66 const uint8_t am_cattr[CATTR_TBL_SIZE] =
67 {
68     AM_CATTR_NONE,                                                          /* 0x00 */
69     AM_CATTR_NONE,                                                          /* 0x01 */
70     AM_CATTR_NONE,                                                          /* 0x02 */
71     AM_CATTR_NONE,                                                          /* 0x03 */
72     AM_CATTR_NONE,                                                          /* 0x04 */
73     AM_CATTR_NONE,                                                          /* 0x05 */
74     AM_CATTR_NONE,                                                          /* 0x06 */
75     AM_CATTR_NONE,                                                          /* 0x07 */
76     AM_CATTR_NONE,                                                          /* 0x08 */
77     AM_CATTR_WHSPACE,                                                       /* 0x09 */
78     AM_CATTR_WHSPACE,                                                       /* 0x0A */
79     AM_CATTR_WHSPACE,                                                       /* 0x0B */
80     AM_CATTR_WHSPACE,                                                       /* 0x0C */
81     AM_CATTR_WHSPACE,                                                       /* 0x0D */
82     AM_CATTR_NONE,                                                          /* 0x0E */
83     AM_CATTR_NONE,                                                          /* 0x0F */
84     AM_CATTR_NONE,                                                          /* 0x00 */
85     AM_CATTR_NONE,                                                          /* 0x11 */
86     AM_CATTR_NONE,                                                          /* 0x12 */
87     AM_CATTR_NONE,                                                          /* 0x13 */
88     AM_CATTR_NONE,                                                          /* 0x14 */
89     AM_CATTR_NONE,                                                          /* 0x15 */
90     AM_CATTR_NONE,                                                          /* 0x16 */
91     AM_CATTR_NONE,                                                          /* 0x17 */
92     AM_CATTR_NONE,                                                          /* 0x18 */
93     AM_CATTR_NONE,                                                          /* 0x19 */
94     AM_CATTR_NONE,                                                          /* 0x1A */
95     AM_CATTR_NONE,                                                          /* 0x1B */
96     AM_CATTR_NONE,                                                          /* 0x1C */
97     AM_CATTR_NONE,                                                          /* 0x1D */
98     AM_CATTR_NONE,                                                          /* 0x1E */
99     AM_CATTR_NONE,                                                          /* 0x1F */
100     AM_CATTR_WHSPACE,                                                       /* 0x20, space */
101     AM_CATTR_FILENM83,                                                      /* 0x21, ! */
102     AM_CATTR_NONE,                                                          /* 0x22, " */
103     AM_CATTR_FILENM83,                                                      /* 0x23, # */
104     AM_CATTR_FILENM83,                                                      /* 0x24, $ */
105     AM_CATTR_FILENM83,                                                      /* 0x25, % */
106     AM_CATTR_FILENM83,                                                      /* 0x26, & */
107     AM_CATTR_FILENM83,                                                      /* 0x27, ' */
108     AM_CATTR_FILENM83,                                                      /* 0x28, ( */
109     AM_CATTR_FILENM83,                                                      /* 0x29, ) */
110     AM_CATTR_NONE,                                                          /* 0x2A, * */
111     AM_CATTR_NONE,                                                          /* 0x2B, + */
112     AM_CATTR_NONE,                                                          /* 0x2C, , */
113     AM_CATTR_FILENM83,                                                      /* 0x2D, - */
114     AM_CATTR_FILENM83,                                                      /* 0x2E, . */
115     AM_CATTR_NONE,                                                          /* 0x2F, / */
116     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x30, 0 */
117     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x31, 1 */
118     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x32, 2 */
119     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x33, 3 */
120     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x34, 4 */
121     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x35, 5 */
122     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x36, 6 */
123     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x37, 7 */
124     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x38, 8 */
125     AM_CATTR_DIGIT | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,                   /* 0x39, 9 */
126     AM_CATTR_NONE,                                                          /* 0x3A, : */
127     AM_CATTR_NONE,                                                          /* 0x3B, ; */
128     AM_CATTR_NONE,                                                          /* 0x3C, < */
129     AM_CATTR_NONE,                                                          /* 0x3D, = */
130     AM_CATTR_NONE,                                                          /* 0x3E, > */
131     AM_CATTR_NONE,                                                          /* 0x3F, ? */
132     AM_CATTR_FILENM83,                                                      /* 0x40, @ */
133     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x41, A */
134     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x42, B */
135     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x43, C */
136     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x44, D */
137     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x45, E */
138     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x46, F */
139     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x47, G */
140     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x48, H */
141     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x49, I */
142     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4A, J */
143     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4B, K */
144     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4C, L */
145     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4D, M */
146     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4E, N */
147     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x4F, O */
148     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x50, P */
149     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x51, Q */
150     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x52, R */
151     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x53, S */
152     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x54, T */
153     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x55, U */
154     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x56, V */
155     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x57, W */
156     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x58, X */
157     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x59, Y */
158     AM_CATTR_ALPHA | AM_CATTR_UPPER | AM_CATTR_FILENM83,                    /* 0x5A, Z */
159     AM_CATTR_NONE,                                                          /* 0x5B, [ */
160     AM_CATTR_NONE,                                                          /* 0x5C, \ */
161     AM_CATTR_NONE,                                                          /* 0x5D, ] */
162     AM_CATTR_FILENM83,                                                      /* 0x5E, ^ */
163     AM_CATTR_FILENM83,                                                      /* 0x5F, _ */
164     AM_CATTR_FILENM83,                                                      /* 0x60, ` */
165     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x61, a */
166     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x62, b */
167     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x63, c */
168     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x64, d */
169     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x65, e */
170     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_XDIGIT | AM_CATTR_FILENM83,  /* 0x66, f */
171     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x67, g */
172     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x68, h */
173     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x69, i */
174     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6A, j */
175     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6B, k */
176     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6C, l */
177     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6D, m */
178     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6E, n */
179     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x6F, o */
180     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x70, p */
181     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x71, q */
182     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x72, r */
183     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x73, s */
184     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x74, t */
185     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x75, u */
186     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x76, v */
187     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x77, w */
188     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x78, x */
189     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x79, y */
190     AM_CATTR_ALPHA | AM_CATTR_LOWER | AM_CATTR_FILENM83,                    /* 0x7A, z */
191     AM_CATTR_FILENM83,                                                      /* 0x7B, { */
192     AM_CATTR_NONE,                                                          /* 0x7C, | */
193     AM_CATTR_FILENM83,                                                      /* 0x7D, } */
194     AM_CATTR_FILENM83,                                                      /* 0x7E, ~ */
195     AM_CATTR_NONE                                                           /* 0x7F, delete */
196 
197     //
198     // All bit7 chars are AM_CATTR_NONE.
199     //
200 };
201 
202 #ifdef AM_UTIL_STRING_CTYPE_DISABLE_MACROS
203 
204 //*****************************************************************************
205 //
206 // Check if the integer param is alphanumeric
207 //
208 //*****************************************************************************
209 int
am_util_string_isalnum(int c)210 am_util_string_isalnum(int c)
211 {
212 #if MINIMIZE_CATTR_TABLE
213     return (c & 0xffffff80) ? 0 : (am_cattr[c] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT)) ? 1 : 0;
214 #else
215     return (am_cattr[c & 0xff] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT)) ? 1 : 0;
216 #endif
217 }
218 
219 //*****************************************************************************
220 //
221 // Check if the integer param is alphabetic
222 //
223 //*****************************************************************************
224 int
am_util_string_isalpha(int c)225 am_util_string_isalpha(int c)
226 {
227 #if MINIMIZE_CATTR_TABLE
228     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_ALPHA) ? 1 : 0;
229 #else
230     return (am_cattr[c & 0xff] & AM_CATTR_ALPHA) ? 1 : 0;
231 #endif
232 }
233 
234 //*****************************************************************************
235 //
236 // Check if the integer param is a digit
237 //
238 //*****************************************************************************
239 int
am_util_string_isdigit(int c)240 am_util_string_isdigit(int c)
241 {
242 #if MINIMIZE_CATTR_TABLE
243     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_DIGIT) ? 1 : 0;
244 #else
245     return (am_cattr[c & 0xff] & AM_CATTR_DIGIT) ? 1 : 0;
246 #endif
247 }
248 
249 //*****************************************************************************
250 //
251 // Check if the integer param is lower case
252 //
253 //*****************************************************************************
254 int
am_util_string_islower(int c)255 am_util_string_islower(int c)
256 {
257 #if MINIMIZE_CATTR_TABLE
258     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_LOWER) ? 1 : 0;
259 #else
260     return (am_cattr[c & 0xff] & AM_CATTR_LOWER) ? 1 : 0;
261 #endif
262 }
263 
264 //*****************************************************************************
265 //
266 // Check if the integer param is the space character
267 //
268 //*****************************************************************************
269 int
am_util_string_isspace(int c)270 am_util_string_isspace(int c)
271 {
272 #if MINIMIZE_CATTR_TABLE
273     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_WHSPACE) ? 1 : 0;
274 #else
275     return (am_cattr[c & 0xff] & AM_CATTR_WHSPACE) ? 1 : 0;
276 #endif
277 }
278 
279 //*****************************************************************************
280 //
281 // Check if the integer param is upper case
282 //
283 //*****************************************************************************
284 int
am_util_string_isupper(int c)285 am_util_string_isupper(int c)
286 {
287 #if MINIMIZE_CATTR_TABLE
288     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_UPPER) ? 1 : 0;
289 #else
290     return (am_cattr[c & 0xff] & AM_CATTR_UPPER) ? 1 : 0;
291 #endif
292 }
293 
294 //*****************************************************************************
295 //
296 // Check if the integer param is a hex digit
297 //
298 //*****************************************************************************
299 int
am_util_string_isxdigit(int c)300 am_util_string_isxdigit(int c)
301 {
302 #if MINIMIZE_CATTR_TABLE
303     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_XDIGIT) ? 1 : 0;
304 #else
305     return (am_cattr[c & 0xff] & AM_CATTR_XDIGIT) ? 1 : 0;
306 #endif
307 }
308 
309 //*****************************************************************************
310 //
311 // Converts the character to lower case
312 //
313 //*****************************************************************************
am_util_string_tolower(int c)314 int am_util_string_tolower(int c)
315 {
316 #if MINIMIZE_CATTR_TABLE
317     return (am_cattr[c & 0x7f] & AM_CATTR_UPPER) ? c | 0x20 : c;
318 #else
319     return (am_cattr[c & 0xff] & AM_CATTR_UPPER) ? c | 0x20 : c;
320 #endif
321 }
322 
323 //*****************************************************************************
324 //
325 // Converts the character to upper case
326 //
327 //*****************************************************************************
am_util_string_toupper(int c)328 int am_util_string_toupper(int c)
329 {
330 #if MINIMIZE_CATTR_TABLE
331     return (am_cattr[c & 0x7f] & AM_CATTR_LOWER) ? c & ~0x20 : c;
332 #else
333     return (am_cattr[c & 0xff] & AM_CATTR_LOWER) ? c & ~0x20 : c;
334 #endif
335 }
336 
337 //*****************************************************************************
338 //
339 // Check if the integer param is part of a filename char
340 //
341 //*****************************************************************************
342 int
am_util_string_isfilenm83(int c)343 am_util_string_isfilenm83(int c)
344 {
345 #if MINIMIZE_CATTR_TABLE
346     return (c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_FILENM83) ? 1 : 0;
347 #else
348     return (am_cattr[c & 0xff] & AM_CATTR_FILENM83) ? 1 : 0;
349 #endif
350 }
351 #endif // AM_UTIL_STRING_CTYPE_DISABLE_MACROS
352 
353 //*****************************************************************************
354 //
355 // Compare two strings.
356 //
357 //*****************************************************************************
358 int32_t
am_util_string_strcmp(const char * str1,const char * str2)359 am_util_string_strcmp(const char *str1, const char *str2)
360 {
361     return am_util_string_strncmp(str1, str2, 0xffffffff);
362 }
363 
364 //*****************************************************************************
365 //
366 // Compare two strings with a specified count.
367 //
368 //*****************************************************************************
369 int32_t
am_util_string_strncmp(const char * str1,const char * str2,uint32_t num)370 am_util_string_strncmp(const char *str1, const char *str2, uint32_t num)
371 {
372     while ( num-- )
373     {
374         // Check for inequality OR end of string
375         if ( *str1 != *str2 || *str1 == '\0' )
376         {
377             return *str1 - *str2;
378         }
379 
380         str1++;
381         str2++;
382     }
383 
384     //
385     // Since we made it here, the strings must be equal to n characters.
386     //
387     return 0;
388 }
389 
390 //*****************************************************************************
391 //
392 // Compare two strings with a specified count and without regard to
393 // letter case in the strings.
394 //
395 //*****************************************************************************
396 int32_t
am_util_string_strnicmp(const char * str1,const char * str2,int num)397 am_util_string_strnicmp(const char *str1, const char *str2, int num)
398 {
399     uint8_t cChar1, cChar2;
400 
401     while ( *str1 && *str2 && num )
402     {
403         cChar1 = *str1;
404         cChar2 = *str2;
405 
406         cChar1 |= ( am_cattr[cChar1] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
407         cChar2 |= ( am_cattr[cChar2] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
408 
409         if ( cChar1 != cChar2 )
410         {
411             return cChar1 - cChar2;
412         }
413 
414         str1++;
415         str2++;
416         num--;
417     }
418 
419     //
420     // Since we made it here, the strings must be equal to n characters.
421     //
422     return 0;
423 }
424 
425 //*****************************************************************************
426 //
427 // Compare two strings with case-insensitivity.
428 //
429 //*****************************************************************************
430 int32_t
am_util_string_stricmp(const char * str1,const char * str2)431 am_util_string_stricmp(const char *str1, const char *str2)
432 {
433     uint8_t cChar1, cChar2;
434 
435     while ( *str1 && *str2 )
436     {
437         cChar1 = *str1++;
438         cChar2 = *str2++;
439 
440         cChar1 |= ( am_cattr[cChar1] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
441         cChar2 |= ( am_cattr[cChar2] & AM_CATTR_UPPER ) ? 0x20 : 0x00;
442 
443         if ( cChar1 != cChar2 )
444         {
445             return cChar1 - cChar2;
446         }
447     }
448 
449     return *str1 - *str2;
450 }
451 
452 //*****************************************************************************
453 //
454 // Return the length of a string.
455 //
456 //*****************************************************************************
457 uint32_t
am_util_string_strlen(const char * pcStr)458 am_util_string_strlen(const char *pcStr)
459 {
460     const char *pcS;
461 
462     //
463     // Loop through the string.
464     //
465     for (pcS = pcStr; *pcS; ++pcS);
466 
467     //
468     // Return the length.
469     //
470     return(pcS - pcStr);
471 }
472 
473 //*****************************************************************************
474 //
475 // Copies a string.
476 //
477 //*****************************************************************************
478 char *
am_util_string_strcpy(char * pcDst,const char * pcSrc)479 am_util_string_strcpy(char *pcDst, const char *pcSrc)
480 {
481     char *pcRet = pcDst;
482 
483     //
484     // Blindly copy the string until we hit a terminating NULL char.
485     //
486     do
487     {
488         *pcDst++ = *pcSrc;
489     } while ( *pcSrc++ );
490 
491     return pcRet;
492 }
493 
494 //*****************************************************************************
495 //
496 // Copies a specified number of characters of a string.
497 //
498 //*****************************************************************************
499 char *
am_util_string_strncpy(char * pcDst,const char * pcSrc,uint32_t uNum)500 am_util_string_strncpy(char *pcDst, const char *pcSrc, uint32_t uNum)
501 {
502     char *pcRet = pcDst;
503 
504     while (uNum > 0)
505     {
506         if ( *pcSrc )
507         {
508             *pcDst++ = *pcSrc++;
509         }
510         else
511         {
512             *pcDst++ = 0x00;
513         }
514         uNum--;
515     }
516 
517     return pcRet;
518 }
519 
520 //*****************************************************************************
521 //
522 // Concatenate a string.
523 //
524 //*****************************************************************************
525 char *
am_util_string_strcat(char * pcDst,const char * pcSrc)526 am_util_string_strcat(char *pcDst, const char *pcSrc)
527 {
528     char *pcRet = pcDst;
529 
530     //
531     // Find the end of the existing string.
532     //
533     while ( *pcDst++ );
534     pcDst--;
535 
536     //
537     // Now, copy the new string.
538     //
539     am_util_string_strcpy(pcDst, pcSrc);
540 
541     return pcRet;
542 }
543 
544 //*****************************************************************************
545 //
546 // End Doxygen group.
547 //! @}
548 //
549 //*****************************************************************************
550 
551