mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-18 12:22:23 +03:00
116 lines
3.4 KiB
Go
116 lines
3.4 KiB
Go
|
// This package is a character-set conversion library for Go.
|
||
|
//
|
||
|
// (DEPRECATED: use code.google.com/p/go.text/encoding, perhaps along with
|
||
|
// code.google.com/p/go.net/html/charset)
|
||
|
package mahonia
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"unicode"
|
||
|
)
|
||
|
|
||
|
// Status is the type for the status return value from a Decoder or Encoder.
|
||
|
type Status int
|
||
|
|
||
|
const (
|
||
|
// SUCCESS means that the character was converted with no problems.
|
||
|
SUCCESS = Status(iota)
|
||
|
|
||
|
// INVALID_CHAR means that the source contained invalid bytes, or that the character
|
||
|
// could not be represented in the destination encoding.
|
||
|
// The Encoder or Decoder should have output a substitute character.
|
||
|
INVALID_CHAR
|
||
|
|
||
|
// NO_ROOM means there were not enough input bytes to form a complete character,
|
||
|
// or there was not enough room in the output buffer to write a complete character.
|
||
|
// No bytes were written, and no internal state was changed in the Encoder or Decoder.
|
||
|
NO_ROOM
|
||
|
|
||
|
// STATE_ONLY means that bytes were read or written indicating a state transition,
|
||
|
// but no actual character was processed. (Examples: byte order marks, ISO-2022 escape sequences)
|
||
|
STATE_ONLY
|
||
|
)
|
||
|
|
||
|
// A Decoder is a function that decodes a character set, one character at a time.
|
||
|
// It works much like utf8.DecodeRune, but has an aditional status return value.
|
||
|
type Decoder func(p []byte) (c rune, size int, status Status)
|
||
|
|
||
|
// An Encoder is a function that encodes a character set, one character at a time.
|
||
|
// It works much like utf8.EncodeRune, but has an additional status return value.
|
||
|
type Encoder func(p []byte, c rune) (size int, status Status)
|
||
|
|
||
|
// A Charset represents a character set that can be converted, and contains functions
|
||
|
// to create Converters to encode and decode strings in that character set.
|
||
|
type Charset struct {
|
||
|
// Name is the character set's canonical name.
|
||
|
Name string
|
||
|
|
||
|
// Aliases returns a list of alternate names.
|
||
|
Aliases []string
|
||
|
|
||
|
// NewDecoder returns a Decoder to convert from the charset to Unicode.
|
||
|
NewDecoder func() Decoder
|
||
|
|
||
|
// NewEncoder returns an Encoder to convert from Unicode to the charset.
|
||
|
NewEncoder func() Encoder
|
||
|
}
|
||
|
|
||
|
// The charsets are stored in charsets under their canonical names.
|
||
|
var charsets = make(map[string]*Charset)
|
||
|
|
||
|
// aliases maps their aliases to their canonical names.
|
||
|
var aliases = make(map[string]string)
|
||
|
|
||
|
// simplifyName converts a name to lower case and removes non-alphanumeric characters.
|
||
|
// This is how the names are used as keys to the maps.
|
||
|
func simplifyName(name string) string {
|
||
|
var buf bytes.Buffer
|
||
|
for _, c := range name {
|
||
|
switch {
|
||
|
case unicode.IsDigit(c):
|
||
|
buf.WriteRune(c)
|
||
|
case unicode.IsLetter(c):
|
||
|
buf.WriteRune(unicode.ToLower(c))
|
||
|
default:
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return buf.String()
|
||
|
}
|
||
|
|
||
|
// RegisterCharset adds a charset to the charsetMap.
|
||
|
func RegisterCharset(cs *Charset) {
|
||
|
name := cs.Name
|
||
|
charsets[name] = cs
|
||
|
aliases[simplifyName(name)] = name
|
||
|
for _, alias := range cs.Aliases {
|
||
|
aliases[simplifyName(alias)] = name
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// GetCharset fetches a charset by name.
|
||
|
// If the name is not found, it returns nil.
|
||
|
func GetCharset(name string) *Charset {
|
||
|
return charsets[aliases[simplifyName(name)]]
|
||
|
}
|
||
|
|
||
|
// NewDecoder returns a Decoder to decode the named charset.
|
||
|
// If the name is not found, it returns nil.
|
||
|
func NewDecoder(name string) Decoder {
|
||
|
cs := GetCharset(name)
|
||
|
if cs == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return cs.NewDecoder()
|
||
|
}
|
||
|
|
||
|
// NewEncoder returns an Encoder to encode the named charset.
|
||
|
func NewEncoder(name string) Encoder {
|
||
|
cs := GetCharset(name)
|
||
|
if cs == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return cs.NewEncoder()
|
||
|
}
|