// 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 "malloc.h"

String	emptystring;

int32
findnull(byte *s)
{
	int32 l;

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

int32
findnullw(uint16 *s)
{
	int32 l;

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

int32 maxstring = 256;

String
gostringsize(int32 l)
{
	String s;

	if(l == 0)
		return emptystring;
	s.str = mal(l+1);	// leave room for NUL for C runtime (e.g., callers of getenv)
	s.len = l;
	if(l > maxstring)
		maxstring = l;
	return s;
}

String
gostring(byte *str)
{
	int32 l;
	String s;

	l = findnull(str);
	s = gostringsize(l);
	mcpy(s.str, str, l);
	return s;
}

String
gostringn(byte *str, int32 l)
{
    String s;

    s = gostringsize(l);
    mcpy(s.str, str, l);
    return s;
}

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

String
gostringw(uint16 *str)
{
	int32 n, i;
	byte buf[8];
	String s;

	n = 0;
	for(i=0; str[i]; i++)
		n += runetochar(buf, str[i]);
	s = gostringsize(n+4);
	n = 0;
	for(i=0; str[i]; i++)
		n += runetochar(s.str+n, str[i]);
	s.len = n;
	return s;
}

String
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);
	mcpy(s3.str, s1.str, s1.len);
	mcpy(s3.str+s1.len, s2.str, s2.len);
	return s3;
}


func catstring(s1 String, s2 String) (s3 String) {
	s3 = catstring(s1, s2);
}

uint32
cmpstring(String s1, String s2)
{
	uint32 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 int32) {
	v = cmpstring(s1, s2);
}

int32
strcmp(byte *s1, byte *s2)
{
	uint32 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;
	}
}

func slicestring(si String, lindex int32, hindex int32) (so String) {
	int32 l;

	if(lindex < 0 || lindex > si.len ||
	   hindex < lindex || hindex > si.len) {
	   	·panicslice();
	}

	l = hindex-lindex;
	so.str = si.str + lindex;
	so.len = l;

//	alternate to create a new string
//	so = gostringsize(l);
//	mcpy(so.str, si.str+lindex, l);
}

func slicestring1(si String, lindex int32) (so String) {
	int32 l;

	if(lindex < 0 || lindex > si.len) {
		·panicslice();
	}

	l = si.len-lindex;
	so.str = si.str + lindex;
	so.len = l;

//	alternate to create a new string
//	so = gostringsize(l);
//	mcpy(so.str, si.str+lindex, l);
}

func indexstring(s String, i int32) (b byte) {
	if(i < 0 || i >= s.len) {
		·panicindex();
	}

	b = s.str[i];
}

func intstring(v int64) (s String) {
	s = gostringsize(8);
	s.len = runetochar(s.str, v);
}

func slicebytetostring(b Slice) (s String) {
	s = gostringsize(b.len);
	mcpy(s.str, b.array, s.len);
}

func stringtoslicebyte(s String) (b Slice) {
	b.array = mallocgc(s.len, RefNoPointers, 1, 1);
	b.len = s.len;
	b.cap = s.len;
	mcpy(b.array, s.str, s.len);
}

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

	a = (int32*)b.array;
	siz1 = 0;
	for(i=0; i<b.len; i++) {
		siz1 += 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 += runetochar(s.str+siz2, a[i]);
	}
	s.len = siz2;
}

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

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

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

enum
{
	Runeself	= 0x80,
};

func stringiter(s String, k int32) (retk int32) {
	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 + charntorune(&l, s.str+k, s.len-k);

out:
}

func stringiter2(s String, k int32) (retk int32, 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 + charntorune(&retv, s.str+k, s.len-k);

out:
}
