• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *    * Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *    * Redistributions in binary form must reproduce the above
10  *      copyright notice, this list of conditions and the following
11  *      disclaimer in the documentation and/or other materials provided
12  *      with the distribution.
13  *    * Neither the name of The Linux Foundation nor the names of its
14  *      contributors may be used to endorse or promote products derived
15  *      from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31 =======================================================================
32 
33 FILE:         std.c
34 
35 SERVICES:     apiOne std lib string stuff
36 
37 =======================================================================
38 */
39 
40 //
41 // someday, drop this #include, implement our own memmove()
42 //
43 #include <stddef.h>
44 #include "AEEstd.h"
45 #include "version.h"
46 
std_getversion(char * pcDst,int nDestSize)47 int  std_getversion(char *pcDst, int nDestSize)
48 {
49    return std_strlcpy(pcDst, VERSION_STRING, nDestSize);
50 }
51 
52 
std_tolower(char c)53 char std_tolower(char c)
54 {
55    if ((c >= 'A') && (c <= 'Z')) {
56       c |= 32;
57    }
58    return c;
59 }
60 
std_toupper(char c)61 char std_toupper(char c)
62 {
63    if ((c >= 'a') && (c <= 'z')) {
64       c &= ~32;
65    }
66    return c;
67 }
68 
69 
x_casecmp(unsigned char c1,unsigned char c2)70 static __inline int x_casecmp(unsigned char c1, unsigned char c2)
71 {
72    int diff = c1 - c2;
73    if (c1 >= 'A' && c1 <= 'Z') {
74       diff += 32;
75    }
76    if (c2 >= 'A' && c2 <= 'Z') {
77       diff -= 32;
78    }
79    return diff;
80 }
81 
82 
std_strncmp(const char * s1,const char * s2,int n)83 int std_strncmp(const char* s1, const char* s2, int n)
84 {
85    if (n > 0) {
86       int i = 0;
87 
88       do {
89          unsigned char c1 = (unsigned char)s1[i];
90          unsigned char c2 = (unsigned char)s2[i];
91          int  diff = c1 - c2;
92 
93          if (diff) {
94             return diff;
95          }
96 
97          if ('\0' == c1) {
98             break;
99          }
100          i++;
101       } while (i < n);
102    }
103 
104    return 0;
105 }
106 
std_strcmp(const char * s1,const char * s2)107 int std_strcmp(const char* s1, const char* s2)
108 {
109    return std_strncmp(s1, s2, MAX_INT32);
110 }
111 
std_strnicmp(const char * s1,const char * s2,int n)112 int std_strnicmp(const char* s1, const char* s2, int n)
113 {
114    if (n > 0) {
115       int i = -n;
116 
117       s1 += n;
118       s2 += n;
119 
120       do {
121          unsigned char c1 = (unsigned char)s1[i];
122          unsigned char c2 = (unsigned char)s2[i];
123 
124          int diff = x_casecmp(c1,c2);
125          if (diff) {
126             return diff;
127          }
128          if ('\0' == c1) {
129             break;
130          }
131       } while (++i);
132    }
133    return 0;
134 }
135 
std_stricmp(const char * s1,const char * s2)136 int std_stricmp(const char* s1, const char* s2)
137 {
138    return std_strnicmp(s1, s2, MAX_INT32);
139 }
140 
std_strlcpy(char * pcDst,const char * cpszSrc,int nDestSize)141 int std_strlcpy(char* pcDst, const char* cpszSrc, int nDestSize)
142 {
143    int nLen = std_strlen(cpszSrc);
144 
145    if (0 < nDestSize) {
146       int n;
147 
148       n = STD_MIN(nLen, nDestSize - 1);
149       (void)std_memmove(pcDst, cpszSrc, n);
150 
151       pcDst[n] = 0;
152    }
153 
154    return nLen;
155 }
156 
std_strlcat(char * pcDst,const char * cpszSrc,int nDestSize)157 int std_strlcat(char* pcDst, const char* cpszSrc, int nDestSize)
158 {
159    int nLen = 0;
160 
161    while ((nLen < nDestSize) && (0 != pcDst[nLen])) {
162       ++nLen;
163    }
164 
165    return nLen + std_strlcpy(pcDst+nLen, cpszSrc, nDestSize-nLen);
166 }
167 
std_strstr(const char * cpszHaystack,const char * cpszNeedle)168 char* std_strstr(const char* cpszHaystack, const char* cpszNeedle)
169 {
170    /* Check the empty needle string as a special case */
171    if ('\0' == *cpszNeedle ) {
172       return (char*)cpszHaystack;
173    }
174 
175    while ('\0' != *cpszHaystack) {
176       /* Find the first character of the needle string in the haystack string */
177       if (*cpszHaystack == *cpszNeedle) {
178          /* check if the rest of the string matches */
179          const char* pHaystack = cpszHaystack;
180          const char* pNeedle = cpszNeedle;
181          do {
182             if ('\0' == *++pNeedle) {
183                /* Found a match */
184                return (char*)cpszHaystack;
185             }
186          } while (*++pHaystack == *pNeedle);
187       }
188       cpszHaystack++;
189    }
190 
191    return 0;
192 }
193 
194 
std_memcmp(const void * p1,const void * p2,int length)195 int std_memcmp(const void* p1, const void* p2, int length)
196 {
197    const unsigned char *cpc1 = p1;
198    const unsigned char *cpc2 = p2;
199 
200    while (length-- > 0) {
201       int diff = *cpc1++ - *cpc2++;
202 
203       if (0 != diff) {
204          return diff;
205       }
206    }
207    return 0;
208 }
209 
std_wstrlen(const AECHAR * s)210 int std_wstrlen(const AECHAR* s)
211 {
212    const AECHAR *sEnd = s;
213 
214    if (! *sEnd)
215       return 0;
216 
217    do {
218       ++sEnd;
219    } while (*sEnd);
220 
221    return sEnd - s;
222 }
223 
224 
std_wstrlcpy(AECHAR * pwcDst,const AECHAR * cpwszSrc,int nDestSize)225 int std_wstrlcpy(AECHAR* pwcDst, const AECHAR* cpwszSrc, int nDestSize)
226 {
227    int nLen = std_wstrlen(cpwszSrc);
228 
229    if (0 < nDestSize) {
230       int n;
231 
232       n = STD_MIN(nLen, nDestSize - 1);
233       /* call memmove, in case n is larger than 1G */
234       (void)std_memsmove(pwcDst, nDestSize*sizeof(AECHAR),
235                      cpwszSrc, ((size_t)n)*sizeof(AECHAR));
236 
237       pwcDst[n] = 0;
238    }
239 
240    return nLen;
241 }
242 
std_wstrlcat(AECHAR * pwcDst,const AECHAR * cpwszSrc,int nDestSize)243 int std_wstrlcat(AECHAR* pwcDst, const AECHAR* cpwszSrc, int nDestSize)
244 {
245    int nLen = 0;
246 
247    while ((nLen < nDestSize) && (0 != pwcDst[nLen])) {
248       ++nLen;
249    }
250 
251    return nLen + std_wstrlcpy(pwcDst+nLen, cpwszSrc, nDestSize-nLen);
252 }
253 
std_strchrend(const char * cpsz,char c)254 char* std_strchrend(const char* cpsz, char c)
255 {
256    while (*cpsz && *cpsz != c) {
257       ++cpsz;
258    }
259    return (char*)cpsz;
260 }
261 
std_strchr(const char * cpszSrch,int c)262 char* std_strchr(const char* cpszSrch, int c)
263 {
264    const char *pc = std_strchrend(cpszSrch, (char)c);
265 
266    return (*pc == c ? (char*)pc : 0);
267 }
268 
std_memstr(const char * cpHaystack,const char * cpszNeedle,int nHaystackLen)269 void* std_memstr(const char* cpHaystack, const char* cpszNeedle,
270                  int nHaystackLen)
271 {
272    int nLen = 0;
273 
274    /* Handle empty needle string as a special case */
275    if ('\0' == *cpszNeedle ) {
276       return (char*)cpHaystack;
277    }
278 
279    /* Find the first character of the needle string in the haystack string */
280    while (nLen < nHaystackLen) {
281       if (cpHaystack[nLen] == *cpszNeedle) {
282          /* check if the rest of the string matches */
283          const char* cpNeedle = cpszNeedle;
284          int nRetIndex = nLen;
285          do {
286             if ('\0' == *++cpNeedle) {
287                /* Found a match */
288                return (void*)(cpHaystack + nRetIndex);
289             }
290             nLen++;
291          } while(cpHaystack[nLen] == *cpNeedle);
292       }
293       else {
294          nLen++;
295       }
296    }
297 
298    return 0;
299 }
300 
std_memchrend(const void * p,int c,int nLen)301 void* std_memchrend(const void* p, int c, int nLen)
302 {
303    const char* cpc = (const char*)p + nLen;
304    int i = -nLen;
305 
306    if (nLen > 0) {
307       do {
308          if (cpc[i] == c) {
309             break;
310          }
311       } while (++i);
312    }
313    return (void*) (cpc + i);
314 }
315 
std_memchr(const void * s,int c,int n)316 void* std_memchr(const void* s, int c, int n)
317 {
318    const char *pEnd = (const char*)std_memchrend(s,c,n);
319    int nEnd = pEnd - (const char*)s;
320 
321    if (nEnd < n) {
322       return (void*)pEnd;
323    }
324    return 0;
325 }
326 
std_memrchr(const void * p,int c,int nLen)327 void* std_memrchr(const void* p, int c, int nLen)
328 {
329    const char* cpc = (const char*)p - 1;
330 
331    if (nLen > 0) {
332       do {
333          if (cpc[nLen] == c) {
334             return (void*) (cpc + nLen);
335          }
336       } while (--nLen);
337    }
338 
339    return 0;
340 }
341 
342 
std_strrchr(const char * cpsz,int c)343 char* std_strrchr(const char* cpsz, int c)
344 {
345    return std_memrchr(cpsz, c, std_strlen(cpsz) + 1);
346 }
347 
348 
std_memrchrbegin(const void * p,int c,int n)349 void* std_memrchrbegin(const void* p, int c, int n)
350 {
351    void *pOut = std_memrchr(p, c, n);
352 
353    return (pOut ? pOut : (void*)p);
354 }
355 
356 
357 // x_scanbytes: internal function;  WARNING:  nLen must be >0
358 //
359 // cStop = character at which to stop (in addition to cpszChars[...])
360 //
361 // Using a bit mask provides a constant-time check for a terminating
362 // character: 10 instructions for inner loop on ADS12arm9.  Initialization
363 // overhead is increased, but this is quickly made up for as searching begins.
364 //
365 //
x_scanbytes(const char * pcBuf,const char * cpszChars,int nLen,unsigned char cStop,boolean bTestEqual)366 static char *x_scanbytes(const char *pcBuf, const char* cpszChars,
367                          int nLen, unsigned char cStop, boolean bTestEqual)
368 {
369    int n;
370    unsigned a[8];
371 
372    // Initialize bit mask based on the input flag that specifies whether
373    // we are looking for a character that matches "any" or "none"
374    // of the characters in the search string
375 
376    #define ENTRY(c)   a[((c)&7)]   // c's bit lives here
377    #define SHIFT(c)   ((c)>>3)     // c's bit is shifted by this much
378 
379    if (bTestEqual) {
380       std_memset(a, 0, STD_SIZEOF(a));
381       do {
382          ENTRY(cStop) |= (0x80000000U >> SHIFT(cStop));
383          cStop = (unsigned char)*cpszChars++;
384       } while (cStop);
385    }
386    else {
387       std_memset(a, 0xFF, STD_SIZEOF(a));
388 
389       while (0 != (cStop = (unsigned char)*cpszChars++)) {
390          ENTRY(cStop) ^= (0x80000000U >> SHIFT(cStop));
391       }
392    }
393 
394 
395    // Search buffer
396 
397    pcBuf += nLen;
398    n = -nLen;
399    do {
400       unsigned char uc = (unsigned char)pcBuf[n];
401       // testing for negative after shift is quicker than comparison
402       if ( (int)(ENTRY(uc) << SHIFT(uc)) < 0) {
403          break;
404       }
405    } while (++n);
406 
407    return (char*)(pcBuf+n);
408 }
409 
410 
std_memchrsend(const void * pBuf,const char * cpszChars,int nLen)411 void* std_memchrsend(const void* pBuf, const char* cpszChars, int nLen)
412 {
413    if (nLen <= 0) {
414       return (void*)pBuf;
415    }
416    if ('\0' == *cpszChars) {
417       return (char*)pBuf + nLen;
418    }
419 
420    return x_scanbytes((const char*)pBuf, cpszChars+1, nLen,
421                       (unsigned char)*cpszChars, TRUE);
422 }
423 
424 
std_strchrsend(const char * cpszSrch,const char * cpszChars)425 char* std_strchrsend(const char* cpszSrch, const char* cpszChars)
426 {
427    return x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', TRUE);
428 }
429 
430 
std_strchrs(const char * cpszSrch,const char * cpszChars)431 char *std_strchrs(const char* cpszSrch, const char* cpszChars)
432 {
433    const char *pc = std_strchrsend(cpszSrch, cpszChars);
434 
435    return (*pc ? (char*)pc : 0);
436 }
437 
438 
std_striends(const char * cpsz,const char * cpszSuffix)439 char* std_striends(const char* cpsz, const char* cpszSuffix)
440 {
441    int nOffset = std_strlen(cpsz) - std_strlen(cpszSuffix);
442 
443    if ((0 <= nOffset) &&
444        (0 == std_stricmp(cpsz+nOffset, cpszSuffix))) {
445 
446       return (char*)(cpsz+nOffset);
447    }
448 
449    return 0;
450 }
451 
452 
std_strends(const char * cpsz,const char * cpszSuffix)453 char* std_strends(const char* cpsz, const char* cpszSuffix)
454 {
455    int nOffset = std_strlen(cpsz) - std_strlen(cpszSuffix);
456 
457    if ((0 <= nOffset) &&
458        (0 == std_strcmp(cpsz+nOffset, cpszSuffix))) {
459 
460       return (char*)(cpsz + nOffset);
461    }
462 
463    return 0;
464 }
465 
std_strbegins(const char * cpsz,const char * cpszPrefix)466 char* std_strbegins(const char* cpsz, const char* cpszPrefix)
467 {
468    for (;;) {
469       if ('\0' == *cpszPrefix) {
470          return (char*)cpsz;
471       }
472 
473       if (*cpszPrefix != *cpsz) {
474          return 0;
475       }
476 
477       ++cpszPrefix;
478       ++cpsz;
479    }
480    // not reached
481 }
482 
std_stribegins(const char * cpsz,const char * cpszPrefix)483 char* std_stribegins(const char* cpsz, const char* cpszPrefix)
484 {
485    for (;;) {
486       if ('\0' == *cpszPrefix) {
487          return (char*)cpsz;
488       }
489 
490       if (x_casecmp((unsigned char)*cpszPrefix, (unsigned char)*cpsz)) {
491          return 0;
492       }
493 
494       ++cpszPrefix;
495       ++cpsz;
496    }
497    // not reached
498 }
499 
std_strcspn(const char * cpszSrch,const char * cpszChars)500 int std_strcspn(const char* cpszSrch, const char* cpszChars)
501 {
502    const char *pc = x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', TRUE);
503 
504    return (pc - cpszSrch);
505 }
506 
std_strspn(const char * cpszSrch,const char * cpszChars)507 int std_strspn(const char* cpszSrch, const char* cpszChars)
508 {
509    const char *pc = x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', FALSE);
510 
511    return (pc - cpszSrch);
512 }
513 
std_wstrncmp(const AECHAR * s1,const AECHAR * s2,int nLen)514 int std_wstrncmp(const AECHAR* s1, const AECHAR* s2, int nLen)
515 {
516    if (nLen > 0) {
517       int i;
518 
519       s1 += nLen;
520       s2 += nLen;
521       i = -nLen;
522       do {
523          AECHAR c1 = s1[i];
524          AECHAR c2 = s2[i];
525          int  diff = c1 - c2;
526 
527          if (diff) {
528             return diff;
529          }
530 
531          if ('\0' == c1) {
532             break;
533          }
534       } while (++i);
535    }
536 
537    return 0;
538 }
539 
std_wstrcmp(const AECHAR * s1,const AECHAR * s2)540 int std_wstrcmp(const AECHAR* s1, const AECHAR* s2)
541 {
542    return std_wstrncmp(s1, s2, MAX_INT32);
543 }
544 
std_wstrchr(const AECHAR * cpwszText,AECHAR ch)545 AECHAR* std_wstrchr(const AECHAR* cpwszText, AECHAR ch)
546 {
547    for (; ; cpwszText++) {
548       AECHAR chn = *cpwszText;
549 
550       if (chn == ch) {
551          return (AECHAR *)cpwszText;
552       }
553       else if ( chn == (AECHAR)0 ) {
554          return 0;
555       }
556    }
557 }
558 
std_wstrrchr(const AECHAR * cpwszText,AECHAR ch)559 AECHAR* std_wstrrchr(const AECHAR* cpwszText, AECHAR ch)
560 {
561    const AECHAR* p = 0;
562 
563    do {
564       if (*cpwszText == ch) {
565          p = cpwszText;
566       }
567    } while (*cpwszText++ != (AECHAR)0);
568 
569    return (AECHAR*)p;
570 }
571