]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libc/fmt/fmtquote.c
libc: use MOVP instruction for arm64 memmove() and memset()
[plan9front.git] / sys / src / libc / fmt / fmtquote.c
1 #include <u.h>
2 #include <libc.h>
3 #include "fmtdef.h"
4
5 /*
6  * How many bytes of output UTF will be produced by quoting (if necessary) this string?
7  * How many runes? How much of the input will be consumed?
8  * The parameter q is filled in by _quotesetup.
9  * The string may be UTF or Runes (s or r).
10  * Return count does not include NUL.
11  * Terminate the scan at the first of:
12  *      NUL in input
13  *      count exceeded in input
14  *      count exceeded on output
15  * *ninp is set to number of input bytes accepted.
16  * nin may be <0 initially, to avoid checking input by count.
17  */
18 void
19 _quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
20 {
21         int w;
22         Rune c;
23
24         q->quoted = 0;
25         q->nbytesout = 0;
26         q->nrunesout = 0;
27         q->nbytesin = 0;
28         q->nrunesin = 0;
29         if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
30                 if(nout < 2)
31                         return;
32                 q->quoted = 1;
33                 q->nbytesout = 2;
34                 q->nrunesout = 2;
35         }
36         for(; nin!=0; nin--){
37                 if(s)
38                         w = chartorune(&c, s);
39                 else{
40                         c = *r;
41                         w = runelen(c);
42                 }
43
44                 if(c == '\0')
45                         break;
46                 if(runesout){
47                         if(q->nrunesout+1 > nout)
48                                 break;
49                 }else{
50                         if(q->nbytesout+w > nout)
51                                 break;
52                 }
53
54                 if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){
55                         if(!q->quoted){
56                                 if(runesout){
57                                         if(1+q->nrunesout+1+1 > nout)   /* no room for quotes */
58                                                 break;
59                                 }else{
60                                         if(1+q->nbytesout+w+1 > nout)   /* no room for quotes */
61                                                 break;
62                                 }
63                                 q->nrunesout += 2;      /* include quotes */
64                                 q->nbytesout += 2;      /* include quotes */
65                                 q->quoted = 1;
66                         }
67                         if(c == '\'')   {
68                                 if(runesout){
69                                         if(1+q->nrunesout+1 > nout)     /* no room for quotes */
70                                                 break;
71                                 }else{
72                                         if(1+q->nbytesout+w > nout)     /* no room for quotes */
73                                                 break;
74                                 }
75                                 q->nbytesout++;
76                                 q->nrunesout++; /* quotes reproduce as two characters */
77                         }
78                 }
79
80                 /* advance input */
81                 if(s)
82                         s += w;
83                 else
84                         r++;
85                 q->nbytesin += w;
86                 q->nrunesin++;
87
88                 /* advance output */
89                 q->nbytesout += w;
90                 q->nrunesout++;
91         }
92 }
93
94 static int
95 qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
96 {
97         Rune r, *rm, *rme;
98         char *t, *s, *m, *me;
99         Rune *rt, *rs;
100         ulong fl;
101         int nc, w;
102
103         m = sin;
104         me = m + q->nbytesin;
105         rm = rin;
106         rme = rm + q->nrunesin;
107
108         w = f->width;
109         fl = f->flags;
110         if(f->runes){
111                 if(!(fl & FmtLeft) && _rfmtpad(f, w - q->nrunesout) < 0)
112                         return -1;
113         }else{
114                 if(!(fl & FmtLeft) && _fmtpad(f, w - q->nbytesout) < 0)
115                         return -1;
116         }
117         t = f->to;
118         s = f->stop;
119         rt = f->to;
120         rs = f->stop;
121         if(f->runes)
122                 FMTRCHAR(f, rt, rs, '\'');
123         else
124                 FMTRUNE(f, t, s, '\'');
125         for(nc = q->nrunesin; nc > 0; nc--){
126                 if(sin){
127                         r = *(uchar*)m;
128                         if(r < Runeself)
129                                 m++;
130                         else if((me - m) >= UTFmax || fullrune(m, me-m))
131                                 m += chartorune(&r, m);
132                         else
133                                 break;
134                 }else{
135                         if(rm >= rme)
136                                 break;
137                         r = *(uchar*)rm++;
138                 }
139                 if(f->runes){
140                         FMTRCHAR(f, rt, rs, r);
141                         if(r == '\'')
142                                 FMTRCHAR(f, rt, rs, r);
143                 }else{
144                         FMTRUNE(f, t, s, r);
145                         if(r == '\'')
146                                 FMTRUNE(f, t, s, r);
147                 }
148         }
149
150         if(f->runes){
151                 FMTRCHAR(f, rt, rs, '\'');
152                 USED(rs);
153                 f->nfmt += rt - (Rune *)f->to;
154                 f->to = rt;
155                 if(fl & FmtLeft && _rfmtpad(f, w - q->nrunesout) < 0)
156                         return -1;
157         }else{
158                 FMTRUNE(f, t, s, '\'');
159                 USED(s);
160                 f->nfmt += t - (char *)f->to;
161                 f->to = t;
162                 if(fl & FmtLeft && _fmtpad(f, w - q->nbytesout) < 0)
163                         return -1;
164         }
165         return 0;
166 }
167
168 int
169 _quotestrfmt(int runesin, Fmt *f)
170 {
171         int nin, outlen;
172         Rune *r;
173         char *s;
174         Quoteinfo q;
175
176         nin = -1;
177         if(f->flags&FmtPrec)
178                 nin = f->prec;
179         if(runesin){
180                 r = va_arg(f->args, Rune *);
181                 s = nil;
182         }else{
183                 s = va_arg(f->args, char *);
184                 r = nil;
185         }
186         if(!s && !r)
187                 return _fmtcpy(f, "<nil>", 5, 5);
188
189         if(f->flush)
190                 outlen = 0x7FFFFFFF;    /* if we can flush, no output limit */
191         else if(f->runes)
192                 outlen = (Rune*)f->stop - (Rune*)f->to;
193         else
194                 outlen = (char*)f->stop - (char*)f->to;
195
196         _quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
197 //print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout);
198
199         if(runesin){
200                 if(!q.quoted)
201                         return _fmtrcpy(f, r, q.nrunesin);
202                 return qstrfmt(nil, r, &q, f);
203         }
204
205         if(!q.quoted)
206                 return _fmtcpy(f, s, q.nrunesin, q.nbytesin);
207         return qstrfmt(s, nil, &q, f);
208 }
209
210 int
211 quotestrfmt(Fmt *f)
212 {
213         return _quotestrfmt(0, f);
214 }
215
216 int
217 quoterunestrfmt(Fmt *f)
218 {
219         return _quotestrfmt(1, f);
220 }
221
222 void
223 quotefmtinstall(void)
224 {
225         fmtinstall('q', quotestrfmt);
226         fmtinstall('Q', quoterunestrfmt);
227 }
228
229 int
230 _needsquotes(char *s, int *quotelenp)
231 {
232         Quoteinfo q;
233
234         _quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
235         *quotelenp = q.nbytesout;
236
237         return q.quoted;
238 }
239
240 int
241 _runeneedsquotes(Rune *r, int *quotelenp)
242 {
243         Quoteinfo q;
244
245         _quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
246         *quotelenp = q.nrunesout;
247
248         return q.quoted;
249 }