// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Byte buffers and string vectors.

#include "a.h"

// binit prepares an uninitialized buffer for use.
void
binit(Buf *b)
{
	b->p = nil;
	b->len = 0;
	b->cap = 0;
}

// breset truncates the buffer back to zero length.
void
breset(Buf *b)
{
	b->len = 0;
}

// bfree frees the storage associated with a buffer.
void
bfree(Buf *b)
{
	xfree(b->p);
	binit(b);
}

// bgrow ensures that the buffer has at least n more bytes
// between its len and cap.
void
bgrow(Buf *b, int n)
{
	int want;
	
	want = b->len+n;
	if(want > b->cap) {
		b->cap = 2*want;
		if(b->cap < 64)
			b->cap = 64;
		b->p = xrealloc(b->p, b->cap);
	}
}

// bwrite appends the n bytes at v to the buffer.
void
bwrite(Buf *b, void *v, int n)
{
	bgrow(b, n);
	xmemmove(b->p+b->len, v, n);
	b->len += n;
}

// bwritestr appends the string p to the buffer.
void
bwritestr(Buf *b, char *p)
{
	bwrite(b, p, xstrlen(p));
}

// bstr returns a pointer to a NUL-terminated string of the
// buffer contents.  The pointer points into the buffer.
char*
bstr(Buf *b)
{
	bgrow(b, 1);
	b->p[b->len] = '\0';
	return b->p;
}

// btake takes ownership of the string form of the buffer.
// After this call, the buffer has zero length and does not
// refer to the memory that btake returned.
char*
btake(Buf *b)
{
	char *p;
	
	p = bstr(b);
	binit(b);
	return p;
}

// bwriteb appends the src buffer to the dst buffer.
void
bwriteb(Buf *dst, Buf *src)
{
	bwrite(dst, src->p, src->len);
}

// bequal reports whether the buffers have the same content.
bool
bequal(Buf *s, Buf *t)
{
	return s->len == t->len && xmemcmp(s->p, t->p, s->len) == 0;
}

// bsubst rewites b to replace all occurrences of x with y.
void
bsubst(Buf *b, char *x, char *y)
{
	char *p;
	int nx, ny, pos;

	nx = xstrlen(x);
	ny = xstrlen(y);

	pos = 0;
	for(;;) {
		p = xstrstr(bstr(b)+pos, x);
		if(p == nil)
			break;
		if(nx != ny) {
			if(nx < ny) {
				pos = p - b->p;
				bgrow(b, ny-nx);
				p = b->p + pos;
			}
			xmemmove(p+ny, p+nx, (b->p+b->len)-(p+nx));
		}
		xmemmove(p, y, ny);
		pos = p+ny - b->p;
		b->len += ny - nx;
	}
}

// The invariant with the vectors is that v->p[0:v->len] is allocated
// strings that are owned by the vector.  The data beyond v->len may
// be garbage.

// vinit prepares an uninitialized vector for use.
void
vinit(Vec *v)
{
	v->p = nil;
	v->len = 0;
	v->cap = 0;
}

// vreset truncates the vector back to zero length.
void
vreset(Vec *v)
{
	int i;
	
	for(i=0; i<v->len; i++) {
		xfree(v->p[i]);
		v->p[i] = nil;
	}
	v->len = 0;
}

// vfree frees the storage associated with the vector.
void
vfree(Vec *v)
{
	vreset(v);
	xfree(v->p);
	vinit(v);
}


// vgrow ensures that the vector has room for at least 
// n more entries between len and cap.
void
vgrow(Vec *v, int n)
{
	int want;
	
	want = v->len+n;
	if(want > v->cap) {
		v->cap = 2*want;
		if(v->cap < 64)
			v->cap = 64;
		v->p = xrealloc(v->p, v->cap*sizeof v->p[0]);
	}
}

// vcopy copies the srclen strings at src into the vector.
void
vcopy(Vec *dst, char **src, int srclen)
{
	int i;
	
	// use vadd, to make copies of strings
	for(i=0; i<srclen; i++)
		vadd(dst, src[i]);
}

// vadd adds a copy of the string p to the vector.
void
vadd(Vec *v, char *p)
{
	vgrow(v, 1);
	if(p != nil)
		p = xstrdup(p);
	v->p[v->len++] = p;
}

// vaddn adds a string consisting of the n bytes at p to the vector.
void
vaddn(Vec *v, char *p, int n)
{
	char *q;

	vgrow(v, 1);
	q = xmalloc(n+1);
	xmemmove(q, p, n);
	q[n] = '\0';
	v->p[v->len++] = q;
}

static int
strpcmp(const void *a, const void *b)
{
	return xstrcmp(*(char**)a, *(char**)b);
}

// vuniq sorts the vector and then discards duplicates,
// in the manner of sort | uniq.
void
vuniq(Vec *v)
{
	int i, n;

	xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp);
	n = 0;
	for(i=0; i<v->len; i++) {
		if(n>0 && streq(v->p[i], v->p[n-1]))
			xfree(v->p[i]);
		else
			v->p[n++] = v->p[i];
	}
	v->len = n;
}

// splitlines replaces the vector v with the result of splitting
// the input p after each \n.
void
splitlines(Vec *v, char *p)
{
	int i;
	char *start;
	
	vreset(v);
	start = p;
	for(i=0; p[i]; i++) {
		if(p[i] == '\n') {
			vaddn(v, start, (p+i+1)-start);
			start = p+i+1;
		}
	}
	if(*start != '\0')
		vadd(v, start);
}

// splitfields replaces the vector v with the result of splitting
// the input p into non-empty fields containing no spaces.
void
splitfields(Vec *v, char *p)
{
	char *start;

	vreset(v);
	for(;;) {
		while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
			p++;
		if(*p == '\0')
			break;
		start = p;
		while(*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != '\0')
			p++;
		vaddn(v, start, p-start);
	}
}
