diff options
| author | Keith Randall <khr@golang.org> | 2014-06-17 00:36:23 -0700 |
|---|---|---|
| committer | Keith Randall <khr@golang.org> | 2014-06-17 00:36:23 -0700 |
| commit | 0f4b53c1c2db3ae7f3ed25ba7e5149baf14fc46c (patch) | |
| tree | 41042f48f85f1a5038404c7a2980619737fe0743 /src/pkg/runtime/string.c | |
| parent | ee8e687874b56f7c3ab1dd5585390b84dc74b14e (diff) | |
| download | go-0f4b53c1c2db3ae7f3ed25ba7e5149baf14fc46c.tar.xz | |
runtime: reconstitute runetochar for use by gostringw.
Fixes windows builds (hopefully).
LGTM=bradfitz
R=golang-codereviews, bradfitz, alex.brainman
CC=golang-codereviews
https://golang.org/cl/103470045
Diffstat (limited to 'src/pkg/runtime/string.c')
| -rw-r--r-- | src/pkg/runtime/string.c | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/src/pkg/runtime/string.c b/src/pkg/runtime/string.c index d5b668bd61..60a0545a9a 100644 --- a/src/pkg/runtime/string.c +++ b/src/pkg/runtime/string.c @@ -100,6 +100,94 @@ runtime·gostringnocopy(byte *str) return s; } +// TODO: move this elsewhere +enum +{ + Bit1 = 7, + Bitx = 6, + Bit2 = 5, + Bit3 = 4, + Bit4 = 3, + Bit5 = 2, + + Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ + T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ + T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ + T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ + + Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ + Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ + Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ + + Maskx = (1<<Bitx)-1, /* 0011 1111 */ + + Runeerror = 0xFFFD, + + SurrogateMin = 0xD800, + SurrogateMax = 0xDFFF, + + Runemax = 0x10FFFF, /* maximum rune value */ +}; + +static int32 +runetochar(byte *str, int32 rune) /* note: in original, arg2 was pointer */ +{ + /* Runes are signed, so convert to unsigned for range check. */ + uint32 c; + + /* + * one character sequence + * 00000-0007F => 00-7F + */ + c = rune; + if(c <= Rune1) { + str[0] = c; + return 1; + } + + /* + * two character sequence + * 0080-07FF => T2 Tx + */ + if(c <= Rune2) { + str[0] = T2 | (c >> 1*Bitx); + str[1] = Tx | (c & Maskx); + return 2; + } + + /* + * If the Rune is out of range or a surrogate half, convert it to the error rune. + * Do this test here because the error rune encodes to three bytes. + * Doing it earlier would duplicate work, since an out of range + * Rune wouldn't have fit in one or two bytes. + */ + if (c > Runemax) + c = Runeerror; + if (SurrogateMin <= c && c <= SurrogateMax) + c = Runeerror; + + /* + * three character sequence + * 0800-FFFF => T3 Tx Tx + */ + if (c <= Rune3) { + str[0] = T3 | (c >> 2*Bitx); + str[1] = Tx | ((c >> 1*Bitx) & Maskx); + str[2] = Tx | (c & Maskx); + return 3; + } + + /* + * four character sequence (21-bit value) + * 10000-1FFFFF => T4 Tx Tx Tx + */ + str[0] = T4 | (c >> 3*Bitx); + str[1] = Tx | ((c >> 2*Bitx) & Maskx); + str[2] = Tx | ((c >> 1*Bitx) & Maskx); + str[3] = Tx | (c & Maskx); + return 4; +} + String runtime·gostringw(uint16 *str) { @@ -109,14 +197,14 @@ runtime·gostringw(uint16 *str) n1 = 0; for(i=0; str[i]; i++) - n1 += runtime·runetochar(buf, str[i]); + n1 += 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]); + n2 += runetochar(s.str+n2, str[i]); } s.len = n2; s.str[s.len] = 0; |
