// Copyright 2009 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.

package runtime
#include "runtime.h"
#include "arch_GOARCH.h"
#include "malloc.h"
#include "race.h"

String	runtime·emptystring;

int32
runtime·findnull(byte *s)
{
	int32 l;

	if(s == nil)
		return 0;
	for(l=0; s[l]!=0; l++)
		;
	return l;
}

int32
runtime·findnullw(uint16 *s)
{
	int32 l;

	if(s == nil)
		return 0;
	for(l=0; s[l]!=0; l++)
		;
	return l;
}

uint32 runtime·maxstring = 256; // a hint for print

static String
gostringsize(intgo l)
{
	String s;
	uint32 ms;

	if(l == 0)
		return runtime·emptystring;
	// leave room for NUL for C runtime (e.g., callers of getenv)
	s.str = runtime·mallocgc(l+1, FlagNoPointers, 1, 0);
	s.len = l;
	s.str[l] = 0;
	for(;;) {
		ms = runtime·maxstring;
		if((uint32)l <= ms || runtime·cas(&runtime·maxstring, ms, (uint32)l))
			break;
	}
	return s;
}

String
runtime·gostring(byte *str)
{
	intgo l;
	String s;

	l = runtime·findnull(str);
	s = gostringsize(l);
	runtime·memmove(s.str, str, l);
	return s;
}

String
runtime·gostringn(byte *str, intgo l)
{
	String s;

	s = gostringsize(l);
	runtime·memmove(s.str, str, l);
	return s;
}

Slice
runtime·gobytes(byte *p, intgo n)
{
	Slice sl;

	sl.array = runtime·mallocgc(n, FlagNoPointers, 1, 0);
	sl.len = n;
	sl.cap = n;
	runtime·memmove(sl.array, p, n);
	return sl;
}

String
runtime·gostringnocopy(byte *str)
{
	String s;
	
	s.str = str;
	s.len = runtime·findnull(str);
	return s;
}

String
runtime·gostringw(uint16 *str)
{
	intgo n1, n2, i;
	byte buf[8];
	String s;

	n1 = 0;
	for(i=0; str[i]; i++)
		n1 += runtime·runetochar(buf, str[i]);
	s = gostringsize(n1+4);
	n2 = 0;
	for(i=0; str[i]; i++) {
		// check for race
		if(n2 >= n1)
			break;
		n2 += runtime·runetochar(s.str+n2, str[i]);
	}
	s.len = n2;
	s.str[s.len] = 0;
	return s;
}

String
runtime·catstring(String s1, String s2)
{
	String s3;

	if(s1.len == 0)
		return s2;
	if(s2.len == 0)
		return s1;

	s3 = gostringsize(s1.len + s2.len);
	runtime·memmove(s3.str, s1.str, s1.len);
	runtime·memmove(s3.str+s1.len, s2.str, s2.len);
	return s3;
}

static String
concatstring(intgo n, String *s)
{
	intgo i, l, count;
	String out;

	l = 0;
	count = 0;
	for(i=0; i<n; i++) {
		if(l + s[i].len < l)
			runtime·throw("string concatenation too long");
		l += s[i].len;
		if(s[i].len > 0) {
			count++;
			out = s[i];
		}
	}
	if(count == 0)
		return runtime·emptystring;
	if(count == 1) // zero or one non-empty string in concatenation
		return out;
	
	out = gostringsize(l);
	l = 0;
	for(i=0; i<n; i++) {
		runtime·memmove(out.str+l, s[i].str, s[i].len);
		l += s[i].len;
	}
	return out;
}

#pragma textflag 7
// s1 is the first of n strings.
// the output string follows.
func concatstring(n int, s1 String) {
	(&s1)[n] = concatstring(n, &s1);
}

static int32
cmpstring(String s1, String s2)
{
	uintgo i, l;
	byte c1, c2;

	l = s1.len;
	if(s2.len < l)
		l = s2.len;
	for(i=0; i<l; i++) {
		c1 = s1.str[i];
		c2 = s2.str[i];
		if(c1 < c2)
			return -1;
		if(c1 > c2)
			return +1;
	}
	if(s1.len < s2.len)
		return -1;
	if(s1.len > s2.len)
		return +1;
	return 0;
}

