private string readUtfString()
{
// read two-byte Length
int len1 = r();
int len2 = r();
if ((len1 | len2) < 0) throw IOErr.make("Unexpected end of stream").val;
int utflen = len1 << 8 | len2;
char[] buf = new char[utflen]; // char buffer we read into
int bnum = 0, cnum = 0; // byte count, char count
// read the chars
int c, c2, c3;
while (bnum < utflen)
{
c = r(); bnum++;
if (c < 0) throw IOErr.make("Unexpected end of stream").val;
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
/* 0xxxxxxx*/
buf[cnum++]=(char)c;
break;
case 12: case 13:
/* 110x xxxx 10xx xxxx*/
if (bnum >= utflen) throw IOErr.make("UTF encoding error").val;
c2 = r(); bnum++;
if (c2 < 0) throw IOErr.make("Unexpected end of stream").val;
if ((c2 & 0xC0) != 0x80) throw IOErr.make("UTF encoding error").val;
buf[cnum++]=(char)(((c & 0x1F) << 6) | (c2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
if (bnum+1 >= utflen) throw IOErr.make("UTF encoding error").val;
c2 = r(); bnum++;
c3 = r(); bnum++;
if ((c2|c3) < 0) throw IOErr.make("Unexpected end of stream").val;
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) throw IOErr.make("UTF encoding error").val;
buf[cnum++]=(char)(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw IOErr.make("UTF encoding error").val;
}
}
// allocate as string
return new string(buf, 0, cnum);
}