1 /*@ Implementation of cs.h: basic tools, like copy etc.
2  *@ TODO ASM optimization hook (like mem tools).
3  *
4  * Copyright (c) 2017 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
5  * SPDX-License-Identifier: ISC
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 #undef su_FILE
20 #define su_FILE su_cs_tools
21 #define su_SOURCE
22 #define su_SOURCE_CS_TOOLS
23 
24 #include "su/code.h"
25 
26 #include "su/cs.h"
27 #include "su/code-in.h"
28 
29 sz
su_cs_cmp(char const * cp1,char const * cp2)30 su_cs_cmp(char const *cp1, char const *cp2){
31    sz rv;
32    NYD_IN;
33    ASSERT_NYD_EXEC(cp1 != NIL, rv = (cp2 == NIL) ? 0 : -1);
34    ASSERT_NYD_EXEC(cp2 != NIL, rv = 1);
35 
36    for(;;){
37       u8 c1, c2;
38 
39       c1 = *cp1++;
40       c2 = *cp2++;
41       if((rv = c1 - c2) != 0 || c1 == '\0')
42          break;
43    }
44    NYD_OU;
45    return rv;
46 }
47 
48 sz
su_cs_cmp_n(char const * cp1,char const * cp2,uz n)49 su_cs_cmp_n(char const *cp1, char const *cp2, uz n){
50    sz rv;
51    NYD_IN;
52    ASSERT_NYD_EXEC(cp1 != NIL, rv = (cp2 == NIL) ? 0 : -1);
53    ASSERT_NYD_EXEC(cp2 != NIL, rv = 1);
54 
55    for(rv = 0; n != 0; --n){
56       u8 c1, c2;
57 
58       c1 = *cp1++;
59       c2 = *cp2++;
60       if((rv = c1 - c2) != 0 || c1 == '\0')
61          break;
62    }
63    NYD_OU;
64    return rv;
65 }
66 
67 char *
su_cs_copy_n(char * dst,char const * src,uz n)68 su_cs_copy_n(char *dst, char const *src, uz n){
69    NYD_IN;
70    ASSERT_NYD(n == 0 || dst != NIL);
71    ASSERT_NYD_EXEC(src != NIL, *dst = '\0');
72 
73    if(LIKELY(n > 0)){
74       char *cp;
75 
76       cp = dst;
77       do if((*cp++ = *src++) == '\0')
78          goto jleave;
79       while(--n > 0);
80       *--cp = '\0';
81    }
82    dst = NIL;
83 jleave:
84    NYD_OU;
85    return dst;
86 }
87 
88 uz
su_cs_len(char const * cp)89 su_cs_len(char const *cp){
90    char const *cp_base;
91    NYD_IN;
92    ASSERT_NYD_EXEC(cp != NIL, cp_base = cp);
93 
94    for(cp_base = cp; *cp != '\0'; ++cp)
95       ;
96    NYD_OU;
97    return P2UZ(cp - cp_base);
98 }
99 
100 char *
su_cs_pcopy(char * dst,char const * src)101 su_cs_pcopy(char *dst, char const *src){
102    NYD_IN;
103    ASSERT_NYD(dst != NIL);
104    ASSERT_NYD_EXEC(src != NIL, *dst = '\0');
105 
106    while((*dst = *src++) != '\0')
107       ++dst;
108    NYD_OU;
109    return dst;
110 }
111 
112 char *
su_cs_pcopy_n(char * dst,char const * src,uz n)113 su_cs_pcopy_n(char *dst, char const *src, uz n){
114    NYD_IN;
115    ASSERT_NYD(n == 0 || dst != NIL);
116    ASSERT_NYD_EXEC(src != NIL, *dst = '\0');
117 
118    if(LIKELY(n > 0)){
119       do{
120          if((*dst = *src++) == '\0')
121             goto jleave;
122          ++dst;
123       }while(--n > 0);
124       *--dst = '\0';
125    }
126    dst = NIL;
127 jleave:
128    NYD_OU;
129    return dst;
130 }
131 
132 char *
su_cs_sep_c(char ** iolist,char sep,boole ignore_empty)133 su_cs_sep_c(char **iolist, char sep, boole ignore_empty){
134    char *base, c, *cp;
135    NYD_IN;
136    ASSERT_NYD_EXEC(iolist != NIL, base = NIL);
137 
138    for(base = *iolist; base != NIL; base = *iolist){
139       /* Skip WS */
140       while((c = *base) != '\0' && su_cs_is_space(c))
141          ++base;
142 
143       if((cp = su_cs_find_c(base, sep)) != NIL)
144          *iolist = &cp[1];
145       else{
146          *iolist = NIL;
147          cp = &base[su_cs_len(base)];
148       }
149 
150       /* Chop WS */
151       while(cp > base && su_cs_is_space(cp[-1]))
152          --cp;
153       *cp = '\0';
154 
155       if(*base != '\0' || !ignore_empty)
156          break;
157    }
158    NYD_OU;
159    return base;
160 }
161 
162 char *
su_cs_sep_escable_c(char ** iolist,char sep,boole ignore_empty)163 su_cs_sep_escable_c(char **iolist, char sep, boole ignore_empty){
164    char *cp, c, *base;
165    boole isesc, anyesc;
166    NYD_IN;
167    ASSERT_NYD_EXEC(iolist != NIL, base = NIL);
168 
169    for(base = *iolist; base != NIL; base = *iolist){
170       /* Skip WS */
171       while((c = *base) != '\0' && su_cs_is_space(c))
172          ++base;
173 
174       /* Do not recognize escaped sep characters, keep track of whether we
175        * have seen any such tuple along the way */
176       for(isesc = anyesc = FAL0, cp = base;; ++cp){
177          if(UNLIKELY((c = *cp) == '\0')){
178             *iolist = NIL;
179             break;
180          }else if(!isesc){
181             if(c == sep){
182                *iolist = &cp[1];
183                break;
184             }
185             isesc = (c == '\\');
186          }else{
187             isesc = FAL0;
188             anyesc |= (c == sep);
189          }
190       }
191 
192       /* Chop WS */
193       while(cp > base && su_cs_is_space(cp[-1]))
194          --cp;
195       *cp = '\0';
196 
197       /* Need to strip reverse solidus escaping sep's? */
198       if(*base != '\0' && anyesc){
199          char *ins;
200 
201          for(ins = cp = base;; ++ins)
202             if((c = *cp) == '\\' && cp[1] == sep){
203                *ins = sep;
204                cp += 2;
205             }else if((*ins = c) == '\0')
206                break;
207             else
208                ++cp;
209       }
210 
211       if(*base != '\0' || !ignore_empty)
212          break;
213    }
214 
215    NYD_OU;
216    return base;
217 }
218 
219 #include "su/code-ou.h"
220 /* s-it-mode */
221