1 //*****************************************************************************
2 //
3 //! @file am_util_string.h
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 #ifndef AM_UTIL_STRING_H
51 #define AM_UTIL_STRING_H
52 
53 #ifdef __cplusplus
54 extern "C"
55 {
56 #endif
57 
58 
59 //*****************************************************************************
60 //
61 // Character attributes lookup table defines.
62 //
63 //*****************************************************************************
64 #define AM_CATTR_NONE       0x00
65 #define AM_CATTR_ALPHA      0x01
66 #define AM_CATTR_LOWER      0x02
67 #define AM_CATTR_UPPER      0x04
68 #define AM_CATTR_DIGIT      0x08
69 #define AM_CATTR_XDIGIT     0x10
70 #define AM_CATTR_WHSPACE    0x20
71 #define AM_CATTR_FILENM83   0x80
72 
73 //
74 // Set MINIMIZE_CATTR_TABLE to 1 to configure for minimal CATTR table size,
75 //  (256 instead of 512 bytes) but at a cost of slightly larger code size.
76 //  However, setting this option also provides an additional level of checking
77 //  of the argument; if the argument is not a uint8_t, the functions are
78 //  guaranteed to return 0.
79 //
80 #define MINIMIZE_CATTR_TABLE    0
81 
82 
83 //*****************************************************************************
84 //
85 // Globals
86 //
87 //*****************************************************************************
88 extern const uint8_t am_cattr[];
89 
90 
91 //*****************************************************************************
92 //
93 // External function definitions
94 //
95 //*****************************************************************************
96 
97 //*****************************************************************************
98 //
99 //! @brief Compare two strings.
100 //!
101 //! @param str1 is the first string to compare.
102 //! @param str2 is the second string to compare
103 //!
104 //! This function steps through a pair of strings, character by character, to
105 //! determine if the strings contain the same characters. If the strings match,
106 //! this function will return a zero. If str1 is alphabetically earlier than
107 //! str2, the return value will be negative. Otherwise, the return value will
108 //! be positive.
109 //!
110 //! @return 0 for a perfect match, negative value if str1<str2, positive value
111 //!  if str1>str2.
112 //
113 //*****************************************************************************
114 extern int32_t am_util_string_strcmp(const char *str1, const char *str2);
115 
116 //*****************************************************************************
117 //
118 //! @brief Compare two strings with case-insensitivity.
119 //!
120 //! @param str1 is the first string to compare.
121 //! @param str2 is the second string to compare
122 //!
123 //! This function compares each character in the 2 strings, converting all
124 //! alpha characters to lower-case to make the comparison.
125 //!
126 //! To illustrate a possible unexpected outcome due to comparing the strings
127 //! as lower case, consider the example strings "AMBIQ_MICRO" and "AMBIQMICRO".
128 //! For these strings, stricmp() will return a negative value (indicating the
129 //! first as before the second), whereas strcmp() will return a positive value.
130 //!
131 //! @return 0 for a case-insensitive match, negative value if str1<str2,
132 //!  positive value if str1>str2.
133 //
134 //*****************************************************************************
135 extern int32_t am_util_string_stricmp(const char *str1, const char *str2);
136 
137 //*****************************************************************************
138 //
139 //! @brief Compare two strings with a specified count.
140 //!
141 //! @param str1 is the first string to compare.
142 //! @param str2 is the second string to compare
143 //! @param num is the maximum number of characters to compare.
144 //!
145 //! This function steps through a pair of strings, character by character, to
146 //! determine if the strings contain the same characters. If the strings match,
147 //! this function will return a zero. If str1 is alphabetically earlier than
148 //! str2, the return value will be negative. Otherwise, the return value will
149 //! be positive.
150 //!
151 //! @return 0 for a perfect match, negative value if str1<str2, positive value
152 //!  if str1>str2.
153 //
154 //*****************************************************************************
155 extern int32_t am_util_string_strncmp(const char *str1, const char *str2,
156                                       uint32_t num);
157 
158 //*****************************************************************************
159 //
160 //! @brief Compare two strings with a specified count and without regard to
161 //! letter case in the strings.
162 //!
163 //! @param str1 is the first string to compare.
164 //! @param str2 is the second string to compare
165 //! @param num is the maximum number of characters to compare.
166 //!
167 //! This function steps through a pair of strings, character by character, to
168 //! determine if the strings contain the same characters. If the strings match,
169 //! this function will return a zero. If str1 is alphabetically earlier than
170 //! str2, the return value will be negative. Otherwise, the return value will
171 //! be positive.
172 //!
173 //! @return 0 for a perfect match, negative value if str1<str2, positive value
174 //!  if str1>str2.
175 //
176 //*****************************************************************************
177 extern int32_t am_util_string_strnicmp(const char *str1, const char *str2,
178                                       int num);
179 
180 //*****************************************************************************
181 //
182 //! @brief Return the length of a string.
183 //!
184 //! @param pcStr pointer to the string.
185 //!
186 //! This function returns the length of the string at pcStr.
187 //!
188 //! @return length of the string pcStr.
189 //
190 //*****************************************************************************
191 extern uint32_t am_util_string_strlen(const char *pcStr);
192 
193 //*****************************************************************************
194 //
195 //! @brief Copies a string.
196 //!
197 //! @param pcDst pointer to the destination string.
198 //! @param pcSrc pointer to the source string to be copied to pcDst.
199 //!
200 //! This function copies pcSrc to the location specified by pcDst.
201 //!
202 //! @return pcDst (the location of the destination string).
203 //
204 //*****************************************************************************
205 extern char *am_util_string_strcpy(char *pcDst, const char *pcSrc);
206 
207 //*****************************************************************************
208 //
209 //! @brief Copies a specified number of characters of a string.
210 //!
211 //! @param pcDst pointer to the destination string.
212 //! @param pcSrc pointer to the source string to be copied to pcDst.
213 //! @param uNum  length of string
214 //!
215 //! This function copies uNum characters of pcSrc to the location specified
216 //!  by pcDst.
217 //! If uNum is less than the length of pcSrc, a NULL terminating character
218 //!  is not appended to the copied string. Thus the resultant string will be
219 //!  exactly uNum chars in length and not terminated.
220 //! If uNum is greater than the length of pcSrc, then pcDst is padded with
221 //!  NULL characters up to the uNum length.
222 //! Behavior is undefined if the addresses ranges overlap.
223 //!
224 //! @return pcDst (the location of the destination string).
225 //
226 //*****************************************************************************
227 extern char *am_util_string_strncpy(char *pcDst, const char *pcSrc, uint32_t uNum);
228 
229 //*****************************************************************************
230 //
231 //! @brief Concatenate a string.
232 //!
233 //! @param pcDst pointer to the destination string.
234 //! @param pcSrc pointer to the source string to be copied to pcDst.
235 //!
236 //! This function concatenates the string at pcSrc to the existing string
237 //! at pcDst.
238 //!
239 //! Both strings, pcDst and pcSrc, must be NULL-terminated.
240 //! No overflow checking is performed.
241 //! pcDst and pcSrc shall not overlap.
242 //!
243 //! @return pcDst (the location of the destination string).
244 //
245 //*****************************************************************************
246 extern char *am_util_string_strcat(char *pcDst, const char *pcSrc);
247 
248 //*****************************************************************************
249 //
250 // Character "is" macros and functions
251 //
252 // By default all of the "is" functions are implemented as macros.  To implement
253 //  as functions rather than macros, use a global compiler command line (-D)
254 //  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
255 //
256 #ifdef AM_UTIL_STRING_CTYPE_DISABLE_MACROS
257 //*****************************************************************************
258 //
259 //! @brief Check if the integer param is alphanumeric
260 //!
261 //! Tests a given integer value in order to determine
262 //!  whether the integer satisfies the test condition.
263 //! This function is based on the C99 standard function.
264 //!
265 //! By default this function is implemented as a macro. To implement
266 //!  as a function, use a global compiler command line (-D)
267 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
268 //!
269 //! @param c - integer to test
270 //!
271 //! @return returns a nonzero value if the integer satisfies
272 //!  the test condition and 0 if it does not.
273 //
274 //*****************************************************************************
275 extern int am_util_string_isalnum(int c);
276 
277 //*****************************************************************************
278 //
279 //! @brief Check if the integer param is alphabetic
280 //!
281 //! Tests a given integer value in order to determine
282 //!  whether the integer satisfies the test condition.
283 //! This function is based on the C99 standard function.
284 //!
285 //! By default this function is implemented as a macro. To implement
286 //!  as a function, use a global compiler command line (-D)
287 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
288 //!
289 //! @param c - integer to test
290 //!
291 //! @return returns a nonzero value if the integer satisfies
292 //!  the test condition and 0 if it does not.
293 //
294 //*****************************************************************************
295 extern int am_util_string_isalpha(int c);
296 
297 //*****************************************************************************
298 //
299 //! @brief Check if the integer param is a digit
300 //!
301 //! Tests a given integer value in order to determine
302 //!  whether the integer satisfies the test condition.
303 //! This function is based on the C99 standard function.
304 //!
305 //! By default this function is implemented as a macro. To implement
306 //!  as a function, use a global compiler command line (-D)
307 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
308 //!
309 //! @param c - integer to test
310 //!
311 //! @return returns a nonzero value if the integer satisfies
312 //!  the test condition and 0 if it does not.
313 //
314 //*****************************************************************************
315 extern int am_util_string_isdigit(int c);
316 
317 //*****************************************************************************
318 //
319 //! @brief Check if the integer param is lower case
320 //!
321 //! Tests a given integer value in order to determine
322 //!  whether the integer satisfies the test condition.
323 //! This function is based on the C99 standard function.
324 //!
325 //! By default this function is implemented as a macro. To implement
326 //!  as a function, use a global compiler command line (-D)
327 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
328 //!
329 //! @param c - integer to test
330 //!
331 //! @return returns a nonzero value if the integer satisfies
332 //!  the test condition and 0 if it does not.
333 //
334 //*****************************************************************************
335 extern int am_util_string_islower(int c);
336 
337 //*****************************************************************************
338 //
339 //! @brief Check if the integer param is the space character
340 //!
341 //! Tests a given integer value in order to determine
342 //!  whether the integer satisfies the test condition.
343 //! This function is based on the C99 standard function.
344 //!
345 //! By default this function is implemented as a macro. To implement
346 //!  as a function, use a global compiler command line (-D)
347 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
348 //!
349 //! @param c - integer to test
350 //!
351 //! @return returns a nonzero value if the integer satisfies
352 //!  the test condition and 0 if it does not.
353 //
354 //*****************************************************************************
355 extern int am_util_string_isspace(int c);
356 
357 //*****************************************************************************
358 //
359 //! @brief Check if the integer param is upper case
360 //!
361 //! Tests a given integer value in order to determine
362 //!  whether the integer satisfies the test condition.
363 //! This function is based on the C99 standard function.
364 //!
365 //! By default this function is implemented as a macro. To implement
366 //!  as a function, use a global compiler command line (-D)
367 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
368 //!
369 //! @param c - integer to test
370 //!
371 //! @return returns a nonzero value if the integer satisfies
372 //!  the test condition and 0 if it does not.
373 //
374 //*****************************************************************************
375 extern int am_util_string_isupper(int c);
376 
377 //*****************************************************************************
378 //
379 //! @brief Check if the integer param is a hex digit
380 //!
381 //! Tests a given integer value in order to determine
382 //!  whether the integer satisfies the test condition.
383 //! This function is based on the C99 standard function.
384 //!
385 //! By default this function is implemented as a macro. To implement
386 //!  as a function, use a global compiler command line (-D)
387 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
388 //!
389 //! @param c - integer to test
390 //!
391 //! @return returns a nonzero value if the integer satisfies
392 //!  the test condition and 0 if it does not.
393 //
394 //*****************************************************************************
395 extern int am_util_string_isxdigit(int c);
396 
397 //*****************************************************************************
398 //
399 //! @brief Converts the character to lower case
400 //!
401 //! Tests a given integer value in order to determine
402 //!  whether the integer satisfies the test condition.
403 //! This function is based on the C99 standard function.
404 //!
405 //! By default this function is implemented as a macro. To implement
406 //!  as a function, use a global compiler command line (-D)
407 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
408 //!
409 //! @param c - integer to test
410 //!
411 //! @return returns the input param as lower case
412 //
413 //*****************************************************************************
414 extern int am_util_string_tolower(int c);
415 
416 //*****************************************************************************
417 //
418 //! @brief Converts the character to upper case
419 //!
420 //! Tests a given integer value in order to determine
421 //!  whether the integer satisfies the test condition.
422 //! This function is based on the C99 standard function.
423 //!
424 //! By default this function is implemented as a macro. To implement
425 //!  as a function, use a global compiler command line (-D)
426 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
427 //!
428 //! @param c - integer to test
429 //!
430 //! @return returns the input param as upper case
431 //
432 //*****************************************************************************
433 extern int am_util_string_toupper(int c);
434 
435 //*****************************************************************************
436 //
437 //! @brief Check if the integer param is part of a filename char
438 //!
439 //! Tests a given integer value in order to determine
440 //!  whether the integer satisfies the test condition.
441 //! This function is based on the C99 standard function.
442 //!
443 //! By default this function is implemented as a macro. To implement
444 //!  as a function, use a global compiler command line (-D)
445 //!  option to define AM_UTIL_STRING_CTYPE_DISABLE_MACROS.
446 //!
447 //! @param c - integer to test
448 //!
449 //! @return returns a nonzero value if the integer satisfies
450 //!  the test condition and 0 if it does not.
451 //
452 //*****************************************************************************
453 extern int am_util_string_isfilenm83(int c);
454 #else
455 #if MINIMIZE_CATTR_TABLE
456 #define am_util_string_isalnum(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT)) ? 1 : 0)
457 #define am_util_string_isalpha(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_ALPHA) ? 1 : 0)
458 #define am_util_string_isdigit(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_DIGIT) ? 1 : 0)
459 #define am_util_string_islower(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_LOWER) ? 1 : 0)
460 #define am_util_string_isspace(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_WHSPACE) ? 1 : 0)
461 #define am_util_string_isupper(c)       ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_UPPER) ? 1 : 0)
462 #define am_util_string_isxdigit(c)      ((c & 0xffffff80) ? 0 : (am_cattr[c] & AM_CATTR_XDIGIT) ? 1 : 0)
463 #define am_util_string_tolower(c)       ((am_cattr[c & 0x7f] & AM_CATTR_UPPER) ? c | 0x20 : c)
464 #define am_util_string_toupper(c)       ((am_cattr[c & 0x7f] & AM_CATTR_LOWER) ? c & ~0x20 : c)
465 #else
466 #define am_util_string_isalnum(c)       (am_cattr[c & 0xff] & (AM_CATTR_ALPHA | AM_CATTR_DIGIT))
467 #define am_util_string_isalpha(c)       (am_cattr[c & 0xff] & AM_CATTR_ALPHA)
468 #define am_util_string_isdigit(c)       (am_cattr[c & 0xff] & AM_CATTR_DIGIT)
469 #define am_util_string_islower(c)       (am_cattr[c & 0xff] & AM_CATTR_LOWER)
470 #define am_util_string_isspace(c)       (am_cattr[c & 0xff] & AM_CATTR_WHSPACE)
471 #define am_util_string_isupper(c)       (am_cattr[c & 0xff] & AM_CATTR_UPPER)
472 #define am_util_string_isxdigit(c)      (am_cattr[c & 0xff] & AM_CATTR_XDIGIT)
473 #define am_util_string_tolower(c)       ((am_cattr[c & 0xff] & AM_CATTR_UPPER) ? c | 0x20 : c)
474 #define am_util_string_toupper(c)       ((am_cattr[c & 0xff] & AM_CATTR_LOWER) ? c & ~0x20 : c)
475 #endif // MINIMIZE_CATTR_TABLE
476 
477 #define am_util_string_isfilenm83(c)    (am_cattr[c & 0xff] & AM_CATTR_FILENM83)
478 #endif // AM_UTIL_STRING_CTYPE_DISABLE_MACROS
479 
480 #ifdef __cplusplus
481 }
482 #endif
483 
484 #endif // AM_UTIL_STRING_H
485 
486 //*****************************************************************************
487 //
488 // End Doxygen group.
489 //! @}
490 //
491 //*****************************************************************************
492 
493