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  }