shithub: purgatorio

ref: df03eca7e7cbfadf1cf8c8c5a94390eaa5013a8b
dir: /appl/lib/convcs/utf16_btos.b/

View raw version
implement Btos;

include "sys.m";
include "convcs.m";

Littleendian, Bigendian: con iota;

sys : Sys;
default := Bigendian;

init(arg : string) : string
{
	sys = load Sys Sys->PATH;
	case arg {
	"le" =>
		default = Littleendian;
	"be" =>
		default = Bigendian;
	}
	return nil;
}


btos(state : Convcs->State, b : array of byte, n : int) : (Convcs->State, string, int)
{
	endian: int;
	i := 0;
	if(state != nil)
		endian = state[0];
	else if (len b >= 2) {
		state = " ";
		# XXX should probably not do this if we've been told the endianness
		case (int b[0] << 8) | int b[1] {
		16rfeff =>
			endian = Bigendian;
			i += 2;
		16rfffe =>
			endian = Littleendian;
			i += 2;
		* =>
			endian = guessendian(b);
		}
		state[0] = endian;
	}
	nb := len b & ~1;
	if(n > 0 && nb - i > n * 2)
		nb = i + n * 2;
	out := "";
	if(endian == Bigendian){
		for(; i < nb; i += 2)
			out[len out] = (int b[i] << 8) | int b[i + 1];
	}else{
		for(; i < nb; i += 2)
			out[len out] = int b[i] | int b[i + 1] << 8;
	}
	if(n == 0 && i < len b)
		out[len out] = Sys->UTFerror;
		
	return (state, out, i);
}

guessendian(nil: array of byte): int
{
	# XXX might be able to do better than this in the absence of endian hints.
	return default;
}