mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-26 17:08:25 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			171 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package mahonia
 | |
| 
 | |
| import (
 | |
| 	"unicode/utf16"
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	for i := 0; i < len(utf16Charsets); i++ {
 | |
| 		RegisterCharset(&utf16Charsets[i])
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var utf16Charsets = []Charset{
 | |
| 	{
 | |
| 		Name: "UTF-16",
 | |
| 		NewDecoder: func() Decoder {
 | |
| 			var decodeRune Decoder
 | |
| 			return func(p []byte) (c rune, size int, status Status) {
 | |
| 				if decodeRune == nil {
 | |
| 					// haven't read the BOM yet
 | |
| 					if len(p) < 2 {
 | |
| 						status = NO_ROOM
 | |
| 						return
 | |
| 					}
 | |
| 
 | |
| 					switch {
 | |
| 					case p[0] == 0xfe && p[1] == 0xff:
 | |
| 						decodeRune = decodeUTF16beRune
 | |
| 						return 0, 2, STATE_ONLY
 | |
| 					case p[0] == 0xff && p[1] == 0xfe:
 | |
| 						decodeRune = decodeUTF16leRune
 | |
| 						return 0, 2, STATE_ONLY
 | |
| 					default:
 | |
| 						decodeRune = decodeUTF16beRune
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return decodeRune(p)
 | |
| 			}
 | |
| 		},
 | |
| 		NewEncoder: func() Encoder {
 | |
| 			wroteBOM := false
 | |
| 			return func(p []byte, c rune) (size int, status Status) {
 | |
| 				if !wroteBOM {
 | |
| 					if len(p) < 2 {
 | |
| 						status = NO_ROOM
 | |
| 						return
 | |
| 					}
 | |
| 
 | |
| 					p[0] = 0xfe
 | |
| 					p[1] = 0xff
 | |
| 					wroteBOM = true
 | |
| 					return 2, STATE_ONLY
 | |
| 				}
 | |
| 
 | |
| 				return encodeUTF16beRune(p, c)
 | |
| 			}
 | |
| 		},
 | |
| 	},
 | |
| 	{
 | |
| 		Name:       "UTF-16BE",
 | |
| 		NewDecoder: func() Decoder { return decodeUTF16beRune },
 | |
| 		NewEncoder: func() Encoder { return encodeUTF16beRune },
 | |
| 	},
 | |
| 	{
 | |
| 		Name:       "UTF-16LE",
 | |
| 		NewDecoder: func() Decoder { return decodeUTF16leRune },
 | |
| 		NewEncoder: func() Encoder { return encodeUTF16leRune },
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func decodeUTF16beRune(p []byte) (r rune, size int, status Status) {
 | |
| 	if len(p) < 2 {
 | |
| 		status = NO_ROOM
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c := rune(p[0])<<8 + rune(p[1])
 | |
| 
 | |
| 	if utf16.IsSurrogate(c) {
 | |
| 		if len(p) < 4 {
 | |
| 			status = NO_ROOM
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		c2 := rune(p[2])<<8 + rune(p[3])
 | |
| 		c = utf16.DecodeRune(c, c2)
 | |
| 
 | |
| 		if c == 0xfffd {
 | |
| 			return c, 2, INVALID_CHAR
 | |
| 		} else {
 | |
| 			return c, 4, SUCCESS
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return c, 2, SUCCESS
 | |
| }
 | |
| 
 | |
| func encodeUTF16beRune(p []byte, c rune) (size int, status Status) {
 | |
| 	if c < 0x10000 {
 | |
| 		if len(p) < 2 {
 | |
| 			status = NO_ROOM
 | |
| 			return
 | |
| 		}
 | |
| 		p[0] = byte(c >> 8)
 | |
| 		p[1] = byte(c)
 | |
| 		return 2, SUCCESS
 | |
| 	}
 | |
| 
 | |
| 	if len(p) < 4 {
 | |
| 		status = NO_ROOM
 | |
| 		return
 | |
| 	}
 | |
| 	s1, s2 := utf16.EncodeRune(c)
 | |
| 	p[0] = byte(s1 >> 8)
 | |
| 	p[1] = byte(s1)
 | |
| 	p[2] = byte(s2 >> 8)
 | |
| 	p[3] = byte(s2)
 | |
| 	return 4, SUCCESS
 | |
| }
 | |
| 
 | |
| func decodeUTF16leRune(p []byte) (r rune, size int, status Status) {
 | |
| 	if len(p) < 2 {
 | |
| 		status = NO_ROOM
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	c := rune(p[1])<<8 + rune(p[0])
 | |
| 
 | |
| 	if utf16.IsSurrogate(c) {
 | |
| 		if len(p) < 4 {
 | |
| 			status = NO_ROOM
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		c2 := rune(p[3])<<8 + rune(p[2])
 | |
| 		c = utf16.DecodeRune(c, c2)
 | |
| 
 | |
| 		if c == 0xfffd {
 | |
| 			return c, 2, INVALID_CHAR
 | |
| 		} else {
 | |
| 			return c, 4, SUCCESS
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return c, 2, SUCCESS
 | |
| }
 | |
| 
 | |
| func encodeUTF16leRune(p []byte, c rune) (size int, status Status) {
 | |
| 	if c < 0x10000 {
 | |
| 		if len(p) < 2 {
 | |
| 			status = NO_ROOM
 | |
| 			return
 | |
| 		}
 | |
| 		p[1] = byte(c >> 8)
 | |
| 		p[0] = byte(c)
 | |
| 		return 2, SUCCESS
 | |
| 	}
 | |
| 
 | |
| 	if len(p) < 4 {
 | |
| 		status = NO_ROOM
 | |
| 		return
 | |
| 	}
 | |
| 	s1, s2 := utf16.EncodeRune(c)
 | |
| 	p[1] = byte(s1 >> 8)
 | |
| 	p[0] = byte(s1)
 | |
| 	p[3] = byte(s2 >> 8)
 | |
| 	p[2] = byte(s2)
 | |
| 	return 4, SUCCESS
 | |
| }
 |