func cmpstring(s1 String, s2 String) (v int) {
	v = cmpstring(s1, s2);
}

func eqstring(s1 String, s2 String) (v bool) {
	if(s1.len != s2.len) {
		v = false;
		return;
	}
	if(s1.str == s2.str) {
		v = true;
		return;
	}
	v = runtime·memeq(s1.str, s2.str, s1.len);
}

int32
runtime·strcmp(byte *s1, byte *s2)
{
	uintptr i;
	byte c1, c2;

	for(i=0;; i++) {
		c1 = s1[i];
		c2 = s2[i];
		if(c1 < c2)
			return -1;
		if(c1 > c2)
			return +1;
		if(c1 == 0)
			return 0;
	}
}

byte*
runtime·strstr(byte *s1, byte *s2)
{
	byte *sp1, *sp2;

	if(*s2 == 0)
		return s1;
	for(; *s1; s1++) {
		if(*s1 != *s2)
			continue;
		sp1 = s1;
		sp2 = s2;
		for(;;) {
			if(*sp2 == 0)
				return s1;
			if(*sp1++ != *sp2++)
				break;
		}
	}
	return nil;
}

func intstring(v int64) (s String) {
	s = gostringsize(8);
	s.len = runtime·runetochar(s.str, v);
	s.str[s.len] = 0;
}

func slicebytetostring(b Slice) (s String) {
	void *pc;

	if(raceenabled) {
		pc = runtime·getcallerpc(&b);
		runtime·racereadrangepc(b.array, b.len, 1, pc, runtime·slicebytetostring);
	}
	s = gostringsize(b.len);
	runtime·memmove(s.str, b.array, s.len);
}

func stringtoslicebyte(s String) (b Slice) {
	b.array = runtime·mallocgc(s.len, FlagNoPointers, 1, 0);
	b.len = s.len;
	b.cap = s.len;
	runtime·memmove(b.array, s.str, s.len);
}

func slicerunetostring(b Slice) (s String) {
	intgo siz1, siz2, i;
	int32 *a;
	byte dum[8];
	void *pc;

	if(raceenabled) {
		pc = runtime·getcallerpc(&b);
		runtime·racereadrangepc(b.array, b.len*sizeof(*a), sizeof(*a), pc, runtime·slicerunetostring);
	}
	a = (int32*)b.array;
	siz1 = 0;
	for(i=0; i<b.len; i++) {
		siz1 += runtime·runetochar(dum, a[i]);
	}

	s = gostringsize(siz1+4);
	siz2 = 0;
	for(i=0; i<b.len; i++) {
		// check for race
		if(siz2 >= siz1)
			break;
		siz2 += runtime·runetochar(s.str+siz2, a[i]);
	}
	s.len = siz2;
	s.str[s.len] = 0;
}

func stringtoslicerune(s String) (b Slice) {
	intgo n;
	int32 dum, *r;
	uint8 *p, *ep;

	// two passes.
	// unlike slicerunetostring, no race because strings are immutable.
	p = s.str;
	ep = s.str+s.len;
	n = 0;
	while(p < ep) {
		p += runtime·charntorune(&dum, p, ep-p);
		n++;
	}

	b.array = runtime·mallocgc(n*sizeof(r[0]), FlagNoPointers, 1, 0);
	b.len = n;
	b.cap = n;
	p = s.str;
	r = (int32*)b.array;
	while(p < ep)
		p += runtime·charntorune(r++, p, ep-p);
}

enum
{
	Runeself	= 0x80,
};

func stringiter(s String, k int) (retk int) {
	int32 l;

	if(k >= s.len) {
		// retk=0 is end of iteration
		retk = 0;
		goto out;
	}

	l = s.str[k];
	if(l < Runeself) {
		retk = k+1;
		goto out;
	}

	// multi-char rune
	retk = k + runtime·charntorune(&l, s.str+k, s.len-k);

out:
}

func stringiter2(s String, k int) (retk int, retv int32) {
	if(k >= s.len) {
		// retk=0 is end of iteration
		retk = 0;
		retv = 0;
		goto out;
	}

	retv = s.str[k];
	if(retv < Runeself) {
		retk = k+1;
		goto out;
	}

	// multi-char rune
	retk = k + runtime·charntorune(&retv, s.str+k, s.len-k);

out:
}
