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