github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/dist/buf.c (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Byte buffers and string vectors. 6 7 #include "a.h" 8 9 // binit prepares an uninitialized buffer for use. 10 void 11 binit(Buf *b) 12 { 13 b->p = nil; 14 b->len = 0; 15 b->cap = 0; 16 } 17 18 // breset truncates the buffer back to zero length. 19 void 20 breset(Buf *b) 21 { 22 b->len = 0; 23 } 24 25 // bfree frees the storage associated with a buffer. 26 void 27 bfree(Buf *b) 28 { 29 xfree(b->p); 30 binit(b); 31 } 32 33 // bgrow ensures that the buffer has at least n more bytes 34 // between its len and cap. 35 void 36 bgrow(Buf *b, int n) 37 { 38 int want; 39 40 want = b->len+n; 41 if(want > b->cap) { 42 b->cap = 2*want; 43 if(b->cap < 64) 44 b->cap = 64; 45 b->p = xrealloc(b->p, b->cap); 46 } 47 } 48 49 // bwrite appends the n bytes at v to the buffer. 50 void 51 bwrite(Buf *b, void *v, int n) 52 { 53 bgrow(b, n); 54 xmemmove(b->p+b->len, v, n); 55 b->len += n; 56 } 57 58 // bwritestr appends the string p to the buffer. 59 void 60 bwritestr(Buf *b, char *p) 61 { 62 bwrite(b, p, xstrlen(p)); 63 } 64 65 // bstr returns a pointer to a NUL-terminated string of the 66 // buffer contents. The pointer points into the buffer. 67 char* 68 bstr(Buf *b) 69 { 70 bgrow(b, 1); 71 b->p[b->len] = '\0'; 72 return b->p; 73 } 74 75 // btake takes ownership of the string form of the buffer. 76 // After this call, the buffer has zero length and does not 77 // refer to the memory that btake returned. 78 char* 79 btake(Buf *b) 80 { 81 char *p; 82 83 p = bstr(b); 84 binit(b); 85 return p; 86 } 87 88 // bwriteb appends the src buffer to the dst buffer. 89 void 90 bwriteb(Buf *dst, Buf *src) 91 { 92 bwrite(dst, src->p, src->len); 93 } 94 95 // bequal reports whether the buffers have the same content. 96 bool 97 bequal(Buf *s, Buf *t) 98 { 99 return s->len == t->len && xmemcmp(s->p, t->p, s->len) == 0; 100 } 101 102 // bsubst rewites b to replace all occurrences of x with y. 103 void 104 bsubst(Buf *b, char *x, char *y) 105 { 106 char *p; 107 int nx, ny, pos; 108 109 nx = xstrlen(x); 110 ny = xstrlen(y); 111 112 pos = 0; 113 for(;;) { 114 p = xstrstr(bstr(b)+pos, x); 115 if(p == nil) 116 break; 117 if(nx != ny) { 118 if(nx < ny) { 119 pos = p - b->p; 120 bgrow(b, ny-nx); 121 p = b->p + pos; 122 } 123 xmemmove(p+ny, p+nx, (b->p+b->len)-(p+nx)); 124 } 125 xmemmove(p, y, ny); 126 pos = p+ny - b->p; 127 b->len += ny - nx; 128 } 129 } 130 131 // The invariant with the vectors is that v->p[0:v->len] is allocated 132 // strings that are owned by the vector. The data beyond v->len may 133 // be garbage. 134 135 // vinit prepares an uninitialized vector for use. 136 void 137 vinit(Vec *v) 138 { 139 v->p = nil; 140 v->len = 0; 141 v->cap = 0; 142 } 143 144 // vreset truncates the vector back to zero length. 145 void 146 vreset(Vec *v) 147 { 148 int i; 149 150 for(i=0; i<v->len; i++) { 151 xfree(v->p[i]); 152 v->p[i] = nil; 153 } 154 v->len = 0; 155 } 156 157 // vfree frees the storage associated with the vector. 158 void 159 vfree(Vec *v) 160 { 161 vreset(v); 162 xfree(v->p); 163 vinit(v); 164 } 165 166 167 // vgrow ensures that the vector has room for at least 168 // n more entries between len and cap. 169 void 170 vgrow(Vec *v, int n) 171 { 172 int want; 173 174 want = v->len+n; 175 if(want > v->cap) { 176 v->cap = 2*want; 177 if(v->cap < 64) 178 v->cap = 64; 179 v->p = xrealloc(v->p, v->cap*sizeof v->p[0]); 180 } 181 } 182 183 // vcopy copies the srclen strings at src into the vector. 184 void 185 vcopy(Vec *dst, char **src, int srclen) 186 { 187 int i; 188 189 // use vadd, to make copies of strings 190 for(i=0; i<srclen; i++) 191 vadd(dst, src[i]); 192 } 193 194 // vadd adds a copy of the string p to the vector. 195 void 196 vadd(Vec *v, char *p) 197 { 198 vgrow(v, 1); 199 if(p != nil) 200 p = xstrdup(p); 201 v->p[v->len++] = p; 202 } 203 204 // vaddn adds a string consisting of the n bytes at p to the vector. 205 static void 206 vaddn(Vec *v, char *p, int n) 207 { 208 char *q; 209 210 vgrow(v, 1); 211 q = xmalloc(n+1); 212 xmemmove(q, p, n); 213 q[n] = '\0'; 214 v->p[v->len++] = q; 215 } 216 217 static int 218 strpcmp(const void *a, const void *b) 219 { 220 return xstrcmp(*(char**)a, *(char**)b); 221 } 222 223 // vuniq sorts the vector and then discards duplicates, 224 // in the manner of sort | uniq. 225 void 226 vuniq(Vec *v) 227 { 228 int i, n; 229 230 xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp); 231 n = 0; 232 for(i=0; i<v->len; i++) { 233 if(n>0 && streq(v->p[i], v->p[n-1])) 234 xfree(v->p[i]); 235 else 236 v->p[n++] = v->p[i]; 237 } 238 v->len = n; 239 } 240 241 // splitlines replaces the vector v with the result of splitting 242 // the input p after each \n. If there is a \r immediately before 243 // each \n, it will be removed. 244 void 245 splitlines(Vec *v, char *p) 246 { 247 int i; 248 char *start; 249 250 vreset(v); 251 start = p; 252 for(i=0; p[i]; i++) { 253 if((p[i] == '\r' && p[i+1] == '\n') || p[i] == '\n') { 254 vaddn(v, start, (p+i+1)-start); 255 if(p[i] == '\r') { 256 v->p[v->len-1][(p+i)-start] = '\n'; 257 i++; 258 } 259 start = p+i+1; 260 } 261 } 262 if(*start != '\0') 263 vadd(v, start); 264 } 265 266 // splitfields replaces the vector v with the result of splitting 267 // the input p into non-empty fields containing no spaces. 268 void 269 splitfields(Vec *v, char *p) 270 { 271 char *start; 272 273 vreset(v); 274 for(;;) { 275 while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') 276 p++; 277 if(*p == '\0') 278 break; 279 start = p; 280 while(*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != '\0') 281 p++; 282 vaddn(v, start, p-start); 283 } 284 }