func decode2utf8()

in string.go [345:412]


func decode2utf8(r *bufio.Reader, data []byte, start, end int) (int, int, int, error) {
	var err error

	charCount := 0

	for start < end {
		ch := data[start]
		if ch < 0x80 {
			start++
			charCount++
			continue
		}

		if start+1 == end {
			data[end], err = r.ReadByte()
			if err != nil {
				return start, end, 0, err
			}
			end++
		}

		if (ch & 0xe0) == 0xc0 {
			start += 2
			charCount++
			continue
		}

		if start+2 == end {
			data[end], err = r.ReadByte()
			if err != nil {
				return start, end, 0, err
			}
			end++
		}

		if (ch & 0xf0) == 0xe0 {
			c1 := ((uint32(ch) & 0x0f) << 12) + ((uint32(data[start+1]) & 0x3f) << 6) + (uint32(data[start+2]) & 0x3f)

			if c1 >= 0xD800 && c1 <= 0xDBFF {
				if start+6 >= end {
					_, err = io.ReadFull(r, data[end:start+6])
					if err != nil {
						return start, end, 0, err
					}
					end = start + 6
				}

				c2 := ((uint32(data[start+3]) & 0x0f) << 12) + ((uint32(data[start+4]) & 0x3f) << 6) + (uint32(data[start+5]) & 0x3f)
				c := (c1-0xD800)<<10 + (c2 - 0xDC00) + 0x10000

				n := utf8.EncodeRune(data[start:], rune(c))
				copy(data[start+n:], data[start+6:end])
				start, end = start+n, end-6+n

				charCount += 2
				continue
			}

			start += 3
			charCount++
			continue
		}

		return start, end, 0, fmt.Errorf("bad utf-8 encoding at %x", ch)
	}

	return start, end, charCount, nil
}