Update dependencies
This commit is contained in:
parent
bf5616c65b
commit
d6d374b28d
13962 changed files with 48226 additions and 3618880 deletions
162
vendor/golang.org/x/text/cases/cases.go
generated
vendored
162
vendor/golang.org/x/text/cases/cases.go
generated
vendored
|
|
@ -1,162 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go gen_trieval.go
|
||||
|
||||
// Package cases provides general and language-specific case mappers.
|
||||
package cases // import "golang.org/x/text/cases"
|
||||
|
||||
import (
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// References:
|
||||
// - Unicode Reference Manual Chapter 3.13, 4.2, and 5.18.
|
||||
// - http://www.unicode.org/reports/tr29/
|
||||
// - http://www.unicode.org/Public/6.3.0/ucd/CaseFolding.txt
|
||||
// - http://www.unicode.org/Public/6.3.0/ucd/SpecialCasing.txt
|
||||
// - http://www.unicode.org/Public/6.3.0/ucd/DerivedCoreProperties.txt
|
||||
// - http://www.unicode.org/Public/6.3.0/ucd/auxiliary/WordBreakProperty.txt
|
||||
// - http://www.unicode.org/Public/6.3.0/ucd/auxiliary/WordBreakTest.txt
|
||||
// - http://userguide.icu-project.org/transforms/casemappings
|
||||
|
||||
// TODO:
|
||||
// - Case folding
|
||||
// - Wide and Narrow?
|
||||
// - Segmenter option for title casing.
|
||||
// - ASCII fast paths
|
||||
// - Encode Soft-Dotted property within trie somehow.
|
||||
|
||||
// A Caser transforms given input to a certain case. It implements
|
||||
// transform.Transformer.
|
||||
//
|
||||
// A Caser may be stateful and should therefore not be shared between
|
||||
// goroutines.
|
||||
type Caser struct {
|
||||
t transform.SpanningTransformer
|
||||
}
|
||||
|
||||
// Bytes returns a new byte slice with the result of converting b to the case
|
||||
// form implemented by c.
|
||||
func (c Caser) Bytes(b []byte) []byte {
|
||||
b, _, _ = transform.Bytes(c.t, b)
|
||||
return b
|
||||
}
|
||||
|
||||
// String returns a string with the result of transforming s to the case form
|
||||
// implemented by c.
|
||||
func (c Caser) String(s string) string {
|
||||
s, _, _ = transform.String(c.t, s)
|
||||
return s
|
||||
}
|
||||
|
||||
// Reset resets the Caser to be reused for new input after a previous call to
|
||||
// Transform.
|
||||
func (c Caser) Reset() { c.t.Reset() }
|
||||
|
||||
// Transform implements the transform.Transformer interface and transforms the
|
||||
// given input to the case form implemented by c.
|
||||
func (c Caser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
return c.t.Transform(dst, src, atEOF)
|
||||
}
|
||||
|
||||
// Span implements the transform.SpanningTransformer interface.
|
||||
func (c Caser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
return c.t.Span(src, atEOF)
|
||||
}
|
||||
|
||||
// Upper returns a Caser for language-specific uppercasing.
|
||||
func Upper(t language.Tag, opts ...Option) Caser {
|
||||
return Caser{makeUpper(t, getOpts(opts...))}
|
||||
}
|
||||
|
||||
// Lower returns a Caser for language-specific lowercasing.
|
||||
func Lower(t language.Tag, opts ...Option) Caser {
|
||||
return Caser{makeLower(t, getOpts(opts...))}
|
||||
}
|
||||
|
||||
// Title returns a Caser for language-specific title casing. It uses an
|
||||
// approximation of the default Unicode Word Break algorithm.
|
||||
func Title(t language.Tag, opts ...Option) Caser {
|
||||
return Caser{makeTitle(t, getOpts(opts...))}
|
||||
}
|
||||
|
||||
// Fold returns a Caser that implements Unicode case folding. The returned Caser
|
||||
// is stateless and safe to use concurrently by multiple goroutines.
|
||||
//
|
||||
// Case folding does not normalize the input and may not preserve a normal form.
|
||||
// Use the collate or search package for more convenient and linguistically
|
||||
// sound comparisons. Use golang.org/x/text/secure/precis for string comparisons
|
||||
// where security aspects are a concern.
|
||||
func Fold(opts ...Option) Caser {
|
||||
return Caser{makeFold(getOpts(opts...))}
|
||||
}
|
||||
|
||||
// An Option is used to modify the behavior of a Caser.
|
||||
type Option func(o options) options
|
||||
|
||||
// TODO: consider these options to take a boolean as well, like FinalSigma.
|
||||
// The advantage of using this approach is that other providers of a lower-case
|
||||
// algorithm could set different defaults by prefixing a user-provided slice
|
||||
// of options with their own. This is handy, for instance, for the precis
|
||||
// package which would override the default to not handle the Greek final sigma.
|
||||
|
||||
var (
|
||||
// NoLower disables the lowercasing of non-leading letters for a title
|
||||
// caser.
|
||||
NoLower Option = noLower
|
||||
|
||||
// Compact omits mappings in case folding for characters that would grow the
|
||||
// input. (Unimplemented.)
|
||||
Compact Option = compact
|
||||
)
|
||||
|
||||
// TODO: option to preserve a normal form, if applicable?
|
||||
|
||||
type options struct {
|
||||
noLower bool
|
||||
simple bool
|
||||
|
||||
// TODO: segmenter, max ignorable, alternative versions, etc.
|
||||
|
||||
ignoreFinalSigma bool
|
||||
}
|
||||
|
||||
func getOpts(o ...Option) (res options) {
|
||||
for _, f := range o {
|
||||
res = f(res)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func noLower(o options) options {
|
||||
o.noLower = true
|
||||
return o
|
||||
}
|
||||
|
||||
func compact(o options) options {
|
||||
o.simple = true
|
||||
return o
|
||||
}
|
||||
|
||||
// HandleFinalSigma specifies whether the special handling of Greek final sigma
|
||||
// should be enabled. Unicode prescribes handling the Greek final sigma for all
|
||||
// locales, but standards like IDNA and PRECIS override this default.
|
||||
func HandleFinalSigma(enable bool) Option {
|
||||
if enable {
|
||||
return handleFinalSigma
|
||||
}
|
||||
return ignoreFinalSigma
|
||||
}
|
||||
|
||||
func ignoreFinalSigma(o options) options {
|
||||
o.ignoreFinalSigma = true
|
||||
return o
|
||||
}
|
||||
|
||||
func handleFinalSigma(o options) options {
|
||||
o.ignoreFinalSigma = false
|
||||
return o
|
||||
}
|
||||
376
vendor/golang.org/x/text/cases/context.go
generated
vendored
376
vendor/golang.org/x/text/cases/context.go
generated
vendored
|
|
@ -1,376 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
import "golang.org/x/text/transform"
|
||||
|
||||
// A context is used for iterating over source bytes, fetching case info and
|
||||
// writing to a destination buffer.
|
||||
//
|
||||
// Casing operations may need more than one rune of context to decide how a rune
|
||||
// should be cased. Casing implementations should call checkpoint on context
|
||||
// whenever it is known to be safe to return the runes processed so far.
|
||||
//
|
||||
// It is recommended for implementations to not allow for more than 30 case
|
||||
// ignorables as lookahead (analogous to the limit in norm) and to use state if
|
||||
// unbounded lookahead is needed for cased runes.
|
||||
type context struct {
|
||||
dst, src []byte
|
||||
atEOF bool
|
||||
|
||||
pDst int // pDst points past the last written rune in dst.
|
||||
pSrc int // pSrc points to the start of the currently scanned rune.
|
||||
|
||||
// checkpoints safe to return in Transform, where nDst <= pDst and nSrc <= pSrc.
|
||||
nDst, nSrc int
|
||||
err error
|
||||
|
||||
sz int // size of current rune
|
||||
info info // case information of currently scanned rune
|
||||
|
||||
// State preserved across calls to Transform.
|
||||
isMidWord bool // false if next cased letter needs to be title-cased.
|
||||
}
|
||||
|
||||
func (c *context) Reset() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
|
||||
// ret returns the return values for the Transform method. It checks whether
|
||||
// there were insufficient bytes in src to complete and introduces an error
|
||||
// accordingly, if necessary.
|
||||
func (c *context) ret() (nDst, nSrc int, err error) {
|
||||
if c.err != nil || c.nSrc == len(c.src) {
|
||||
return c.nDst, c.nSrc, c.err
|
||||
}
|
||||
// This point is only reached by mappers if there was no short destination
|
||||
// buffer. This means that the source buffer was exhausted and that c.sz was
|
||||
// set to 0 by next.
|
||||
if c.atEOF && c.pSrc == len(c.src) {
|
||||
return c.pDst, c.pSrc, nil
|
||||
}
|
||||
return c.nDst, c.nSrc, transform.ErrShortSrc
|
||||
}
|
||||
|
||||
// retSpan returns the return values for the Span method. It checks whether
|
||||
// there were insufficient bytes in src to complete and introduces an error
|
||||
// accordingly, if necessary.
|
||||
func (c *context) retSpan() (n int, err error) {
|
||||
_, nSrc, err := c.ret()
|
||||
return nSrc, err
|
||||
}
|
||||
|
||||
// checkpoint sets the return value buffer points for Transform to the current
|
||||
// positions.
|
||||
func (c *context) checkpoint() {
|
||||
if c.err == nil {
|
||||
c.nDst, c.nSrc = c.pDst, c.pSrc+c.sz
|
||||
}
|
||||
}
|
||||
|
||||
// unreadRune causes the last rune read by next to be reread on the next
|
||||
// invocation of next. Only one unreadRune may be called after a call to next.
|
||||
func (c *context) unreadRune() {
|
||||
c.sz = 0
|
||||
}
|
||||
|
||||
func (c *context) next() bool {
|
||||
c.pSrc += c.sz
|
||||
if c.pSrc == len(c.src) || c.err != nil {
|
||||
c.info, c.sz = 0, 0
|
||||
return false
|
||||
}
|
||||
v, sz := trie.lookup(c.src[c.pSrc:])
|
||||
c.info, c.sz = info(v), sz
|
||||
if c.sz == 0 {
|
||||
if c.atEOF {
|
||||
// A zero size means we have an incomplete rune. If we are atEOF,
|
||||
// this means it is an illegal rune, which we will consume one
|
||||
// byte at a time.
|
||||
c.sz = 1
|
||||
} else {
|
||||
c.err = transform.ErrShortSrc
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// writeBytes adds bytes to dst.
|
||||
func (c *context) writeBytes(b []byte) bool {
|
||||
if len(c.dst)-c.pDst < len(b) {
|
||||
c.err = transform.ErrShortDst
|
||||
return false
|
||||
}
|
||||
// This loop is faster than using copy.
|
||||
for _, ch := range b {
|
||||
c.dst[c.pDst] = ch
|
||||
c.pDst++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// writeString writes the given string to dst.
|
||||
func (c *context) writeString(s string) bool {
|
||||
if len(c.dst)-c.pDst < len(s) {
|
||||
c.err = transform.ErrShortDst
|
||||
return false
|
||||
}
|
||||
// This loop is faster than using copy.
|
||||
for i := 0; i < len(s); i++ {
|
||||
c.dst[c.pDst] = s[i]
|
||||
c.pDst++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// copy writes the current rune to dst.
|
||||
func (c *context) copy() bool {
|
||||
return c.writeBytes(c.src[c.pSrc : c.pSrc+c.sz])
|
||||
}
|
||||
|
||||
// copyXOR copies the current rune to dst and modifies it by applying the XOR
|
||||
// pattern of the case info. It is the responsibility of the caller to ensure
|
||||
// that this is a rune with a XOR pattern defined.
|
||||
func (c *context) copyXOR() bool {
|
||||
if !c.copy() {
|
||||
return false
|
||||
}
|
||||
if c.info&xorIndexBit == 0 {
|
||||
// Fast path for 6-bit XOR pattern, which covers most cases.
|
||||
c.dst[c.pDst-1] ^= byte(c.info >> xorShift)
|
||||
} else {
|
||||
// Interpret XOR bits as an index.
|
||||
// TODO: test performance for unrolling this loop. Verify that we have
|
||||
// at least two bytes and at most three.
|
||||
idx := c.info >> xorShift
|
||||
for p := c.pDst - 1; ; p-- {
|
||||
c.dst[p] ^= xorData[idx]
|
||||
idx--
|
||||
if xorData[idx] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// hasPrefix returns true if src[pSrc:] starts with the given string.
|
||||
func (c *context) hasPrefix(s string) bool {
|
||||
b := c.src[c.pSrc:]
|
||||
if len(b) < len(s) {
|
||||
return false
|
||||
}
|
||||
for i, c := range b[:len(s)] {
|
||||
if c != s[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// caseType returns an info with only the case bits, normalized to either
|
||||
// cLower, cUpper, cTitle or cUncased.
|
||||
func (c *context) caseType() info {
|
||||
cm := c.info & 0x7
|
||||
if cm < 4 {
|
||||
return cm
|
||||
}
|
||||
if cm >= cXORCase {
|
||||
// xor the last bit of the rune with the case type bits.
|
||||
b := c.src[c.pSrc+c.sz-1]
|
||||
return info(b&1) ^ cm&0x3
|
||||
}
|
||||
if cm == cIgnorableCased {
|
||||
return cLower
|
||||
}
|
||||
return cUncased
|
||||
}
|
||||
|
||||
// lower writes the lowercase version of the current rune to dst.
|
||||
func lower(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cLower {
|
||||
return c.copy()
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
return c.copyXOR()
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
offset := 2 + e[0]&lengthMask // size of header + fold string
|
||||
if nLower := (e[1] >> lengthBits) & lengthMask; nLower != noChange {
|
||||
return c.writeString(e[offset : offset+nLower])
|
||||
}
|
||||
return c.copy()
|
||||
}
|
||||
|
||||
func isLower(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cLower {
|
||||
return true
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
if nLower := (e[1] >> lengthBits) & lengthMask; nLower != noChange {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// upper writes the uppercase version of the current rune to dst.
|
||||
func upper(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cUpper {
|
||||
return c.copy()
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
return c.copyXOR()
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
offset := 2 + e[0]&lengthMask // size of header + fold string
|
||||
// Get length of first special case mapping.
|
||||
n := (e[1] >> lengthBits) & lengthMask
|
||||
if ct == cTitle {
|
||||
// The first special case mapping is for lower. Set n to the second.
|
||||
if n == noChange {
|
||||
n = 0
|
||||
}
|
||||
n, e = e[1]&lengthMask, e[n:]
|
||||
}
|
||||
if n != noChange {
|
||||
return c.writeString(e[offset : offset+n])
|
||||
}
|
||||
return c.copy()
|
||||
}
|
||||
|
||||
// isUpper writes the isUppercase version of the current rune to dst.
|
||||
func isUpper(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cUpper {
|
||||
return true
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
// Get length of first special case mapping.
|
||||
n := (e[1] >> lengthBits) & lengthMask
|
||||
if ct == cTitle {
|
||||
n = e[1] & lengthMask
|
||||
}
|
||||
if n != noChange {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// title writes the title case version of the current rune to dst.
|
||||
func title(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cTitle {
|
||||
return c.copy()
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
if ct == cLower {
|
||||
return c.copyXOR()
|
||||
}
|
||||
return c.copy()
|
||||
}
|
||||
// Get the exception data.
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
offset := 2 + e[0]&lengthMask // size of header + fold string
|
||||
|
||||
nFirst := (e[1] >> lengthBits) & lengthMask
|
||||
if nTitle := e[1] & lengthMask; nTitle != noChange {
|
||||
if nFirst != noChange {
|
||||
e = e[nFirst:]
|
||||
}
|
||||
return c.writeString(e[offset : offset+nTitle])
|
||||
}
|
||||
if ct == cLower && nFirst != noChange {
|
||||
// Use the uppercase version instead.
|
||||
return c.writeString(e[offset : offset+nFirst])
|
||||
}
|
||||
// Already in correct case.
|
||||
return c.copy()
|
||||
}
|
||||
|
||||
// isTitle reports whether the current rune is in title case.
|
||||
func isTitle(c *context) bool {
|
||||
ct := c.caseType()
|
||||
if c.info&hasMappingMask == 0 || ct == cTitle {
|
||||
return true
|
||||
}
|
||||
if c.info&exceptionBit == 0 {
|
||||
if ct == cLower {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// Get the exception data.
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
if nTitle := e[1] & lengthMask; nTitle != noChange {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
nFirst := (e[1] >> lengthBits) & lengthMask
|
||||
if ct == cLower && nFirst != noChange {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// foldFull writes the foldFull version of the current rune to dst.
|
||||
func foldFull(c *context) bool {
|
||||
if c.info&hasMappingMask == 0 {
|
||||
return c.copy()
|
||||
}
|
||||
ct := c.caseType()
|
||||
if c.info&exceptionBit == 0 {
|
||||
if ct != cLower || c.info&inverseFoldBit != 0 {
|
||||
return c.copyXOR()
|
||||
}
|
||||
return c.copy()
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
n := e[0] & lengthMask
|
||||
if n == 0 {
|
||||
if ct == cLower {
|
||||
return c.copy()
|
||||
}
|
||||
n = (e[1] >> lengthBits) & lengthMask
|
||||
}
|
||||
return c.writeString(e[2 : 2+n])
|
||||
}
|
||||
|
||||
// isFoldFull reports whether the current run is mapped to foldFull
|
||||
func isFoldFull(c *context) bool {
|
||||
if c.info&hasMappingMask == 0 {
|
||||
return true
|
||||
}
|
||||
ct := c.caseType()
|
||||
if c.info&exceptionBit == 0 {
|
||||
if ct != cLower || c.info&inverseFoldBit != 0 {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
e := exceptions[c.info>>exceptionShift:]
|
||||
n := e[0] & lengthMask
|
||||
if n == 0 && ct == cLower {
|
||||
return true
|
||||
}
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
438
vendor/golang.org/x/text/cases/context_test.go
generated
vendored
438
vendor/golang.org/x/text/cases/context_test.go
generated
vendored
|
|
@ -1,438 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
"golang.org/x/text/unicode/rangetable"
|
||||
)
|
||||
|
||||
// The following definitions are taken directly from Chapter 3 of The Unicode
|
||||
// Standard.
|
||||
|
||||
func propCased(r rune) bool {
|
||||
return propLower(r) || propUpper(r) || unicode.IsTitle(r)
|
||||
}
|
||||
|
||||
func propLower(r rune) bool {
|
||||
return unicode.IsLower(r) || unicode.Is(unicode.Other_Lowercase, r)
|
||||
}
|
||||
|
||||
func propUpper(r rune) bool {
|
||||
return unicode.IsUpper(r) || unicode.Is(unicode.Other_Uppercase, r)
|
||||
}
|
||||
|
||||
func propIgnore(r rune) bool {
|
||||
if unicode.In(r, unicode.Mn, unicode.Me, unicode.Cf, unicode.Lm, unicode.Sk) {
|
||||
return true
|
||||
}
|
||||
return caseIgnorable[r]
|
||||
}
|
||||
|
||||
func hasBreakProp(r rune) bool {
|
||||
// binary search over ranges
|
||||
lo := 0
|
||||
hi := len(breakProp)
|
||||
for lo < hi {
|
||||
m := lo + (hi-lo)/2
|
||||
bp := &breakProp[m]
|
||||
if bp.lo <= r && r <= bp.hi {
|
||||
return true
|
||||
}
|
||||
if r < bp.lo {
|
||||
hi = m
|
||||
} else {
|
||||
lo = m + 1
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func contextFromRune(r rune) *context {
|
||||
c := context{dst: make([]byte, 128), src: []byte(string(r)), atEOF: true}
|
||||
c.next()
|
||||
return &c
|
||||
}
|
||||
|
||||
func TestCaseProperties(t *testing.T) {
|
||||
if unicode.Version != UnicodeVersion {
|
||||
// Properties of existing code points may change by Unicode version, so
|
||||
// we need to skip.
|
||||
t.Skipf("Skipping as core Unicode version %s different than %s", unicode.Version, UnicodeVersion)
|
||||
}
|
||||
assigned := rangetable.Assigned(UnicodeVersion)
|
||||
coreVersion := rangetable.Assigned(unicode.Version)
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if !unicode.In(r, assigned) || !unicode.In(r, coreVersion) {
|
||||
continue
|
||||
}
|
||||
c := contextFromRune(r)
|
||||
if got, want := c.info.isCaseIgnorable(), propIgnore(r); got != want {
|
||||
t.Errorf("caseIgnorable(%U): got %v; want %v (%x)", r, got, want, c.info)
|
||||
}
|
||||
// New letters may change case types, but existing case pairings should
|
||||
// not change. See Case Pair Stability in
|
||||
// http://unicode.org/policies/stability_policy.html.
|
||||
if rf := unicode.SimpleFold(r); rf != r && unicode.In(rf, assigned) {
|
||||
if got, want := c.info.isCased(), propCased(r); got != want {
|
||||
t.Errorf("cased(%U): got %v; want %v (%x)", r, got, want, c.info)
|
||||
}
|
||||
if got, want := c.caseType() == cUpper, propUpper(r); got != want {
|
||||
t.Errorf("upper(%U): got %v; want %v (%x)", r, got, want, c.info)
|
||||
}
|
||||
if got, want := c.caseType() == cLower, propLower(r); got != want {
|
||||
t.Errorf("lower(%U): got %v; want %v (%x)", r, got, want, c.info)
|
||||
}
|
||||
}
|
||||
if got, want := c.info.isBreak(), hasBreakProp(r); got != want {
|
||||
t.Errorf("isBreak(%U): got %v; want %v (%x)", r, got, want, c.info)
|
||||
}
|
||||
}
|
||||
// TODO: get title case from unicode file.
|
||||
}
|
||||
|
||||
func TestMapping(t *testing.T) {
|
||||
assigned := rangetable.Assigned(UnicodeVersion)
|
||||
coreVersion := rangetable.Assigned(unicode.Version)
|
||||
if coreVersion == nil {
|
||||
coreVersion = assigned
|
||||
}
|
||||
apply := func(r rune, f func(c *context) bool) string {
|
||||
c := contextFromRune(r)
|
||||
f(c)
|
||||
return string(c.dst[:c.pDst])
|
||||
}
|
||||
|
||||
for r, tt := range special {
|
||||
if got, want := apply(r, lower), tt.toLower; got != want {
|
||||
t.Errorf("lowerSpecial:(%U): got %+q; want %+q", r, got, want)
|
||||
}
|
||||
if got, want := apply(r, title), tt.toTitle; got != want {
|
||||
t.Errorf("titleSpecial:(%U): got %+q; want %+q", r, got, want)
|
||||
}
|
||||
if got, want := apply(r, upper), tt.toUpper; got != want {
|
||||
t.Errorf("upperSpecial:(%U): got %+q; want %+q", r, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if !unicode.In(r, assigned) || !unicode.In(r, coreVersion) {
|
||||
continue
|
||||
}
|
||||
if rf := unicode.SimpleFold(r); rf == r || !unicode.In(rf, assigned) {
|
||||
continue
|
||||
}
|
||||
if _, ok := special[r]; ok {
|
||||
continue
|
||||
}
|
||||
want := string(unicode.ToLower(r))
|
||||
if got := apply(r, lower); got != want {
|
||||
t.Errorf("lower:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
|
||||
}
|
||||
|
||||
want = string(unicode.ToUpper(r))
|
||||
if got := apply(r, upper); got != want {
|
||||
t.Errorf("upper:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
|
||||
}
|
||||
|
||||
want = string(unicode.ToTitle(r))
|
||||
if got := apply(r, title); got != want {
|
||||
t.Errorf("title:%q (%U): got %q %U; want %q %U", r, r, got, []rune(got), want, []rune(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func runeFoldData(r rune) (x struct{ simple, full, special string }) {
|
||||
x = foldMap[r]
|
||||
if x.simple == "" {
|
||||
x.simple = string(unicode.ToLower(r))
|
||||
}
|
||||
if x.full == "" {
|
||||
x.full = string(unicode.ToLower(r))
|
||||
}
|
||||
if x.special == "" {
|
||||
x.special = x.full
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestFoldData(t *testing.T) {
|
||||
assigned := rangetable.Assigned(UnicodeVersion)
|
||||
coreVersion := rangetable.Assigned(unicode.Version)
|
||||
if coreVersion == nil {
|
||||
coreVersion = assigned
|
||||
}
|
||||
apply := func(r rune, f func(c *context) bool) (string, info) {
|
||||
c := contextFromRune(r)
|
||||
f(c)
|
||||
return string(c.dst[:c.pDst]), c.info.cccType()
|
||||
}
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if !unicode.In(r, assigned) || !unicode.In(r, coreVersion) {
|
||||
continue
|
||||
}
|
||||
x := runeFoldData(r)
|
||||
if got, info := apply(r, foldFull); got != x.full {
|
||||
t.Errorf("full:%q (%U): got %q %U; want %q %U (ccc=%x)", r, r, got, []rune(got), x.full, []rune(x.full), info)
|
||||
}
|
||||
// TODO: special and simple.
|
||||
}
|
||||
}
|
||||
|
||||
func TestCCC(t *testing.T) {
|
||||
assigned := rangetable.Assigned(UnicodeVersion)
|
||||
normVersion := rangetable.Assigned(norm.Version)
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if !unicode.In(r, assigned) || !unicode.In(r, normVersion) {
|
||||
continue
|
||||
}
|
||||
c := contextFromRune(r)
|
||||
|
||||
p := norm.NFC.PropertiesString(string(r))
|
||||
want := cccOther
|
||||
switch p.CCC() {
|
||||
case 0:
|
||||
want = cccZero
|
||||
case above:
|
||||
want = cccAbove
|
||||
}
|
||||
if got := c.info.cccType(); got != want {
|
||||
t.Errorf("%U: got %x; want %x", r, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWordBreaks(t *testing.T) {
|
||||
for _, tt := range breakTest {
|
||||
testtext.Run(t, tt, func(t *testing.T) {
|
||||
parts := strings.Split(tt, "|")
|
||||
want := ""
|
||||
for _, s := range parts {
|
||||
found := false
|
||||
// This algorithm implements title casing given word breaks
|
||||
// as defined in the Unicode standard 3.13 R3.
|
||||
for _, r := range s {
|
||||
title := unicode.ToTitle(r)
|
||||
lower := unicode.ToLower(r)
|
||||
if !found && title != lower {
|
||||
found = true
|
||||
want += string(title)
|
||||
} else {
|
||||
want += string(lower)
|
||||
}
|
||||
}
|
||||
}
|
||||
src := strings.Join(parts, "")
|
||||
got := Title(language.Und).String(src)
|
||||
if got != want {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContext(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
dstSize int
|
||||
atEOF bool
|
||||
src string
|
||||
out string
|
||||
nSrc int
|
||||
err error
|
||||
ops string
|
||||
prefixArg string
|
||||
prefixWant bool
|
||||
}{{
|
||||
desc: "next: past end, atEOF, no checkpoint",
|
||||
dstSize: 10,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 2,
|
||||
ops: "next;next;next",
|
||||
// Test that calling prefix with a non-empty argument when the buffer
|
||||
// is depleted returns false.
|
||||
prefixArg: "x",
|
||||
prefixWant: false,
|
||||
}, {
|
||||
desc: "next: not at end, atEOF, no checkpoint",
|
||||
dstSize: 10,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortSrc,
|
||||
ops: "next;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "next: past end, !atEOF, no checkpoint",
|
||||
dstSize: 10,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortSrc,
|
||||
ops: "next;next;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "next: past end, !atEOF, checkpoint",
|
||||
dstSize: 10,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 2,
|
||||
ops: "next;next;checkpoint;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "copy: exact count, atEOF, no checkpoint",
|
||||
dstSize: 2,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "12",
|
||||
nSrc: 2,
|
||||
ops: "next;copy;next;copy;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "copy: past end, !atEOF, no checkpoint",
|
||||
dstSize: 2,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortSrc,
|
||||
ops: "next;copy;next;copy;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "copy: past end, !atEOF, checkpoint",
|
||||
dstSize: 2,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "12",
|
||||
nSrc: 2,
|
||||
ops: "next;copy;next;copy;checkpoint;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "copy: short dst",
|
||||
dstSize: 1,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortDst,
|
||||
ops: "next;copy;next;copy;checkpoint;next",
|
||||
prefixArg: "12",
|
||||
prefixWant: false,
|
||||
}, {
|
||||
desc: "copy: short dst, checkpointed",
|
||||
dstSize: 1,
|
||||
atEOF: false,
|
||||
src: "12",
|
||||
out: "1",
|
||||
nSrc: 1,
|
||||
err: transform.ErrShortDst,
|
||||
ops: "next;copy;checkpoint;next;copy;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "writeString: simple",
|
||||
dstSize: 3,
|
||||
atEOF: true,
|
||||
src: "1",
|
||||
out: "1ab",
|
||||
nSrc: 1,
|
||||
ops: "next;copy;writeab;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "writeString: short dst",
|
||||
dstSize: 2,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortDst,
|
||||
ops: "next;copy;writeab;next",
|
||||
prefixArg: "2",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "writeString: simple",
|
||||
dstSize: 3,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "1ab",
|
||||
nSrc: 2,
|
||||
ops: "next;copy;next;writeab;next",
|
||||
prefixArg: "",
|
||||
prefixWant: true,
|
||||
}, {
|
||||
desc: "writeString: short dst",
|
||||
dstSize: 2,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
err: transform.ErrShortDst,
|
||||
ops: "next;copy;next;writeab;next",
|
||||
prefixArg: "1",
|
||||
prefixWant: false,
|
||||
}, {
|
||||
desc: "prefix",
|
||||
dstSize: 2,
|
||||
atEOF: true,
|
||||
src: "12",
|
||||
out: "",
|
||||
nSrc: 0,
|
||||
// Context will assign an ErrShortSrc if the input wasn't exhausted.
|
||||
err: transform.ErrShortSrc,
|
||||
prefixArg: "12",
|
||||
prefixWant: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
c := context{dst: make([]byte, tt.dstSize), src: []byte(tt.src), atEOF: tt.atEOF}
|
||||
|
||||
for _, op := range strings.Split(tt.ops, ";") {
|
||||
switch op {
|
||||
case "next":
|
||||
c.next()
|
||||
case "checkpoint":
|
||||
c.checkpoint()
|
||||
case "writeab":
|
||||
c.writeString("ab")
|
||||
case "copy":
|
||||
c.copy()
|
||||
case "":
|
||||
default:
|
||||
t.Fatalf("unknown op %q", op)
|
||||
}
|
||||
}
|
||||
if got := c.hasPrefix(tt.prefixArg); got != tt.prefixWant {
|
||||
t.Errorf("%s:\nprefix was %v; want %v", tt.desc, got, tt.prefixWant)
|
||||
}
|
||||
nDst, nSrc, err := c.ret()
|
||||
if err != tt.err {
|
||||
t.Errorf("%s:\nerror was %v; want %v", tt.desc, err, tt.err)
|
||||
}
|
||||
if out := string(c.dst[:nDst]); out != tt.out {
|
||||
t.Errorf("%s:\nout was %q; want %q", tt.desc, out, tt.out)
|
||||
}
|
||||
if nSrc != tt.nSrc {
|
||||
t.Errorf("%s:\nnSrc was %d; want %d", tt.desc, nSrc, tt.nSrc)
|
||||
}
|
||||
}
|
||||
}
|
||||
53
vendor/golang.org/x/text/cases/example_test.go
generated
vendored
53
vendor/golang.org/x/text/cases/example_test.go
generated
vendored
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func Example() {
|
||||
src := []string{
|
||||
"hello world!",
|
||||
"i with dot",
|
||||
"'n ijsberg",
|
||||
"here comes O'Brian",
|
||||
}
|
||||
for _, c := range []cases.Caser{
|
||||
cases.Lower(language.Und),
|
||||
cases.Upper(language.Turkish),
|
||||
cases.Title(language.Dutch),
|
||||
cases.Title(language.Und, cases.NoLower),
|
||||
} {
|
||||
fmt.Println()
|
||||
for _, s := range src {
|
||||
fmt.Println(c.String(s))
|
||||
}
|
||||
}
|
||||
|
||||
// Output:
|
||||
// hello world!
|
||||
// i with dot
|
||||
// 'n ijsberg
|
||||
// here comes o'brian
|
||||
//
|
||||
// HELLO WORLD!
|
||||
// İ WİTH DOT
|
||||
// 'N İJSBERG
|
||||
// HERE COMES O'BRİAN
|
||||
//
|
||||
// Hello World!
|
||||
// I With Dot
|
||||
// 'n IJsberg
|
||||
// Here Comes O'brian
|
||||
//
|
||||
// Hello World!
|
||||
// I With Dot
|
||||
// 'N Ijsberg
|
||||
// Here Comes O'Brian
|
||||
}
|
||||
34
vendor/golang.org/x/text/cases/fold.go
generated
vendored
34
vendor/golang.org/x/text/cases/fold.go
generated
vendored
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
import "golang.org/x/text/transform"
|
||||
|
||||
type caseFolder struct{ transform.NopResetter }
|
||||
|
||||
// caseFolder implements the Transformer interface for doing case folding.
|
||||
func (t *caseFolder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
c := context{dst: dst, src: src, atEOF: atEOF}
|
||||
for c.next() {
|
||||
foldFull(&c)
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
func (t *caseFolder) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
c := context{src: src, atEOF: atEOF}
|
||||
for c.next() && isFoldFull(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
func makeFold(o options) transform.SpanningTransformer {
|
||||
// TODO: Special case folding, through option Language, Special/Turkic, or
|
||||
// both.
|
||||
// TODO: Implement Compact options.
|
||||
return &caseFolder{}
|
||||
}
|
||||
51
vendor/golang.org/x/text/cases/fold_test.go
generated
vendored
51
vendor/golang.org/x/text/cases/fold_test.go
generated
vendored
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
)
|
||||
|
||||
var foldTestCases = []string{
|
||||
"βß\u13f8", // "βssᏰ"
|
||||
"ab\u13fc\uab7aꭰ", // abᏴᎪᎠ
|
||||
"affifflast", // affifflast
|
||||
"Iİiı\u0345", // ii̇iıι
|
||||
"µµΜΜςσΣΣ", // μμμμσσσσ
|
||||
}
|
||||
|
||||
func TestFold(t *testing.T) {
|
||||
for _, tc := range foldTestCases {
|
||||
testEntry := func(name string, c Caser, m func(r rune) string) {
|
||||
want := ""
|
||||
for _, r := range tc {
|
||||
want += m(r)
|
||||
}
|
||||
if got := c.String(tc); got != want {
|
||||
t.Errorf("%s(%s) = %+q; want %+q", name, tc, got, want)
|
||||
}
|
||||
dst := make([]byte, 256) // big enough to hold any result
|
||||
src := []byte(tc)
|
||||
v := testtext.AllocsPerRun(20, func() {
|
||||
c.Transform(dst, src, true)
|
||||
})
|
||||
if v > 0 {
|
||||
t.Errorf("%s(%s): number of allocs was %f; want 0", name, tc, v)
|
||||
}
|
||||
}
|
||||
testEntry("FullFold", Fold(), func(r rune) string {
|
||||
return runeFoldData(r).full
|
||||
})
|
||||
// TODO:
|
||||
// testEntry("SimpleFold", Fold(Compact), func(r rune) string {
|
||||
// return runeFoldData(r).simple
|
||||
// })
|
||||
// testEntry("SpecialFold", Fold(Turkic), func(r rune) string {
|
||||
// return runeFoldData(r).special
|
||||
// })
|
||||
}
|
||||
}
|
||||
839
vendor/golang.org/x/text/cases/gen.go
generated
vendored
839
vendor/golang.org/x/text/cases/gen.go
generated
vendored
|
|
@ -1,839 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This program generates the trie for casing operations. The Unicode casing
|
||||
// algorithm requires the lookup of various properties and mappings for each
|
||||
// rune. The table generated by this generator combines several of the most
|
||||
// frequently used of these into a single trie so that they can be accessed
|
||||
// with a single lookup.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/triegen"
|
||||
"golang.org/x/text/internal/ucd"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
genTables()
|
||||
genTablesTest()
|
||||
gen.Repackage("gen_trieval.go", "trieval.go", "cases")
|
||||
}
|
||||
|
||||
// runeInfo contains all information for a rune that we care about for casing
|
||||
// operations.
|
||||
type runeInfo struct {
|
||||
Rune rune
|
||||
|
||||
entry info // trie value for this rune.
|
||||
|
||||
CaseMode info
|
||||
|
||||
// Simple case mappings.
|
||||
Simple [1 + maxCaseMode][]rune
|
||||
|
||||
// Special casing
|
||||
HasSpecial bool
|
||||
Conditional bool
|
||||
Special [1 + maxCaseMode][]rune
|
||||
|
||||
// Folding
|
||||
FoldSimple rune
|
||||
FoldSpecial rune
|
||||
FoldFull []rune
|
||||
|
||||
// TODO: FC_NFKC, or equivalent data.
|
||||
|
||||
// Properties
|
||||
SoftDotted bool
|
||||
CaseIgnorable bool
|
||||
Cased bool
|
||||
DecomposeGreek bool
|
||||
BreakType string
|
||||
BreakCat breakCategory
|
||||
|
||||
// We care mostly about 0, Above, and IotaSubscript.
|
||||
CCC byte
|
||||
}
|
||||
|
||||
type breakCategory int
|
||||
|
||||
const (
|
||||
breakBreak breakCategory = iota
|
||||
breakLetter
|
||||
breakMid
|
||||
)
|
||||
|
||||
// mapping returns the case mapping for the given case type.
|
||||
func (r *runeInfo) mapping(c info) string {
|
||||
if r.HasSpecial {
|
||||
return string(r.Special[c])
|
||||
}
|
||||
if len(r.Simple[c]) != 0 {
|
||||
return string(r.Simple[c])
|
||||
}
|
||||
return string(r.Rune)
|
||||
}
|
||||
|
||||
func parse(file string, f func(p *ucd.Parser)) {
|
||||
ucd.Parse(gen.OpenUCDFile(file), f)
|
||||
}
|
||||
|
||||
func parseUCD() []runeInfo {
|
||||
chars := make([]runeInfo, unicode.MaxRune)
|
||||
|
||||
get := func(r rune) *runeInfo {
|
||||
c := &chars[r]
|
||||
c.Rune = r
|
||||
return c
|
||||
}
|
||||
|
||||
parse("UnicodeData.txt", func(p *ucd.Parser) {
|
||||
ri := get(p.Rune(0))
|
||||
ri.CCC = byte(p.Int(ucd.CanonicalCombiningClass))
|
||||
ri.Simple[cLower] = p.Runes(ucd.SimpleLowercaseMapping)
|
||||
ri.Simple[cUpper] = p.Runes(ucd.SimpleUppercaseMapping)
|
||||
ri.Simple[cTitle] = p.Runes(ucd.SimpleTitlecaseMapping)
|
||||
if p.String(ucd.GeneralCategory) == "Lt" {
|
||||
ri.CaseMode = cTitle
|
||||
}
|
||||
})
|
||||
|
||||
// <code>; <property>
|
||||
parse("PropList.txt", func(p *ucd.Parser) {
|
||||
if p.String(1) == "Soft_Dotted" {
|
||||
chars[p.Rune(0)].SoftDotted = true
|
||||
}
|
||||
})
|
||||
|
||||
// <code>; <word break type>
|
||||
parse("DerivedCoreProperties.txt", func(p *ucd.Parser) {
|
||||
ri := get(p.Rune(0))
|
||||
switch p.String(1) {
|
||||
case "Case_Ignorable":
|
||||
ri.CaseIgnorable = true
|
||||
case "Cased":
|
||||
ri.Cased = true
|
||||
case "Lowercase":
|
||||
ri.CaseMode = cLower
|
||||
case "Uppercase":
|
||||
ri.CaseMode = cUpper
|
||||
}
|
||||
})
|
||||
|
||||
// <code>; <lower> ; <title> ; <upper> ; (<condition_list> ;)?
|
||||
parse("SpecialCasing.txt", func(p *ucd.Parser) {
|
||||
// We drop all conditional special casing and deal with them manually in
|
||||
// the language-specific case mappers. Rune 0x03A3 is the only one with
|
||||
// a conditional formatting that is not language-specific. However,
|
||||
// dealing with this letter is tricky, especially in a streaming
|
||||
// context, so we deal with it in the Caser for Greek specifically.
|
||||
ri := get(p.Rune(0))
|
||||
if p.String(4) == "" {
|
||||
ri.HasSpecial = true
|
||||
ri.Special[cLower] = p.Runes(1)
|
||||
ri.Special[cTitle] = p.Runes(2)
|
||||
ri.Special[cUpper] = p.Runes(3)
|
||||
} else {
|
||||
ri.Conditional = true
|
||||
}
|
||||
})
|
||||
|
||||
// TODO: Use text breaking according to UAX #29.
|
||||
// <code>; <word break type>
|
||||
parse("auxiliary/WordBreakProperty.txt", func(p *ucd.Parser) {
|
||||
ri := get(p.Rune(0))
|
||||
ri.BreakType = p.String(1)
|
||||
|
||||
// We collapse the word breaking properties onto the categories we need.
|
||||
switch p.String(1) { // TODO: officially we need to canonicalize.
|
||||
case "MidLetter", "MidNumLet", "Single_Quote":
|
||||
ri.BreakCat = breakMid
|
||||
if !ri.CaseIgnorable {
|
||||
// finalSigma relies on the fact that all breakMid runes are
|
||||
// also a Case_Ignorable. Revisit this code when this changes.
|
||||
log.Fatalf("Rune %U, which has a break category mid, is not a case ignorable", ri)
|
||||
}
|
||||
case "ALetter", "Hebrew_Letter", "Numeric", "Extend", "ExtendNumLet", "Format", "ZWJ":
|
||||
ri.BreakCat = breakLetter
|
||||
}
|
||||
})
|
||||
|
||||
// <code>; <type>; <mapping>
|
||||
parse("CaseFolding.txt", func(p *ucd.Parser) {
|
||||
ri := get(p.Rune(0))
|
||||
switch p.String(1) {
|
||||
case "C":
|
||||
ri.FoldSimple = p.Rune(2)
|
||||
ri.FoldFull = p.Runes(2)
|
||||
case "S":
|
||||
ri.FoldSimple = p.Rune(2)
|
||||
case "T":
|
||||
ri.FoldSpecial = p.Rune(2)
|
||||
case "F":
|
||||
ri.FoldFull = p.Runes(2)
|
||||
default:
|
||||
log.Fatalf("%U: unknown type: %s", p.Rune(0), p.String(1))
|
||||
}
|
||||
})
|
||||
|
||||
return chars
|
||||
}
|
||||
|
||||
func genTables() {
|
||||
chars := parseUCD()
|
||||
verifyProperties(chars)
|
||||
|
||||
t := triegen.NewTrie("case")
|
||||
for i := range chars {
|
||||
c := &chars[i]
|
||||
makeEntry(c)
|
||||
t.Insert(rune(i), uint64(c.entry))
|
||||
}
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteGoFile("tables.go", "cases")
|
||||
|
||||
gen.WriteUnicodeVersion(w)
|
||||
|
||||
// TODO: write CLDR version after adding a mechanism to detect that the
|
||||
// tables on which the manually created locale-sensitive casing code is
|
||||
// based hasn't changed.
|
||||
|
||||
w.WriteVar("xorData", string(xorData))
|
||||
w.WriteVar("exceptions", string(exceptionData))
|
||||
|
||||
sz, err := t.Gen(w, triegen.Compact(&sparseCompacter{}))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
w.Size += sz
|
||||
}
|
||||
|
||||
func makeEntry(ri *runeInfo) {
|
||||
if ri.CaseIgnorable {
|
||||
if ri.Cased {
|
||||
ri.entry = cIgnorableCased
|
||||
} else {
|
||||
ri.entry = cIgnorableUncased
|
||||
}
|
||||
} else {
|
||||
ri.entry = ri.CaseMode
|
||||
}
|
||||
|
||||
// TODO: handle soft-dotted.
|
||||
|
||||
ccc := cccOther
|
||||
switch ri.CCC {
|
||||
case 0: // Not_Reordered
|
||||
ccc = cccZero
|
||||
case above: // Above
|
||||
ccc = cccAbove
|
||||
}
|
||||
switch ri.BreakCat {
|
||||
case breakBreak:
|
||||
ccc = cccBreak
|
||||
case breakMid:
|
||||
ri.entry |= isMidBit
|
||||
}
|
||||
|
||||
ri.entry |= ccc
|
||||
|
||||
if ri.CaseMode == cUncased {
|
||||
return
|
||||
}
|
||||
|
||||
// Need to do something special.
|
||||
if ri.CaseMode == cTitle || ri.HasSpecial || ri.mapping(cTitle) != ri.mapping(cUpper) {
|
||||
makeException(ri)
|
||||
return
|
||||
}
|
||||
if f := string(ri.FoldFull); len(f) > 0 && f != ri.mapping(cUpper) && f != ri.mapping(cLower) {
|
||||
makeException(ri)
|
||||
return
|
||||
}
|
||||
|
||||
// Rune is either lowercase or uppercase.
|
||||
|
||||
orig := string(ri.Rune)
|
||||
mapped := ""
|
||||
if ri.CaseMode == cUpper {
|
||||
mapped = ri.mapping(cLower)
|
||||
} else {
|
||||
mapped = ri.mapping(cUpper)
|
||||
}
|
||||
|
||||
if len(orig) != len(mapped) {
|
||||
makeException(ri)
|
||||
return
|
||||
}
|
||||
|
||||
if string(ri.FoldFull) == ri.mapping(cUpper) {
|
||||
ri.entry |= inverseFoldBit
|
||||
}
|
||||
|
||||
n := len(orig)
|
||||
|
||||
// Create per-byte XOR mask.
|
||||
var b []byte
|
||||
for i := 0; i < n; i++ {
|
||||
b = append(b, orig[i]^mapped[i])
|
||||
}
|
||||
|
||||
// Remove leading 0 bytes, but keep at least one byte.
|
||||
for ; len(b) > 1 && b[0] == 0; b = b[1:] {
|
||||
}
|
||||
|
||||
if len(b) == 1 && b[0]&0xc0 == 0 {
|
||||
ri.entry |= info(b[0]) << xorShift
|
||||
return
|
||||
}
|
||||
|
||||
key := string(b)
|
||||
x, ok := xorCache[key]
|
||||
if !ok {
|
||||
xorData = append(xorData, 0) // for detecting start of sequence
|
||||
xorData = append(xorData, b...)
|
||||
|
||||
x = len(xorData) - 1
|
||||
xorCache[key] = x
|
||||
}
|
||||
ri.entry |= info(x<<xorShift) | xorIndexBit
|
||||
}
|
||||
|
||||
var xorCache = map[string]int{}
|
||||
|
||||
// xorData contains byte-wise XOR data for the least significant bytes of a
|
||||
// UTF-8 encoded rune. An index points to the last byte. The sequence starts
|
||||
// with a zero terminator.
|
||||
var xorData = []byte{}
|
||||
|
||||
// See the comments in gen_trieval.go re "the exceptions slice".
|
||||
var exceptionData = []byte{0}
|
||||
|
||||
// makeException encodes case mappings that cannot be expressed in a simple
|
||||
// XOR diff.
|
||||
func makeException(ri *runeInfo) {
|
||||
ccc := ri.entry & cccMask
|
||||
// Set exception bit and retain case type.
|
||||
ri.entry &= 0x0007
|
||||
ri.entry |= exceptionBit
|
||||
|
||||
if len(exceptionData) >= 1<<numExceptionBits {
|
||||
log.Fatalf("%U:exceptionData too large %x > %d bits", ri.Rune, len(exceptionData), numExceptionBits)
|
||||
}
|
||||
|
||||
// Set the offset in the exceptionData array.
|
||||
ri.entry |= info(len(exceptionData) << exceptionShift)
|
||||
|
||||
orig := string(ri.Rune)
|
||||
tc := ri.mapping(cTitle)
|
||||
uc := ri.mapping(cUpper)
|
||||
lc := ri.mapping(cLower)
|
||||
ff := string(ri.FoldFull)
|
||||
|
||||
// addString sets the length of a string and adds it to the expansions array.
|
||||
addString := func(s string, b *byte) {
|
||||
if len(s) == 0 {
|
||||
// Zero-length mappings exist, but only for conditional casing,
|
||||
// which we are representing outside of this table.
|
||||
log.Fatalf("%U: has zero-length mapping.", ri.Rune)
|
||||
}
|
||||
*b <<= 3
|
||||
if s != orig {
|
||||
n := len(s)
|
||||
if n > 7 {
|
||||
log.Fatalf("%U: mapping larger than 7 (%d)", ri.Rune, n)
|
||||
}
|
||||
*b |= byte(n)
|
||||
exceptionData = append(exceptionData, s...)
|
||||
}
|
||||
}
|
||||
|
||||
// byte 0:
|
||||
exceptionData = append(exceptionData, byte(ccc)|byte(len(ff)))
|
||||
|
||||
// byte 1:
|
||||
p := len(exceptionData)
|
||||
exceptionData = append(exceptionData, 0)
|
||||
|
||||
if len(ff) > 7 { // May be zero-length.
|
||||
log.Fatalf("%U: fold string larger than 7 (%d)", ri.Rune, len(ff))
|
||||
}
|
||||
exceptionData = append(exceptionData, ff...)
|
||||
ct := ri.CaseMode
|
||||
if ct != cLower {
|
||||
addString(lc, &exceptionData[p])
|
||||
}
|
||||
if ct != cUpper {
|
||||
addString(uc, &exceptionData[p])
|
||||
}
|
||||
if ct != cTitle {
|
||||
// If title is the same as upper, we set it to the original string so
|
||||
// that it will be marked as not present. This implies title case is
|
||||
// the same as upper case.
|
||||
if tc == uc {
|
||||
tc = orig
|
||||
}
|
||||
addString(tc, &exceptionData[p])
|
||||
}
|
||||
}
|
||||
|
||||
// sparseCompacter is a trie value block Compacter. There are many cases where
|
||||
// successive runes alternate between lower- and upper-case. This Compacter
|
||||
// exploits this by adding a special case type where the case value is obtained
|
||||
// from or-ing it with the least-significant bit of the rune, creating large
|
||||
// ranges of equal case values that compress well.
|
||||
type sparseCompacter struct {
|
||||
sparseBlocks [][]uint16
|
||||
sparseOffsets []uint16
|
||||
sparseCount int
|
||||
}
|
||||
|
||||
// makeSparse returns the number of elements that compact block would contain
|
||||
// as well as the modified values.
|
||||
func makeSparse(vals []uint64) ([]uint16, int) {
|
||||
// Copy the values.
|
||||
values := make([]uint16, len(vals))
|
||||
for i, v := range vals {
|
||||
values[i] = uint16(v)
|
||||
}
|
||||
|
||||
alt := func(i int, v uint16) uint16 {
|
||||
if cm := info(v & fullCasedMask); cm == cUpper || cm == cLower {
|
||||
// Convert cLower or cUpper to cXORCase value, which has the form 11x.
|
||||
xor := v
|
||||
xor &^= 1
|
||||
xor |= uint16(i&1) ^ (v & 1)
|
||||
xor |= 0x4
|
||||
return xor
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
var count int
|
||||
var previous uint16
|
||||
for i, v := range values {
|
||||
if v != 0 {
|
||||
// Try if the unmodified value is equal to the previous.
|
||||
if v == previous {
|
||||
continue
|
||||
}
|
||||
|
||||
// Try if the xor-ed value is equal to the previous value.
|
||||
a := alt(i, v)
|
||||
if a == previous {
|
||||
values[i] = a
|
||||
continue
|
||||
}
|
||||
|
||||
// This is a new value.
|
||||
count++
|
||||
|
||||
// Use the xor-ed value if it will be identical to the next value.
|
||||
if p := i + 1; p < len(values) && alt(p, values[p]) == a {
|
||||
values[i] = a
|
||||
v = a
|
||||
}
|
||||
}
|
||||
previous = v
|
||||
}
|
||||
return values, count
|
||||
}
|
||||
|
||||
func (s *sparseCompacter) Size(v []uint64) (int, bool) {
|
||||
_, n := makeSparse(v)
|
||||
|
||||
// We limit using this method to having 16 entries.
|
||||
if n > 16 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return 2 + int(reflect.TypeOf(valueRange{}).Size())*n, true
|
||||
}
|
||||
|
||||
func (s *sparseCompacter) Store(v []uint64) uint32 {
|
||||
h := uint32(len(s.sparseOffsets))
|
||||
values, sz := makeSparse(v)
|
||||
s.sparseBlocks = append(s.sparseBlocks, values)
|
||||
s.sparseOffsets = append(s.sparseOffsets, uint16(s.sparseCount))
|
||||
s.sparseCount += sz
|
||||
return h
|
||||
}
|
||||
|
||||
func (s *sparseCompacter) Handler() string {
|
||||
// The sparse global variable and its lookup method is defined in gen_trieval.go.
|
||||
return "sparse.lookup"
|
||||
}
|
||||
|
||||
func (s *sparseCompacter) Print(w io.Writer) (retErr error) {
|
||||
p := func(format string, args ...interface{}) {
|
||||
_, err := fmt.Fprintf(w, format, args...)
|
||||
if retErr == nil && err != nil {
|
||||
retErr = err
|
||||
}
|
||||
}
|
||||
|
||||
ls := len(s.sparseBlocks)
|
||||
if ls == len(s.sparseOffsets) {
|
||||
s.sparseOffsets = append(s.sparseOffsets, uint16(s.sparseCount))
|
||||
}
|
||||
p("// sparseOffsets: %d entries, %d bytes\n", ls+1, (ls+1)*2)
|
||||
p("var sparseOffsets = %#v\n\n", s.sparseOffsets)
|
||||
|
||||
ns := s.sparseCount
|
||||
p("// sparseValues: %d entries, %d bytes\n", ns, ns*4)
|
||||
p("var sparseValues = [%d]valueRange {", ns)
|
||||
for i, values := range s.sparseBlocks {
|
||||
p("\n// Block %#x, offset %#x", i, s.sparseOffsets[i])
|
||||
var v uint16
|
||||
for i, nv := range values {
|
||||
if nv != v {
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+i-1)
|
||||
}
|
||||
if nv != 0 {
|
||||
p("\n{value:%#04x,lo:%#02x", nv, 0x80+i)
|
||||
}
|
||||
}
|
||||
v = nv
|
||||
}
|
||||
if v != 0 {
|
||||
p(",hi:%#02x},", 0x80+len(values)-1)
|
||||
}
|
||||
}
|
||||
p("\n}\n\n")
|
||||
return
|
||||
}
|
||||
|
||||
// verifyProperties that properties of the runes that are relied upon in the
|
||||
// implementation. Each property is marked with an identifier that is referred
|
||||
// to in the places where it is used.
|
||||
func verifyProperties(chars []runeInfo) {
|
||||
for i, c := range chars {
|
||||
r := rune(i)
|
||||
|
||||
// Rune properties.
|
||||
|
||||
// A.1: modifier never changes on lowercase. [ltLower]
|
||||
if c.CCC > 0 && unicode.ToLower(r) != r {
|
||||
log.Fatalf("%U: non-starter changes when lowercased", r)
|
||||
}
|
||||
|
||||
// A.2: properties of decompositions starting with I or J. [ltLower]
|
||||
d := norm.NFD.PropertiesString(string(r)).Decomposition()
|
||||
if len(d) > 0 {
|
||||
if d[0] == 'I' || d[0] == 'J' {
|
||||
// A.2.1: we expect at least an ASCII character and a modifier.
|
||||
if len(d) < 3 {
|
||||
log.Fatalf("%U: length of decomposition was %d; want >= 3", r, len(d))
|
||||
}
|
||||
|
||||
// All subsequent runes are modifiers and all have the same CCC.
|
||||
runes := []rune(string(d[1:]))
|
||||
ccc := chars[runes[0]].CCC
|
||||
|
||||
for _, mr := range runes[1:] {
|
||||
mc := chars[mr]
|
||||
|
||||
// A.2.2: all modifiers have a CCC of Above or less.
|
||||
if ccc == 0 || ccc > above {
|
||||
log.Fatalf("%U: CCC of successive rune (%U) was %d; want (0,230]", r, mr, ccc)
|
||||
}
|
||||
|
||||
// A.2.3: a sequence of modifiers all have the same CCC.
|
||||
if mc.CCC != ccc {
|
||||
log.Fatalf("%U: CCC of follow-up modifier (%U) was %d; want %d", r, mr, mc.CCC, ccc)
|
||||
}
|
||||
|
||||
// A.2.4: for each trailing r, r in [0x300, 0x311] <=> CCC == Above.
|
||||
if (ccc == above) != (0x300 <= mr && mr <= 0x311) {
|
||||
log.Fatalf("%U: modifier %U in [U+0300, U+0311] != ccc(%U) == 230", r, mr, mr)
|
||||
}
|
||||
|
||||
if i += len(string(mr)); i >= len(d) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A.3: no U+0307 in decomposition of Soft-Dotted rune. [ltUpper]
|
||||
if unicode.Is(unicode.Soft_Dotted, r) && strings.Contains(string(d), "\u0307") {
|
||||
log.Fatalf("%U: decomposition of soft-dotted rune may not contain U+0307", r)
|
||||
}
|
||||
|
||||
// A.4: only rune U+0345 may be of CCC Iota_Subscript. [elUpper]
|
||||
if c.CCC == iotaSubscript && r != 0x0345 {
|
||||
log.Fatalf("%U: only rune U+0345 may have CCC Iota_Subscript", r)
|
||||
}
|
||||
|
||||
// A.5: soft-dotted runes do not have exceptions.
|
||||
if c.SoftDotted && c.entry&exceptionBit != 0 {
|
||||
log.Fatalf("%U: soft-dotted has exception", r)
|
||||
}
|
||||
|
||||
// A.6: Greek decomposition. [elUpper]
|
||||
if unicode.Is(unicode.Greek, r) {
|
||||
if b := norm.NFD.PropertiesString(string(r)).Decomposition(); b != nil {
|
||||
runes := []rune(string(b))
|
||||
// A.6.1: If a Greek rune decomposes and the first rune of the
|
||||
// decomposition is greater than U+00FF, the rune is always
|
||||
// great and not a modifier.
|
||||
if f := runes[0]; unicode.IsMark(f) || f > 0xFF && !unicode.Is(unicode.Greek, f) {
|
||||
log.Fatalf("%U: expected first rune of Greek decomposition to be letter, found %U", r, f)
|
||||
}
|
||||
// A.6.2: Any follow-up rune in a Greek decomposition is a
|
||||
// modifier of which the first should be gobbled in
|
||||
// decomposition.
|
||||
for _, m := range runes[1:] {
|
||||
switch m {
|
||||
case 0x0313, 0x0314, 0x0301, 0x0300, 0x0306, 0x0342, 0x0308, 0x0304, 0x345:
|
||||
default:
|
||||
log.Fatalf("%U: modifier %U is outside of expected Greek modifier set", r, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Breaking properties.
|
||||
|
||||
// B.1: all runes with CCC > 0 are of break type Extend.
|
||||
if c.CCC > 0 && c.BreakType != "Extend" {
|
||||
log.Fatalf("%U: CCC == %d, but got break type %s; want Extend", r, c.CCC, c.BreakType)
|
||||
}
|
||||
|
||||
// B.2: all cased runes with c.CCC == 0 are of break type ALetter.
|
||||
if c.CCC == 0 && c.Cased && c.BreakType != "ALetter" {
|
||||
log.Fatalf("%U: cased, but got break type %s; want ALetter", r, c.BreakType)
|
||||
}
|
||||
|
||||
// B.3: letter category.
|
||||
if c.CCC == 0 && c.BreakCat != breakBreak && !c.CaseIgnorable {
|
||||
if c.BreakCat != breakLetter {
|
||||
log.Fatalf("%U: check for letter break type gave %d; want %d", r, c.BreakCat, breakLetter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func genTablesTest() {
|
||||
w := &bytes.Buffer{}
|
||||
|
||||
fmt.Fprintln(w, "var (")
|
||||
printProperties(w, "DerivedCoreProperties.txt", "Case_Ignorable", verifyIgnore)
|
||||
|
||||
// We discard the output as we know we have perfect functions. We run them
|
||||
// just to verify the properties are correct.
|
||||
n := printProperties(ioutil.Discard, "DerivedCoreProperties.txt", "Cased", verifyCased)
|
||||
n += printProperties(ioutil.Discard, "DerivedCoreProperties.txt", "Lowercase", verifyLower)
|
||||
n += printProperties(ioutil.Discard, "DerivedCoreProperties.txt", "Uppercase", verifyUpper)
|
||||
if n > 0 {
|
||||
log.Fatalf("One of the discarded properties does not have a perfect filter.")
|
||||
}
|
||||
|
||||
// <code>; <lower> ; <title> ; <upper> ; (<condition_list> ;)?
|
||||
fmt.Fprintln(w, "\tspecial = map[rune]struct{ toLower, toTitle, toUpper string }{")
|
||||
parse("SpecialCasing.txt", func(p *ucd.Parser) {
|
||||
// Skip conditional entries.
|
||||
if p.String(4) != "" {
|
||||
return
|
||||
}
|
||||
r := p.Rune(0)
|
||||
fmt.Fprintf(w, "\t\t0x%04x: {%q, %q, %q},\n",
|
||||
r, string(p.Runes(1)), string(p.Runes(2)), string(p.Runes(3)))
|
||||
})
|
||||
fmt.Fprint(w, "\t}\n\n")
|
||||
|
||||
// <code>; <type>; <runes>
|
||||
table := map[rune]struct{ simple, full, special string }{}
|
||||
parse("CaseFolding.txt", func(p *ucd.Parser) {
|
||||
r := p.Rune(0)
|
||||
t := p.String(1)
|
||||
v := string(p.Runes(2))
|
||||
if t != "T" && v == string(unicode.ToLower(r)) {
|
||||
return
|
||||
}
|
||||
x := table[r]
|
||||
switch t {
|
||||
case "C":
|
||||
x.full = v
|
||||
x.simple = v
|
||||
case "S":
|
||||
x.simple = v
|
||||
case "F":
|
||||
x.full = v
|
||||
case "T":
|
||||
x.special = v
|
||||
}
|
||||
table[r] = x
|
||||
})
|
||||
fmt.Fprintln(w, "\tfoldMap = map[rune]struct{ simple, full, special string }{")
|
||||
for r := rune(0); r < 0x10FFFF; r++ {
|
||||
x, ok := table[r]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(w, "\t\t0x%04x: {%q, %q, %q},\n", r, x.simple, x.full, x.special)
|
||||
}
|
||||
fmt.Fprint(w, "\t}\n\n")
|
||||
|
||||
// Break property
|
||||
notBreak := map[rune]bool{}
|
||||
parse("auxiliary/WordBreakProperty.txt", func(p *ucd.Parser) {
|
||||
switch p.String(1) {
|
||||
case "Extend", "Format", "MidLetter", "MidNumLet", "Single_Quote",
|
||||
"ALetter", "Hebrew_Letter", "Numeric", "ExtendNumLet", "ZWJ":
|
||||
notBreak[p.Rune(0)] = true
|
||||
}
|
||||
})
|
||||
|
||||
fmt.Fprintln(w, "\tbreakProp = []struct{ lo, hi rune }{")
|
||||
inBreak := false
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if isBreak := !notBreak[r]; isBreak != inBreak {
|
||||
if isBreak {
|
||||
fmt.Fprintf(w, "\t\t{0x%x, ", r)
|
||||
} else {
|
||||
fmt.Fprintf(w, "0x%x},\n", r-1)
|
||||
}
|
||||
inBreak = isBreak
|
||||
}
|
||||
}
|
||||
if inBreak {
|
||||
fmt.Fprintf(w, "0x%x},\n", lastRuneForTesting)
|
||||
}
|
||||
fmt.Fprint(w, "\t}\n\n")
|
||||
|
||||
// Word break test
|
||||
// Filter out all samples that do not contain cased characters.
|
||||
cased := map[rune]bool{}
|
||||
parse("DerivedCoreProperties.txt", func(p *ucd.Parser) {
|
||||
if p.String(1) == "Cased" {
|
||||
cased[p.Rune(0)] = true
|
||||
}
|
||||
})
|
||||
|
||||
fmt.Fprintln(w, "\tbreakTest = []string{")
|
||||
parse("auxiliary/WordBreakTest.txt", func(p *ucd.Parser) {
|
||||
c := strings.Split(p.String(0), " ")
|
||||
|
||||
const sep = '|'
|
||||
numCased := 0
|
||||
test := ""
|
||||
for ; len(c) >= 2; c = c[2:] {
|
||||
if c[0] == "÷" && test != "" {
|
||||
test += string(sep)
|
||||
}
|
||||
i, err := strconv.ParseUint(c[1], 16, 32)
|
||||
r := rune(i)
|
||||
if err != nil {
|
||||
log.Fatalf("Invalid rune %q.", c[1])
|
||||
}
|
||||
if r == sep {
|
||||
log.Fatalf("Separator %q not allowed in test data. Pick another one.", sep)
|
||||
}
|
||||
if cased[r] {
|
||||
numCased++
|
||||
}
|
||||
test += string(r)
|
||||
}
|
||||
if numCased > 1 {
|
||||
fmt.Fprintf(w, "\t\t%q,\n", test)
|
||||
}
|
||||
})
|
||||
fmt.Fprintln(w, "\t}")
|
||||
|
||||
fmt.Fprintln(w, ")")
|
||||
|
||||
gen.WriteGoFile("tables_test.go", "cases", w.Bytes())
|
||||
}
|
||||
|
||||
// These functions are just used for verification that their definition have not
|
||||
// changed in the Unicode Standard.
|
||||
|
||||
func verifyCased(r rune) bool {
|
||||
return verifyLower(r) || verifyUpper(r) || unicode.IsTitle(r)
|
||||
}
|
||||
|
||||
func verifyLower(r rune) bool {
|
||||
return unicode.IsLower(r) || unicode.Is(unicode.Other_Lowercase, r)
|
||||
}
|
||||
|
||||
func verifyUpper(r rune) bool {
|
||||
return unicode.IsUpper(r) || unicode.Is(unicode.Other_Uppercase, r)
|
||||
}
|
||||
|
||||
// verifyIgnore is an approximation of the Case_Ignorable property using the
|
||||
// core unicode package. It is used to reduce the size of the test data.
|
||||
func verifyIgnore(r rune) bool {
|
||||
props := []*unicode.RangeTable{
|
||||
unicode.Mn,
|
||||
unicode.Me,
|
||||
unicode.Cf,
|
||||
unicode.Lm,
|
||||
unicode.Sk,
|
||||
}
|
||||
for _, p := range props {
|
||||
if unicode.Is(p, r) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// printProperties prints tables of rune properties from the given UCD file.
|
||||
// A filter func f can be given to exclude certain values. A rune r will have
|
||||
// the indicated property if it is in the generated table or if f(r).
|
||||
func printProperties(w io.Writer, file, property string, f func(r rune) bool) int {
|
||||
verify := map[rune]bool{}
|
||||
n := 0
|
||||
varNameParts := strings.Split(property, "_")
|
||||
varNameParts[0] = strings.ToLower(varNameParts[0])
|
||||
fmt.Fprintf(w, "\t%s = map[rune]bool{\n", strings.Join(varNameParts, ""))
|
||||
parse(file, func(p *ucd.Parser) {
|
||||
if p.String(1) == property {
|
||||
r := p.Rune(0)
|
||||
verify[r] = true
|
||||
if !f(r) {
|
||||
n++
|
||||
fmt.Fprintf(w, "\t\t0x%.4x: true,\n", r)
|
||||
}
|
||||
}
|
||||
})
|
||||
fmt.Fprint(w, "\t}\n\n")
|
||||
|
||||
// Verify that f is correct, that is, it represents a subset of the property.
|
||||
for r := rune(0); r <= lastRuneForTesting; r++ {
|
||||
if !verify[r] && f(r) {
|
||||
log.Fatalf("Incorrect filter func for property %q.", property)
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// The newCaseTrie, sparseValues and sparseOffsets definitions below are
|
||||
// placeholders referred to by gen_trieval.go. The real definitions are
|
||||
// generated by this program and written to tables.go.
|
||||
|
||||
func newCaseTrie(int) int { return 0 }
|
||||
|
||||
var (
|
||||
sparseValues [0]valueRange
|
||||
sparseOffsets [0]uint16
|
||||
)
|
||||
219
vendor/golang.org/x/text/cases/gen_trieval.go
generated
vendored
219
vendor/golang.org/x/text/cases/gen_trieval.go
generated
vendored
|
|
@ -1,219 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file contains definitions for interpreting the trie value of the case
|
||||
// trie generated by "go run gen*.go". It is shared by both the generator
|
||||
// program and the resultant package. Sharing is achieved by the generator
|
||||
// copying gen_trieval.go to trieval.go and changing what's above this comment.
|
||||
|
||||
// info holds case information for a single rune. It is the value returned
|
||||
// by a trie lookup. Most mapping information can be stored in a single 16-bit
|
||||
// value. If not, for example when a rune is mapped to multiple runes, the value
|
||||
// stores some basic case data and an index into an array with additional data.
|
||||
//
|
||||
// The per-rune values have the following format:
|
||||
//
|
||||
// if (exception) {
|
||||
// 15..5 unsigned exception index
|
||||
// 4 unused
|
||||
// } else {
|
||||
// 15..8 XOR pattern or index to XOR pattern for case mapping
|
||||
// Only 13..8 are used for XOR patterns.
|
||||
// 7 inverseFold (fold to upper, not to lower)
|
||||
// 6 index: interpret the XOR pattern as an index
|
||||
// or isMid if case mode is cIgnorableUncased.
|
||||
// 5..4 CCC: zero (normal or break), above or other
|
||||
// }
|
||||
// 3 exception: interpret this value as an exception index
|
||||
// (TODO: is this bit necessary? Probably implied from case mode.)
|
||||
// 2..0 case mode
|
||||
//
|
||||
// For the non-exceptional cases, a rune must be either uncased, lowercase or
|
||||
// uppercase. If the rune is cased, the XOR pattern maps either a lowercase
|
||||
// rune to uppercase or an uppercase rune to lowercase (applied to the 10
|
||||
// least-significant bits of the rune).
|
||||
//
|
||||
// See the definitions below for a more detailed description of the various
|
||||
// bits.
|
||||
type info uint16
|
||||
|
||||
const (
|
||||
casedMask = 0x0003
|
||||
fullCasedMask = 0x0007
|
||||
ignorableMask = 0x0006
|
||||
ignorableValue = 0x0004
|
||||
|
||||
inverseFoldBit = 1 << 7
|
||||
isMidBit = 1 << 6
|
||||
|
||||
exceptionBit = 1 << 3
|
||||
exceptionShift = 5
|
||||
numExceptionBits = 11
|
||||
|
||||
xorIndexBit = 1 << 6
|
||||
xorShift = 8
|
||||
|
||||
// There is no mapping if all xor bits and the exception bit are zero.
|
||||
hasMappingMask = 0xff80 | exceptionBit
|
||||
)
|
||||
|
||||
// The case mode bits encodes the case type of a rune. This includes uncased,
|
||||
// title, upper and lower case and case ignorable. (For a definition of these
|
||||
// terms see Chapter 3 of The Unicode Standard Core Specification.) In some rare
|
||||
// cases, a rune can be both cased and case-ignorable. This is encoded by
|
||||
// cIgnorableCased. A rune of this type is always lower case. Some runes are
|
||||
// cased while not having a mapping.
|
||||
//
|
||||
// A common pattern for scripts in the Unicode standard is for upper and lower
|
||||
// case runes to alternate for increasing rune values (e.g. the accented Latin
|
||||
// ranges starting from U+0100 and U+1E00 among others and some Cyrillic
|
||||
// characters). We use this property by defining a cXORCase mode, where the case
|
||||
// mode (always upper or lower case) is derived from the rune value. As the XOR
|
||||
// pattern for case mappings is often identical for successive runes, using
|
||||
// cXORCase can result in large series of identical trie values. This, in turn,
|
||||
// allows us to better compress the trie blocks.
|
||||
const (
|
||||
cUncased info = iota // 000
|
||||
cTitle // 001
|
||||
cLower // 010
|
||||
cUpper // 011
|
||||
cIgnorableUncased // 100
|
||||
cIgnorableCased // 101 // lower case if mappings exist
|
||||
cXORCase // 11x // case is cLower | ((rune&1) ^ x)
|
||||
|
||||
maxCaseMode = cUpper
|
||||
)
|
||||
|
||||
func (c info) isCased() bool {
|
||||
return c&casedMask != 0
|
||||
}
|
||||
|
||||
func (c info) isCaseIgnorable() bool {
|
||||
return c&ignorableMask == ignorableValue
|
||||
}
|
||||
|
||||
func (c info) isNotCasedAndNotCaseIgnorable() bool {
|
||||
return c&fullCasedMask == 0
|
||||
}
|
||||
|
||||
func (c info) isCaseIgnorableAndNotCased() bool {
|
||||
return c&fullCasedMask == cIgnorableUncased
|
||||
}
|
||||
|
||||
func (c info) isMid() bool {
|
||||
return c&(fullCasedMask|isMidBit) == isMidBit|cIgnorableUncased
|
||||
}
|
||||
|
||||
// The case mapping implementation will need to know about various Canonical
|
||||
// Combining Class (CCC) values. We encode two of these in the trie value:
|
||||
// cccZero (0) and cccAbove (230). If the value is cccOther, it means that
|
||||
// CCC(r) > 0, but not 230. A value of cccBreak means that CCC(r) == 0 and that
|
||||
// the rune also has the break category Break (see below).
|
||||
const (
|
||||
cccBreak info = iota << 4
|
||||
cccZero
|
||||
cccAbove
|
||||
cccOther
|
||||
|
||||
cccMask = cccBreak | cccZero | cccAbove | cccOther
|
||||
)
|
||||
|
||||
const (
|
||||
starter = 0
|
||||
above = 230
|
||||
iotaSubscript = 240
|
||||
)
|
||||
|
||||
// The exceptions slice holds data that does not fit in a normal info entry.
|
||||
// The entry is pointed to by the exception index in an entry. It has the
|
||||
// following format:
|
||||
//
|
||||
// Header
|
||||
// byte 0:
|
||||
// 7..6 unused
|
||||
// 5..4 CCC type (same bits as entry)
|
||||
// 3 unused
|
||||
// 2..0 length of fold
|
||||
//
|
||||
// byte 1:
|
||||
// 7..6 unused
|
||||
// 5..3 length of 1st mapping of case type
|
||||
// 2..0 length of 2nd mapping of case type
|
||||
//
|
||||
// case 1st 2nd
|
||||
// lower -> upper, title
|
||||
// upper -> lower, title
|
||||
// title -> lower, upper
|
||||
//
|
||||
// Lengths with the value 0x7 indicate no value and implies no change.
|
||||
// A length of 0 indicates a mapping to zero-length string.
|
||||
//
|
||||
// Body bytes:
|
||||
// case folding bytes
|
||||
// lowercase mapping bytes
|
||||
// uppercase mapping bytes
|
||||
// titlecase mapping bytes
|
||||
// closure mapping bytes (for NFKC_Casefold). (TODO)
|
||||
//
|
||||
// Fallbacks:
|
||||
// missing fold -> lower
|
||||
// missing title -> upper
|
||||
// all missing -> original rune
|
||||
//
|
||||
// exceptions starts with a dummy byte to enforce that there is no zero index
|
||||
// value.
|
||||
const (
|
||||
lengthMask = 0x07
|
||||
lengthBits = 3
|
||||
noChange = 0
|
||||
)
|
||||
|
||||
// References to generated trie.
|
||||
|
||||
var trie = newCaseTrie(0)
|
||||
|
||||
var sparse = sparseBlocks{
|
||||
values: sparseValues[:],
|
||||
offsets: sparseOffsets[:],
|
||||
}
|
||||
|
||||
// Sparse block lookup code.
|
||||
|
||||
// valueRange is an entry in a sparse block.
|
||||
type valueRange struct {
|
||||
value uint16
|
||||
lo, hi byte
|
||||
}
|
||||
|
||||
type sparseBlocks struct {
|
||||
values []valueRange
|
||||
offsets []uint16
|
||||
}
|
||||
|
||||
// lookup returns the value from values block n for byte b using binary search.
|
||||
func (s *sparseBlocks) lookup(n uint32, b byte) uint16 {
|
||||
lo := s.offsets[n]
|
||||
hi := s.offsets[n+1]
|
||||
for lo < hi {
|
||||
m := lo + (hi-lo)/2
|
||||
r := s.values[m]
|
||||
if r.lo <= b && b <= r.hi {
|
||||
return r.value
|
||||
}
|
||||
if b < r.lo {
|
||||
hi = m
|
||||
} else {
|
||||
lo = m + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// lastRuneForTesting is the last rune used for testing. Everything after this
|
||||
// is boring.
|
||||
const lastRuneForTesting = rune(0x1FFFF)
|
||||
61
vendor/golang.org/x/text/cases/icu.go
generated
vendored
61
vendor/golang.org/x/text/cases/icu.go
generated
vendored
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build icu
|
||||
|
||||
package cases
|
||||
|
||||
// Ideally these functions would be defined in a test file, but go test doesn't
|
||||
// allow CGO in tests. The build tag should ensure either way that these
|
||||
// functions will not end up in the package.
|
||||
|
||||
// TODO: Ensure that the correct ICU version is set.
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -licui18n.57 -licuuc.57
|
||||
#include <stdlib.h>
|
||||
#include <unicode/ustring.h>
|
||||
#include <unicode/utypes.h>
|
||||
#include <unicode/localpointer.h>
|
||||
#include <unicode/ucasemap.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func doICU(tag, caser, input string) string {
|
||||
err := C.UErrorCode(0)
|
||||
loc := C.CString(tag)
|
||||
cm := C.ucasemap_open(loc, C.uint32_t(0), &err)
|
||||
|
||||
buf := make([]byte, len(input)*4)
|
||||
dst := (*C.char)(unsafe.Pointer(&buf[0]))
|
||||
src := C.CString(input)
|
||||
|
||||
cn := C.int32_t(0)
|
||||
|
||||
switch caser {
|
||||
case "fold":
|
||||
cn = C.ucasemap_utf8FoldCase(cm,
|
||||
dst, C.int32_t(len(buf)),
|
||||
src, C.int32_t(len(input)),
|
||||
&err)
|
||||
case "lower":
|
||||
cn = C.ucasemap_utf8ToLower(cm,
|
||||
dst, C.int32_t(len(buf)),
|
||||
src, C.int32_t(len(input)),
|
||||
&err)
|
||||
case "upper":
|
||||
cn = C.ucasemap_utf8ToUpper(cm,
|
||||
dst, C.int32_t(len(buf)),
|
||||
src, C.int32_t(len(input)),
|
||||
&err)
|
||||
case "title":
|
||||
cn = C.ucasemap_utf8ToTitle(cm,
|
||||
dst, C.int32_t(len(buf)),
|
||||
src, C.int32_t(len(input)),
|
||||
&err)
|
||||
}
|
||||
return string(buf[:cn])
|
||||
}
|
||||
210
vendor/golang.org/x/text/cases/icu_test.go
generated
vendored
210
vendor/golang.org/x/text/cases/icu_test.go
generated
vendored
|
|
@ -1,210 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build icu
|
||||
|
||||
package cases
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
func TestICUConformance(t *testing.T) {
|
||||
// Build test set.
|
||||
input := []string{
|
||||
"a.a a_a",
|
||||
"a\u05d0a",
|
||||
"\u05d0'a",
|
||||
"a\u03084a",
|
||||
"a\u0308a",
|
||||
"a3\u30a3a",
|
||||
"a\u303aa",
|
||||
"a_\u303a_a",
|
||||
"1_a..a",
|
||||
"1_a.a",
|
||||
"a..a.",
|
||||
"a--a-",
|
||||
"a-a-",
|
||||
"a\u200ba",
|
||||
"a\u200b\u200ba",
|
||||
"a\u00ad\u00ada", // Format
|
||||
"a\u00ada",
|
||||
"a''a", // SingleQuote
|
||||
"a'a",
|
||||
"a::a", // MidLetter
|
||||
"a:a",
|
||||
"a..a", // MidNumLet
|
||||
"a.a",
|
||||
"a;;a", // MidNum
|
||||
"a;a",
|
||||
"a__a", // ExtendNumlet
|
||||
"a_a",
|
||||
"ΟΣ''a",
|
||||
}
|
||||
add := func(x interface{}) {
|
||||
switch v := x.(type) {
|
||||
case string:
|
||||
input = append(input, v)
|
||||
case []string:
|
||||
for _, s := range v {
|
||||
input = append(input, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
add(tc.src)
|
||||
add(tc.lower)
|
||||
add(tc.upper)
|
||||
add(tc.title)
|
||||
}
|
||||
for _, tc := range bufferTests {
|
||||
add(tc.src)
|
||||
}
|
||||
for _, tc := range breakTest {
|
||||
add(strings.Replace(tc, "|", "", -1))
|
||||
}
|
||||
for _, tc := range foldTestCases {
|
||||
add(tc)
|
||||
}
|
||||
|
||||
// Compare ICU to Go.
|
||||
for _, c := range []string{"lower", "upper", "title", "fold"} {
|
||||
for _, tag := range []string{
|
||||
"und", "af", "az", "el", "lt", "nl", "tr",
|
||||
} {
|
||||
for _, s := range input {
|
||||
if exclude(c, tag, s) {
|
||||
continue
|
||||
}
|
||||
testtext.Run(t, path.Join(c, tag, s), func(t *testing.T) {
|
||||
want := doICU(tag, c, s)
|
||||
got := doGo(tag, c, s)
|
||||
if norm.NFC.String(got) != norm.NFC.String(want) {
|
||||
t.Errorf("\n in %[3]q (%+[3]q)\n got %[1]q (%+[1]q)\n want %[2]q (%+[2]q)", got, want, s)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exclude indicates if a string should be excluded from testing.
|
||||
func exclude(cm, tag, s string) bool {
|
||||
list := []struct{ cm, tags, pattern string }{
|
||||
// TODO: Go does not handle certain esoteric breaks correctly. This will be
|
||||
// fixed once we have a real word break iterator. Alternatively, it
|
||||
// seems like we're not too far off from making it work, so we could
|
||||
// fix these last steps. But first verify that using a separate word
|
||||
// breaker does not hurt performance.
|
||||
{"title", "af nl", "a''a"},
|
||||
{"", "", "א'a"},
|
||||
|
||||
// All the exclusions below seem to be issues with the ICU
|
||||
// implementation (at version 57) and thus are not marked as TODO.
|
||||
|
||||
// ICU does not handle leading apostrophe for Dutch and
|
||||
// Afrikaans correctly. See http://unicode.org/cldr/trac/ticket/7078.
|
||||
{"title", "af nl", "'n"},
|
||||
{"title", "af nl", "'N"},
|
||||
|
||||
// Go terminates the final sigma check after a fixed number of
|
||||
// ignorables have been found. This ensures that the algorithm can make
|
||||
// progress in a streaming scenario.
|
||||
{"lower title", "", "\u039f\u03a3...............................a"},
|
||||
// This also applies to upper in Greek.
|
||||
// NOTE: we could fix the following two cases by adding state to elUpper
|
||||
// and aztrLower. However, considering a modifier to not belong to the
|
||||
// preceding letter after the maximum modifiers count is reached is
|
||||
// consistent with the behavior of unicode/norm.
|
||||
{"upper", "el", "\u03bf" + strings.Repeat("\u0321", 29) + "\u0313"},
|
||||
{"lower", "az tr lt", "I" + strings.Repeat("\u0321", 30) + "\u0307\u0300"},
|
||||
{"upper", "lt", "i" + strings.Repeat("\u0321", 30) + "\u0307\u0300"},
|
||||
{"lower", "lt", "I" + strings.Repeat("\u0321", 30) + "\u0300"},
|
||||
|
||||
// ICU title case seems to erroneously removes \u0307 from an upper case
|
||||
// I unconditionally, instead of only when lowercasing. The ICU
|
||||
// transform algorithm transforms these cases consistently with our
|
||||
// implementation.
|
||||
{"title", "az tr", "\u0307"},
|
||||
|
||||
// The spec says to remove \u0307 after Soft-Dotted characters. ICU
|
||||
// transforms conform but ucasemap_utf8ToUpper does not.
|
||||
{"upper title", "lt", "i\u0307"},
|
||||
{"upper title", "lt", "i" + strings.Repeat("\u0321", 29) + "\u0307\u0300"},
|
||||
|
||||
// Both Unicode and CLDR prescribe an extra explicit dot above after a
|
||||
// Soft_Dotted character if there are other modifiers.
|
||||
// ucasemap_utf8ToUpper does not do this; ICU transforms do.
|
||||
// The issue with ucasemap_utf8ToUpper seems to be that it does not
|
||||
// consider the modifiers that are part of composition in the evaluation
|
||||
// of More_Above. For instance, according to the More_Above rule for lt,
|
||||
// a dotted capital I (U+0130) becomes i\u0307\u0307 (an small i with
|
||||
// two additional dots). This seems odd, but is correct. ICU is
|
||||
// definitely not correct as it produces different results for different
|
||||
// normal forms. For instance, for an İ:
|
||||
// \u0130 (NFC) -> i\u0307 (incorrect)
|
||||
// I\u0307 (NFD) -> i\u0307\u0307 (correct)
|
||||
// We could argue that we should not add a \u0307 if there already is
|
||||
// one, but this may be hard to get correct and is not conform the
|
||||
// standard.
|
||||
{"lower title", "lt", "\u0130"},
|
||||
{"lower title", "lt", "\u00cf"},
|
||||
|
||||
// We are conform ICU ucasemap_utf8ToUpper if we remove support for
|
||||
// elUpper. However, this is clearly not conform the spec. Moreover, the
|
||||
// ICU transforms _do_ implement this transform and produces results
|
||||
// consistent with our implementation. Note that we still prefer to use
|
||||
// ucasemap_utf8ToUpper instead of transforms as the latter have
|
||||
// inconsistencies in the word breaking algorithm.
|
||||
{"upper", "el", "\u0386"}, // GREEK CAPITAL LETTER ALPHA WITH TONOS
|
||||
{"upper", "el", "\u0389"}, // GREEK CAPITAL LETTER ETA WITH TONOS
|
||||
{"upper", "el", "\u038A"}, // GREEK CAPITAL LETTER IOTA WITH TONOS
|
||||
|
||||
{"upper", "el", "\u0391"}, // GREEK CAPITAL LETTER ALPHA
|
||||
{"upper", "el", "\u0397"}, // GREEK CAPITAL LETTER ETA
|
||||
{"upper", "el", "\u0399"}, // GREEK CAPITAL LETTER IOTA
|
||||
|
||||
{"upper", "el", "\u03AC"}, // GREEK SMALL LETTER ALPHA WITH TONOS
|
||||
{"upper", "el", "\u03AE"}, // GREEK SMALL LETTER ALPHA WITH ETA
|
||||
{"upper", "el", "\u03AF"}, // GREEK SMALL LETTER ALPHA WITH IOTA
|
||||
|
||||
{"upper", "el", "\u03B1"}, // GREEK SMALL LETTER ALPHA
|
||||
{"upper", "el", "\u03B7"}, // GREEK SMALL LETTER ETA
|
||||
{"upper", "el", "\u03B9"}, // GREEK SMALL LETTER IOTA
|
||||
}
|
||||
for _, x := range list {
|
||||
if x.cm != "" && strings.Index(x.cm, cm) == -1 {
|
||||
continue
|
||||
}
|
||||
if x.tags != "" && strings.Index(x.tags, tag) == -1 {
|
||||
continue
|
||||
}
|
||||
if strings.Index(s, x.pattern) != -1 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func doGo(tag, caser, input string) string {
|
||||
var c Caser
|
||||
t := language.MustParse(tag)
|
||||
switch caser {
|
||||
case "lower":
|
||||
c = Lower(t)
|
||||
case "upper":
|
||||
c = Upper(t)
|
||||
case "title":
|
||||
c = Title(t)
|
||||
case "fold":
|
||||
c = Fold()
|
||||
}
|
||||
return c.String(input)
|
||||
}
|
||||
82
vendor/golang.org/x/text/cases/info.go
generated
vendored
82
vendor/golang.org/x/text/cases/info.go
generated
vendored
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
func (c info) cccVal() info {
|
||||
if c&exceptionBit != 0 {
|
||||
return info(exceptions[c>>exceptionShift]) & cccMask
|
||||
}
|
||||
return c & cccMask
|
||||
}
|
||||
|
||||
func (c info) cccType() info {
|
||||
ccc := c.cccVal()
|
||||
if ccc <= cccZero {
|
||||
return cccZero
|
||||
}
|
||||
return ccc
|
||||
}
|
||||
|
||||
// TODO: Implement full Unicode breaking algorithm:
|
||||
// 1) Implement breaking in separate package.
|
||||
// 2) Use the breaker here.
|
||||
// 3) Compare table size and performance of using the more generic breaker.
|
||||
//
|
||||
// Note that we can extend the current algorithm to be much more accurate. This
|
||||
// only makes sense, though, if the performance and/or space penalty of using
|
||||
// the generic breaker is big. Extra data will only be needed for non-cased
|
||||
// runes, which means there are sufficient bits left in the caseType.
|
||||
// ICU prohibits breaking in such cases as well.
|
||||
|
||||
// For the purpose of title casing we use an approximation of the Unicode Word
|
||||
// Breaking algorithm defined in Annex #29:
|
||||
// http://www.unicode.org/reports/tr29/#Default_Grapheme_Cluster_Table.
|
||||
//
|
||||
// For our approximation, we group the Word Break types into the following
|
||||
// categories, with associated rules:
|
||||
//
|
||||
// 1) Letter:
|
||||
// ALetter, Hebrew_Letter, Numeric, ExtendNumLet, Extend, Format_FE, ZWJ.
|
||||
// Rule: Never break between consecutive runes of this category.
|
||||
//
|
||||
// 2) Mid:
|
||||
// MidLetter, MidNumLet, Single_Quote.
|
||||
// (Cf. case-ignorable: MidLetter, MidNumLet, Single_Quote or cat is Mn,
|
||||
// Me, Cf, Lm or Sk).
|
||||
// Rule: Don't break between Letter and Mid, but break between two Mids.
|
||||
//
|
||||
// 3) Break:
|
||||
// Any other category: NewLine, MidNum, CR, LF, Double_Quote, Katakana, and
|
||||
// Other.
|
||||
// These categories should always result in a break between two cased letters.
|
||||
// Rule: Always break.
|
||||
//
|
||||
// Note 1: the Katakana and MidNum categories can, in esoteric cases, result in
|
||||
// preventing a break between two cased letters. For now we will ignore this
|
||||
// (e.g. [ALetter] [ExtendNumLet] [Katakana] [ExtendNumLet] [ALetter] and
|
||||
// [ALetter] [Numeric] [MidNum] [Numeric] [ALetter].)
|
||||
//
|
||||
// Note 2: the rule for Mid is very approximate, but works in most cases. To
|
||||
// improve, we could store the categories in the trie value and use a FA to
|
||||
// manage breaks. See TODO comment above.
|
||||
//
|
||||
// Note 3: according to the spec, it is possible for the Extend category to
|
||||
// introduce breaks between other categories grouped in Letter. However, this
|
||||
// is undesirable for our purposes. ICU prevents breaks in such cases as well.
|
||||
|
||||
// isBreak returns whether this rune should introduce a break.
|
||||
func (c info) isBreak() bool {
|
||||
return c.cccVal() == cccBreak
|
||||
}
|
||||
|
||||
// isLetter returns whether the rune is of break type ALetter, Hebrew_Letter,
|
||||
// Numeric, ExtendNumLet, or Extend.
|
||||
func (c info) isLetter() bool {
|
||||
ccc := c.cccVal()
|
||||
if ccc == cccZero {
|
||||
return !c.isCaseIgnorable()
|
||||
}
|
||||
return ccc != cccBreak
|
||||
}
|
||||
816
vendor/golang.org/x/text/cases/map.go
generated
vendored
816
vendor/golang.org/x/text/cases/map.go
generated
vendored
|
|
@ -1,816 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
// This file contains the definitions of case mappings for all supported
|
||||
// languages. The rules for the language-specific tailorings were taken and
|
||||
// modified from the CLDR transform definitions in common/transforms.
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// A mapFunc takes a context set to the current rune and writes the mapped
|
||||
// version to the same context. It may advance the context to the next rune. It
|
||||
// returns whether a checkpoint is possible: whether the pDst bytes written to
|
||||
// dst so far won't need changing as we see more source bytes.
|
||||
type mapFunc func(*context) bool
|
||||
|
||||
// A spanFunc takes a context set to the current rune and returns whether this
|
||||
// rune would be altered when written to the output. It may advance the context
|
||||
// to the next rune. It returns whether a checkpoint is possible.
|
||||
type spanFunc func(*context) bool
|
||||
|
||||
// maxIgnorable defines the maximum number of ignorables to consider for
|
||||
// lookahead operations.
|
||||
const maxIgnorable = 30
|
||||
|
||||
// supported lists the language tags for which we have tailorings.
|
||||
const supported = "und af az el lt nl tr"
|
||||
|
||||
func init() {
|
||||
tags := []language.Tag{}
|
||||
for _, s := range strings.Split(supported, " ") {
|
||||
tags = append(tags, language.MustParse(s))
|
||||
}
|
||||
matcher = internal.NewInheritanceMatcher(tags)
|
||||
Supported = language.NewCoverage(tags)
|
||||
}
|
||||
|
||||
var (
|
||||
matcher *internal.InheritanceMatcher
|
||||
|
||||
Supported language.Coverage
|
||||
|
||||
// We keep the following lists separate, instead of having a single per-
|
||||
// language struct, to give the compiler a chance to remove unused code.
|
||||
|
||||
// Some uppercase mappers are stateless, so we can precompute the
|
||||
// Transformers and save a bit on runtime allocations.
|
||||
upperFunc = []struct {
|
||||
upper mapFunc
|
||||
span spanFunc
|
||||
}{
|
||||
{nil, nil}, // und
|
||||
{nil, nil}, // af
|
||||
{aztrUpper(upper), isUpper}, // az
|
||||
{elUpper, noSpan}, // el
|
||||
{ltUpper(upper), noSpan}, // lt
|
||||
{nil, nil}, // nl
|
||||
{aztrUpper(upper), isUpper}, // tr
|
||||
}
|
||||
|
||||
undUpper transform.SpanningTransformer = &undUpperCaser{}
|
||||
undLower transform.SpanningTransformer = &undLowerCaser{}
|
||||
undLowerIgnoreSigma transform.SpanningTransformer = &undLowerIgnoreSigmaCaser{}
|
||||
|
||||
lowerFunc = []mapFunc{
|
||||
nil, // und
|
||||
nil, // af
|
||||
aztrLower, // az
|
||||
nil, // el
|
||||
ltLower, // lt
|
||||
nil, // nl
|
||||
aztrLower, // tr
|
||||
}
|
||||
|
||||
titleInfos = []struct {
|
||||
title mapFunc
|
||||
lower mapFunc
|
||||
titleSpan spanFunc
|
||||
rewrite func(*context)
|
||||
}{
|
||||
{title, lower, isTitle, nil}, // und
|
||||
{title, lower, isTitle, afnlRewrite}, // af
|
||||
{aztrUpper(title), aztrLower, isTitle, nil}, // az
|
||||
{title, lower, isTitle, nil}, // el
|
||||
{ltUpper(title), ltLower, noSpan, nil}, // lt
|
||||
{nlTitle, lower, nlTitleSpan, afnlRewrite}, // nl
|
||||
{aztrUpper(title), aztrLower, isTitle, nil}, // tr
|
||||
}
|
||||
)
|
||||
|
||||
func makeUpper(t language.Tag, o options) transform.SpanningTransformer {
|
||||
_, i, _ := matcher.Match(t)
|
||||
f := upperFunc[i].upper
|
||||
if f == nil {
|
||||
return undUpper
|
||||
}
|
||||
return &simpleCaser{f: f, span: upperFunc[i].span}
|
||||
}
|
||||
|
||||
func makeLower(t language.Tag, o options) transform.SpanningTransformer {
|
||||
_, i, _ := matcher.Match(t)
|
||||
f := lowerFunc[i]
|
||||
if f == nil {
|
||||
if o.ignoreFinalSigma {
|
||||
return undLowerIgnoreSigma
|
||||
}
|
||||
return undLower
|
||||
}
|
||||
if o.ignoreFinalSigma {
|
||||
return &simpleCaser{f: f, span: isLower}
|
||||
}
|
||||
return &lowerCaser{
|
||||
first: f,
|
||||
midWord: finalSigma(f),
|
||||
}
|
||||
}
|
||||
|
||||
func makeTitle(t language.Tag, o options) transform.SpanningTransformer {
|
||||
_, i, _ := matcher.Match(t)
|
||||
x := &titleInfos[i]
|
||||
lower := x.lower
|
||||
if o.noLower {
|
||||
lower = (*context).copy
|
||||
} else if !o.ignoreFinalSigma {
|
||||
lower = finalSigma(lower)
|
||||
}
|
||||
return &titleCaser{
|
||||
title: x.title,
|
||||
lower: lower,
|
||||
titleSpan: x.titleSpan,
|
||||
rewrite: x.rewrite,
|
||||
}
|
||||
}
|
||||
|
||||
func noSpan(c *context) bool {
|
||||
c.err = transform.ErrEndOfSpan
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: consider a similar special case for the fast majority lower case. This
|
||||
// is a bit more involved so will require some more precise benchmarking to
|
||||
// justify it.
|
||||
|
||||
type undUpperCaser struct{ transform.NopResetter }
|
||||
|
||||
// undUpperCaser implements the Transformer interface for doing an upper case
|
||||
// mapping for the root locale (und). It eliminates the need for an allocation
|
||||
// as it prevents escaping by not using function pointers.
|
||||
func (t undUpperCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
c := context{dst: dst, src: src, atEOF: atEOF}
|
||||
for c.next() {
|
||||
upper(&c)
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
func (t undUpperCaser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
c := context{src: src, atEOF: atEOF}
|
||||
for c.next() && isUpper(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
// undLowerIgnoreSigmaCaser implements the Transformer interface for doing
|
||||
// a lower case mapping for the root locale (und) ignoring final sigma
|
||||
// handling. This casing algorithm is used in some performance-critical packages
|
||||
// like secure/precis and x/net/http/idna, which warrants its special-casing.
|
||||
type undLowerIgnoreSigmaCaser struct{ transform.NopResetter }
|
||||
|
||||
func (t undLowerIgnoreSigmaCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
c := context{dst: dst, src: src, atEOF: atEOF}
|
||||
for c.next() && lower(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
|
||||
}
|
||||
|
||||
// Span implements a generic lower-casing. This is possible as isLower works
|
||||
// for all lowercasing variants. All lowercase variants only vary in how they
|
||||
// transform a non-lowercase letter. They will never change an already lowercase
|
||||
// letter. In addition, there is no state.
|
||||
func (t undLowerIgnoreSigmaCaser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
c := context{src: src, atEOF: atEOF}
|
||||
for c.next() && isLower(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
type simpleCaser struct {
|
||||
context
|
||||
f mapFunc
|
||||
span spanFunc
|
||||
}
|
||||
|
||||
// simpleCaser implements the Transformer interface for doing a case operation
|
||||
// on a rune-by-rune basis.
|
||||
func (t *simpleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
c := context{dst: dst, src: src, atEOF: atEOF}
|
||||
for c.next() && t.f(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
func (t *simpleCaser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
c := context{src: src, atEOF: atEOF}
|
||||
for c.next() && t.span(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
// undLowerCaser implements the Transformer interface for doing a lower case
|
||||
// mapping for the root locale (und) ignoring final sigma handling. This casing
|
||||
// algorithm is used in some performance-critical packages like secure/precis
|
||||
// and x/net/http/idna, which warrants its special-casing.
|
||||
type undLowerCaser struct{ transform.NopResetter }
|
||||
|
||||
func (t undLowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
c := context{dst: dst, src: src, atEOF: atEOF}
|
||||
|
||||
for isInterWord := true; c.next(); {
|
||||
if isInterWord {
|
||||
if c.info.isCased() {
|
||||
if !lower(&c) {
|
||||
break
|
||||
}
|
||||
isInterWord = false
|
||||
} else if !c.copy() {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if c.info.isNotCasedAndNotCaseIgnorable() {
|
||||
if !c.copy() {
|
||||
break
|
||||
}
|
||||
isInterWord = true
|
||||
} else if !c.hasPrefix("Σ") {
|
||||
if !lower(&c) {
|
||||
break
|
||||
}
|
||||
} else if !finalSigmaBody(&c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
func (t undLowerCaser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
c := context{src: src, atEOF: atEOF}
|
||||
for c.next() && isLower(&c) {
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
// lowerCaser implements the Transformer interface. The default Unicode lower
|
||||
// casing requires different treatment for the first and subsequent characters
|
||||
// of a word, most notably to handle the Greek final Sigma.
|
||||
type lowerCaser struct {
|
||||
undLowerIgnoreSigmaCaser
|
||||
|
||||
context
|
||||
|
||||
first, midWord mapFunc
|
||||
}
|
||||
|
||||
func (t *lowerCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
t.context = context{dst: dst, src: src, atEOF: atEOF}
|
||||
c := &t.context
|
||||
|
||||
for isInterWord := true; c.next(); {
|
||||
if isInterWord {
|
||||
if c.info.isCased() {
|
||||
if !t.first(c) {
|
||||
break
|
||||
}
|
||||
isInterWord = false
|
||||
} else if !c.copy() {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if c.info.isNotCasedAndNotCaseIgnorable() {
|
||||
if !c.copy() {
|
||||
break
|
||||
}
|
||||
isInterWord = true
|
||||
} else if !t.midWord(c) {
|
||||
break
|
||||
}
|
||||
}
|
||||
c.checkpoint()
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
// titleCaser implements the Transformer interface. Title casing algorithms
|
||||
// distinguish between the first letter of a word and subsequent letters of the
|
||||
// same word. It uses state to avoid requiring a potentially infinite lookahead.
|
||||
type titleCaser struct {
|
||||
context
|
||||
|
||||
// rune mappings used by the actual casing algorithms.
|
||||
title mapFunc
|
||||
lower mapFunc
|
||||
titleSpan spanFunc
|
||||
|
||||
rewrite func(*context)
|
||||
}
|
||||
|
||||
// Transform implements the standard Unicode title case algorithm as defined in
|
||||
// Chapter 3 of The Unicode Standard:
|
||||
// toTitlecase(X): Find the word boundaries in X according to Unicode Standard
|
||||
// Annex #29, "Unicode Text Segmentation." For each word boundary, find the
|
||||
// first cased character F following the word boundary. If F exists, map F to
|
||||
// Titlecase_Mapping(F); then map all characters C between F and the following
|
||||
// word boundary to Lowercase_Mapping(C).
|
||||
func (t *titleCaser) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
t.context = context{dst: dst, src: src, atEOF: atEOF, isMidWord: t.isMidWord}
|
||||
c := &t.context
|
||||
|
||||
if !c.next() {
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
for {
|
||||
p := c.info
|
||||
if t.rewrite != nil {
|
||||
t.rewrite(c)
|
||||
}
|
||||
|
||||
wasMid := p.isMid()
|
||||
// Break out of this loop on failure to ensure we do not modify the
|
||||
// state incorrectly.
|
||||
if p.isCased() {
|
||||
if !c.isMidWord {
|
||||
if !t.title(c) {
|
||||
break
|
||||
}
|
||||
c.isMidWord = true
|
||||
} else if !t.lower(c) {
|
||||
break
|
||||
}
|
||||
} else if !c.copy() {
|
||||
break
|
||||
} else if p.isBreak() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
|
||||
// As we save the state of the transformer, it is safe to call
|
||||
// checkpoint after any successful write.
|
||||
if !(c.isMidWord && wasMid) {
|
||||
c.checkpoint()
|
||||
}
|
||||
|
||||
if !c.next() {
|
||||
break
|
||||
}
|
||||
if wasMid && c.info.isMid() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
}
|
||||
return c.ret()
|
||||
}
|
||||
|
||||
func (t *titleCaser) Span(src []byte, atEOF bool) (n int, err error) {
|
||||
t.context = context{src: src, atEOF: atEOF, isMidWord: t.isMidWord}
|
||||
c := &t.context
|
||||
|
||||
if !c.next() {
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
for {
|
||||
p := c.info
|
||||
if t.rewrite != nil {
|
||||
t.rewrite(c)
|
||||
}
|
||||
|
||||
wasMid := p.isMid()
|
||||
// Break out of this loop on failure to ensure we do not modify the
|
||||
// state incorrectly.
|
||||
if p.isCased() {
|
||||
if !c.isMidWord {
|
||||
if !t.titleSpan(c) {
|
||||
break
|
||||
}
|
||||
c.isMidWord = true
|
||||
} else if !isLower(c) {
|
||||
break
|
||||
}
|
||||
} else if p.isBreak() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
// As we save the state of the transformer, it is safe to call
|
||||
// checkpoint after any successful write.
|
||||
if !(c.isMidWord && wasMid) {
|
||||
c.checkpoint()
|
||||
}
|
||||
|
||||
if !c.next() {
|
||||
break
|
||||
}
|
||||
if wasMid && c.info.isMid() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
}
|
||||
return c.retSpan()
|
||||
}
|
||||
|
||||
// finalSigma adds Greek final Sigma handing to another casing function. It
|
||||
// determines whether a lowercased sigma should be σ or ς, by looking ahead for
|
||||
// case-ignorables and a cased letters.
|
||||
func finalSigma(f mapFunc) mapFunc {
|
||||
return func(c *context) bool {
|
||||
if !c.hasPrefix("Σ") {
|
||||
return f(c)
|
||||
}
|
||||
return finalSigmaBody(c)
|
||||
}
|
||||
}
|
||||
|
||||
func finalSigmaBody(c *context) bool {
|
||||
// Current rune must be ∑.
|
||||
|
||||
// ::NFD();
|
||||
// # 03A3; 03C2; 03A3; 03A3; Final_Sigma; # GREEK CAPITAL LETTER SIGMA
|
||||
// Σ } [:case-ignorable:]* [:cased:] → σ;
|
||||
// [:cased:] [:case-ignorable:]* { Σ → ς;
|
||||
// ::Any-Lower;
|
||||
// ::NFC();
|
||||
|
||||
p := c.pDst
|
||||
c.writeString("ς")
|
||||
|
||||
// TODO: we should do this here, but right now this will never have an
|
||||
// effect as this is called when the prefix is Sigma, whereas Dutch and
|
||||
// Afrikaans only test for an apostrophe.
|
||||
//
|
||||
// if t.rewrite != nil {
|
||||
// t.rewrite(c)
|
||||
// }
|
||||
|
||||
// We need to do one more iteration after maxIgnorable, as a cased
|
||||
// letter is not an ignorable and may modify the result.
|
||||
wasMid := false
|
||||
for i := 0; i < maxIgnorable+1; i++ {
|
||||
if !c.next() {
|
||||
return false
|
||||
}
|
||||
if !c.info.isCaseIgnorable() {
|
||||
// All Midword runes are also case ignorable, so we are
|
||||
// guaranteed to have a letter or word break here. As we are
|
||||
// unreading the run, there is no need to unset c.isMidWord;
|
||||
// the title caser will handle this.
|
||||
if c.info.isCased() {
|
||||
// p+1 is guaranteed to be in bounds: if writing ς was
|
||||
// successful, p+1 will contain the second byte of ς. If not,
|
||||
// this function will have returned after c.next returned false.
|
||||
c.dst[p+1]++ // ς → σ
|
||||
}
|
||||
c.unreadRune()
|
||||
return true
|
||||
}
|
||||
// A case ignorable may also introduce a word break, so we may need
|
||||
// to continue searching even after detecting a break.
|
||||
isMid := c.info.isMid()
|
||||
if (wasMid && isMid) || c.info.isBreak() {
|
||||
c.isMidWord = false
|
||||
}
|
||||
wasMid = isMid
|
||||
c.copy()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// finalSigmaSpan would be the same as isLower.
|
||||
|
||||
// elUpper implements Greek upper casing, which entails removing a predefined
|
||||
// set of non-blocked modifiers. Note that these accents should not be removed
|
||||
// for title casing!
|
||||
// Example: "Οδός" -> "ΟΔΟΣ".
|
||||
func elUpper(c *context) bool {
|
||||
// From CLDR:
|
||||
// [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Above:]]*? { [\u0313\u0314\u0301\u0300\u0306\u0342\u0308\u0304] → ;
|
||||
// [:Greek:] [^[:ccc=Not_Reordered:][:ccc=Iota_Subscript:]]*? { \u0345 → ;
|
||||
|
||||
r, _ := utf8.DecodeRune(c.src[c.pSrc:])
|
||||
oldPDst := c.pDst
|
||||
if !upper(c) {
|
||||
return false
|
||||
}
|
||||
if !unicode.Is(unicode.Greek, r) {
|
||||
return true
|
||||
}
|
||||
i := 0
|
||||
// Take the properties of the uppercased rune that is already written to the
|
||||
// destination. This saves us the trouble of having to uppercase the
|
||||
// decomposed rune again.
|
||||
if b := norm.NFD.Properties(c.dst[oldPDst:]).Decomposition(); b != nil {
|
||||
// Restore the destination position and process the decomposed rune.
|
||||
r, sz := utf8.DecodeRune(b)
|
||||
if r <= 0xFF { // See A.6.1
|
||||
return true
|
||||
}
|
||||
c.pDst = oldPDst
|
||||
// Insert the first rune and ignore the modifiers. See A.6.2.
|
||||
c.writeBytes(b[:sz])
|
||||
i = len(b[sz:]) / 2 // Greek modifiers are always of length 2.
|
||||
}
|
||||
|
||||
for ; i < maxIgnorable && c.next(); i++ {
|
||||
switch r, _ := utf8.DecodeRune(c.src[c.pSrc:]); r {
|
||||
// Above and Iota Subscript
|
||||
case 0x0300, // U+0300 COMBINING GRAVE ACCENT
|
||||
0x0301, // U+0301 COMBINING ACUTE ACCENT
|
||||
0x0304, // U+0304 COMBINING MACRON
|
||||
0x0306, // U+0306 COMBINING BREVE
|
||||
0x0308, // U+0308 COMBINING DIAERESIS
|
||||
0x0313, // U+0313 COMBINING COMMA ABOVE
|
||||
0x0314, // U+0314 COMBINING REVERSED COMMA ABOVE
|
||||
0x0342, // U+0342 COMBINING GREEK PERISPOMENI
|
||||
0x0345: // U+0345 COMBINING GREEK YPOGEGRAMMENI
|
||||
// No-op. Gobble the modifier.
|
||||
|
||||
default:
|
||||
switch v, _ := trie.lookup(c.src[c.pSrc:]); info(v).cccType() {
|
||||
case cccZero:
|
||||
c.unreadRune()
|
||||
return true
|
||||
|
||||
// We don't need to test for IotaSubscript as the only rune that
|
||||
// qualifies (U+0345) was already excluded in the switch statement
|
||||
// above. See A.4.
|
||||
|
||||
case cccAbove:
|
||||
return c.copy()
|
||||
default:
|
||||
// Some other modifier. We're still allowed to gobble Greek
|
||||
// modifiers after this.
|
||||
c.copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
return i == maxIgnorable
|
||||
}
|
||||
|
||||
// TODO: implement elUpperSpan (low-priority: complex and infrequent).
|
||||
|
||||
func ltLower(c *context) bool {
|
||||
// From CLDR:
|
||||
// # Introduce an explicit dot above when lowercasing capital I's and J's
|
||||
// # whenever there are more accents above.
|
||||
// # (of the accents used in Lithuanian: grave, acute, tilde above, and ogonek)
|
||||
// # 0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I
|
||||
// # 004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J
|
||||
// # 012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK
|
||||
// # 00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE
|
||||
// # 00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE
|
||||
// # 0128; 0069 0307 0303; 0128; 0128; lt; # LATIN CAPITAL LETTER I WITH TILDE
|
||||
// ::NFD();
|
||||
// I } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0307;
|
||||
// J } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → j \u0307;
|
||||
// I \u0328 (Į) } [^[:ccc=Not_Reordered:][:ccc=Above:]]* [:ccc=Above:] → i \u0328 \u0307;
|
||||
// I \u0300 (Ì) → i \u0307 \u0300;
|
||||
// I \u0301 (Í) → i \u0307 \u0301;
|
||||
// I \u0303 (Ĩ) → i \u0307 \u0303;
|
||||
// ::Any-Lower();
|
||||
// ::NFC();
|
||||
|
||||
i := 0
|
||||
if r := c.src[c.pSrc]; r < utf8.RuneSelf {
|
||||
lower(c)
|
||||
if r != 'I' && r != 'J' {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
p := norm.NFD.Properties(c.src[c.pSrc:])
|
||||
if d := p.Decomposition(); len(d) >= 3 && (d[0] == 'I' || d[0] == 'J') {
|
||||
// UTF-8 optimization: the decomposition will only have an above
|
||||
// modifier if the last rune of the decomposition is in [U+300-U+311].
|
||||
// In all other cases, a decomposition starting with I is always
|
||||
// an I followed by modifiers that are not cased themselves. See A.2.
|
||||
if d[1] == 0xCC && d[2] <= 0x91 { // A.2.4.
|
||||
if !c.writeBytes(d[:1]) {
|
||||
return false
|
||||
}
|
||||
c.dst[c.pDst-1] += 'a' - 'A' // lower
|
||||
|
||||
// Assumption: modifier never changes on lowercase. See A.1.
|
||||
// Assumption: all modifiers added have CCC = Above. See A.2.3.
|
||||
return c.writeString("\u0307") && c.writeBytes(d[1:])
|
||||
}
|
||||
// In all other cases the additional modifiers will have a CCC
|
||||
// that is less than 230 (Above). We will insert the U+0307, if
|
||||
// needed, after these modifiers so that a string in FCD form
|
||||
// will remain so. See A.2.2.
|
||||
lower(c)
|
||||
i = 1
|
||||
} else {
|
||||
return lower(c)
|
||||
}
|
||||
}
|
||||
|
||||
for ; i < maxIgnorable && c.next(); i++ {
|
||||
switch c.info.cccType() {
|
||||
case cccZero:
|
||||
c.unreadRune()
|
||||
return true
|
||||
case cccAbove:
|
||||
return c.writeString("\u0307") && c.copy() // See A.1.
|
||||
default:
|
||||
c.copy() // See A.1.
|
||||
}
|
||||
}
|
||||
return i == maxIgnorable
|
||||
}
|
||||
|
||||
// ltLowerSpan would be the same as isLower.
|
||||
|
||||
func ltUpper(f mapFunc) mapFunc {
|
||||
return func(c *context) bool {
|
||||
// Unicode:
|
||||
// 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
|
||||
//
|
||||
// From CLDR:
|
||||
// # Remove \u0307 following soft-dotteds (i, j, and the like), with possible
|
||||
// # intervening non-230 marks.
|
||||
// ::NFD();
|
||||
// [:Soft_Dotted:] [^[:ccc=Not_Reordered:][:ccc=Above:]]* { \u0307 → ;
|
||||
// ::Any-Upper();
|
||||
// ::NFC();
|
||||
|
||||
// TODO: See A.5. A soft-dotted rune never has an exception. This would
|
||||
// allow us to overload the exception bit and encode this property in
|
||||
// info. Need to measure performance impact of this.
|
||||
r, _ := utf8.DecodeRune(c.src[c.pSrc:])
|
||||
oldPDst := c.pDst
|
||||
if !f(c) {
|
||||
return false
|
||||
}
|
||||
if !unicode.Is(unicode.Soft_Dotted, r) {
|
||||
return true
|
||||
}
|
||||
|
||||
// We don't need to do an NFD normalization, as a soft-dotted rune never
|
||||
// contains U+0307. See A.3.
|
||||
|
||||
i := 0
|
||||
for ; i < maxIgnorable && c.next(); i++ {
|
||||
switch c.info.cccType() {
|
||||
case cccZero:
|
||||
c.unreadRune()
|
||||
return true
|
||||
case cccAbove:
|
||||
if c.hasPrefix("\u0307") {
|
||||
// We don't do a full NFC, but rather combine runes for
|
||||
// some of the common cases. (Returning NFC or
|
||||
// preserving normal form is neither a requirement nor
|
||||
// a possibility anyway).
|
||||
if !c.next() {
|
||||
return false
|
||||
}
|
||||
if c.dst[oldPDst] == 'I' && c.pDst == oldPDst+1 && c.src[c.pSrc] == 0xcc {
|
||||
s := ""
|
||||
switch c.src[c.pSrc+1] {
|
||||
case 0x80: // U+0300 COMBINING GRAVE ACCENT
|
||||
s = "\u00cc" // U+00CC LATIN CAPITAL LETTER I WITH GRAVE
|
||||
case 0x81: // U+0301 COMBINING ACUTE ACCENT
|
||||
s = "\u00cd" // U+00CD LATIN CAPITAL LETTER I WITH ACUTE
|
||||
case 0x83: // U+0303 COMBINING TILDE
|
||||
s = "\u0128" // U+0128 LATIN CAPITAL LETTER I WITH TILDE
|
||||
case 0x88: // U+0308 COMBINING DIAERESIS
|
||||
s = "\u00cf" // U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS
|
||||
default:
|
||||
}
|
||||
if s != "" {
|
||||
c.pDst = oldPDst
|
||||
return c.writeString(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
return c.copy()
|
||||
default:
|
||||
c.copy()
|
||||
}
|
||||
}
|
||||
return i == maxIgnorable
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement ltUpperSpan (low priority: complex and infrequent).
|
||||
|
||||
func aztrUpper(f mapFunc) mapFunc {
|
||||
return func(c *context) bool {
|
||||
// i→İ;
|
||||
if c.src[c.pSrc] == 'i' {
|
||||
return c.writeString("İ")
|
||||
}
|
||||
return f(c)
|
||||
}
|
||||
}
|
||||
|
||||
func aztrLower(c *context) (done bool) {
|
||||
// From CLDR:
|
||||
// # I and i-dotless; I-dot and i are case pairs in Turkish and Azeri
|
||||
// # 0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE
|
||||
// İ→i;
|
||||
// # When lowercasing, remove dot_above in the sequence I + dot_above, which will turn into i.
|
||||
// # This matches the behavior of the canonically equivalent I-dot_above
|
||||
// # 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
|
||||
// # When lowercasing, unless an I is before a dot_above, it turns into a dotless i.
|
||||
// # 0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I
|
||||
// I([^[:ccc=Not_Reordered:][:ccc=Above:]]*)\u0307 → i$1 ;
|
||||
// I→ı ;
|
||||
// ::Any-Lower();
|
||||
if c.hasPrefix("\u0130") { // İ
|
||||
return c.writeString("i")
|
||||
}
|
||||
if c.src[c.pSrc] != 'I' {
|
||||
return lower(c)
|
||||
}
|
||||
|
||||
// We ignore the lower-case I for now, but insert it later when we know
|
||||
// which form we need.
|
||||
start := c.pSrc + c.sz
|
||||
|
||||
i := 0
|
||||
Loop:
|
||||
// We check for up to n ignorables before \u0307. As \u0307 is an
|
||||
// ignorable as well, n is maxIgnorable-1.
|
||||
for ; i < maxIgnorable && c.next(); i++ {
|
||||
switch c.info.cccType() {
|
||||
case cccAbove:
|
||||
if c.hasPrefix("\u0307") {
|
||||
return c.writeString("i") && c.writeBytes(c.src[start:c.pSrc]) // ignore U+0307
|
||||
}
|
||||
done = true
|
||||
break Loop
|
||||
case cccZero:
|
||||
c.unreadRune()
|
||||
done = true
|
||||
break Loop
|
||||
default:
|
||||
// We'll write this rune after we know which starter to use.
|
||||
}
|
||||
}
|
||||
if i == maxIgnorable {
|
||||
done = true
|
||||
}
|
||||
return c.writeString("ı") && c.writeBytes(c.src[start:c.pSrc+c.sz]) && done
|
||||
}
|
||||
|
||||
// aztrLowerSpan would be the same as isLower.
|
||||
|
||||
func nlTitle(c *context) bool {
|
||||
// From CLDR:
|
||||
// # Special titlecasing for Dutch initial "ij".
|
||||
// ::Any-Title();
|
||||
// # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29)
|
||||
// [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
|
||||
if c.src[c.pSrc] != 'I' && c.src[c.pSrc] != 'i' {
|
||||
return title(c)
|
||||
}
|
||||
|
||||
if !c.writeString("I") || !c.next() {
|
||||
return false
|
||||
}
|
||||
if c.src[c.pSrc] == 'j' || c.src[c.pSrc] == 'J' {
|
||||
return c.writeString("J")
|
||||
}
|
||||
c.unreadRune()
|
||||
return true
|
||||
}
|
||||
|
||||
func nlTitleSpan(c *context) bool {
|
||||
// From CLDR:
|
||||
// # Special titlecasing for Dutch initial "ij".
|
||||
// ::Any-Title();
|
||||
// # Fix up Ij at the beginning of a "word" (per Any-Title, notUAX #29)
|
||||
// [:^WB=ALetter:] [:WB=Extend:]* [[:WB=MidLetter:][:WB=MidNumLet:]]? { Ij } → IJ ;
|
||||
if c.src[c.pSrc] != 'I' {
|
||||
return isTitle(c)
|
||||
}
|
||||
if !c.next() || c.src[c.pSrc] == 'j' {
|
||||
return false
|
||||
}
|
||||
if c.src[c.pSrc] != 'J' {
|
||||
c.unreadRune()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Not part of CLDR, but see http://unicode.org/cldr/trac/ticket/7078.
|
||||
func afnlRewrite(c *context) {
|
||||
if c.hasPrefix("'") || c.hasPrefix("’") {
|
||||
c.isMidWord = true
|
||||
}
|
||||
}
|
||||
950
vendor/golang.org/x/text/cases/map_test.go
generated
vendored
950
vendor/golang.org/x/text/cases/map_test.go
generated
vendored
|
|
@ -1,950 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cases
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/transform"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
lang string
|
||||
src interface{} // string, []string, or nil to skip test
|
||||
title interface{} // string, []string, or nil to skip test
|
||||
lower interface{} // string, []string, or nil to skip test
|
||||
upper interface{} // string, []string, or nil to skip test
|
||||
opts options
|
||||
}
|
||||
|
||||
var testCases = []testCase{
|
||||
0: {
|
||||
lang: "und",
|
||||
src: "abc aBc ABC abC İsıI ΕΣΆΣ",
|
||||
title: "Abc Abc Abc Abc İsıi Εσάσ",
|
||||
lower: "abc abc abc abc i\u0307sıi εσάσ",
|
||||
upper: "ABC ABC ABC ABC İSII ΕΣΆΣ",
|
||||
opts: getOpts(HandleFinalSigma(false)),
|
||||
},
|
||||
|
||||
1: {
|
||||
lang: "und",
|
||||
src: "abc aBc ABC abC İsıI ΕΣΆΣ Σ _Σ -Σ",
|
||||
title: "Abc Abc Abc Abc İsıi Εσάς Σ _Σ -Σ",
|
||||
lower: "abc abc abc abc i\u0307sıi εσάς σ _σ -σ",
|
||||
upper: "ABC ABC ABC ABC İSII ΕΣΆΣ Σ _Σ -Σ",
|
||||
opts: getOpts(HandleFinalSigma(true)),
|
||||
},
|
||||
|
||||
2: { // Title cased runes.
|
||||
lang: supported,
|
||||
src: "DžA",
|
||||
title: "Dža",
|
||||
lower: "dža",
|
||||
upper: "DŽA",
|
||||
},
|
||||
|
||||
3: {
|
||||
// Title breaking.
|
||||
lang: supported,
|
||||
src: []string{
|
||||
"FOO CASE TEST",
|
||||
"DON'T DO THiS",
|
||||
"χωΡΊΣ χωΡΊΣ^a χωΡΊΣ:a χωΡΊΣ:^a χωΡΊΣ^ όμΩΣ Σ",
|
||||
"with-hyphens",
|
||||
"49ers 49ers",
|
||||
`"capitalize a^a -hyphen 0X _u a_u:a`,
|
||||
"MidNumLet a.b\u2018c\u2019d\u2024e\ufe52f\uff07f\uff0eg",
|
||||
"MidNum a,b;c\u037ed\u0589e\u060cf\u2044g\ufe50h",
|
||||
"\u0345 x\u3031x x\u05d0x \u05d0x a'.a a.a a4,a",
|
||||
},
|
||||
title: []string{
|
||||
"Foo Case Test",
|
||||
"Don't Do This",
|
||||
"Χωρίς Χωρίσ^A Χωρίσ:a Χωρίσ:^A Χωρίς^ Όμως Σ",
|
||||
"With-Hyphens",
|
||||
// Note that 49Ers is correct according to the spec.
|
||||
// TODO: provide some option to the user to treat different
|
||||
// characters as cased.
|
||||
"49Ers 49Ers",
|
||||
`"Capitalize A^A -Hyphen 0X _U A_u:a`,
|
||||
"Midnumlet A.b\u2018c\u2019d\u2024e\ufe52f\uff07f\uff0eg",
|
||||
"Midnum A,B;C\u037eD\u0589E\u060cF\u2044G\ufe50H",
|
||||
"\u0399 X\u3031X X\u05d0x \u05d0X A'.A A.a A4,A",
|
||||
},
|
||||
},
|
||||
|
||||
// TODO: These are known deviations from the options{} Unicode Word Breaking
|
||||
// Algorithm.
|
||||
// {
|
||||
// "und",
|
||||
// "x_\u3031_x a4,4a",
|
||||
// "X_\u3031_x A4,4a", // Currently is "X_\U3031_X A4,4A".
|
||||
// "x_\u3031_x a4,4a",
|
||||
// "X_\u3031_X A4,4A",
|
||||
// options{},
|
||||
// },
|
||||
|
||||
4: {
|
||||
// Tests title options
|
||||
lang: "und",
|
||||
src: "abc aBc ABC abC İsıI o'Brien",
|
||||
title: "Abc ABc ABC AbC İsıI O'Brien",
|
||||
opts: getOpts(NoLower),
|
||||
},
|
||||
|
||||
5: {
|
||||
lang: "el",
|
||||
src: "aBc ΟΔΌΣ Οδός Σο ΣΟ Σ oΣ ΟΣ σ ἕξ \u03ac",
|
||||
title: "Abc Οδός Οδός Σο Σο Σ Oς Ος Σ Ἕξ \u0386",
|
||||
lower: "abc οδός οδός σο σο σ oς ος σ ἕξ \u03ac",
|
||||
upper: "ABC ΟΔΟΣ ΟΔΟΣ ΣΟ ΣΟ Σ OΣ ΟΣ Σ ΕΞ \u0391", // Uppercase removes accents
|
||||
},
|
||||
|
||||
6: {
|
||||
lang: "tr az",
|
||||
src: "Isiİ İsıI I\u0307sIiİ İsıI\u0307 I\u0300\u0307",
|
||||
title: "Isii İsıı I\u0307sıii İsıi I\u0300\u0307",
|
||||
lower: "ısii isıı isıii isıi \u0131\u0300\u0307",
|
||||
upper: "ISİİ İSII I\u0307SIİİ İSII\u0307 I\u0300\u0307",
|
||||
},
|
||||
|
||||
7: {
|
||||
lang: "lt",
|
||||
src: "I Ï J J̈ Į Į̈ Ì Í Ĩ xi̇̈ xj̇̈ xį̇̈ xi̇̀ xi̇́ xi̇̃ XI XÏ XJ XJ̈ XĮ XĮ̈ XI̟̤",
|
||||
title: "I Ï J J̈ Į Į̈ Ì Í Ĩ Xi̇̈ Xj̇̈ Xį̇̈ Xi̇̀ Xi̇́ Xi̇̃ Xi Xi̇̈ Xj Xj̇̈ Xį Xį̇̈ Xi̟̤",
|
||||
lower: "i i̇̈ j j̇̈ į į̇̈ i̇̀ i̇́ i̇̃ xi̇̈ xj̇̈ xį̇̈ xi̇̀ xi̇́ xi̇̃ xi xi̇̈ xj xj̇̈ xį xį̇̈ xi̟̤",
|
||||
upper: "I Ï J J̈ Į Į̈ Ì Í Ĩ XÏ XJ̈ XĮ̈ XÌ XÍ XĨ XI XÏ XJ XJ̈ XĮ XĮ̈ XI̟̤",
|
||||
},
|
||||
|
||||
8: {
|
||||
lang: "lt",
|
||||
src: "\u012e\u0300 \u00cc i\u0307\u0300 i\u0307\u0301 i\u0307\u0303 i\u0307\u0308 i\u0300\u0307",
|
||||
title: "\u012e\u0300 \u00cc \u00cc \u00cd \u0128 \u00cf I\u0300\u0307",
|
||||
lower: "\u012f\u0307\u0300 i\u0307\u0300 i\u0307\u0300 i\u0307\u0301 i\u0307\u0303 i\u0307\u0308 i\u0300\u0307",
|
||||
upper: "\u012e\u0300 \u00cc \u00cc \u00cd \u0128 \u00cf I\u0300\u0307",
|
||||
},
|
||||
|
||||
9: {
|
||||
lang: "nl",
|
||||
src: "ijs IJs Ij Ijs İJ İJs aa aA 'ns 'S",
|
||||
title: "IJs IJs IJ IJs İj İjs Aa Aa 'ns 's",
|
||||
},
|
||||
|
||||
// Note: this specification is not currently part of CLDR. The same holds
|
||||
// for the leading apostrophe handling for Dutch.
|
||||
// See http://unicode.org/cldr/trac/ticket/7078.
|
||||
10: {
|
||||
lang: "af",
|
||||
src: "wag 'n bietjie",
|
||||
title: "Wag 'n Bietjie",
|
||||
lower: "wag 'n bietjie",
|
||||
upper: "WAG 'N BIETJIE",
|
||||
},
|
||||
}
|
||||
|
||||
func TestCaseMappings(t *testing.T) {
|
||||
for i, tt := range testCases {
|
||||
src, ok := tt.src.([]string)
|
||||
if !ok {
|
||||
src = strings.Split(tt.src.(string), " ")
|
||||
}
|
||||
|
||||
for _, lang := range strings.Split(tt.lang, " ") {
|
||||
tag := language.MustParse(lang)
|
||||
testEntry := func(name string, mk func(language.Tag, options) transform.SpanningTransformer, gold interface{}) {
|
||||
c := Caser{mk(tag, tt.opts)}
|
||||
if gold != nil {
|
||||
wants, ok := gold.([]string)
|
||||
if !ok {
|
||||
wants = strings.Split(gold.(string), " ")
|
||||
}
|
||||
for j, want := range wants {
|
||||
if got := c.String(src[j]); got != want {
|
||||
t.Errorf("%d:%s:\n%s.String(%+q):\ngot %+q;\nwant %+q", i, lang, name, src[j], got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
dst := make([]byte, 256) // big enough to hold any result
|
||||
src := []byte(strings.Join(src, " "))
|
||||
v := testtext.AllocsPerRun(20, func() {
|
||||
c.Transform(dst, src, true)
|
||||
})
|
||||
if v > 1.1 {
|
||||
t.Errorf("%d:%s:\n%s: number of allocs was %f; want 0", i, lang, name, v)
|
||||
}
|
||||
}
|
||||
testEntry("Upper", makeUpper, tt.upper)
|
||||
testEntry("Lower", makeLower, tt.lower)
|
||||
testEntry("Title", makeTitle, tt.title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestAlloc tests that some mapping methods should not cause any allocation.
|
||||
func TestAlloc(t *testing.T) {
|
||||
dst := make([]byte, 256) // big enough to hold any result
|
||||
src := []byte(txtNonASCII)
|
||||
|
||||
for i, f := range []func() Caser{
|
||||
func() Caser { return Upper(language.Und) },
|
||||
func() Caser { return Lower(language.Und) },
|
||||
func() Caser { return Lower(language.Und, HandleFinalSigma(false)) },
|
||||
// TODO: use a shared copy for these casers as well, in order of
|
||||
// importance, starting with the most important:
|
||||
// func() Caser { return Title(language.Und) },
|
||||
// func() Caser { return Title(language.Und, HandleFinalSigma(false)) },
|
||||
} {
|
||||
testtext.Run(t, "", func(t *testing.T) {
|
||||
var c Caser
|
||||
v := testtext.AllocsPerRun(10, func() {
|
||||
c = f()
|
||||
})
|
||||
if v > 0 {
|
||||
// TODO: Right now only Upper has 1 allocation. Special-case Lower
|
||||
// and Title as well to have less allocations for the root locale.
|
||||
t.Errorf("%d:init: number of allocs was %f; want 0", i, v)
|
||||
}
|
||||
v = testtext.AllocsPerRun(2, func() {
|
||||
c.Transform(dst, src, true)
|
||||
})
|
||||
if v > 0 {
|
||||
t.Errorf("%d:transform: number of allocs was %f; want 0", i, v)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testHandover(t *testing.T, c Caser, src string) {
|
||||
want := c.String(src)
|
||||
// Find the common prefix.
|
||||
pSrc := 0
|
||||
for ; pSrc < len(src) && pSrc < len(want) && want[pSrc] == src[pSrc]; pSrc++ {
|
||||
}
|
||||
|
||||
// Test handover for each substring of the prefix.
|
||||
for i := 0; i < pSrc; i++ {
|
||||
testtext.Run(t, fmt.Sprint("interleave/", i), func(t *testing.T) {
|
||||
dst := make([]byte, 4*len(src))
|
||||
c.Reset()
|
||||
nSpan, _ := c.Span([]byte(src[:i]), false)
|
||||
copy(dst, src[:nSpan])
|
||||
nTransform, _, _ := c.Transform(dst[nSpan:], []byte(src[nSpan:]), true)
|
||||
got := string(dst[:nSpan+nTransform])
|
||||
if got != want {
|
||||
t.Errorf("full string: got %q; want %q", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandover(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
t Caser
|
||||
first, second string
|
||||
}{{
|
||||
"title/nosigma/single midword",
|
||||
Title(language.Und, HandleFinalSigma(false)),
|
||||
"A.", "a",
|
||||
}, {
|
||||
"title/nosigma/single midword",
|
||||
Title(language.Und, HandleFinalSigma(false)),
|
||||
"A", ".a",
|
||||
}, {
|
||||
"title/nosigma/double midword",
|
||||
Title(language.Und, HandleFinalSigma(false)),
|
||||
"A..", "a",
|
||||
}, {
|
||||
"title/nosigma/double midword",
|
||||
Title(language.Und, HandleFinalSigma(false)),
|
||||
"A.", ".a",
|
||||
}, {
|
||||
"title/nosigma/double midword",
|
||||
Title(language.Und, HandleFinalSigma(false)),
|
||||
"A", "..a",
|
||||
}, {
|
||||
"title/sigma/single midword",
|
||||
Title(language.Und),
|
||||
"ΟΣ.", "a",
|
||||
}, {
|
||||
"title/sigma/single midword",
|
||||
Title(language.Und),
|
||||
"ΟΣ", ".a",
|
||||
}, {
|
||||
"title/sigma/double midword",
|
||||
Title(language.Und),
|
||||
"ΟΣ..", "a",
|
||||
}, {
|
||||
"title/sigma/double midword",
|
||||
Title(language.Und),
|
||||
"ΟΣ.", ".a",
|
||||
}, {
|
||||
"title/sigma/double midword",
|
||||
Title(language.Und),
|
||||
"ΟΣ", "..a",
|
||||
}, {
|
||||
"title/af/leading apostrophe",
|
||||
Title(language.Afrikaans),
|
||||
"'", "n bietje",
|
||||
}}
|
||||
for _, tc := range testCases {
|
||||
testtext.Run(t, tc.desc, func(t *testing.T) {
|
||||
src := tc.first + tc.second
|
||||
want := tc.t.String(src)
|
||||
tc.t.Reset()
|
||||
n, _ := tc.t.Span([]byte(tc.first), false)
|
||||
|
||||
dst := make([]byte, len(want))
|
||||
copy(dst, tc.first[:n])
|
||||
|
||||
nDst, _, _ := tc.t.Transform(dst[n:], []byte(src[n:]), true)
|
||||
got := string(dst[:n+nDst])
|
||||
if got != want {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// minBufSize is the size of the buffer by which the casing operation in
|
||||
// this package are guaranteed to make progress.
|
||||
const minBufSize = norm.MaxSegmentSize
|
||||
|
||||
type bufferTest struct {
|
||||
desc, src, want string
|
||||
firstErr error
|
||||
dstSize, srcSize int
|
||||
t transform.SpanningTransformer
|
||||
}
|
||||
|
||||
var bufferTests []bufferTest
|
||||
|
||||
func init() {
|
||||
bufferTests = []bufferTest{{
|
||||
desc: "und/upper/short dst",
|
||||
src: "abcdefg",
|
||||
want: "ABCDEFG",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/upper/short src",
|
||||
src: "123é56",
|
||||
want: "123É56",
|
||||
firstErr: transform.ErrShortSrc,
|
||||
dstSize: 4,
|
||||
srcSize: 4,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/upper/no error on short",
|
||||
src: "12",
|
||||
want: "12",
|
||||
firstErr: nil,
|
||||
dstSize: 1,
|
||||
srcSize: 1,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/short dst",
|
||||
src: "ABCDEFG",
|
||||
want: "abcdefg",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/short src",
|
||||
src: "123É56",
|
||||
want: "123é56",
|
||||
firstErr: transform.ErrShortSrc,
|
||||
dstSize: 4,
|
||||
srcSize: 4,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/no error on short",
|
||||
src: "12",
|
||||
want: "12",
|
||||
firstErr: nil,
|
||||
dstSize: 1,
|
||||
srcSize: 1,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/simple (no final sigma)",
|
||||
src: "ΟΣ ΟΣΣ",
|
||||
want: "οσ οσσ",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Und, HandleFinalSigma(false)),
|
||||
}, {
|
||||
desc: "und/title/simple (no final sigma)",
|
||||
src: "ΟΣ ΟΣΣ",
|
||||
want: "Οσ Οσσ",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und, HandleFinalSigma(false)),
|
||||
}, {
|
||||
desc: "und/title/final sigma: no error",
|
||||
src: "ΟΣ",
|
||||
want: "Ος",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: short source",
|
||||
src: "ΟΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣ",
|
||||
want: "Οσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσς",
|
||||
firstErr: transform.ErrShortSrc,
|
||||
dstSize: minBufSize,
|
||||
srcSize: 10,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: short destination 1",
|
||||
src: "ΟΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣ",
|
||||
want: "Οσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσς",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 10,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: short destination 2",
|
||||
src: "ΟΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣ",
|
||||
want: "Οσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσς",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 9,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: short destination 3",
|
||||
src: "ΟΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣΣ",
|
||||
want: "Οσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσς",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 8,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/clipped UTF-8 rune",
|
||||
src: "σσσσσσσσσσσ",
|
||||
want: "Σσσσσσσσσσσ",
|
||||
firstErr: transform.ErrShortSrc,
|
||||
dstSize: minBufSize,
|
||||
srcSize: 5,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/clipped UTF-8 rune atEOF",
|
||||
src: "σσσ" + string([]byte{0xCF}),
|
||||
want: "Σσσ" + string([]byte{0xCF}),
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/final sigma: max ignorables",
|
||||
src: "ΟΣ" + strings.Repeat(".", maxIgnorable) + "a",
|
||||
want: "Οσ" + strings.Repeat(".", maxIgnorable) + "A",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/long string",
|
||||
src: "AA" + strings.Repeat(".", maxIgnorable+1) + "a",
|
||||
want: "Aa" + strings.Repeat(".", maxIgnorable+1) + "A",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("AA" + strings.Repeat(".", maxIgnorable+1)),
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/final sigma: too many ignorables",
|
||||
src: "ΟΣ" + strings.Repeat(".", maxIgnorable+1) + "a",
|
||||
want: "Ος" + strings.Repeat(".", maxIgnorable+1) + "A",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("ΟΣ" + strings.Repeat(".", maxIgnorable+1)),
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: apostrophe",
|
||||
src: "ΟΣ''a",
|
||||
want: "Οσ''A",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "el/upper/max ignorables",
|
||||
src: "ο" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0313",
|
||||
want: "Ο" + strings.Repeat("\u0321", maxIgnorable-1),
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "el/upper/too many ignorables",
|
||||
src: "ο" + strings.Repeat("\u0321", maxIgnorable) + "\u0313",
|
||||
want: "Ο" + strings.Repeat("\u0321", maxIgnorable) + "\u0313",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("ο" + strings.Repeat("\u0321", maxIgnorable)),
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "el/upper/short dst",
|
||||
src: "123ο",
|
||||
want: "123Ο",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "lt/lower/max ignorables",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0300",
|
||||
want: "i" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0307\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/too many ignorables",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable) + "\u0300",
|
||||
want: "i" + strings.Repeat("\u0321", maxIgnorable) + "\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("I" + strings.Repeat("\u0321", maxIgnorable)),
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/decomposition with short dst buffer 1",
|
||||
src: "aaaaa\u00cc", // U+00CC LATIN CAPITAL LETTER I GRAVE
|
||||
firstErr: transform.ErrShortDst,
|
||||
want: "aaaaai\u0307\u0300",
|
||||
dstSize: 5,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/decomposition with short dst buffer 2",
|
||||
src: "aaaa\u00cc", // U+00CC LATIN CAPITAL LETTER I GRAVE
|
||||
firstErr: transform.ErrShortDst,
|
||||
want: "aaaai\u0307\u0300",
|
||||
dstSize: 5,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/upper/max ignorables",
|
||||
src: "i" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0307\u0300",
|
||||
want: "I" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Upper(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/upper/too many ignorables",
|
||||
src: "i" + strings.Repeat("\u0321", maxIgnorable) + "\u0307\u0300",
|
||||
want: "I" + strings.Repeat("\u0321", maxIgnorable) + "\u0307\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("i" + strings.Repeat("\u0321", maxIgnorable)),
|
||||
t: Upper(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/upper/short dst",
|
||||
src: "12i\u0307\u0300",
|
||||
want: "12\u00cc",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Upper(language.Lithuanian),
|
||||
}, {
|
||||
desc: "aztr/lower/max ignorables",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0307\u0300",
|
||||
want: "i" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: minBufSize,
|
||||
t: Lower(language.Turkish),
|
||||
}, {
|
||||
desc: "aztr/lower/too many ignorables",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable) + "\u0307\u0300",
|
||||
want: "\u0131" + strings.Repeat("\u0321", maxIgnorable) + "\u0307\u0300",
|
||||
dstSize: minBufSize,
|
||||
srcSize: len("I" + strings.Repeat("\u0321", maxIgnorable)),
|
||||
t: Lower(language.Turkish),
|
||||
}, {
|
||||
desc: "nl/title/pre-IJ cutoff",
|
||||
src: " ij",
|
||||
want: " IJ",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 2,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Dutch),
|
||||
}, {
|
||||
desc: "nl/title/mid-IJ cutoff",
|
||||
src: " ij",
|
||||
want: " IJ",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Dutch),
|
||||
}, {
|
||||
desc: "af/title/apostrophe",
|
||||
src: "'n bietje",
|
||||
want: "'n Bietje",
|
||||
firstErr: transform.ErrShortDst,
|
||||
dstSize: 3,
|
||||
srcSize: minBufSize,
|
||||
t: Title(language.Afrikaans),
|
||||
}}
|
||||
}
|
||||
|
||||
func TestShortBuffersAndOverflow(t *testing.T) {
|
||||
for i, tt := range bufferTests {
|
||||
testtext.Run(t, tt.desc, func(t *testing.T) {
|
||||
buf := make([]byte, tt.dstSize)
|
||||
got := []byte{}
|
||||
var nSrc, nDst int
|
||||
var err error
|
||||
for p := 0; p < len(tt.src); p += nSrc {
|
||||
q := p + tt.srcSize
|
||||
if q > len(tt.src) {
|
||||
q = len(tt.src)
|
||||
}
|
||||
nDst, nSrc, err = tt.t.Transform(buf, []byte(tt.src[p:q]), q == len(tt.src))
|
||||
got = append(got, buf[:nDst]...)
|
||||
|
||||
if p == 0 && err != tt.firstErr {
|
||||
t.Errorf("%d:%s:\n error was %v; want %v", i, tt.desc, err, tt.firstErr)
|
||||
break
|
||||
}
|
||||
}
|
||||
if string(got) != tt.want {
|
||||
t.Errorf("%d:%s:\ngot %+q;\nwant %+q", i, tt.desc, got, tt.want)
|
||||
}
|
||||
testHandover(t, Caser{tt.t}, tt.src)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpan(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
desc string
|
||||
src string
|
||||
want string
|
||||
atEOF bool
|
||||
err error
|
||||
t Caser
|
||||
}{{
|
||||
desc: "und/upper/basic",
|
||||
src: "abcdefg",
|
||||
want: "",
|
||||
atEOF: true,
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/upper/short src",
|
||||
src: "123É"[:4],
|
||||
want: "123",
|
||||
atEOF: false,
|
||||
err: transform.ErrShortSrc,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/upper/no error on short",
|
||||
src: "12",
|
||||
want: "12",
|
||||
atEOF: false,
|
||||
t: Upper(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/basic",
|
||||
src: "ABCDEFG",
|
||||
want: "",
|
||||
atEOF: true,
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/short src num",
|
||||
src: "123é"[:4],
|
||||
want: "123",
|
||||
atEOF: false,
|
||||
err: transform.ErrShortSrc,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/short src greek",
|
||||
src: "αβγé"[:7],
|
||||
want: "αβγ",
|
||||
atEOF: false,
|
||||
err: transform.ErrShortSrc,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/no error on short",
|
||||
src: "12",
|
||||
want: "12",
|
||||
atEOF: false,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/lower/simple (no final sigma)",
|
||||
src: "ος οσσ",
|
||||
want: "οσ οσσ",
|
||||
atEOF: true,
|
||||
t: Lower(language.Und, HandleFinalSigma(false)),
|
||||
}, {
|
||||
desc: "und/title/simple (no final sigma)",
|
||||
src: "Οσ Οσσ",
|
||||
want: "Οσ Οσσ",
|
||||
atEOF: true,
|
||||
t: Title(language.Und, HandleFinalSigma(false)),
|
||||
}, {
|
||||
desc: "und/lower/final sigma: no error",
|
||||
src: "οΣ", // Oς
|
||||
want: "ο", // Oς
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Lower(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: no error",
|
||||
src: "ΟΣ", // Oς
|
||||
want: "Ο", // Oς
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/final sigma: no short source!",
|
||||
src: "ΟσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσΣ",
|
||||
want: "Οσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσσ",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/clipped UTF-8 rune",
|
||||
src: "Σσ" + string([]byte{0xCF}),
|
||||
want: "Σσ",
|
||||
atEOF: false,
|
||||
err: transform.ErrShortSrc,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "und/title/clipped UTF-8 rune atEOF",
|
||||
src: "Σσσ" + string([]byte{0xCF}),
|
||||
want: "Σσσ" + string([]byte{0xCF}),
|
||||
atEOF: true,
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/long string",
|
||||
src: "A" + strings.Repeat("a", maxIgnorable+5),
|
||||
want: "A" + strings.Repeat("a", maxIgnorable+5),
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/cyrillic",
|
||||
src: "При",
|
||||
want: "При",
|
||||
atEOF: true,
|
||||
t: Title(language.Und, HandleFinalSigma(false)),
|
||||
}, {
|
||||
// Note: the choice to change the final sigma at the end in case of
|
||||
// too many case ignorables is arbitrary. The main reason for this
|
||||
// choice is that it results in simpler code.
|
||||
desc: "und/title/final sigma: max ignorables",
|
||||
src: "Οσ" + strings.Repeat(".", maxIgnorable) + "A",
|
||||
want: "Οσ" + strings.Repeat(".", maxIgnorable) + "A",
|
||||
t: Title(language.Und),
|
||||
}, {
|
||||
desc: "el/upper/max ignorables - not implemented",
|
||||
src: "Ο" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0313",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "el/upper/too many ignorables - not implemented",
|
||||
src: "Ο" + strings.Repeat("\u0321", maxIgnorable) + "\u0313",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "el/upper/short dst",
|
||||
src: "123ο",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Greek),
|
||||
}, {
|
||||
desc: "lt/lower/max ignorables",
|
||||
src: "i" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0307\u0300",
|
||||
want: "i" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0307\u0300",
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/isLower",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable) + "\u0300",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/not identical",
|
||||
src: "aaaaa\u00cc", // U+00CC LATIN CAPITAL LETTER I GRAVE
|
||||
err: transform.ErrEndOfSpan,
|
||||
want: "aaaaa",
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/lower/identical",
|
||||
src: "aaaai\u0307\u0300", // U+00CC LATIN CAPITAL LETTER I GRAVE
|
||||
want: "aaaai\u0307\u0300",
|
||||
t: Lower(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/upper/not implemented",
|
||||
src: "I" + strings.Repeat("\u0321", maxIgnorable-1) + "\u0300",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Lithuanian),
|
||||
}, {
|
||||
desc: "lt/upper/not implemented, ascii",
|
||||
src: "AB",
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Upper(language.Lithuanian),
|
||||
}, {
|
||||
desc: "nl/title/pre-IJ cutoff",
|
||||
src: " IJ",
|
||||
want: " IJ",
|
||||
t: Title(language.Dutch),
|
||||
}, {
|
||||
desc: "nl/title/mid-IJ cutoff",
|
||||
src: " Ia",
|
||||
want: " Ia",
|
||||
t: Title(language.Dutch),
|
||||
}, {
|
||||
desc: "af/title/apostrophe",
|
||||
src: "'n Bietje",
|
||||
want: "'n Bietje",
|
||||
t: Title(language.Afrikaans),
|
||||
}, {
|
||||
desc: "af/title/apostrophe-incorrect",
|
||||
src: "'N Bietje",
|
||||
// The Single_Quote (a MidWord), needs to be retained as unspanned so
|
||||
// that a successive call to Transform can detect that N should not be
|
||||
// capitalized.
|
||||
want: "",
|
||||
err: transform.ErrEndOfSpan,
|
||||
t: Title(language.Afrikaans),
|
||||
}} {
|
||||
testtext.Run(t, tt.desc, func(t *testing.T) {
|
||||
for p := 0; p < len(tt.want); p += utf8.RuneLen([]rune(tt.src[p:])[0]) {
|
||||
tt.t.Reset()
|
||||
n, err := tt.t.Span([]byte(tt.src[:p]), false)
|
||||
if err != nil && err != transform.ErrShortSrc {
|
||||
t.Errorf("early failure:Span(%+q): %v (%d < %d)", tt.src[:p], err, n, len(tt.want))
|
||||
break
|
||||
}
|
||||
}
|
||||
tt.t.Reset()
|
||||
n, err := tt.t.Span([]byte(tt.src), tt.atEOF)
|
||||
if n != len(tt.want) || err != tt.err {
|
||||
t.Errorf("Span(%+q, %v): got %d, %v; want %d, %v", tt.src, tt.atEOF, n, err, len(tt.want), tt.err)
|
||||
}
|
||||
testHandover(t, tt.t, tt.src)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var txtASCII = strings.Repeat("The quick brown fox jumps over the lazy dog. ", 50)
|
||||
|
||||
// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
|
||||
const txt_vn = `Với các điều kiện sau: Ghi nhận công của tác giả. Nếu bạn sử
|
||||
dụng, chuyển đổi, hoặc xây dựng dự án từ nội dung được chia sẻ này, bạn phải áp
|
||||
dụng giấy phép này hoặc một giấy phép khác có các điều khoản tương tự như giấy
|
||||
phép này cho dự án của bạn. Hiểu rằng: Miễn — Bất kỳ các điều kiện nào trên đây
|
||||
cũng có thể được miễn bỏ nếu bạn được sự cho phép của người sở hữu bản quyền.
|
||||
Phạm vi công chúng — Khi tác phẩm hoặc bất kỳ chương nào của tác phẩm đã trong
|
||||
vùng dành cho công chúng theo quy định của pháp luật thì tình trạng của nó không
|
||||
bị ảnh hưởng bởi giấy phép trong bất kỳ trường hợp nào.`
|
||||
|
||||
// http://creativecommons.org/licenses/by-sa/2.5/cn/
|
||||
const txt_cn = `您可以自由: 复制、发行、展览、表演、放映、
|
||||
广播或通过信息网络传播本作品 创作演绎作品
|
||||
对本作品进行商业性使用 惟须遵守下列条件:
|
||||
署名 — 您必须按照作者或者许可人指定的方式对作品进行署名。
|
||||
相同方式共享 — 如果您改变、转换本作品或者以本作品为基础进行创作,
|
||||
您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。`
|
||||
|
||||
// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
|
||||
const txt_ru = `При обязательном соблюдении следующих условий: Attribution — Вы
|
||||
должны атрибутировать произведение (указывать автора и источник) в порядке,
|
||||
предусмотренном автором или лицензиаром (но только так, чтобы никоим образом не
|
||||
подразумевалось, что они поддерживают вас или использование вами данного
|
||||
произведения). Υπό τις ακόλουθες προϋποθέσεις:`
|
||||
|
||||
// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
|
||||
const txt_gr = `Αναφορά Δημιουργού — Θα πρέπει να κάνετε την αναφορά στο έργο με
|
||||
τον τρόπο που έχει οριστεί από το δημιουργό ή το χορηγούντο την άδεια (χωρίς
|
||||
όμως να εννοείται με οποιονδήποτε τρόπο ότι εγκρίνουν εσάς ή τη χρήση του έργου
|
||||
από εσάς). Παρόμοια Διανομή — Εάν αλλοιώσετε, τροποποιήσετε ή δημιουργήσετε
|
||||
περαιτέρω βασισμένοι στο έργο θα μπορείτε να διανέμετε το έργο που θα προκύψει
|
||||
μόνο με την ίδια ή παρόμοια άδεια.`
|
||||
|
||||
const txtNonASCII = txt_vn + txt_cn + txt_ru + txt_gr
|
||||
|
||||
// TODO: Improve ASCII performance.
|
||||
|
||||
func BenchmarkCasers(b *testing.B) {
|
||||
for _, s := range []struct{ name, text string }{
|
||||
{"ascii", txtASCII},
|
||||
{"nonASCII", txtNonASCII},
|
||||
{"short", "При"},
|
||||
} {
|
||||
src := []byte(s.text)
|
||||
// Measure case mappings in bytes package for comparison.
|
||||
for _, f := range []struct {
|
||||
name string
|
||||
fn func(b []byte) []byte
|
||||
}{
|
||||
{"lower", bytes.ToLower},
|
||||
{"title", bytes.ToTitle},
|
||||
{"upper", bytes.ToUpper},
|
||||
} {
|
||||
testtext.Bench(b, path.Join(s.name, "bytes", f.name), func(b *testing.B) {
|
||||
b.SetBytes(int64(len(src)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
f.fn(src)
|
||||
}
|
||||
})
|
||||
}
|
||||
for _, t := range []struct {
|
||||
name string
|
||||
caser transform.SpanningTransformer
|
||||
}{
|
||||
{"fold/default", Fold()},
|
||||
{"upper/default", Upper(language.Und)},
|
||||
{"lower/sigma", Lower(language.Und)},
|
||||
{"lower/simple", Lower(language.Und, HandleFinalSigma(false))},
|
||||
{"title/sigma", Title(language.Und)},
|
||||
{"title/simple", Title(language.Und, HandleFinalSigma(false))},
|
||||
} {
|
||||
c := Caser{t.caser}
|
||||
dst := make([]byte, len(src))
|
||||
testtext.Bench(b, path.Join(s.name, t.name, "transform"), func(b *testing.B) {
|
||||
b.SetBytes(int64(len(src)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Reset()
|
||||
c.Transform(dst, src, true)
|
||||
}
|
||||
})
|
||||
// No need to check span for simple cases, as they will be the same
|
||||
// as sigma.
|
||||
if strings.HasSuffix(t.name, "/simple") {
|
||||
continue
|
||||
}
|
||||
spanSrc := c.Bytes(src)
|
||||
testtext.Bench(b, path.Join(s.name, t.name, "span"), func(b *testing.B) {
|
||||
c.Reset()
|
||||
if n, _ := c.Span(spanSrc, true); n < len(spanSrc) {
|
||||
b.Fatalf("spanner is not recognizing text %q as done (at %d)", spanSrc, n)
|
||||
}
|
||||
b.SetBytes(int64(len(spanSrc)))
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Reset()
|
||||
c.Span(spanSrc, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
2251
vendor/golang.org/x/text/cases/tables.go
generated
vendored
2251
vendor/golang.org/x/text/cases/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
1158
vendor/golang.org/x/text/cases/tables_test.go
generated
vendored
1158
vendor/golang.org/x/text/cases/tables_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
215
vendor/golang.org/x/text/cases/trieval.go
generated
vendored
215
vendor/golang.org/x/text/cases/trieval.go
generated
vendored
|
|
@ -1,215 +0,0 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package cases
|
||||
|
||||
// This file contains definitions for interpreting the trie value of the case
|
||||
// trie generated by "go run gen*.go". It is shared by both the generator
|
||||
// program and the resultant package. Sharing is achieved by the generator
|
||||
// copying gen_trieval.go to trieval.go and changing what's above this comment.
|
||||
|
||||
// info holds case information for a single rune. It is the value returned
|
||||
// by a trie lookup. Most mapping information can be stored in a single 16-bit
|
||||
// value. If not, for example when a rune is mapped to multiple runes, the value
|
||||
// stores some basic case data and an index into an array with additional data.
|
||||
//
|
||||
// The per-rune values have the following format:
|
||||
//
|
||||
// if (exception) {
|
||||
// 15..5 unsigned exception index
|
||||
// 4 unused
|
||||
// } else {
|
||||
// 15..8 XOR pattern or index to XOR pattern for case mapping
|
||||
// Only 13..8 are used for XOR patterns.
|
||||
// 7 inverseFold (fold to upper, not to lower)
|
||||
// 6 index: interpret the XOR pattern as an index
|
||||
// or isMid if case mode is cIgnorableUncased.
|
||||
// 5..4 CCC: zero (normal or break), above or other
|
||||
// }
|
||||
// 3 exception: interpret this value as an exception index
|
||||
// (TODO: is this bit necessary? Probably implied from case mode.)
|
||||
// 2..0 case mode
|
||||
//
|
||||
// For the non-exceptional cases, a rune must be either uncased, lowercase or
|
||||
// uppercase. If the rune is cased, the XOR pattern maps either a lowercase
|
||||
// rune to uppercase or an uppercase rune to lowercase (applied to the 10
|
||||
// least-significant bits of the rune).
|
||||
//
|
||||
// See the definitions below for a more detailed description of the various
|
||||
// bits.
|
||||
type info uint16
|
||||
|
||||
const (
|
||||
casedMask = 0x0003
|
||||
fullCasedMask = 0x0007
|
||||
ignorableMask = 0x0006
|
||||
ignorableValue = 0x0004
|
||||
|
||||
inverseFoldBit = 1 << 7
|
||||
isMidBit = 1 << 6
|
||||
|
||||
exceptionBit = 1 << 3
|
||||
exceptionShift = 5
|
||||
numExceptionBits = 11
|
||||
|
||||
xorIndexBit = 1 << 6
|
||||
xorShift = 8
|
||||
|
||||
// There is no mapping if all xor bits and the exception bit are zero.
|
||||
hasMappingMask = 0xff80 | exceptionBit
|
||||
)
|
||||
|
||||
// The case mode bits encodes the case type of a rune. This includes uncased,
|
||||
// title, upper and lower case and case ignorable. (For a definition of these
|
||||
// terms see Chapter 3 of The Unicode Standard Core Specification.) In some rare
|
||||
// cases, a rune can be both cased and case-ignorable. This is encoded by
|
||||
// cIgnorableCased. A rune of this type is always lower case. Some runes are
|
||||
// cased while not having a mapping.
|
||||
//
|
||||
// A common pattern for scripts in the Unicode standard is for upper and lower
|
||||
// case runes to alternate for increasing rune values (e.g. the accented Latin
|
||||
// ranges starting from U+0100 and U+1E00 among others and some Cyrillic
|
||||
// characters). We use this property by defining a cXORCase mode, where the case
|
||||
// mode (always upper or lower case) is derived from the rune value. As the XOR
|
||||
// pattern for case mappings is often identical for successive runes, using
|
||||
// cXORCase can result in large series of identical trie values. This, in turn,
|
||||
// allows us to better compress the trie blocks.
|
||||
const (
|
||||
cUncased info = iota // 000
|
||||
cTitle // 001
|
||||
cLower // 010
|
||||
cUpper // 011
|
||||
cIgnorableUncased // 100
|
||||
cIgnorableCased // 101 // lower case if mappings exist
|
||||
cXORCase // 11x // case is cLower | ((rune&1) ^ x)
|
||||
|
||||
maxCaseMode = cUpper
|
||||
)
|
||||
|
||||
func (c info) isCased() bool {
|
||||
return c&casedMask != 0
|
||||
}
|
||||
|
||||
func (c info) isCaseIgnorable() bool {
|
||||
return c&ignorableMask == ignorableValue
|
||||
}
|
||||
|
||||
func (c info) isNotCasedAndNotCaseIgnorable() bool {
|
||||
return c&fullCasedMask == 0
|
||||
}
|
||||
|
||||
func (c info) isCaseIgnorableAndNotCased() bool {
|
||||
return c&fullCasedMask == cIgnorableUncased
|
||||
}
|
||||
|
||||
func (c info) isMid() bool {
|
||||
return c&(fullCasedMask|isMidBit) == isMidBit|cIgnorableUncased
|
||||
}
|
||||
|
||||
// The case mapping implementation will need to know about various Canonical
|
||||
// Combining Class (CCC) values. We encode two of these in the trie value:
|
||||
// cccZero (0) and cccAbove (230). If the value is cccOther, it means that
|
||||
// CCC(r) > 0, but not 230. A value of cccBreak means that CCC(r) == 0 and that
|
||||
// the rune also has the break category Break (see below).
|
||||
const (
|
||||
cccBreak info = iota << 4
|
||||
cccZero
|
||||
cccAbove
|
||||
cccOther
|
||||
|
||||
cccMask = cccBreak | cccZero | cccAbove | cccOther
|
||||
)
|
||||
|
||||
const (
|
||||
starter = 0
|
||||
above = 230
|
||||
iotaSubscript = 240
|
||||
)
|
||||
|
||||
// The exceptions slice holds data that does not fit in a normal info entry.
|
||||
// The entry is pointed to by the exception index in an entry. It has the
|
||||
// following format:
|
||||
//
|
||||
// Header
|
||||
// byte 0:
|
||||
// 7..6 unused
|
||||
// 5..4 CCC type (same bits as entry)
|
||||
// 3 unused
|
||||
// 2..0 length of fold
|
||||
//
|
||||
// byte 1:
|
||||
// 7..6 unused
|
||||
// 5..3 length of 1st mapping of case type
|
||||
// 2..0 length of 2nd mapping of case type
|
||||
//
|
||||
// case 1st 2nd
|
||||
// lower -> upper, title
|
||||
// upper -> lower, title
|
||||
// title -> lower, upper
|
||||
//
|
||||
// Lengths with the value 0x7 indicate no value and implies no change.
|
||||
// A length of 0 indicates a mapping to zero-length string.
|
||||
//
|
||||
// Body bytes:
|
||||
// case folding bytes
|
||||
// lowercase mapping bytes
|
||||
// uppercase mapping bytes
|
||||
// titlecase mapping bytes
|
||||
// closure mapping bytes (for NFKC_Casefold). (TODO)
|
||||
//
|
||||
// Fallbacks:
|
||||
// missing fold -> lower
|
||||
// missing title -> upper
|
||||
// all missing -> original rune
|
||||
//
|
||||
// exceptions starts with a dummy byte to enforce that there is no zero index
|
||||
// value.
|
||||
const (
|
||||
lengthMask = 0x07
|
||||
lengthBits = 3
|
||||
noChange = 0
|
||||
)
|
||||
|
||||
// References to generated trie.
|
||||
|
||||
var trie = newCaseTrie(0)
|
||||
|
||||
var sparse = sparseBlocks{
|
||||
values: sparseValues[:],
|
||||
offsets: sparseOffsets[:],
|
||||
}
|
||||
|
||||
// Sparse block lookup code.
|
||||
|
||||
// valueRange is an entry in a sparse block.
|
||||
type valueRange struct {
|
||||
value uint16
|
||||
lo, hi byte
|
||||
}
|
||||
|
||||
type sparseBlocks struct {
|
||||
values []valueRange
|
||||
offsets []uint16
|
||||
}
|
||||
|
||||
// lookup returns the value from values block n for byte b using binary search.
|
||||
func (s *sparseBlocks) lookup(n uint32, b byte) uint16 {
|
||||
lo := s.offsets[n]
|
||||
hi := s.offsets[n+1]
|
||||
for lo < hi {
|
||||
m := lo + (hi-lo)/2
|
||||
r := s.values[m]
|
||||
if r.lo <= b && b <= r.hi {
|
||||
return r.value
|
||||
}
|
||||
if b < r.lo {
|
||||
hi = m
|
||||
} else {
|
||||
lo = m + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// lastRuneForTesting is the last rune used for testing. Everything after this
|
||||
// is boring.
|
||||
const lastRuneForTesting = rune(0x1FFFF)
|
||||
35
vendor/golang.org/x/text/cmd/gotext/doc.go
generated
vendored
35
vendor/golang.org/x/text/cmd/gotext/doc.go
generated
vendored
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// DO NOT EDIT THIS FILE. GENERATED BY go generate.
|
||||
// Edit the documentation in other files and rerun go generate to generate this one.
|
||||
|
||||
// gotext is a tool for managing text in Go source code.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// gotext command [arguments]
|
||||
//
|
||||
// The commands are:
|
||||
//
|
||||
// extract extract strings to be translated from code
|
||||
//
|
||||
// Use "go help [command]" for more information about a command.
|
||||
//
|
||||
// Additional help topics:
|
||||
//
|
||||
//
|
||||
// Use "gotext help [topic]" for more information about that topic.
|
||||
//
|
||||
//
|
||||
// Extract strings to be translated from code
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go extract <package>*
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
package main
|
||||
195
vendor/golang.org/x/text/cmd/gotext/extract.go
generated
vendored
195
vendor/golang.org/x/text/cmd/gotext/extract.go
generated
vendored
|
|
@ -1,195 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/constant"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - merge information into existing files
|
||||
// - handle different file formats (PO, XLIFF)
|
||||
// - handle features (gender, plural)
|
||||
// - message rewriting
|
||||
|
||||
var cmdExtract = &Command{
|
||||
Run: runExtract,
|
||||
UsageLine: "extract <package>*",
|
||||
Short: "extract strings to be translated from code",
|
||||
}
|
||||
|
||||
func runExtract(cmd *Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
args = []string{"."}
|
||||
}
|
||||
|
||||
conf := loader.Config{
|
||||
Build: &build.Default,
|
||||
ParserMode: parser.ParseComments,
|
||||
}
|
||||
|
||||
// Use the initial packages from the command line.
|
||||
args, err := conf.FromArgs(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load, parse and type-check the whole program.
|
||||
iprog, err := conf.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// print returns Go syntax for the specified node.
|
||||
print := func(n ast.Node) string {
|
||||
var buf bytes.Buffer
|
||||
format.Node(&buf, conf.Fset, n)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var translations []Translation
|
||||
|
||||
for _, info := range iprog.InitialPackages() {
|
||||
for _, f := range info.Files {
|
||||
// Associate comments with nodes.
|
||||
cmap := ast.NewCommentMap(iprog.Fset, f, f.Comments)
|
||||
getComment := func(n ast.Node) string {
|
||||
cs := cmap.Filter(n).Comments()
|
||||
if len(cs) > 0 {
|
||||
return strings.TrimSpace(cs[0].Text())
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Find function calls.
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
call, ok := n.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// Skip calls of functions other than
|
||||
// (*message.Printer).{Sp,Fp,P}rintf.
|
||||
sel, ok := call.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
meth := info.Selections[sel]
|
||||
if meth == nil || meth.Kind() != types.MethodVal {
|
||||
return true
|
||||
}
|
||||
// TODO: remove cheap hack and check if the type either
|
||||
// implements some interface or is specifically of type
|
||||
// "golang.org/x/text/message".Printer.
|
||||
m, ok := extractFuncs[path.Base(meth.Recv().String())]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// argn is the index of the format string.
|
||||
argn, ok := m[meth.Obj().Name()]
|
||||
if !ok || argn >= len(call.Args) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Skip calls with non-constant format string.
|
||||
fmtstr := info.Types[call.Args[argn]].Value
|
||||
if fmtstr == nil || fmtstr.Kind() != constant.String {
|
||||
return true
|
||||
}
|
||||
|
||||
posn := conf.Fset.Position(call.Lparen)
|
||||
filepos := fmt.Sprintf("%s:%d:%d", filepath.Base(posn.Filename), posn.Line, posn.Column)
|
||||
|
||||
// TODO: identify the type of the format argument. If it is not
|
||||
// a string, multiple keys may be defined.
|
||||
var key []string
|
||||
|
||||
// TODO: replace substitutions (%v) with a translator friendly
|
||||
// notation. For instance:
|
||||
// "%d files remaining" -> "{numFiles} files remaining", or
|
||||
// "%d files remaining" -> "{arg1} files remaining"
|
||||
// Alternatively, this could be done at a later stage.
|
||||
msg := constant.StringVal(fmtstr)
|
||||
|
||||
// Construct a Translation unit.
|
||||
c := Translation{
|
||||
Key: key,
|
||||
Position: filepath.Join(info.Pkg.Path(), filepos),
|
||||
Original: Text{Msg: msg},
|
||||
ExtractedComment: getComment(call.Args[0]),
|
||||
// TODO(fix): this doesn't get the before comment.
|
||||
// Comment: getComment(call),
|
||||
}
|
||||
|
||||
for i, arg := range call.Args[argn+1:] {
|
||||
var val string
|
||||
if v := info.Types[arg].Value; v != nil {
|
||||
val = v.ExactString()
|
||||
}
|
||||
posn := conf.Fset.Position(arg.Pos())
|
||||
filepos := fmt.Sprintf("%s:%d:%d", filepath.Base(posn.Filename), posn.Line, posn.Column)
|
||||
c.Args = append(c.Args, Argument{
|
||||
ID: i + 1,
|
||||
Type: info.Types[arg].Type.String(),
|
||||
UnderlyingType: info.Types[arg].Type.Underlying().String(),
|
||||
Expr: print(arg),
|
||||
Value: val,
|
||||
Comment: getComment(arg),
|
||||
Position: filepath.Join(info.Pkg.Path(), filepos),
|
||||
// TODO report whether it implements
|
||||
// interfaces plural.Interface,
|
||||
// gender.Interface.
|
||||
})
|
||||
}
|
||||
|
||||
translations = append(translations, c)
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(translations, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tag := range getLangs() {
|
||||
// TODO: merge with existing files, don't overwrite.
|
||||
os.MkdirAll(*dir, 0744)
|
||||
file := filepath.Join(*dir, fmt.Sprintf("gotext_%v.out.json", tag))
|
||||
if err := ioutil.WriteFile(file, data, 0744); err != nil {
|
||||
return fmt.Errorf("could not create file: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractFuncs indicates the types and methods for which to extract strings,
|
||||
// and which argument to extract.
|
||||
// TODO: use the types in conf.Import("golang.org/x/text/message") to extract
|
||||
// the correct instances.
|
||||
var extractFuncs = map[string]map[string]int{
|
||||
// TODO: Printer -> *golang.org/x/text/message.Printer
|
||||
"message.Printer": {
|
||||
"Printf": 0,
|
||||
"Sprintf": 0,
|
||||
"Fprintf": 1,
|
||||
},
|
||||
}
|
||||
356
vendor/golang.org/x/text/cmd/gotext/main.go
generated
vendored
356
vendor/golang.org/x/text/cmd/gotext/main.go
generated
vendored
|
|
@ -1,356 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go build -o gotext.latest
|
||||
//go:generate ./gotext.latest help gendocumentation
|
||||
//go:generate rm gotext.latest
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/tools/go/buildutil"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
|
||||
}
|
||||
|
||||
var (
|
||||
dir = flag.String("dir", "textdata", "default subdirectory to store translation files")
|
||||
langs = flag.String("lang", "en", "comma-separated list of languages to process")
|
||||
)
|
||||
|
||||
// NOTE: the Command struct is copied from the go tool in core.
|
||||
|
||||
// A Command is an implementation of a go command
|
||||
// like go build or go fix.
|
||||
type Command struct {
|
||||
// Run runs the command.
|
||||
// The args are the arguments after the command name.
|
||||
Run func(cmd *Command, args []string) error
|
||||
|
||||
// UsageLine is the one-line usage message.
|
||||
// The first word in the line is taken to be the command name.
|
||||
UsageLine string
|
||||
|
||||
// Short is the short description shown in the 'go help' output.
|
||||
Short string
|
||||
|
||||
// Long is the long message shown in the 'go help <this-command>' output.
|
||||
Long string
|
||||
|
||||
// Flag is a set of flags specific to this command.
|
||||
Flag flag.FlagSet
|
||||
}
|
||||
|
||||
// Name returns the command's name: the first word in the usage line.
|
||||
func (c *Command) Name() string {
|
||||
name := c.UsageLine
|
||||
i := strings.Index(name, " ")
|
||||
if i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (c *Command) Usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
|
||||
fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// Runnable reports whether the command can be run; otherwise
|
||||
// it is a documentation pseudo-command such as importpath.
|
||||
func (c *Command) Runnable() bool {
|
||||
return c.Run != nil
|
||||
}
|
||||
|
||||
// Commands lists the available commands and help topics.
|
||||
// The order here is the order in which they are printed by 'go help'.
|
||||
var commands = []*Command{
|
||||
cmdExtract,
|
||||
// TODO:
|
||||
// - generate code from translations.
|
||||
// - update: full-cycle update of extraction, sending, and integration
|
||||
// - report: report of freshness of translations
|
||||
}
|
||||
|
||||
var exitStatus = 0
|
||||
var exitMu sync.Mutex
|
||||
|
||||
func setExitStatus(n int) {
|
||||
exitMu.Lock()
|
||||
if exitStatus < n {
|
||||
exitStatus = n
|
||||
}
|
||||
exitMu.Unlock()
|
||||
}
|
||||
|
||||
var origEnv []string
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
usage()
|
||||
}
|
||||
|
||||
if args[0] == "help" {
|
||||
help(args[1:])
|
||||
return
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] && cmd.Runnable() {
|
||||
cmd.Flag.Usage = func() { cmd.Usage() }
|
||||
cmd.Flag.Parse(args[1:])
|
||||
args = cmd.Flag.Args()
|
||||
if err := cmd.Run(cmd, args); err != nil {
|
||||
fatalf("gotext: %v", err)
|
||||
}
|
||||
exit()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "gotext: unknown subcommand %q\nRun 'go help' for usage.\n", args[0])
|
||||
setExitStatus(2)
|
||||
exit()
|
||||
}
|
||||
|
||||
var usageTemplate = `gotext is a tool for managing text in Go source code.
|
||||
|
||||
Usage:
|
||||
|
||||
gotext command [arguments]
|
||||
|
||||
The commands are:
|
||||
{{range .}}{{if .Runnable}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use "go help [command]" for more information about a command.
|
||||
|
||||
Additional help topics:
|
||||
{{range .}}{{if not .Runnable}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}
|
||||
|
||||
Use "gotext help [topic]" for more information about that topic.
|
||||
|
||||
`
|
||||
|
||||
var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}
|
||||
|
||||
{{end}}{{.Long | trim}}
|
||||
`
|
||||
|
||||
var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}}
|
||||
|
||||
{{end}}{{if .Runnable}}Usage:
|
||||
|
||||
go {{.UsageLine}}
|
||||
|
||||
{{end}}{{.Long | trim}}
|
||||
|
||||
|
||||
{{end}}`
|
||||
|
||||
// commentWriter writes a Go comment to the underlying io.Writer,
|
||||
// using line comment form (//).
|
||||
type commentWriter struct {
|
||||
W io.Writer
|
||||
wroteSlashes bool // Wrote "//" at the beginning of the current line.
|
||||
}
|
||||
|
||||
func (c *commentWriter) Write(p []byte) (int, error) {
|
||||
var n int
|
||||
for i, b := range p {
|
||||
if !c.wroteSlashes {
|
||||
s := "//"
|
||||
if b != '\n' {
|
||||
s = "// "
|
||||
}
|
||||
if _, err := io.WriteString(c.W, s); err != nil {
|
||||
return n, err
|
||||
}
|
||||
c.wroteSlashes = true
|
||||
}
|
||||
n0, err := c.W.Write(p[i : i+1])
|
||||
n += n0
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
if b == '\n' {
|
||||
c.wroteSlashes = false
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// An errWriter wraps a writer, recording whether a write error occurred.
|
||||
type errWriter struct {
|
||||
w io.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
func (w *errWriter) Write(b []byte) (int, error) {
|
||||
n, err := w.w.Write(b)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// tmpl executes the given template text on data, writing the result to w.
|
||||
func tmpl(w io.Writer, text string, data interface{}) {
|
||||
t := template.New("top")
|
||||
t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
|
||||
template.Must(t.Parse(text))
|
||||
ew := &errWriter{w: w}
|
||||
err := t.Execute(ew, data)
|
||||
if ew.err != nil {
|
||||
// I/O error writing. Ignore write on closed pipe.
|
||||
if strings.Contains(ew.err.Error(), "pipe") {
|
||||
os.Exit(1)
|
||||
}
|
||||
fatalf("writing output: %v", ew.err)
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func capitalize(s string) string {
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
r, n := utf8.DecodeRuneInString(s)
|
||||
return string(unicode.ToTitle(r)) + s[n:]
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
bw := bufio.NewWriter(w)
|
||||
tmpl(bw, usageTemplate, commands)
|
||||
bw.Flush()
|
||||
}
|
||||
|
||||
func usage() {
|
||||
printUsage(os.Stderr)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
// help implements the 'help' command.
|
||||
func help(args []string) {
|
||||
if len(args) == 0 {
|
||||
printUsage(os.Stdout)
|
||||
// not exit 2: succeeded at 'go help'.
|
||||
return
|
||||
}
|
||||
if len(args) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
|
||||
os.Exit(2) // failed at 'go help'
|
||||
}
|
||||
|
||||
arg := args[0]
|
||||
|
||||
// 'go help documentation' generates doc.go.
|
||||
if strings.HasSuffix(arg, "documentation") {
|
||||
w := &bytes.Buffer{}
|
||||
|
||||
fmt.Fprintln(w, "// Copyright 2016 The Go Authors. All rights reserved.")
|
||||
fmt.Fprintln(w, "// Use of this source code is governed by a BSD-style")
|
||||
fmt.Fprintln(w, "// license that can be found in the LICENSE file.")
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "// DO NOT EDIT THIS FILE. GENERATED BY go generate.")
|
||||
fmt.Fprintln(w, "// Edit the documentation in other files and rerun go generate to generate this one.")
|
||||
fmt.Fprintln(w)
|
||||
buf := new(bytes.Buffer)
|
||||
printUsage(buf)
|
||||
usage := &Command{Long: buf.String()}
|
||||
tmpl(&commentWriter{W: w}, documentationTemplate, append([]*Command{usage}, commands...))
|
||||
fmt.Fprintln(w, "package main")
|
||||
if arg == "gendocumentation" {
|
||||
b, err := format.Source(w.Bytes())
|
||||
if err != nil {
|
||||
errorf("Could not format generated docs: %v\n", err)
|
||||
}
|
||||
if err := ioutil.WriteFile("doc.go", b, 0666); err != nil {
|
||||
errorf("Could not create file alldocs.go: %v\n", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println(w.String())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == arg {
|
||||
tmpl(os.Stdout, helpTemplate, cmd)
|
||||
// not exit 2: succeeded at 'go help cmd'.
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg)
|
||||
os.Exit(2) // failed at 'go help cmd'
|
||||
}
|
||||
|
||||
func getLangs() (tags []language.Tag) {
|
||||
for _, t := range strings.Split(*langs, ",") {
|
||||
tag, err := language.Parse(t)
|
||||
if err != nil {
|
||||
fatalf("gotext: could not parse language %q: %v", t, err)
|
||||
}
|
||||
tags = append(tags, tag)
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
var atexitFuncs []func()
|
||||
|
||||
func atexit(f func()) {
|
||||
atexitFuncs = append(atexitFuncs, f)
|
||||
}
|
||||
|
||||
func exit() {
|
||||
for _, f := range atexitFuncs {
|
||||
f()
|
||||
}
|
||||
os.Exit(exitStatus)
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
errorf(format, args...)
|
||||
exit()
|
||||
}
|
||||
|
||||
func errorf(format string, args ...interface{}) {
|
||||
log.Printf(format, args...)
|
||||
setExitStatus(1)
|
||||
}
|
||||
|
||||
func exitIfErrors() {
|
||||
if exitStatus != 0 {
|
||||
exit()
|
||||
}
|
||||
}
|
||||
127
vendor/golang.org/x/text/cmd/gotext/message.go
generated
vendored
127
vendor/golang.org/x/text/cmd/gotext/message.go
generated
vendored
|
|
@ -1,127 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// TODO: these definitions should be moved to a package so that the can be used
|
||||
// by other tools.
|
||||
|
||||
// The file contains the structures used to define translations of a certain
|
||||
// messages.
|
||||
//
|
||||
// A translation may have multiple translations strings, or messages, depending
|
||||
// on the feature values of the various arguments. For instance, consider
|
||||
// a hypothetical translation from English to English, where the source defines
|
||||
// the format string "%d file(s) remaining". A completed translation, expressed
|
||||
// in JS, for this format string could look like:
|
||||
//
|
||||
// {
|
||||
// "Key": [
|
||||
// "\"%d files(s) remaining\""
|
||||
// ],
|
||||
// "Original": {
|
||||
// "Msg": "\"%d files(s) remaining\""
|
||||
// },
|
||||
// "Translation": {
|
||||
// "Select": {
|
||||
// "Feature": "plural",
|
||||
// "Arg": 1,
|
||||
// "Case": {
|
||||
// "one": { "Msg": "1 file remaining" },
|
||||
// "other": { "Msg": "%d files remaining" }
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// "Args": [
|
||||
// {
|
||||
// "ID": 2,
|
||||
// "Type": "int",
|
||||
// "UnderlyingType": "int",
|
||||
// "Expr": "nFiles",
|
||||
// "Comment": "number of files remaining",
|
||||
// "Position": "golang.org/x/text/cmd/gotext/demo.go:34:3"
|
||||
// }
|
||||
// ],
|
||||
// "Position": "golang.org/x/text/cmd/gotext/demo.go:33:10",
|
||||
// }
|
||||
//
|
||||
// Alternatively, the Translation section could be written as:
|
||||
//
|
||||
// "Translation": {
|
||||
// "Msg": "%d %[files]s remaining",
|
||||
// "Var": {
|
||||
// "files" : {
|
||||
// "Select": {
|
||||
// "Feature": "plural",
|
||||
// "Arg": 1,
|
||||
// "Case": {
|
||||
// "one": { "Msg": "file" },
|
||||
// "other": { "Msg": "files" }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// A Translation describes a translation for a single language for a single
|
||||
// message.
|
||||
type Translation struct {
|
||||
// Key contains a list of identifiers for the message. If this list is empty
|
||||
// Original is used as the key.
|
||||
Key []string `json:"key,omitempty"`
|
||||
Original Text `json:"original"`
|
||||
Translation Text `json:"translation"`
|
||||
ExtractedComment string `json:"extractedComment,omitempty"`
|
||||
TranslatorComment string `json:"translatorComment,omitempty"`
|
||||
|
||||
Args []Argument `json:"args,omitempty"`
|
||||
|
||||
// Extraction information.
|
||||
Position string `json:"position,omitempty"` // filePosition:line
|
||||
}
|
||||
|
||||
// An Argument contains information about the arguments passed to a message.
|
||||
type Argument struct {
|
||||
ID interface{} `json:"id"` // An int for printf-style calls, but could be a string.
|
||||
Type string `json:"type"`
|
||||
UnderlyingType string `json:"underlyingType"`
|
||||
Expr string `json:"expr"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
Position string `json:"position,omitempty"`
|
||||
|
||||
// Features contains the features that are available for the implementation
|
||||
// of this argument.
|
||||
Features []Feature `json:"features,omitempty"`
|
||||
}
|
||||
|
||||
// Feature holds information about a feature that can be implemented by
|
||||
// an Argument.
|
||||
type Feature struct {
|
||||
Type string `json:"type"` // Right now this is only gender and plural.
|
||||
|
||||
// TODO: possible values and examples for the language under consideration.
|
||||
|
||||
}
|
||||
|
||||
// Text defines a message to be displayed.
|
||||
type Text struct {
|
||||
// Msg and Select contains the message to be displayed. Within a Text value
|
||||
// either Msg or Select is defined.
|
||||
Msg string `json:"msg,omitempty"`
|
||||
Select *Select `json:"select,omitempty"`
|
||||
// Var defines a map of variables that may be substituted in the selected
|
||||
// message.
|
||||
Var map[string]Text `json:"var,omitempty"`
|
||||
// Example contains an example message formatted with default values.
|
||||
Example string `json:"example,omitempty"`
|
||||
}
|
||||
|
||||
// Type Select selects a Text based on the feature value associated with
|
||||
// a feature of a certain argument.
|
||||
type Select struct {
|
||||
Feature string `json:"feature"` // Name of variable or Feature type
|
||||
Arg interface{} `json:"arg"` // The argument ID.
|
||||
Cases map[string]Text `json:"cases"`
|
||||
}
|
||||
7
vendor/golang.org/x/text/collate/tools/colcmp/Makefile
generated
vendored
7
vendor/golang.org/x/text/collate/tools/colcmp/Makefile
generated
vendored
|
|
@ -1,7 +0,0 @@
|
|||
# Copyright 2012 The Go Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
chars:
|
||||
go run ../../maketables.go -tables=chars -package=main > chars.go
|
||||
gofmt -w -s chars.go
|
||||
1156
vendor/golang.org/x/text/collate/tools/colcmp/chars.go
generated
vendored
1156
vendor/golang.org/x/text/collate/tools/colcmp/chars.go
generated
vendored
File diff suppressed because one or more lines are too long
97
vendor/golang.org/x/text/collate/tools/colcmp/col.go
generated
vendored
97
vendor/golang.org/x/text/collate/tools/colcmp/col.go
generated
vendored
|
|
@ -1,97 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"unicode/utf16"
|
||||
|
||||
"golang.org/x/text/collate"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Input holds an input string in both UTF-8 and UTF-16 format.
|
||||
type Input struct {
|
||||
index int // used for restoring to original random order
|
||||
UTF8 []byte
|
||||
UTF16 []uint16
|
||||
key []byte // used for sorting
|
||||
}
|
||||
|
||||
func (i Input) String() string {
|
||||
return string(i.UTF8)
|
||||
}
|
||||
|
||||
func makeInput(s8 []byte, s16 []uint16) Input {
|
||||
return Input{UTF8: s8, UTF16: s16}
|
||||
}
|
||||
|
||||
func makeInputString(s string) Input {
|
||||
return Input{
|
||||
UTF8: []byte(s),
|
||||
UTF16: utf16.Encode([]rune(s)),
|
||||
}
|
||||
}
|
||||
|
||||
// Collator is an interface for architecture-specific implementations of collation.
|
||||
type Collator interface {
|
||||
// Key generates a sort key for the given input. Implemenations
|
||||
// may return nil if a collator does not support sort keys.
|
||||
Key(s Input) []byte
|
||||
|
||||
// Compare returns -1 if a < b, 1 if a > b and 0 if a == b.
|
||||
Compare(a, b Input) int
|
||||
}
|
||||
|
||||
// CollatorFactory creates a Collator for a given language tag.
|
||||
type CollatorFactory struct {
|
||||
name string
|
||||
makeFn func(tag string) (Collator, error)
|
||||
description string
|
||||
}
|
||||
|
||||
var collators = []CollatorFactory{}
|
||||
|
||||
// AddFactory registers f as a factory for an implementation of Collator.
|
||||
func AddFactory(f CollatorFactory) {
|
||||
collators = append(collators, f)
|
||||
}
|
||||
|
||||
func getCollator(name, locale string) Collator {
|
||||
for _, f := range collators {
|
||||
if f.name == name {
|
||||
col, err := f.makeFn(locale)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return col
|
||||
}
|
||||
}
|
||||
log.Fatalf("collator of type %q not found", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// goCollator is an implemention of Collator using go's own collator.
|
||||
type goCollator struct {
|
||||
c *collate.Collator
|
||||
buf collate.Buffer
|
||||
}
|
||||
|
||||
func init() {
|
||||
AddFactory(CollatorFactory{"go", newGoCollator, "Go's native collator implementation."})
|
||||
}
|
||||
|
||||
func newGoCollator(loc string) (Collator, error) {
|
||||
c := &goCollator{c: collate.New(language.Make(loc))}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *goCollator) Key(b Input) []byte {
|
||||
return c.c.Key(&c.buf, b.UTF8)
|
||||
}
|
||||
|
||||
func (c *goCollator) Compare(a, b Input) int {
|
||||
return c.c.Compare(a.UTF8, b.UTF8)
|
||||
}
|
||||
529
vendor/golang.org/x/text/collate/tools/colcmp/colcmp.go
generated
vendored
529
vendor/golang.org/x/text/collate/tools/colcmp/colcmp.go
generated
vendored
|
|
@ -1,529 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main // import "golang.org/x/text/collate/tools/colcmp"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
var (
|
||||
doNorm = flag.Bool("norm", false, "normalize input strings")
|
||||
cases = flag.Bool("case", false, "generate case variants")
|
||||
verbose = flag.Bool("verbose", false, "print results")
|
||||
debug = flag.Bool("debug", false, "output debug information")
|
||||
locales = flag.String("locale", "en_US", "the locale to use. May be a comma-separated list for some commands.")
|
||||
col = flag.String("col", "go", "collator to test")
|
||||
gold = flag.String("gold", "go", "collator used as the gold standard")
|
||||
usecmp = flag.Bool("usecmp", false,
|
||||
`use comparison instead of sort keys when sorting. Must be "test", "gold" or "both"`)
|
||||
cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
||||
exclude = flag.String("exclude", "", "exclude errors that contain any of the characters")
|
||||
limit = flag.Int("limit", 5000000, "maximum number of samples to generate for one run")
|
||||
)
|
||||
|
||||
func failOnError(err error) {
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test holds test data for testing a locale-collator pair.
|
||||
// Test also provides functionality that is commonly used by the various commands.
|
||||
type Test struct {
|
||||
ctxt *Context
|
||||
Name string
|
||||
Locale string
|
||||
ColName string
|
||||
|
||||
Col Collator
|
||||
UseCompare bool
|
||||
|
||||
Input []Input
|
||||
Duration time.Duration
|
||||
|
||||
start time.Time
|
||||
msg string
|
||||
count int
|
||||
}
|
||||
|
||||
func (t *Test) clear() {
|
||||
t.Col = nil
|
||||
t.Input = nil
|
||||
}
|
||||
|
||||
const (
|
||||
msgGeneratingInput = "generating input"
|
||||
msgGeneratingKeys = "generating keys"
|
||||
msgSorting = "sorting"
|
||||
)
|
||||
|
||||
var lastLen = 0
|
||||
|
||||
func (t *Test) SetStatus(msg string) {
|
||||
if *debug || *verbose {
|
||||
fmt.Printf("%s: %s...\n", t.Name, msg)
|
||||
} else if t.ctxt.out != nil {
|
||||
fmt.Fprint(t.ctxt.out, strings.Repeat(" ", lastLen))
|
||||
fmt.Fprint(t.ctxt.out, strings.Repeat("\b", lastLen))
|
||||
fmt.Fprint(t.ctxt.out, msg, "...")
|
||||
lastLen = len(msg) + 3
|
||||
fmt.Fprint(t.ctxt.out, strings.Repeat("\b", lastLen))
|
||||
}
|
||||
}
|
||||
|
||||
// Start is used by commands to signal the start of an operation.
|
||||
func (t *Test) Start(msg string) {
|
||||
t.SetStatus(msg)
|
||||
t.count = 0
|
||||
t.msg = msg
|
||||
t.start = time.Now()
|
||||
}
|
||||
|
||||
// Stop is used by commands to signal the end of an operation.
|
||||
func (t *Test) Stop() (time.Duration, int) {
|
||||
d := time.Now().Sub(t.start)
|
||||
t.Duration += d
|
||||
if *debug || *verbose {
|
||||
fmt.Printf("%s: %s done. (%.3fs /%dK ops)\n", t.Name, t.msg, d.Seconds(), t.count/1000)
|
||||
}
|
||||
return d, t.count
|
||||
}
|
||||
|
||||
// generateKeys generates sort keys for all the inputs.
|
||||
func (t *Test) generateKeys() {
|
||||
for i, s := range t.Input {
|
||||
b := t.Col.Key(s)
|
||||
t.Input[i].key = b
|
||||
if *debug {
|
||||
fmt.Printf("%s (%X): %X\n", string(s.UTF8), s.UTF16, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort sorts the inputs. It generates sort keys if this is required by the
|
||||
// chosen sort method.
|
||||
func (t *Test) Sort() (tkey, tsort time.Duration, nkey, nsort int) {
|
||||
if *cpuprofile != "" {
|
||||
f, err := os.Create(*cpuprofile)
|
||||
failOnError(err)
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
if t.UseCompare || t.Col.Key(t.Input[0]) == nil {
|
||||
t.Start(msgSorting)
|
||||
sort.Sort(&testCompare{*t})
|
||||
tsort, nsort = t.Stop()
|
||||
} else {
|
||||
t.Start(msgGeneratingKeys)
|
||||
t.generateKeys()
|
||||
t.count = len(t.Input)
|
||||
tkey, nkey = t.Stop()
|
||||
t.Start(msgSorting)
|
||||
sort.Sort(t)
|
||||
tsort, nsort = t.Stop()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (t *Test) Swap(a, b int) {
|
||||
t.Input[a], t.Input[b] = t.Input[b], t.Input[a]
|
||||
}
|
||||
|
||||
func (t *Test) Less(a, b int) bool {
|
||||
t.count++
|
||||
return bytes.Compare(t.Input[a].key, t.Input[b].key) == -1
|
||||
}
|
||||
|
||||
func (t Test) Len() int {
|
||||
return len(t.Input)
|
||||
}
|
||||
|
||||
type testCompare struct {
|
||||
Test
|
||||
}
|
||||
|
||||
func (t *testCompare) Less(a, b int) bool {
|
||||
t.count++
|
||||
return t.Col.Compare(t.Input[a], t.Input[b]) == -1
|
||||
}
|
||||
|
||||
type testRestore struct {
|
||||
Test
|
||||
}
|
||||
|
||||
func (t *testRestore) Less(a, b int) bool {
|
||||
return t.Input[a].index < t.Input[b].index
|
||||
}
|
||||
|
||||
// GenerateInput generates input phrases for the locale tested by t.
|
||||
func (t *Test) GenerateInput() {
|
||||
t.Input = nil
|
||||
if t.ctxt.lastLocale != t.Locale {
|
||||
gen := phraseGenerator{}
|
||||
gen.init(t.Locale)
|
||||
t.SetStatus(msgGeneratingInput)
|
||||
t.ctxt.lastInput = nil // allow the previous value to be garbage collected.
|
||||
t.Input = gen.generate(*doNorm)
|
||||
t.ctxt.lastInput = t.Input
|
||||
t.ctxt.lastLocale = t.Locale
|
||||
} else {
|
||||
t.Input = t.ctxt.lastInput
|
||||
for i := range t.Input {
|
||||
t.Input[i].key = nil
|
||||
}
|
||||
sort.Sort(&testRestore{*t})
|
||||
}
|
||||
}
|
||||
|
||||
// Context holds all tests and settings translated from command line options.
|
||||
type Context struct {
|
||||
test []*Test
|
||||
last *Test
|
||||
|
||||
lastLocale string
|
||||
lastInput []Input
|
||||
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
func (ts *Context) Printf(format string, a ...interface{}) {
|
||||
ts.assertBuf()
|
||||
fmt.Fprintf(ts.out, format, a...)
|
||||
}
|
||||
|
||||
func (ts *Context) Print(a ...interface{}) {
|
||||
ts.assertBuf()
|
||||
fmt.Fprint(ts.out, a...)
|
||||
}
|
||||
|
||||
// assertBuf sets up an io.Writer for output, if it doesn't already exist.
|
||||
// In debug and verbose mode, output is buffered so that the regular output
|
||||
// will not interfere with the additional output. Otherwise, output is
|
||||
// written directly to stdout for a more responsive feel.
|
||||
func (ts *Context) assertBuf() {
|
||||
if ts.out != nil {
|
||||
return
|
||||
}
|
||||
if *debug || *verbose {
|
||||
ts.out = &bytes.Buffer{}
|
||||
} else {
|
||||
ts.out = os.Stdout
|
||||
}
|
||||
}
|
||||
|
||||
// flush flushes the contents of ts.out to stdout, if it is not stdout already.
|
||||
func (ts *Context) flush() {
|
||||
if ts.out != nil {
|
||||
if _, ok := ts.out.(io.ReadCloser); !ok {
|
||||
io.Copy(os.Stdout, ts.out.(io.Reader))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parseTests creates all tests from command lines and returns
|
||||
// a Context to hold them.
|
||||
func parseTests() *Context {
|
||||
ctxt := &Context{}
|
||||
colls := strings.Split(*col, ",")
|
||||
for _, loc := range strings.Split(*locales, ",") {
|
||||
loc = strings.TrimSpace(loc)
|
||||
for _, name := range colls {
|
||||
name = strings.TrimSpace(name)
|
||||
col := getCollator(name, loc)
|
||||
ctxt.test = append(ctxt.test, &Test{
|
||||
ctxt: ctxt,
|
||||
Locale: loc,
|
||||
ColName: name,
|
||||
UseCompare: *usecmp,
|
||||
Col: col,
|
||||
})
|
||||
}
|
||||
}
|
||||
return ctxt
|
||||
}
|
||||
|
||||
func (c *Context) Len() int {
|
||||
return len(c.test)
|
||||
}
|
||||
|
||||
func (c *Context) Test(i int) *Test {
|
||||
if c.last != nil {
|
||||
c.last.clear()
|
||||
}
|
||||
c.last = c.test[i]
|
||||
return c.last
|
||||
}
|
||||
|
||||
func parseInput(args []string) []Input {
|
||||
input := []Input{}
|
||||
for _, s := range args {
|
||||
rs := []rune{}
|
||||
for len(s) > 0 {
|
||||
var r rune
|
||||
r, _, s, _ = strconv.UnquoteChar(s, '\'')
|
||||
rs = append(rs, r)
|
||||
}
|
||||
s = string(rs)
|
||||
if *doNorm {
|
||||
s = norm.NFD.String(s)
|
||||
}
|
||||
input = append(input, makeInputString(s))
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
// A Command is an implementation of a colcmp command.
|
||||
type Command struct {
|
||||
Run func(cmd *Context, args []string)
|
||||
Usage string
|
||||
Short string
|
||||
Long string
|
||||
}
|
||||
|
||||
func (cmd Command) Name() string {
|
||||
return strings.SplitN(cmd.Usage, " ", 2)[0]
|
||||
}
|
||||
|
||||
var commands = []*Command{
|
||||
cmdSort,
|
||||
cmdBench,
|
||||
cmdRegress,
|
||||
}
|
||||
|
||||
const sortHelp = `
|
||||
Sort sorts a given list of strings. Strings are separated by whitespace.
|
||||
`
|
||||
|
||||
var cmdSort = &Command{
|
||||
Run: runSort,
|
||||
Usage: "sort <string>*",
|
||||
Short: "sort a given list of strings",
|
||||
Long: sortHelp,
|
||||
}
|
||||
|
||||
func runSort(ctxt *Context, args []string) {
|
||||
input := parseInput(args)
|
||||
if len(input) == 0 {
|
||||
log.Fatalf("Nothing to sort.")
|
||||
}
|
||||
if ctxt.Len() > 1 {
|
||||
ctxt.Print("COLL LOCALE RESULT\n")
|
||||
}
|
||||
for i := 0; i < ctxt.Len(); i++ {
|
||||
t := ctxt.Test(i)
|
||||
t.Input = append(t.Input, input...)
|
||||
t.Sort()
|
||||
if ctxt.Len() > 1 {
|
||||
ctxt.Printf("%-5s %-5s ", t.ColName, t.Locale)
|
||||
}
|
||||
for _, s := range t.Input {
|
||||
ctxt.Print(string(s.UTF8), " ")
|
||||
}
|
||||
ctxt.Print("\n")
|
||||
}
|
||||
}
|
||||
|
||||
const benchHelp = `
|
||||
Bench runs a benchmark for the given list of collator implementations.
|
||||
If no collator implementations are given, the go collator will be used.
|
||||
`
|
||||
|
||||
var cmdBench = &Command{
|
||||
Run: runBench,
|
||||
Usage: "bench",
|
||||
Short: "benchmark a given list of collator implementations",
|
||||
Long: benchHelp,
|
||||
}
|
||||
|
||||
func runBench(ctxt *Context, args []string) {
|
||||
ctxt.Printf("%-7s %-5s %-6s %-24s %-24s %-5s %s\n", "LOCALE", "COLL", "N", "KEYS", "SORT", "AVGLN", "TOTAL")
|
||||
for i := 0; i < ctxt.Len(); i++ {
|
||||
t := ctxt.Test(i)
|
||||
ctxt.Printf("%-7s %-5s ", t.Locale, t.ColName)
|
||||
t.GenerateInput()
|
||||
ctxt.Printf("%-6s ", fmt.Sprintf("%dK", t.Len()/1000))
|
||||
tkey, tsort, nkey, nsort := t.Sort()
|
||||
p := func(dur time.Duration, n int) {
|
||||
s := ""
|
||||
if dur > 0 {
|
||||
s = fmt.Sprintf("%6.3fs ", dur.Seconds())
|
||||
if n > 0 {
|
||||
s += fmt.Sprintf("%15s", fmt.Sprintf("(%4.2f ns/op)", float64(dur)/float64(n)))
|
||||
}
|
||||
}
|
||||
ctxt.Printf("%-24s ", s)
|
||||
}
|
||||
p(tkey, nkey)
|
||||
p(tsort, nsort)
|
||||
|
||||
total := 0
|
||||
for _, s := range t.Input {
|
||||
total += len(s.key)
|
||||
}
|
||||
ctxt.Printf("%-5d ", total/t.Len())
|
||||
ctxt.Printf("%6.3fs\n", t.Duration.Seconds())
|
||||
if *debug {
|
||||
for _, s := range t.Input {
|
||||
fmt.Print(string(s.UTF8), " ")
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const regressHelp = `
|
||||
Regress runs a monkey test by comparing the results of randomly generated tests
|
||||
between two implementations of a collator. The user may optionally pass a list
|
||||
of strings to regress against instead of the default test set.
|
||||
`
|
||||
|
||||
var cmdRegress = &Command{
|
||||
Run: runRegress,
|
||||
Usage: "regress -gold=<col> -test=<col> [string]*",
|
||||
Short: "run a monkey test between two collators",
|
||||
Long: regressHelp,
|
||||
}
|
||||
|
||||
const failedKeyCompare = `
|
||||
%s:%d: incorrect comparison result for input:
|
||||
a: %q (%.4X)
|
||||
key: %s
|
||||
b: %q (%.4X)
|
||||
key: %s
|
||||
Compare(a, b) = %d; want %d.
|
||||
|
||||
gold keys:
|
||||
a: %s
|
||||
b: %s
|
||||
`
|
||||
|
||||
const failedCompare = `
|
||||
%s:%d: incorrect comparison result for input:
|
||||
a: %q (%.4X)
|
||||
b: %q (%.4X)
|
||||
Compare(a, b) = %d; want %d.
|
||||
`
|
||||
|
||||
func keyStr(b []byte) string {
|
||||
buf := &bytes.Buffer{}
|
||||
for _, v := range b {
|
||||
fmt.Fprintf(buf, "%.2X ", v)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func runRegress(ctxt *Context, args []string) {
|
||||
input := parseInput(args)
|
||||
for i := 0; i < ctxt.Len(); i++ {
|
||||
t := ctxt.Test(i)
|
||||
if len(input) > 0 {
|
||||
t.Input = append(t.Input, input...)
|
||||
} else {
|
||||
t.GenerateInput()
|
||||
}
|
||||
t.Sort()
|
||||
count := 0
|
||||
gold := getCollator(*gold, t.Locale)
|
||||
for i := 1; i < len(t.Input); i++ {
|
||||
ia := t.Input[i-1]
|
||||
ib := t.Input[i]
|
||||
if bytes.IndexAny(ib.UTF8, *exclude) != -1 {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if bytes.IndexAny(ia.UTF8, *exclude) != -1 {
|
||||
continue
|
||||
}
|
||||
goldCmp := gold.Compare(ia, ib)
|
||||
if cmp := bytes.Compare(ia.key, ib.key); cmp != goldCmp {
|
||||
count++
|
||||
a := string(ia.UTF8)
|
||||
b := string(ib.UTF8)
|
||||
fmt.Printf(failedKeyCompare, t.Locale, i-1, a, []rune(a), keyStr(ia.key), b, []rune(b), keyStr(ib.key), cmp, goldCmp, keyStr(gold.Key(ia)), keyStr(gold.Key(ib)))
|
||||
} else if cmp := t.Col.Compare(ia, ib); cmp != goldCmp {
|
||||
count++
|
||||
a := string(ia.UTF8)
|
||||
b := string(ib.UTF8)
|
||||
fmt.Printf(failedCompare, t.Locale, i-1, a, []rune(a), b, []rune(b), cmp, goldCmp)
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
ctxt.Printf("Found %d inconsistencies in %d entries.\n", count, t.Len()-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const helpTemplate = `
|
||||
colcmp is a tool for testing and benchmarking collation
|
||||
|
||||
Usage: colcmp command [arguments]
|
||||
|
||||
The commands are:
|
||||
{{range .}}
|
||||
{{.Name | printf "%-11s"}} {{.Short}}{{end}}
|
||||
|
||||
Use "col help [topic]" for more information about that topic.
|
||||
`
|
||||
|
||||
const detailedHelpTemplate = `
|
||||
Usage: colcmp {{.Usage}}
|
||||
|
||||
{{.Long | trim}}
|
||||
`
|
||||
|
||||
func runHelp(args []string) {
|
||||
t := template.New("help")
|
||||
t.Funcs(template.FuncMap{"trim": strings.TrimSpace})
|
||||
if len(args) < 1 {
|
||||
template.Must(t.Parse(helpTemplate))
|
||||
failOnError(t.Execute(os.Stderr, &commands))
|
||||
} else {
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == args[0] {
|
||||
template.Must(t.Parse(detailedHelpTemplate))
|
||||
failOnError(t.Execute(os.Stderr, cmd))
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
log.Fatalf("Unknown command %q. Run 'colcmp help'.", args[0])
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
|
||||
ctxt := parseTests()
|
||||
|
||||
if flag.NArg() < 1 {
|
||||
runHelp(nil)
|
||||
}
|
||||
args := flag.Args()[1:]
|
||||
if flag.Arg(0) == "help" {
|
||||
runHelp(args)
|
||||
}
|
||||
for _, cmd := range commands {
|
||||
if cmd.Name() == flag.Arg(0) {
|
||||
cmd.Run(ctxt, args)
|
||||
ctxt.flush()
|
||||
return
|
||||
}
|
||||
}
|
||||
runHelp(flag.Args())
|
||||
}
|
||||
111
vendor/golang.org/x/text/collate/tools/colcmp/darwin.go
generated
vendored
111
vendor/golang.org/x/text/collate/tools/colcmp/darwin.go
generated
vendored
|
|
@ -1,111 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -framework CoreFoundation
|
||||
#include <CoreFoundation/CFBase.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
AddFactory(CollatorFactory{"osx", newOSX16Collator,
|
||||
"OS X/Darwin collator, using native strings."})
|
||||
AddFactory(CollatorFactory{"osx8", newOSX8Collator,
|
||||
"OS X/Darwin collator for UTF-8."})
|
||||
}
|
||||
|
||||
func osxUInt8P(s []byte) *C.UInt8 {
|
||||
return (*C.UInt8)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
|
||||
func osxCharP(s []uint16) *C.UniChar {
|
||||
return (*C.UniChar)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
|
||||
// osxCollator implements an Collator based on OS X's CoreFoundation.
|
||||
type osxCollator struct {
|
||||
loc C.CFLocaleRef
|
||||
opt C.CFStringCompareFlags
|
||||
}
|
||||
|
||||
func (c *osxCollator) init(locale string) {
|
||||
l := C.CFStringCreateWithBytes(
|
||||
nil,
|
||||
osxUInt8P([]byte(locale)),
|
||||
C.CFIndex(len(locale)),
|
||||
C.kCFStringEncodingUTF8,
|
||||
C.Boolean(0),
|
||||
)
|
||||
c.loc = C.CFLocaleCreate(nil, l)
|
||||
}
|
||||
|
||||
func newOSX8Collator(locale string) (Collator, error) {
|
||||
c := &osx8Collator{}
|
||||
c.init(locale)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func newOSX16Collator(locale string) (Collator, error) {
|
||||
c := &osx16Collator{}
|
||||
c.init(locale)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c osxCollator) Key(s Input) []byte {
|
||||
return nil // sort keys not supported by OS X CoreFoundation
|
||||
}
|
||||
|
||||
type osx8Collator struct {
|
||||
osxCollator
|
||||
}
|
||||
|
||||
type osx16Collator struct {
|
||||
osxCollator
|
||||
}
|
||||
|
||||
func (c osx16Collator) Compare(a, b Input) int {
|
||||
sa := C.CFStringCreateWithCharactersNoCopy(
|
||||
nil,
|
||||
osxCharP(a.UTF16),
|
||||
C.CFIndex(len(a.UTF16)),
|
||||
nil,
|
||||
)
|
||||
sb := C.CFStringCreateWithCharactersNoCopy(
|
||||
nil,
|
||||
osxCharP(b.UTF16),
|
||||
C.CFIndex(len(b.UTF16)),
|
||||
nil,
|
||||
)
|
||||
_range := C.CFRangeMake(0, C.CFStringGetLength(sa))
|
||||
return int(C.CFStringCompareWithOptionsAndLocale(sa, sb, _range, c.opt, c.loc))
|
||||
}
|
||||
|
||||
func (c osx8Collator) Compare(a, b Input) int {
|
||||
sa := C.CFStringCreateWithBytesNoCopy(
|
||||
nil,
|
||||
osxUInt8P(a.UTF8),
|
||||
C.CFIndex(len(a.UTF8)),
|
||||
C.kCFStringEncodingUTF8,
|
||||
C.Boolean(0),
|
||||
nil,
|
||||
)
|
||||
sb := C.CFStringCreateWithBytesNoCopy(
|
||||
nil,
|
||||
osxUInt8P(b.UTF8),
|
||||
C.CFIndex(len(b.UTF8)),
|
||||
C.kCFStringEncodingUTF8,
|
||||
C.Boolean(0),
|
||||
nil,
|
||||
)
|
||||
_range := C.CFRangeMake(0, C.CFStringGetLength(sa))
|
||||
return int(C.CFStringCompareWithOptionsAndLocale(sa, sb, _range, c.opt, c.loc))
|
||||
}
|
||||
183
vendor/golang.org/x/text/collate/tools/colcmp/gen.go
generated
vendored
183
vendor/golang.org/x/text/collate/tools/colcmp/gen.go
generated
vendored
|
|
@ -1,183 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/unicode/norm"
|
||||
)
|
||||
|
||||
// TODO: replace with functionality in language package.
|
||||
// parent computes the parent language for the given language.
|
||||
// It returns false if the parent is already root.
|
||||
func parent(locale string) (parent string, ok bool) {
|
||||
if locale == "und" {
|
||||
return "", false
|
||||
}
|
||||
if i := strings.LastIndex(locale, "-"); i != -1 {
|
||||
return locale[:i], true
|
||||
}
|
||||
return "und", true
|
||||
}
|
||||
|
||||
// rewriter is used to both unique strings and create variants of strings
|
||||
// to add to the test set.
|
||||
type rewriter struct {
|
||||
seen map[string]bool
|
||||
addCases bool
|
||||
}
|
||||
|
||||
func newRewriter() *rewriter {
|
||||
return &rewriter{
|
||||
seen: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rewriter) insert(a []string, s string) []string {
|
||||
if !r.seen[s] {
|
||||
r.seen[s] = true
|
||||
a = append(a, s)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// rewrite takes a sequence of strings in, adds variants of the these strings
|
||||
// based on options and removes duplicates.
|
||||
func (r *rewriter) rewrite(ss []string) []string {
|
||||
ns := []string{}
|
||||
for _, s := range ss {
|
||||
ns = r.insert(ns, s)
|
||||
if r.addCases {
|
||||
rs := []rune(s)
|
||||
rn := rs[0]
|
||||
for c := unicode.SimpleFold(rn); c != rn; c = unicode.SimpleFold(c) {
|
||||
rs[0] = c
|
||||
ns = r.insert(ns, string(rs))
|
||||
}
|
||||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
|
||||
// exemplarySet holds a parsed set of characters from the exemplarCharacters table.
|
||||
type exemplarySet struct {
|
||||
typ exemplarType
|
||||
set []string
|
||||
charIndex int // cumulative total of phrases, including this set
|
||||
}
|
||||
|
||||
type phraseGenerator struct {
|
||||
sets [exN]exemplarySet
|
||||
n int
|
||||
}
|
||||
|
||||
func (g *phraseGenerator) init(id string) {
|
||||
ec := exemplarCharacters
|
||||
loc := language.Make(id).String()
|
||||
// get sets for locale or parent locale if the set is not defined.
|
||||
for i := range g.sets {
|
||||
for p, ok := loc, true; ok; p, ok = parent(p) {
|
||||
if set, ok := ec[p]; ok && set[i] != "" {
|
||||
g.sets[i].set = strings.Split(set[i], " ")
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
r := newRewriter()
|
||||
r.addCases = *cases
|
||||
for i := range g.sets {
|
||||
g.sets[i].set = r.rewrite(g.sets[i].set)
|
||||
}
|
||||
// compute indexes
|
||||
for i, set := range g.sets {
|
||||
g.n += len(set.set)
|
||||
g.sets[i].charIndex = g.n
|
||||
}
|
||||
}
|
||||
|
||||
// phrase returns the ith phrase, where i < g.n.
|
||||
func (g *phraseGenerator) phrase(i int) string {
|
||||
for _, set := range g.sets {
|
||||
if i < set.charIndex {
|
||||
return set.set[i-(set.charIndex-len(set.set))]
|
||||
}
|
||||
}
|
||||
panic("index out of range")
|
||||
}
|
||||
|
||||
// generate generates inputs by combining all pairs of examplar strings.
|
||||
// If doNorm is true, all input strings are normalized to NFC.
|
||||
// TODO: allow other variations, statistical models, and random
|
||||
// trailing sequences.
|
||||
func (g *phraseGenerator) generate(doNorm bool) []Input {
|
||||
const (
|
||||
M = 1024 * 1024
|
||||
buf8Size = 30 * M
|
||||
buf16Size = 10 * M
|
||||
)
|
||||
// TODO: use a better way to limit the input size.
|
||||
if sq := int(math.Sqrt(float64(*limit))); g.n > sq {
|
||||
g.n = sq
|
||||
}
|
||||
size := g.n * g.n
|
||||
a := make([]Input, 0, size)
|
||||
buf8 := make([]byte, 0, buf8Size)
|
||||
buf16 := make([]uint16, 0, buf16Size)
|
||||
|
||||
addInput := func(str string) {
|
||||
buf8 = buf8[len(buf8):]
|
||||
buf16 = buf16[len(buf16):]
|
||||
if len(str) > cap(buf8) {
|
||||
buf8 = make([]byte, 0, buf8Size)
|
||||
}
|
||||
if len(str) > cap(buf16) {
|
||||
buf16 = make([]uint16, 0, buf16Size)
|
||||
}
|
||||
if doNorm {
|
||||
buf8 = norm.NFD.AppendString(buf8, str)
|
||||
} else {
|
||||
buf8 = append(buf8, str...)
|
||||
}
|
||||
buf16 = appendUTF16(buf16, buf8)
|
||||
a = append(a, makeInput(buf8, buf16))
|
||||
}
|
||||
for i := 0; i < g.n; i++ {
|
||||
p1 := g.phrase(i)
|
||||
addInput(p1)
|
||||
for j := 0; j < g.n; j++ {
|
||||
p2 := g.phrase(j)
|
||||
addInput(p1 + p2)
|
||||
}
|
||||
}
|
||||
// permutate
|
||||
rnd := rand.New(rand.NewSource(int64(rand.Int())))
|
||||
for i := range a {
|
||||
j := i + rnd.Intn(len(a)-i)
|
||||
a[i], a[j] = a[j], a[i]
|
||||
a[i].index = i // allow restoring this order if input is used multiple times.
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func appendUTF16(buf []uint16, s []byte) []uint16 {
|
||||
for len(s) > 0 {
|
||||
r, sz := utf8.DecodeRune(s)
|
||||
s = s[sz:]
|
||||
r1, r2 := utf16.EncodeRune(r)
|
||||
if r1 != 0xFFFD {
|
||||
buf = append(buf, uint16(r1), uint16(r2))
|
||||
} else {
|
||||
buf = append(buf, uint16(r))
|
||||
}
|
||||
}
|
||||
return buf
|
||||
}
|
||||
209
vendor/golang.org/x/text/collate/tools/colcmp/icu.go
generated
vendored
209
vendor/golang.org/x/text/collate/tools/colcmp/icu.go
generated
vendored
|
|
@ -1,209 +0,0 @@
|
|||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build icu
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -licui18n -licuuc
|
||||
#include <stdlib.h>
|
||||
#include <unicode/ucol.h>
|
||||
#include <unicode/uiter.h>
|
||||
#include <unicode/utypes.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func init() {
|
||||
AddFactory(CollatorFactory{"icu", newUTF16,
|
||||
"Main ICU collator, using native strings."})
|
||||
AddFactory(CollatorFactory{"icu8", newUTF8iter,
|
||||
"ICU collator using ICU iterators to process UTF8."})
|
||||
AddFactory(CollatorFactory{"icu16", newUTF8conv,
|
||||
"ICU collation by first converting UTF8 to UTF16."})
|
||||
}
|
||||
|
||||
func icuCharP(s []byte) *C.char {
|
||||
return (*C.char)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
|
||||
func icuUInt8P(s []byte) *C.uint8_t {
|
||||
return (*C.uint8_t)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
|
||||
func icuUCharP(s []uint16) *C.UChar {
|
||||
return (*C.UChar)(unsafe.Pointer(&s[0]))
|
||||
}
|
||||
func icuULen(s []uint16) C.int32_t {
|
||||
return C.int32_t(len(s))
|
||||
}
|
||||
func icuSLen(s []byte) C.int32_t {
|
||||
return C.int32_t(len(s))
|
||||
}
|
||||
|
||||
// icuCollator implements a Collator based on ICU.
|
||||
type icuCollator struct {
|
||||
loc *C.char
|
||||
col *C.UCollator
|
||||
keyBuf []byte
|
||||
}
|
||||
|
||||
const growBufSize = 10 * 1024 * 1024
|
||||
|
||||
func (c *icuCollator) init(locale string) error {
|
||||
err := C.UErrorCode(0)
|
||||
c.loc = C.CString(locale)
|
||||
c.col = C.ucol_open(c.loc, &err)
|
||||
if err > 0 {
|
||||
return fmt.Errorf("failed opening collator for %q", locale)
|
||||
} else if err < 0 {
|
||||
loc := C.ucol_getLocaleByType(c.col, 0, &err)
|
||||
fmt, ok := map[int]string{
|
||||
-127: "warning: using default collator: %s",
|
||||
-128: "warning: using fallback collator: %s",
|
||||
}[int(err)]
|
||||
if ok {
|
||||
log.Printf(fmt, C.GoString(loc))
|
||||
}
|
||||
}
|
||||
c.keyBuf = make([]byte, 0, growBufSize)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *icuCollator) buf() (*C.uint8_t, C.int32_t) {
|
||||
if len(c.keyBuf) == cap(c.keyBuf) {
|
||||
c.keyBuf = make([]byte, 0, growBufSize)
|
||||
}
|
||||
b := c.keyBuf[len(c.keyBuf):cap(c.keyBuf)]
|
||||
return icuUInt8P(b), icuSLen(b)
|
||||
}
|
||||
|
||||
func (c *icuCollator) extendBuf(n C.int32_t) []byte {
|
||||
end := len(c.keyBuf) + int(n)
|
||||
if end > cap(c.keyBuf) {
|
||||
if len(c.keyBuf) == 0 {
|
||||
log.Fatalf("icuCollator: max string size exceeded: %v > %v", n, growBufSize)
|
||||
}
|
||||
c.keyBuf = make([]byte, 0, growBufSize)
|
||||
return nil
|
||||
}
|
||||
b := c.keyBuf[len(c.keyBuf):end]
|
||||
c.keyBuf = c.keyBuf[:end]
|
||||
return b
|
||||
}
|
||||
|
||||
func (c *icuCollator) Close() error {
|
||||
C.ucol_close(c.col)
|
||||
C.free(unsafe.Pointer(c.loc))
|
||||
return nil
|
||||
}
|
||||
|
||||
// icuUTF16 implements the Collator interface.
|
||||
type icuUTF16 struct {
|
||||
icuCollator
|
||||
}
|
||||
|
||||
func newUTF16(locale string) (Collator, error) {
|
||||
c := &icuUTF16{}
|
||||
return c, c.init(locale)
|
||||
}
|
||||
|
||||
func (c *icuUTF16) Compare(a, b Input) int {
|
||||
return int(C.ucol_strcoll(c.col, icuUCharP(a.UTF16), icuULen(a.UTF16), icuUCharP(b.UTF16), icuULen(b.UTF16)))
|
||||
}
|
||||
|
||||
func (c *icuUTF16) Key(s Input) []byte {
|
||||
bp, bn := c.buf()
|
||||
n := C.ucol_getSortKey(c.col, icuUCharP(s.UTF16), icuULen(s.UTF16), bp, bn)
|
||||
if b := c.extendBuf(n); b != nil {
|
||||
return b
|
||||
}
|
||||
return c.Key(s)
|
||||
}
|
||||
|
||||
// icuUTF8iter implements the Collator interface
|
||||
// This implementation wraps the UTF8 string in an iterator
|
||||
// which is passed to the collator.
|
||||
type icuUTF8iter struct {
|
||||
icuCollator
|
||||
a, b C.UCharIterator
|
||||
}
|
||||
|
||||
func newUTF8iter(locale string) (Collator, error) {
|
||||
c := &icuUTF8iter{}
|
||||
return c, c.init(locale)
|
||||
}
|
||||
|
||||
func (c *icuUTF8iter) Compare(a, b Input) int {
|
||||
err := C.UErrorCode(0)
|
||||
C.uiter_setUTF8(&c.a, icuCharP(a.UTF8), icuSLen(a.UTF8))
|
||||
C.uiter_setUTF8(&c.b, icuCharP(b.UTF8), icuSLen(b.UTF8))
|
||||
return int(C.ucol_strcollIter(c.col, &c.a, &c.b, &err))
|
||||
}
|
||||
|
||||
func (c *icuUTF8iter) Key(s Input) []byte {
|
||||
err := C.UErrorCode(0)
|
||||
state := [2]C.uint32_t{}
|
||||
C.uiter_setUTF8(&c.a, icuCharP(s.UTF8), icuSLen(s.UTF8))
|
||||
bp, bn := c.buf()
|
||||
n := C.ucol_nextSortKeyPart(c.col, &c.a, &(state[0]), bp, bn, &err)
|
||||
if n >= bn {
|
||||
// Force failure.
|
||||
if c.extendBuf(n+1) != nil {
|
||||
log.Fatal("expected extension to fail")
|
||||
}
|
||||
return c.Key(s)
|
||||
}
|
||||
return c.extendBuf(n)
|
||||
}
|
||||
|
||||
// icuUTF8conv implements the Collator interface.
|
||||
// This implementation first converts the give UTF8 string
|
||||
// to UTF16 and then calls the main ICU collation function.
|
||||
type icuUTF8conv struct {
|
||||
icuCollator
|
||||
}
|
||||
|
||||
func newUTF8conv(locale string) (Collator, error) {
|
||||
c := &icuUTF8conv{}
|
||||
return c, c.init(locale)
|
||||
}
|
||||
|
||||
func (c *icuUTF8conv) Compare(sa, sb Input) int {
|
||||
a := encodeUTF16(sa.UTF8)
|
||||
b := encodeUTF16(sb.UTF8)
|
||||
return int(C.ucol_strcoll(c.col, icuUCharP(a), icuULen(a), icuUCharP(b), icuULen(b)))
|
||||
}
|
||||
|
||||
func (c *icuUTF8conv) Key(s Input) []byte {
|
||||
a := encodeUTF16(s.UTF8)
|
||||
bp, bn := c.buf()
|
||||
n := C.ucol_getSortKey(c.col, icuUCharP(a), icuULen(a), bp, bn)
|
||||
if b := c.extendBuf(n); b != nil {
|
||||
return b
|
||||
}
|
||||
return c.Key(s)
|
||||
}
|
||||
|
||||
func encodeUTF16(b []byte) []uint16 {
|
||||
a := []uint16{}
|
||||
for len(b) > 0 {
|
||||
r, sz := utf8.DecodeRune(b)
|
||||
b = b[sz:]
|
||||
r1, r2 := utf16.EncodeRune(r)
|
||||
if r1 != 0xFFFD {
|
||||
a = append(a, uint16(r1), uint16(r2))
|
||||
} else {
|
||||
a = append(a, uint16(r))
|
||||
}
|
||||
}
|
||||
return a
|
||||
}
|
||||
66
vendor/golang.org/x/text/currency/common.go
generated
vendored
66
vendor/golang.org/x/text/currency/common.go
generated
vendored
|
|
@ -1,66 +0,0 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// This file contains code common to gen.go and the package code.
|
||||
|
||||
const (
|
||||
cashShift = 3
|
||||
roundMask = 0x7
|
||||
|
||||
nonTenderBit = 0x8000
|
||||
)
|
||||
|
||||
// currencyInfo contains information about a currency.
|
||||
// bits 0..2: index into roundings for standard rounding
|
||||
// bits 3..5: index into roundings for cash rounding
|
||||
type currencyInfo byte
|
||||
|
||||
// roundingType defines the scale (number of fractional decimals) and increments
|
||||
// in terms of units of size 10^-scale. For example, for scale == 2 and
|
||||
// increment == 1, the currency is rounded to units of 0.01.
|
||||
type roundingType struct {
|
||||
scale, increment uint8
|
||||
}
|
||||
|
||||
// roundings contains rounding data for currencies. This struct is
|
||||
// created by hand as it is very unlikely to change much.
|
||||
var roundings = [...]roundingType{
|
||||
{2, 1}, // default
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{3, 1},
|
||||
{4, 1},
|
||||
{2, 5}, // cash rounding alternative
|
||||
}
|
||||
|
||||
// regionToCode returns a 16-bit region code. Only two-letter codes are
|
||||
// supported. (Three-letter codes are not needed.)
|
||||
func regionToCode(r language.Region) uint16 {
|
||||
if s := r.String(); len(s) == 2 {
|
||||
return uint16(s[0])<<8 | uint16(s[1])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func toDate(t time.Time) uint32 {
|
||||
y := t.Year()
|
||||
if y == 1 {
|
||||
return 0
|
||||
}
|
||||
date := uint32(y) << 4
|
||||
date |= uint32(t.Month())
|
||||
date <<= 5
|
||||
date |= uint32(t.Day())
|
||||
return date
|
||||
}
|
||||
|
||||
func fromDate(date uint32) time.Time {
|
||||
return time.Date(int(date>>9), time.Month((date>>5)&0xf), int(date&0x1f), 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
185
vendor/golang.org/x/text/currency/currency.go
generated
vendored
185
vendor/golang.org/x/text/currency/currency.go
generated
vendored
|
|
@ -1,185 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go gen_common.go -output tables.go
|
||||
|
||||
// Package currency contains currency-related functionality.
|
||||
//
|
||||
// NOTE: the formatting functionality is currently under development and may
|
||||
// change without notice.
|
||||
package currency // import "golang.org/x/text/currency"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/text/internal/tag"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - language-specific currency names.
|
||||
// - currency formatting.
|
||||
// - currency information per region
|
||||
// - register currency code (there are no private use area)
|
||||
|
||||
// TODO: remove Currency type from package language.
|
||||
|
||||
// Kind determines the rounding and rendering properties of a currency value.
|
||||
type Kind struct {
|
||||
rounding rounding
|
||||
// TODO: formatting type: standard, accounting. See CLDR.
|
||||
}
|
||||
|
||||
type rounding byte
|
||||
|
||||
const (
|
||||
standard rounding = iota
|
||||
cash
|
||||
)
|
||||
|
||||
var (
|
||||
// Standard defines standard rounding and formatting for currencies.
|
||||
Standard Kind = Kind{rounding: standard}
|
||||
|
||||
// Cash defines rounding and formatting standards for cash transactions.
|
||||
Cash Kind = Kind{rounding: cash}
|
||||
|
||||
// Accounting defines rounding and formatting standards for accounting.
|
||||
Accounting Kind = Kind{rounding: standard}
|
||||
)
|
||||
|
||||
// Rounding reports the rounding characteristics for the given currency, where
|
||||
// scale is the number of fractional decimals and increment is the number of
|
||||
// units in terms of 10^(-scale) to which to round to.
|
||||
func (k Kind) Rounding(cur Unit) (scale, increment int) {
|
||||
info := currency.Elem(int(cur.index))[3]
|
||||
switch k.rounding {
|
||||
case standard:
|
||||
info &= roundMask
|
||||
case cash:
|
||||
info >>= cashShift
|
||||
}
|
||||
return int(roundings[info].scale), int(roundings[info].increment)
|
||||
}
|
||||
|
||||
// Unit is an ISO 4217 currency designator.
|
||||
type Unit struct {
|
||||
index uint16
|
||||
}
|
||||
|
||||
// String returns the ISO code of u.
|
||||
func (u Unit) String() string {
|
||||
if u.index == 0 {
|
||||
return "XXX"
|
||||
}
|
||||
return currency.Elem(int(u.index))[:3]
|
||||
}
|
||||
|
||||
// Amount creates an Amount for the given currency unit and amount.
|
||||
func (u Unit) Amount(amount interface{}) Amount {
|
||||
// TODO: verify amount is a supported number type
|
||||
return Amount{amount: amount, currency: u}
|
||||
}
|
||||
|
||||
var (
|
||||
errSyntax = errors.New("currency: tag is not well-formed")
|
||||
errValue = errors.New("currency: tag is not a recognized currency")
|
||||
)
|
||||
|
||||
// ParseISO parses a 3-letter ISO 4217 currency code. It returns an error if s
|
||||
// is not well-formed or not a recognized currency code.
|
||||
func ParseISO(s string) (Unit, error) {
|
||||
var buf [4]byte // Take one byte more to detect oversize keys.
|
||||
key := buf[:copy(buf[:], s)]
|
||||
if !tag.FixCase("XXX", key) {
|
||||
return Unit{}, errSyntax
|
||||
}
|
||||
if i := currency.Index(key); i >= 0 {
|
||||
if i == xxx {
|
||||
return Unit{}, nil
|
||||
}
|
||||
return Unit{uint16(i)}, nil
|
||||
}
|
||||
return Unit{}, errValue
|
||||
}
|
||||
|
||||
// MustParseISO is like ParseISO, but panics if the given currency unit
|
||||
// cannot be parsed. It simplifies safe initialization of Unit values.
|
||||
func MustParseISO(s string) Unit {
|
||||
c, err := ParseISO(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// FromRegion reports the currency unit that is currently legal tender in the
|
||||
// given region according to CLDR. It will return false if region currently does
|
||||
// not have a legal tender.
|
||||
func FromRegion(r language.Region) (currency Unit, ok bool) {
|
||||
x := regionToCode(r)
|
||||
i := sort.Search(len(regionToCurrency), func(i int) bool {
|
||||
return regionToCurrency[i].region >= x
|
||||
})
|
||||
if i < len(regionToCurrency) && regionToCurrency[i].region == x {
|
||||
return Unit{regionToCurrency[i].code}, true
|
||||
}
|
||||
return Unit{}, false
|
||||
}
|
||||
|
||||
// FromTag reports the most likely currency for the given tag. It considers the
|
||||
// currency defined in the -u extension and infers the region if necessary.
|
||||
func FromTag(t language.Tag) (Unit, language.Confidence) {
|
||||
if cur := t.TypeForKey("cu"); len(cur) == 3 {
|
||||
c, _ := ParseISO(cur)
|
||||
return c, language.Exact
|
||||
}
|
||||
r, conf := t.Region()
|
||||
if cur, ok := FromRegion(r); ok {
|
||||
return cur, conf
|
||||
}
|
||||
return Unit{}, language.No
|
||||
}
|
||||
|
||||
var (
|
||||
// Undefined and testing.
|
||||
XXX Unit = Unit{}
|
||||
XTS Unit = Unit{xts}
|
||||
|
||||
// G10 currencies https://en.wikipedia.org/wiki/G10_currencies.
|
||||
USD Unit = Unit{usd}
|
||||
EUR Unit = Unit{eur}
|
||||
JPY Unit = Unit{jpy}
|
||||
GBP Unit = Unit{gbp}
|
||||
CHF Unit = Unit{chf}
|
||||
AUD Unit = Unit{aud}
|
||||
NZD Unit = Unit{nzd}
|
||||
CAD Unit = Unit{cad}
|
||||
SEK Unit = Unit{sek}
|
||||
NOK Unit = Unit{nok}
|
||||
|
||||
// Additional common currencies as defined by CLDR.
|
||||
BRL Unit = Unit{brl}
|
||||
CNY Unit = Unit{cny}
|
||||
DKK Unit = Unit{dkk}
|
||||
INR Unit = Unit{inr}
|
||||
RUB Unit = Unit{rub}
|
||||
HKD Unit = Unit{hkd}
|
||||
IDR Unit = Unit{idr}
|
||||
KRW Unit = Unit{krw}
|
||||
MXN Unit = Unit{mxn}
|
||||
PLN Unit = Unit{pln}
|
||||
SAR Unit = Unit{sar}
|
||||
THB Unit = Unit{thb}
|
||||
TRY Unit = Unit{try}
|
||||
TWD Unit = Unit{twd}
|
||||
ZAR Unit = Unit{zar}
|
||||
|
||||
// Precious metals.
|
||||
XAG Unit = Unit{xag}
|
||||
XAU Unit = Unit{xau}
|
||||
XPT Unit = Unit{xpt}
|
||||
XPD Unit = Unit{xpd}
|
||||
)
|
||||
171
vendor/golang.org/x/text/currency/currency_test.go
generated
vendored
171
vendor/golang.org/x/text/currency/currency_test.go
generated
vendored
|
|
@ -1,171 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var (
|
||||
cup = MustParseISO("CUP")
|
||||
czk = MustParseISO("CZK")
|
||||
xcd = MustParseISO("XCD")
|
||||
zwr = MustParseISO("ZWR")
|
||||
)
|
||||
|
||||
func TestParseISO(t *testing.T) {
|
||||
testCases := []struct {
|
||||
in string
|
||||
out Unit
|
||||
ok bool
|
||||
}{
|
||||
{"USD", USD, true},
|
||||
{"xxx", XXX, true},
|
||||
{"xts", XTS, true},
|
||||
{"XX", XXX, false},
|
||||
{"XXXX", XXX, false},
|
||||
{"", XXX, false}, // not well-formed
|
||||
{"UUU", XXX, false}, // unknown
|
||||
{"\u22A9", XXX, false}, // non-ASCII, printable
|
||||
|
||||
{"aaa", XXX, false},
|
||||
{"zzz", XXX, false},
|
||||
{"000", XXX, false},
|
||||
{"999", XXX, false},
|
||||
{"---", XXX, false},
|
||||
{"\x00\x00\x00", XXX, false},
|
||||
{"\xff\xff\xff", XXX, false},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if x, err := ParseISO(tc.in); x != tc.out || err == nil != tc.ok {
|
||||
t.Errorf("%d:%s: was %s, %v; want %s, %v", i, tc.in, x, err == nil, tc.out, tc.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromRegion(t *testing.T) {
|
||||
testCases := []struct {
|
||||
region string
|
||||
currency Unit
|
||||
ok bool
|
||||
}{
|
||||
{"NL", EUR, true},
|
||||
{"BE", EUR, true},
|
||||
{"AG", xcd, true},
|
||||
{"CH", CHF, true},
|
||||
{"CU", cup, true}, // first of multiple
|
||||
{"DG", USD, true}, // does not have M49 code
|
||||
{"150", XXX, false}, // implicit false
|
||||
{"CP", XXX, false}, // explicit false in CLDR
|
||||
{"CS", XXX, false}, // all expired
|
||||
{"ZZ", XXX, false}, // none match
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cur, ok := FromRegion(language.MustParseRegion(tc.region))
|
||||
if cur != tc.currency || ok != tc.ok {
|
||||
t.Errorf("%s: got %v, %v; want %v, %v", tc.region, cur, ok, tc.currency, tc.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromTag(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag string
|
||||
currency Unit
|
||||
conf language.Confidence
|
||||
}{
|
||||
{"nl", EUR, language.Low}, // nl also spoken outside Euro land.
|
||||
{"nl-BE", EUR, language.Exact}, // region is known
|
||||
{"pt", BRL, language.Low},
|
||||
{"en", USD, language.Low},
|
||||
{"en-u-cu-eur", EUR, language.Exact},
|
||||
{"tlh", XXX, language.No}, // Klingon has no country.
|
||||
{"es-419", XXX, language.No},
|
||||
{"und", USD, language.Low},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
cur, conf := FromTag(language.MustParse(tc.tag))
|
||||
if cur != tc.currency || conf != tc.conf {
|
||||
t.Errorf("%s: got %v, %v; want %v, %v", tc.tag, cur, conf, tc.currency, tc.conf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
for i := 4; i < len(currency); i += 4 {
|
||||
if a, b := currency[i-4:i-1], currency[i:i+3]; a >= b {
|
||||
t.Errorf("currency unordered at element %d: %s >= %s", i, a, b)
|
||||
}
|
||||
}
|
||||
// First currency has index 1, last is numCurrencies.
|
||||
if c := currency.Elem(1)[:3]; c != "ADP" {
|
||||
t.Errorf("first was %c; want ADP", c)
|
||||
}
|
||||
if c := currency.Elem(numCurrencies)[:3]; c != "ZWR" {
|
||||
t.Errorf("last was %c; want ZWR", c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKindRounding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
kind Kind
|
||||
cur Unit
|
||||
scale int
|
||||
inc int
|
||||
}{
|
||||
{Standard, USD, 2, 1},
|
||||
{Standard, CHF, 2, 1},
|
||||
{Cash, CHF, 2, 5},
|
||||
{Standard, TWD, 2, 1},
|
||||
{Cash, TWD, 0, 1},
|
||||
{Standard, czk, 2, 1},
|
||||
{Cash, czk, 0, 1},
|
||||
{Standard, zwr, 2, 1},
|
||||
{Cash, zwr, 0, 1},
|
||||
{Standard, KRW, 0, 1},
|
||||
{Cash, KRW, 0, 1}, // Cash defaults to standard.
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
if scale, inc := tc.kind.Rounding(tc.cur); scale != tc.scale && inc != tc.inc {
|
||||
t.Errorf("%d: got %d, %d; want %d, %d", i, scale, inc, tc.scale, tc.inc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const body = `package main
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/text/currency"
|
||||
)
|
||||
func main() {
|
||||
%s
|
||||
}
|
||||
`
|
||||
|
||||
func TestLinking(t *testing.T) {
|
||||
base := getSize(t, `fmt.Print(currency.CLDRVersion)`)
|
||||
symbols := getSize(t, `fmt.Print(currency.Symbol(currency.USD))`)
|
||||
if d := symbols - base; d < 2*1024 {
|
||||
t.Errorf("size(symbols)-size(base) was %d; want > 2K", d)
|
||||
}
|
||||
}
|
||||
|
||||
func getSize(t *testing.T, main string) int {
|
||||
size, err := testtext.CodeSize(fmt.Sprintf(body, main))
|
||||
if err != nil {
|
||||
t.Skipf("skipping link size test; binary size could not be determined: %v", err)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
||||
func BenchmarkString(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
USD.String()
|
||||
}
|
||||
}
|
||||
27
vendor/golang.org/x/text/currency/example_test.go
generated
vendored
27
vendor/golang.org/x/text/currency/example_test.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/currency"
|
||||
)
|
||||
|
||||
func ExampleQuery() {
|
||||
t1799, _ := time.Parse("2006-01-02", "1799-01-01")
|
||||
for it := currency.Query(currency.Date(t1799)); it.Next(); {
|
||||
from := ""
|
||||
if t, ok := it.From(); ok {
|
||||
from = t.Format("2006-01-01")
|
||||
}
|
||||
fmt.Printf("%v is used in %v since: %v\n", it.Unit(), it.Region(), from)
|
||||
}
|
||||
// Output:
|
||||
// GBP is used in GB since: 1694-07-07
|
||||
// GIP is used in GI since: 1713-01-01
|
||||
// USD is used in US since: 1792-01-01
|
||||
}
|
||||
215
vendor/golang.org/x/text/currency/format.go
generated
vendored
215
vendor/golang.org/x/text/currency/format.go
generated
vendored
|
|
@ -1,215 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/text/internal"
|
||||
"golang.org/x/text/internal/format"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Amount is an amount-currency unit pair.
|
||||
type Amount struct {
|
||||
amount interface{} // Change to decimal(64|128).
|
||||
currency Unit
|
||||
}
|
||||
|
||||
// Currency reports the currency unit of this amount.
|
||||
func (a Amount) Currency() Unit { return a.currency }
|
||||
|
||||
// TODO: based on decimal type, but may make sense to customize a bit.
|
||||
// func (a Amount) Decimal()
|
||||
// func (a Amount) Int() (int64, error)
|
||||
// func (a Amount) Fraction() (int64, error)
|
||||
// func (a Amount) Rat() *big.Rat
|
||||
// func (a Amount) Float() (float64, error)
|
||||
// func (a Amount) Scale() uint
|
||||
// func (a Amount) Precision() uint
|
||||
// func (a Amount) Sign() int
|
||||
//
|
||||
// Add/Sub/Div/Mul/Round.
|
||||
|
||||
var space = []byte(" ")
|
||||
|
||||
// Format implements fmt.Formatter. It accepts format.State for
|
||||
// language-specific rendering.
|
||||
func (a Amount) Format(s fmt.State, verb rune) {
|
||||
v := formattedValue{
|
||||
currency: a.currency,
|
||||
amount: a.amount,
|
||||
format: defaultFormat,
|
||||
}
|
||||
v.Format(s, verb)
|
||||
}
|
||||
|
||||
// formattedValue is currency amount or unit that implements language-sensitive
|
||||
// formatting.
|
||||
type formattedValue struct {
|
||||
currency Unit
|
||||
amount interface{} // Amount, Unit, or number.
|
||||
format *options
|
||||
}
|
||||
|
||||
// Format implements fmt.Formatter. It accepts format.State for
|
||||
// language-specific rendering.
|
||||
func (v formattedValue) Format(s fmt.State, verb rune) {
|
||||
var lang int
|
||||
if state, ok := s.(format.State); ok {
|
||||
lang, _ = language.CompactIndex(state.Language())
|
||||
}
|
||||
|
||||
// Get the options. Use DefaultFormat if not present.
|
||||
opt := v.format
|
||||
if opt == nil {
|
||||
opt = defaultFormat
|
||||
}
|
||||
cur := v.currency
|
||||
if cur.index == 0 {
|
||||
cur = opt.currency
|
||||
}
|
||||
|
||||
// TODO: use pattern.
|
||||
io.WriteString(s, opt.symbol(lang, cur))
|
||||
if v.amount != nil {
|
||||
s.Write(space)
|
||||
|
||||
// TODO: apply currency-specific rounding
|
||||
scale, _ := opt.kind.Rounding(cur)
|
||||
if _, ok := s.Precision(); !ok {
|
||||
fmt.Fprintf(s, "%.*f", scale, v.amount)
|
||||
} else {
|
||||
fmt.Fprint(s, v.amount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Formatter decorates a given number, Unit or Amount with formatting options.
|
||||
type Formatter func(amount interface{}) formattedValue
|
||||
|
||||
// func (f Formatter) Options(opts ...Option) Formatter
|
||||
|
||||
// TODO: call this a Formatter or FormatFunc?
|
||||
|
||||
var dummy = USD.Amount(0)
|
||||
|
||||
// adjust creates a new Formatter based on the adjustments of fn on f.
|
||||
func (f Formatter) adjust(fn func(*options)) Formatter {
|
||||
var o options = *(f(dummy).format)
|
||||
fn(&o)
|
||||
return o.format
|
||||
}
|
||||
|
||||
// Default creates a new Formatter that defaults to currency unit c if a numeric
|
||||
// value is passed that is not associated with a currency.
|
||||
func (f Formatter) Default(currency Unit) Formatter {
|
||||
return f.adjust(func(o *options) { o.currency = currency })
|
||||
}
|
||||
|
||||
// Kind sets the kind of the underlying currency unit.
|
||||
func (f Formatter) Kind(k Kind) Formatter {
|
||||
return f.adjust(func(o *options) { o.kind = k })
|
||||
}
|
||||
|
||||
var defaultFormat *options = ISO(dummy).format
|
||||
|
||||
var (
|
||||
// Uses Narrow symbols. Overrides Symbol, if present.
|
||||
NarrowSymbol Formatter = Formatter(formNarrow)
|
||||
|
||||
// Use Symbols instead of ISO codes, when available.
|
||||
Symbol Formatter = Formatter(formSymbol)
|
||||
|
||||
// Use ISO code as symbol.
|
||||
ISO Formatter = Formatter(formISO)
|
||||
|
||||
// TODO:
|
||||
// // Use full name as symbol.
|
||||
// Name Formatter
|
||||
)
|
||||
|
||||
// options configures rendering and rounding options for an Amount.
|
||||
type options struct {
|
||||
currency Unit
|
||||
kind Kind
|
||||
|
||||
symbol func(compactIndex int, c Unit) string
|
||||
}
|
||||
|
||||
func (o *options) format(amount interface{}) formattedValue {
|
||||
v := formattedValue{format: o}
|
||||
switch x := amount.(type) {
|
||||
case Amount:
|
||||
v.amount = x.amount
|
||||
v.currency = x.currency
|
||||
case *Amount:
|
||||
v.amount = x.amount
|
||||
v.currency = x.currency
|
||||
case Unit:
|
||||
v.currency = x
|
||||
case *Unit:
|
||||
v.currency = *x
|
||||
default:
|
||||
if o.currency.index == 0 {
|
||||
panic("cannot format number without a currency being set")
|
||||
}
|
||||
// TODO: Must be a number.
|
||||
v.amount = x
|
||||
v.currency = o.currency
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
var (
|
||||
optISO = options{symbol: lookupISO}
|
||||
optSymbol = options{symbol: lookupSymbol}
|
||||
optNarrow = options{symbol: lookupNarrow}
|
||||
)
|
||||
|
||||
// These need to be functions, rather than curried methods, as curried methods
|
||||
// are evaluated at init time, causing tables to be included unconditionally.
|
||||
func formISO(x interface{}) formattedValue { return optISO.format(x) }
|
||||
func formSymbol(x interface{}) formattedValue { return optSymbol.format(x) }
|
||||
func formNarrow(x interface{}) formattedValue { return optNarrow.format(x) }
|
||||
|
||||
func lookupISO(x int, c Unit) string { return c.String() }
|
||||
func lookupSymbol(x int, c Unit) string { return normalSymbol.lookup(x, c) }
|
||||
func lookupNarrow(x int, c Unit) string { return narrowSymbol.lookup(x, c) }
|
||||
|
||||
type symbolIndex struct {
|
||||
index []uint16 // position corresponds with compact index of language.
|
||||
data []curToIndex
|
||||
}
|
||||
|
||||
var (
|
||||
normalSymbol = symbolIndex{normalLangIndex, normalSymIndex}
|
||||
narrowSymbol = symbolIndex{narrowLangIndex, narrowSymIndex}
|
||||
)
|
||||
|
||||
func (x *symbolIndex) lookup(lang int, c Unit) string {
|
||||
for {
|
||||
index := x.data[x.index[lang]:x.index[lang+1]]
|
||||
i := sort.Search(len(index), func(i int) bool {
|
||||
return index[i].cur >= c.index
|
||||
})
|
||||
if i < len(index) && index[i].cur == c.index {
|
||||
x := index[i].idx
|
||||
start := x + 1
|
||||
end := start + uint16(symbols[x])
|
||||
if start == end {
|
||||
return c.String()
|
||||
}
|
||||
return symbols[start:end]
|
||||
}
|
||||
if lang == 0 {
|
||||
break
|
||||
}
|
||||
lang = int(internal.Parent[lang])
|
||||
}
|
||||
return c.String()
|
||||
}
|
||||
70
vendor/golang.org/x/text/currency/format_test.go
generated
vendored
70
vendor/golang.org/x/text/currency/format_test.go
generated
vendored
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
|
||||
var (
|
||||
en = language.English
|
||||
fr = language.French
|
||||
en_US = language.AmericanEnglish
|
||||
en_GB = language.BritishEnglish
|
||||
en_AU = language.MustParse("en-AU")
|
||||
und = language.Und
|
||||
)
|
||||
|
||||
func TestFormatting(t *testing.T) {
|
||||
testCases := []struct {
|
||||
tag language.Tag
|
||||
value interface{}
|
||||
format Formatter
|
||||
want string
|
||||
}{
|
||||
0: {en, USD.Amount(0.1), nil, "USD 0.10"},
|
||||
1: {en, XPT.Amount(1.0), Symbol, "XPT 1.00"},
|
||||
|
||||
2: {en, USD.Amount(2.0), ISO, "USD 2.00"},
|
||||
3: {und, USD.Amount(3.0), Symbol, "US$ 3.00"},
|
||||
4: {en, USD.Amount(4.0), Symbol, "$ 4.00"},
|
||||
|
||||
5: {en, USD.Amount(5.20), NarrowSymbol, "$ 5.20"},
|
||||
6: {en, AUD.Amount(6.20), Symbol, "A$ 6.20"},
|
||||
|
||||
7: {en_AU, AUD.Amount(7.20), Symbol, "$ 7.20"},
|
||||
8: {en_GB, USD.Amount(8.20), Symbol, "US$ 8.20"},
|
||||
|
||||
9: {en, 9.0, Symbol.Default(EUR), "€ 9.00"},
|
||||
10: {en, 10.123, Symbol.Default(KRW), "₩ 10"},
|
||||
11: {fr, 11.52, Symbol.Default(TWD), "TWD 11.52"},
|
||||
12: {en, 12.123, Symbol.Default(czk), "CZK 12.12"},
|
||||
13: {en, 13.123, Symbol.Default(czk).Kind(Cash), "CZK 13"},
|
||||
14: {en, 14.12345, ISO.Default(MustParseISO("CLF")), "CLF 14.1235"},
|
||||
15: {en, USD.Amount(15.00), ISO.Default(TWD), "USD 15.00"},
|
||||
16: {en, KRW.Amount(16.00), ISO.Kind(Cash), "KRW 16"},
|
||||
|
||||
// TODO: support integers as well.
|
||||
|
||||
17: {en, USD, nil, "USD"},
|
||||
18: {en, USD, ISO, "USD"},
|
||||
19: {en, USD, Symbol, "$"},
|
||||
20: {en_GB, USD, Symbol, "US$"},
|
||||
21: {en_AU, USD, NarrowSymbol, "$"},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
p := message.NewPrinter(tc.tag)
|
||||
v := tc.value
|
||||
if tc.format != nil {
|
||||
v = tc.format(v)
|
||||
}
|
||||
if got := p.Sprint(v); got != tc.want {
|
||||
t.Errorf("%d: got %q; want %q", i, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
400
vendor/golang.org/x/text/currency/gen.go
generated
vendored
400
vendor/golang.org/x/text/currency/gen.go
generated
vendored
|
|
@ -1,400 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generator for currency-related data.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/internal"
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/tag"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/unicode/cldr"
|
||||
)
|
||||
|
||||
var (
|
||||
test = flag.Bool("test", false,
|
||||
"test existing tables; can be used to compare web data with package data.")
|
||||
outputFile = flag.String("output", "tables.go", "output file")
|
||||
|
||||
draft = flag.String("draft",
|
||||
"contributed",
|
||||
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
|
||||
)
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
|
||||
gen.Repackage("gen_common.go", "common.go", "currency")
|
||||
|
||||
// Read the CLDR zip file.
|
||||
r := gen.OpenCLDRCoreZip()
|
||||
defer r.Close()
|
||||
|
||||
d := &cldr.Decoder{}
|
||||
d.SetDirFilter("supplemental", "main")
|
||||
d.SetSectionFilter("numbers")
|
||||
data, err := d.DecodeZip(r)
|
||||
if err != nil {
|
||||
log.Fatalf("DecodeZip: %v", err)
|
||||
}
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteGoFile(*outputFile, "currency")
|
||||
|
||||
fmt.Fprintln(w, `import "golang.org/x/text/internal/tag"`)
|
||||
|
||||
gen.WriteCLDRVersion(w)
|
||||
b := &builder{}
|
||||
b.genCurrencies(w, data.Supplemental())
|
||||
b.genSymbols(w, data)
|
||||
}
|
||||
|
||||
var constants = []string{
|
||||
// Undefined and testing.
|
||||
"XXX", "XTS",
|
||||
// G11 currencies https://en.wikipedia.org/wiki/G10_currencies.
|
||||
"USD", "EUR", "JPY", "GBP", "CHF", "AUD", "NZD", "CAD", "SEK", "NOK", "DKK",
|
||||
// Precious metals.
|
||||
"XAG", "XAU", "XPT", "XPD",
|
||||
|
||||
// Additional common currencies as defined by CLDR.
|
||||
"BRL", "CNY", "INR", "RUB", "HKD", "IDR", "KRW", "MXN", "PLN", "SAR",
|
||||
"THB", "TRY", "TWD", "ZAR",
|
||||
}
|
||||
|
||||
type builder struct {
|
||||
currencies tag.Index
|
||||
numCurrencies int
|
||||
}
|
||||
|
||||
func (b *builder) genCurrencies(w *gen.CodeWriter, data *cldr.SupplementalData) {
|
||||
// 3-letter ISO currency codes
|
||||
// Start with dummy to let index start at 1.
|
||||
currencies := []string{"\x00\x00\x00\x00"}
|
||||
|
||||
// currency codes
|
||||
for _, reg := range data.CurrencyData.Region {
|
||||
for _, cur := range reg.Currency {
|
||||
currencies = append(currencies, cur.Iso4217)
|
||||
}
|
||||
}
|
||||
// Not included in the list for some reasons:
|
||||
currencies = append(currencies, "MVP")
|
||||
|
||||
sort.Strings(currencies)
|
||||
// Unique the elements.
|
||||
k := 0
|
||||
for i := 1; i < len(currencies); i++ {
|
||||
if currencies[k] != currencies[i] {
|
||||
currencies[k+1] = currencies[i]
|
||||
k++
|
||||
}
|
||||
}
|
||||
currencies = currencies[:k+1]
|
||||
|
||||
// Close with dummy for simpler and faster searching.
|
||||
currencies = append(currencies, "\xff\xff\xff\xff")
|
||||
|
||||
// Write currency values.
|
||||
fmt.Fprintln(w, "const (")
|
||||
for _, c := range constants {
|
||||
index := sort.SearchStrings(currencies, c)
|
||||
fmt.Fprintf(w, "\t%s = %d\n", strings.ToLower(c), index)
|
||||
}
|
||||
fmt.Fprint(w, ")")
|
||||
|
||||
// Compute currency-related data that we merge into the table.
|
||||
for _, info := range data.CurrencyData.Fractions[0].Info {
|
||||
if info.Iso4217 == "DEFAULT" {
|
||||
continue
|
||||
}
|
||||
standard := getRoundingIndex(info.Digits, info.Rounding, 0)
|
||||
cash := getRoundingIndex(info.CashDigits, info.CashRounding, standard)
|
||||
|
||||
index := sort.SearchStrings(currencies, info.Iso4217)
|
||||
currencies[index] += mkCurrencyInfo(standard, cash)
|
||||
}
|
||||
|
||||
// Set default values for entries that weren't touched.
|
||||
for i, c := range currencies {
|
||||
if len(c) == 3 {
|
||||
currencies[i] += mkCurrencyInfo(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
b.currencies = tag.Index(strings.Join(currencies, ""))
|
||||
w.WriteComment(`
|
||||
currency holds an alphabetically sorted list of canonical 3-letter currency
|
||||
identifiers. Each identifier is followed by a byte of type currencyInfo,
|
||||
defined in gen_common.go.`)
|
||||
w.WriteConst("currency", b.currencies)
|
||||
|
||||
// Hack alert: gofmt indents a trailing comment after an indented string.
|
||||
// Ensure that the next thing written is not a comment.
|
||||
b.numCurrencies = (len(b.currencies) / 4) - 2
|
||||
w.WriteConst("numCurrencies", b.numCurrencies)
|
||||
|
||||
// Create a table that maps regions to currencies.
|
||||
regionToCurrency := []toCurrency{}
|
||||
|
||||
for _, reg := range data.CurrencyData.Region {
|
||||
if len(reg.Iso3166) != 2 {
|
||||
log.Fatalf("Unexpected group %q in region data", reg.Iso3166)
|
||||
}
|
||||
if len(reg.Currency) == 0 {
|
||||
continue
|
||||
}
|
||||
cur := reg.Currency[0]
|
||||
if cur.To != "" || cur.Tender == "false" {
|
||||
continue
|
||||
}
|
||||
regionToCurrency = append(regionToCurrency, toCurrency{
|
||||
region: regionToCode(language.MustParseRegion(reg.Iso3166)),
|
||||
code: uint16(b.currencies.Index([]byte(cur.Iso4217))),
|
||||
})
|
||||
}
|
||||
sort.Sort(byRegion(regionToCurrency))
|
||||
|
||||
w.WriteType(toCurrency{})
|
||||
w.WriteVar("regionToCurrency", regionToCurrency)
|
||||
|
||||
// Create a table that maps regions to currencies.
|
||||
regionData := []regionInfo{}
|
||||
|
||||
for _, reg := range data.CurrencyData.Region {
|
||||
if len(reg.Iso3166) != 2 {
|
||||
log.Fatalf("Unexpected group %q in region data", reg.Iso3166)
|
||||
}
|
||||
for _, cur := range reg.Currency {
|
||||
from, _ := time.Parse("2006-01-02", cur.From)
|
||||
to, _ := time.Parse("2006-01-02", cur.To)
|
||||
code := uint16(b.currencies.Index([]byte(cur.Iso4217)))
|
||||
if cur.Tender == "false" {
|
||||
code |= nonTenderBit
|
||||
}
|
||||
regionData = append(regionData, regionInfo{
|
||||
region: regionToCode(language.MustParseRegion(reg.Iso3166)),
|
||||
code: code,
|
||||
from: toDate(from),
|
||||
to: toDate(to),
|
||||
})
|
||||
}
|
||||
}
|
||||
sort.Stable(byRegionCode(regionData))
|
||||
|
||||
w.WriteType(regionInfo{})
|
||||
w.WriteVar("regionData", regionData)
|
||||
}
|
||||
|
||||
type regionInfo struct {
|
||||
region uint16
|
||||
code uint16 // 0x8000 not legal tender
|
||||
from uint32
|
||||
to uint32
|
||||
}
|
||||
|
||||
type byRegionCode []regionInfo
|
||||
|
||||
func (a byRegionCode) Len() int { return len(a) }
|
||||
func (a byRegionCode) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byRegionCode) Less(i, j int) bool { return a[i].region < a[j].region }
|
||||
|
||||
type toCurrency struct {
|
||||
region uint16
|
||||
code uint16
|
||||
}
|
||||
|
||||
type byRegion []toCurrency
|
||||
|
||||
func (a byRegion) Len() int { return len(a) }
|
||||
func (a byRegion) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byRegion) Less(i, j int) bool { return a[i].region < a[j].region }
|
||||
|
||||
func mkCurrencyInfo(standard, cash int) string {
|
||||
return string([]byte{byte(cash<<cashShift | standard)})
|
||||
}
|
||||
|
||||
func getRoundingIndex(digits, rounding string, defIndex int) int {
|
||||
round := roundings[defIndex] // default
|
||||
|
||||
if digits != "" {
|
||||
round.scale = parseUint8(digits)
|
||||
}
|
||||
if rounding != "" && rounding != "0" { // 0 means 1 here in CLDR
|
||||
round.increment = parseUint8(rounding)
|
||||
}
|
||||
|
||||
// Will panic if the entry doesn't exist:
|
||||
for i, r := range roundings {
|
||||
if r == round {
|
||||
return i
|
||||
}
|
||||
}
|
||||
log.Fatalf("Rounding entry %#v does not exist.", round)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// genSymbols generates the symbols used for currencies. Most symbols are
|
||||
// defined in root and there is only very small variation per language.
|
||||
// The following rules apply:
|
||||
// - A symbol can be requested as normal or narrow.
|
||||
// - If a symbol is not defined for a currency, it defaults to its ISO code.
|
||||
func (b *builder) genSymbols(w *gen.CodeWriter, data *cldr.CLDR) {
|
||||
d, err := cldr.ParseDraft(*draft)
|
||||
if err != nil {
|
||||
log.Fatalf("filter: %v", err)
|
||||
}
|
||||
|
||||
const (
|
||||
normal = iota
|
||||
narrow
|
||||
numTypes
|
||||
)
|
||||
// language -> currency -> type -> symbol
|
||||
var symbols [language.NumCompactTags][][numTypes]*string
|
||||
|
||||
// Collect symbol information per language.
|
||||
for _, lang := range data.Locales() {
|
||||
ldml := data.RawLDML(lang)
|
||||
if ldml.Numbers == nil || ldml.Numbers.Currencies == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
langIndex, ok := language.CompactIndex(language.MustParse(lang))
|
||||
if !ok {
|
||||
log.Fatalf("No compact index for language %s", lang)
|
||||
}
|
||||
|
||||
symbols[langIndex] = make([][numTypes]*string, b.numCurrencies+1)
|
||||
|
||||
for _, c := range ldml.Numbers.Currencies.Currency {
|
||||
syms := cldr.MakeSlice(&c.Symbol)
|
||||
syms.SelectDraft(d)
|
||||
|
||||
for _, sym := range c.Symbol {
|
||||
v := sym.Data()
|
||||
if v == c.Type {
|
||||
// We define "" to mean the ISO symbol.
|
||||
v = ""
|
||||
}
|
||||
cur := b.currencies.Index([]byte(c.Type))
|
||||
// XXX gets reassigned to 0 in the package's code.
|
||||
if c.Type == "XXX" {
|
||||
cur = 0
|
||||
}
|
||||
if cur == -1 {
|
||||
fmt.Println("Unsupported:", c.Type)
|
||||
continue
|
||||
}
|
||||
|
||||
switch sym.Alt {
|
||||
case "":
|
||||
symbols[langIndex][cur][normal] = &v
|
||||
case "narrow":
|
||||
symbols[langIndex][cur][narrow] = &v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove values identical to the parent.
|
||||
for langIndex, data := range symbols {
|
||||
for curIndex, curs := range data {
|
||||
for typ, sym := range curs {
|
||||
if sym == nil {
|
||||
continue
|
||||
}
|
||||
for p := uint16(langIndex); p != 0; {
|
||||
p = internal.Parent[p]
|
||||
x := symbols[p]
|
||||
if x == nil {
|
||||
continue
|
||||
}
|
||||
if v := x[curIndex][typ]; v != nil || p == 0 {
|
||||
// Value is equal to the default value root value is undefined.
|
||||
parentSym := ""
|
||||
if v != nil {
|
||||
parentSym = *v
|
||||
}
|
||||
if parentSym == *sym {
|
||||
// Value is the same as parent.
|
||||
data[curIndex][typ] = nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create symbol index.
|
||||
symbolData := []byte{0}
|
||||
symbolLookup := map[string]uint16{"": 0} // 0 means default, so block that value.
|
||||
for _, data := range symbols {
|
||||
for _, curs := range data {
|
||||
for _, sym := range curs {
|
||||
if sym == nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := symbolLookup[*sym]; !ok {
|
||||
symbolLookup[*sym] = uint16(len(symbolData))
|
||||
symbolData = append(symbolData, byte(len(*sym)))
|
||||
symbolData = append(symbolData, *sym...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
w.WriteComment(`
|
||||
symbols holds symbol data of the form <n> <str>, where n is the length of
|
||||
the symbol string str.`)
|
||||
w.WriteConst("symbols", string(symbolData))
|
||||
|
||||
// Create index from language to currency lookup to symbol.
|
||||
type curToIndex struct{ cur, idx uint16 }
|
||||
w.WriteType(curToIndex{})
|
||||
|
||||
prefix := []string{"normal", "narrow"}
|
||||
// Create data for regular and narrow symbol data.
|
||||
for typ := normal; typ <= narrow; typ++ {
|
||||
|
||||
indexes := []curToIndex{} // maps currency to symbol index
|
||||
languages := []uint16{}
|
||||
|
||||
for _, data := range symbols {
|
||||
languages = append(languages, uint16(len(indexes)))
|
||||
for curIndex, curs := range data {
|
||||
|
||||
if sym := curs[typ]; sym != nil {
|
||||
indexes = append(indexes, curToIndex{uint16(curIndex), symbolLookup[*sym]})
|
||||
}
|
||||
}
|
||||
}
|
||||
languages = append(languages, uint16(len(indexes)))
|
||||
|
||||
w.WriteVar(prefix[typ]+"LangIndex", languages)
|
||||
w.WriteVar(prefix[typ]+"SymIndex", indexes)
|
||||
}
|
||||
}
|
||||
func parseUint8(str string) uint8 {
|
||||
x, err := strconv.ParseUint(str, 10, 8)
|
||||
if err != nil {
|
||||
// Show line number of where this function was called.
|
||||
log.New(os.Stderr, "", log.Lshortfile).Output(2, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
return uint8(x)
|
||||
}
|
||||
70
vendor/golang.org/x/text/currency/gen_common.go
generated
vendored
70
vendor/golang.org/x/text/currency/gen_common.go
generated
vendored
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// This file contains code common to gen.go and the package code.
|
||||
|
||||
const (
|
||||
cashShift = 3
|
||||
roundMask = 0x7
|
||||
|
||||
nonTenderBit = 0x8000
|
||||
)
|
||||
|
||||
// currencyInfo contains information about a currency.
|
||||
// bits 0..2: index into roundings for standard rounding
|
||||
// bits 3..5: index into roundings for cash rounding
|
||||
type currencyInfo byte
|
||||
|
||||
// roundingType defines the scale (number of fractional decimals) and increments
|
||||
// in terms of units of size 10^-scale. For example, for scale == 2 and
|
||||
// increment == 1, the currency is rounded to units of 0.01.
|
||||
type roundingType struct {
|
||||
scale, increment uint8
|
||||
}
|
||||
|
||||
// roundings contains rounding data for currencies. This struct is
|
||||
// created by hand as it is very unlikely to change much.
|
||||
var roundings = [...]roundingType{
|
||||
{2, 1}, // default
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{3, 1},
|
||||
{4, 1},
|
||||
{2, 5}, // cash rounding alternative
|
||||
}
|
||||
|
||||
// regionToCode returns a 16-bit region code. Only two-letter codes are
|
||||
// supported. (Three-letter codes are not needed.)
|
||||
func regionToCode(r language.Region) uint16 {
|
||||
if s := r.String(); len(s) == 2 {
|
||||
return uint16(s[0])<<8 | uint16(s[1])
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func toDate(t time.Time) uint32 {
|
||||
y := t.Year()
|
||||
if y == 1 {
|
||||
return 0
|
||||
}
|
||||
date := uint32(y) << 4
|
||||
date |= uint32(t.Month())
|
||||
date <<= 5
|
||||
date |= uint32(t.Day())
|
||||
return date
|
||||
}
|
||||
|
||||
func fromDate(date uint32) time.Time {
|
||||
return time.Date(int(date>>9), time.Month((date>>5)&0xf), int(date&0x1f), 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
152
vendor/golang.org/x/text/currency/query.go
generated
vendored
152
vendor/golang.org/x/text/currency/query.go
generated
vendored
|
|
@ -1,152 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// QueryIter represents a set of Units. The default set includes all Units that
|
||||
// are currently in use as legal tender in any Region.
|
||||
type QueryIter interface {
|
||||
// Next returns true if there is a next element available.
|
||||
// It must be called before any of the other methods are called.
|
||||
Next() bool
|
||||
|
||||
// Unit returns the unit of the current iteration.
|
||||
Unit() Unit
|
||||
|
||||
// Region returns the Region for the current iteration.
|
||||
Region() language.Region
|
||||
|
||||
// From returns the date from which the unit was used in the region.
|
||||
// It returns false if this date is unknown.
|
||||
From() (time.Time, bool)
|
||||
|
||||
// To returns the date up till which the unit was used in the region.
|
||||
// It returns false if this date is unknown or if the unit is still in use.
|
||||
To() (time.Time, bool)
|
||||
|
||||
// IsTender reports whether the unit is a legal tender in the region during
|
||||
// the specified date range.
|
||||
IsTender() bool
|
||||
}
|
||||
|
||||
// Query represents a set of Units. The default set includes all Units that are
|
||||
// currently in use as legal tender in any Region.
|
||||
func Query(options ...QueryOption) QueryIter {
|
||||
it := &iter{
|
||||
end: len(regionData),
|
||||
date: 0xFFFFFFFF,
|
||||
}
|
||||
for _, fn := range options {
|
||||
fn(it)
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
// NonTender returns a new query that also includes matching Units that are not
|
||||
// legal tender.
|
||||
var NonTender QueryOption = nonTender
|
||||
|
||||
func nonTender(i *iter) {
|
||||
i.nonTender = true
|
||||
}
|
||||
|
||||
// Historical selects the units for all dates.
|
||||
var Historical QueryOption = historical
|
||||
|
||||
func historical(i *iter) {
|
||||
i.date = hist
|
||||
}
|
||||
|
||||
// A QueryOption can be used to change the set of unit information returned by
|
||||
// a query.
|
||||
type QueryOption func(*iter)
|
||||
|
||||
// Date queries the units that were in use at the given point in history.
|
||||
func Date(t time.Time) QueryOption {
|
||||
d := toDate(t)
|
||||
return func(i *iter) {
|
||||
i.date = d
|
||||
}
|
||||
}
|
||||
|
||||
// Region limits the query to only return entries for the given region.
|
||||
func Region(r language.Region) QueryOption {
|
||||
p, end := len(regionData), len(regionData)
|
||||
x := regionToCode(r)
|
||||
i := sort.Search(len(regionData), func(i int) bool {
|
||||
return regionData[i].region >= x
|
||||
})
|
||||
if i < len(regionData) && regionData[i].region == x {
|
||||
p = i
|
||||
for i++; i < len(regionData) && regionData[i].region == x; i++ {
|
||||
}
|
||||
end = i
|
||||
}
|
||||
return func(i *iter) {
|
||||
i.p, i.end = p, end
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
hist = 0x00
|
||||
now = 0xFFFFFFFF
|
||||
)
|
||||
|
||||
type iter struct {
|
||||
*regionInfo
|
||||
p, end int
|
||||
date uint32
|
||||
nonTender bool
|
||||
}
|
||||
|
||||
func (i *iter) Next() bool {
|
||||
for ; i.p < i.end; i.p++ {
|
||||
i.regionInfo = ®ionData[i.p]
|
||||
if !i.nonTender && !i.IsTender() {
|
||||
continue
|
||||
}
|
||||
if i.date == hist || (i.from <= i.date && (i.to == 0 || i.date <= i.to)) {
|
||||
i.p++
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *regionInfo) Region() language.Region {
|
||||
// TODO: this could be much faster.
|
||||
var buf [2]byte
|
||||
buf[0] = uint8(r.region >> 8)
|
||||
buf[1] = uint8(r.region)
|
||||
return language.MustParseRegion(string(buf[:]))
|
||||
}
|
||||
|
||||
func (r *regionInfo) Unit() Unit {
|
||||
return Unit{r.code &^ nonTenderBit}
|
||||
}
|
||||
|
||||
func (r *regionInfo) IsTender() bool {
|
||||
return r.code&nonTenderBit == 0
|
||||
}
|
||||
|
||||
func (r *regionInfo) From() (time.Time, bool) {
|
||||
if r.from == 0 {
|
||||
return time.Time{}, false
|
||||
}
|
||||
return fromDate(r.from), true
|
||||
}
|
||||
|
||||
func (r *regionInfo) To() (time.Time, bool) {
|
||||
if r.to == 0 {
|
||||
return time.Time{}, false
|
||||
}
|
||||
return fromDate(r.to), true
|
||||
}
|
||||
107
vendor/golang.org/x/text/currency/query_test.go
generated
vendored
107
vendor/golang.org/x/text/currency/query_test.go
generated
vendored
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package currency
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func TestQuery(t *testing.T) {
|
||||
r := func(region string) language.Region {
|
||||
return language.MustParseRegion(region)
|
||||
}
|
||||
t1800, _ := time.Parse("2006-01-02", "1800-01-01")
|
||||
type result struct {
|
||||
region language.Region
|
||||
unit Unit
|
||||
isTender bool
|
||||
from, to string
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
opts []QueryOption
|
||||
results []result
|
||||
}{{
|
||||
name: "XA",
|
||||
opts: []QueryOption{Region(r("XA"))},
|
||||
results: []result{},
|
||||
}, {
|
||||
name: "AC",
|
||||
opts: []QueryOption{Region(r("AC"))},
|
||||
results: []result{
|
||||
{r("AC"), MustParseISO("SHP"), true, "1976-01-01", ""},
|
||||
},
|
||||
}, {
|
||||
name: "US",
|
||||
opts: []QueryOption{Region(r("US"))},
|
||||
results: []result{
|
||||
{r("US"), MustParseISO("USD"), true, "1792-01-01", ""},
|
||||
},
|
||||
}, {
|
||||
name: "US-hist",
|
||||
opts: []QueryOption{Region(r("US")), Historical},
|
||||
results: []result{
|
||||
{r("US"), MustParseISO("USD"), true, "1792-01-01", ""},
|
||||
},
|
||||
}, {
|
||||
name: "US-non-tender",
|
||||
opts: []QueryOption{Region(r("US")), NonTender},
|
||||
results: []result{
|
||||
{r("US"), MustParseISO("USD"), true, "1792-01-01", ""},
|
||||
{r("US"), MustParseISO("USN"), false, "", ""},
|
||||
},
|
||||
}, {
|
||||
name: "US-historical+non-tender",
|
||||
opts: []QueryOption{Region(r("US")), Historical, NonTender},
|
||||
results: []result{
|
||||
{r("US"), MustParseISO("USD"), true, "1792-01-01", ""},
|
||||
{r("US"), MustParseISO("USN"), false, "", ""},
|
||||
{r("US"), MustParseISO("USS"), false, "", "2014-03-01"},
|
||||
},
|
||||
}, {
|
||||
name: "1800",
|
||||
opts: []QueryOption{Date(t1800)},
|
||||
results: []result{
|
||||
{r("CH"), MustParseISO("CHF"), true, "1799-03-17", ""},
|
||||
{r("GB"), MustParseISO("GBP"), true, "1694-07-27", ""},
|
||||
{r("GI"), MustParseISO("GIP"), true, "1713-01-01", ""},
|
||||
// The date for IE and PR seem wrong, so these may be updated at
|
||||
// some point causing the tests to fail.
|
||||
{r("IE"), MustParseISO("GBP"), true, "1800-01-01", "1922-01-01"},
|
||||
{r("PR"), MustParseISO("ESP"), true, "1800-01-01", "1898-12-10"},
|
||||
{r("US"), MustParseISO("USD"), true, "1792-01-01", ""},
|
||||
},
|
||||
}}
|
||||
for _, tc := range testCases {
|
||||
n := 0
|
||||
for it := Query(tc.opts...); it.Next(); n++ {
|
||||
if n < len(tc.results) {
|
||||
got := result{
|
||||
it.Region(),
|
||||
it.Unit(),
|
||||
it.IsTender(),
|
||||
getTime(it.From()),
|
||||
getTime(it.To()),
|
||||
}
|
||||
if got != tc.results[n] {
|
||||
t.Errorf("%s:%d: got %v; want %v", tc.name, n, got, tc.results[n])
|
||||
}
|
||||
}
|
||||
}
|
||||
if n != len(tc.results) {
|
||||
t.Errorf("%s: unexpected number of results: got %d; want %d", tc.name, n, len(tc.results))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTime(t time.Time, ok bool) string {
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return t.Format("2006-01-02")
|
||||
}
|
||||
2574
vendor/golang.org/x/text/currency/tables.go
generated
vendored
2574
vendor/golang.org/x/text/currency/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
93
vendor/golang.org/x/text/currency/tables_test.go
generated
vendored
93
vendor/golang.org/x/text/currency/tables_test.go
generated
vendored
|
|
@ -1,93 +0,0 @@
|
|||
package currency
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
"golang.org/x/text/internal/testtext"
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
"golang.org/x/text/unicode/cldr"
|
||||
)
|
||||
|
||||
var draft = flag.String("draft",
|
||||
"contributed",
|
||||
`Minimal draft requirements (approved, contributed, provisional, unconfirmed).`)
|
||||
|
||||
func TestTables(t *testing.T) {
|
||||
testtext.SkipIfNotLong(t)
|
||||
|
||||
// Read the CLDR zip file.
|
||||
r := gen.OpenCLDRCoreZip()
|
||||
defer r.Close()
|
||||
|
||||
d := &cldr.Decoder{}
|
||||
d.SetDirFilter("supplemental", "main")
|
||||
d.SetSectionFilter("numbers")
|
||||
data, err := d.DecodeZip(r)
|
||||
if err != nil {
|
||||
t.Fatalf("DecodeZip: %v", err)
|
||||
}
|
||||
|
||||
dr, err := cldr.ParseDraft(*draft)
|
||||
if err != nil {
|
||||
t.Fatalf("filter: %v", err)
|
||||
}
|
||||
|
||||
for _, lang := range data.Locales() {
|
||||
p := message.NewPrinter(language.MustParse(lang))
|
||||
|
||||
ldml := data.RawLDML(lang)
|
||||
if ldml.Numbers == nil || ldml.Numbers.Currencies == nil {
|
||||
continue
|
||||
}
|
||||
for _, c := range ldml.Numbers.Currencies.Currency {
|
||||
syms := cldr.MakeSlice(&c.Symbol)
|
||||
syms.SelectDraft(dr)
|
||||
|
||||
for _, sym := range c.Symbol {
|
||||
cur, err := ParseISO(c.Type)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
formatter := Symbol
|
||||
switch sym.Alt {
|
||||
case "":
|
||||
case "narrow":
|
||||
formatter = NarrowSymbol
|
||||
default:
|
||||
continue
|
||||
}
|
||||
want := sym.Data()
|
||||
if got := p.Sprint(formatter(cur)); got != want {
|
||||
t.Errorf("%s:%sSymbol(%s) = %s; want %s", lang, strings.Title(sym.Alt), c.Type, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, reg := range data.Supplemental().CurrencyData.Region {
|
||||
i := 0
|
||||
for ; regionData[i].Region().String() != reg.Iso3166; i++ {
|
||||
}
|
||||
it := Query(Historical, NonTender, Region(language.MustParseRegion(reg.Iso3166)))
|
||||
for _, cur := range reg.Currency {
|
||||
from, _ := time.Parse("2006-01-02", cur.From)
|
||||
to, _ := time.Parse("2006-01-02", cur.To)
|
||||
|
||||
it.Next()
|
||||
for j, r := range []QueryIter{&iter{regionInfo: ®ionData[i]}, it} {
|
||||
if got, _ := r.From(); from != got {
|
||||
t.Errorf("%d:%s:%s:from: got %v; want %v", j, reg.Iso3166, cur.Iso4217, got, from)
|
||||
}
|
||||
if got, _ := r.To(); to != got {
|
||||
t.Errorf("%d:%s:%s:to: got %v; want %v", j, reg.Iso3166, cur.Iso4217, got, to)
|
||||
}
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
249
vendor/golang.org/x/text/encoding/charmap/charmap.go
generated
vendored
249
vendor/golang.org/x/text/encoding/charmap/charmap.go
generated
vendored
|
|
@ -1,249 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run maketables.go
|
||||
|
||||
// Package charmap provides simple character encodings such as IBM Code Page 437
|
||||
// and Windows 1252.
|
||||
package charmap // import "golang.org/x/text/encoding/charmap"
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// These encodings vary only in the way clients should interpret them. Their
|
||||
// coded character set is identical and a single implementation can be shared.
|
||||
var (
|
||||
// ISO8859_6E is the ISO 8859-6E encoding.
|
||||
ISO8859_6E encoding.Encoding = &iso8859_6E
|
||||
|
||||
// ISO8859_6I is the ISO 8859-6I encoding.
|
||||
ISO8859_6I encoding.Encoding = &iso8859_6I
|
||||
|
||||
// ISO8859_8E is the ISO 8859-8E encoding.
|
||||
ISO8859_8E encoding.Encoding = &iso8859_8E
|
||||
|
||||
// ISO8859_8I is the ISO 8859-8I encoding.
|
||||
ISO8859_8I encoding.Encoding = &iso8859_8I
|
||||
|
||||
iso8859_6E = internal.Encoding{
|
||||
Encoding: ISO8859_6,
|
||||
Name: "ISO-8859-6E",
|
||||
MIB: identifier.ISO88596E,
|
||||
}
|
||||
|
||||
iso8859_6I = internal.Encoding{
|
||||
Encoding: ISO8859_6,
|
||||
Name: "ISO-8859-6I",
|
||||
MIB: identifier.ISO88596I,
|
||||
}
|
||||
|
||||
iso8859_8E = internal.Encoding{
|
||||
Encoding: ISO8859_8,
|
||||
Name: "ISO-8859-8E",
|
||||
MIB: identifier.ISO88598E,
|
||||
}
|
||||
|
||||
iso8859_8I = internal.Encoding{
|
||||
Encoding: ISO8859_8,
|
||||
Name: "ISO-8859-8I",
|
||||
MIB: identifier.ISO88598I,
|
||||
}
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All []encoding.Encoding = listAll
|
||||
|
||||
// TODO: implement these encodings, in order of importance.
|
||||
// ASCII, ISO8859_1: Rather common. Close to Windows 1252.
|
||||
// ISO8859_9: Close to Windows 1254.
|
||||
|
||||
// utf8Enc holds a rune's UTF-8 encoding in data[:len].
|
||||
type utf8Enc struct {
|
||||
len uint8
|
||||
data [3]byte
|
||||
}
|
||||
|
||||
// Charmap is an 8-bit character set encoding.
|
||||
type Charmap struct {
|
||||
// name is the encoding's name.
|
||||
name string
|
||||
// mib is the encoding type of this encoder.
|
||||
mib identifier.MIB
|
||||
// asciiSuperset states whether the encoding is a superset of ASCII.
|
||||
asciiSuperset bool
|
||||
// low is the lower bound of the encoded byte for a non-ASCII rune. If
|
||||
// Charmap.asciiSuperset is true then this will be 0x80, otherwise 0x00.
|
||||
low uint8
|
||||
// replacement is the encoded replacement character.
|
||||
replacement byte
|
||||
// decode is the map from encoded byte to UTF-8.
|
||||
decode [256]utf8Enc
|
||||
// encoding is the map from runes to encoded bytes. Each entry is a
|
||||
// uint32: the high 8 bits are the encoded byte and the low 24 bits are
|
||||
// the rune. The table entries are sorted by ascending rune.
|
||||
encode [256]uint32
|
||||
}
|
||||
|
||||
// NewDecoder implements the encoding.Encoding interface.
|
||||
func (m *Charmap) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: charmapDecoder{charmap: m}}
|
||||
}
|
||||
|
||||
// NewEncoder implements the encoding.Encoding interface.
|
||||
func (m *Charmap) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: charmapEncoder{charmap: m}}
|
||||
}
|
||||
|
||||
// String returns the Charmap's name.
|
||||
func (m *Charmap) String() string {
|
||||
return m.name
|
||||
}
|
||||
|
||||
// ID implements an internal interface.
|
||||
func (m *Charmap) ID() (mib identifier.MIB, other string) {
|
||||
return m.mib, ""
|
||||
}
|
||||
|
||||
// charmapDecoder implements transform.Transformer by decoding to UTF-8.
|
||||
type charmapDecoder struct {
|
||||
transform.NopResetter
|
||||
charmap *Charmap
|
||||
}
|
||||
|
||||
func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
for i, c := range src {
|
||||
if m.charmap.asciiSuperset && c < utf8.RuneSelf {
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = c
|
||||
nDst++
|
||||
nSrc = i + 1
|
||||
continue
|
||||
}
|
||||
|
||||
decode := &m.charmap.decode[c]
|
||||
n := int(decode.len)
|
||||
if nDst+n > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
// It's 15% faster to avoid calling copy for these tiny slices.
|
||||
for j := 0; j < n; j++ {
|
||||
dst[nDst] = decode.data[j]
|
||||
nDst++
|
||||
}
|
||||
nSrc = i + 1
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// DecodeByte returns the Charmap's rune decoding of the byte b.
|
||||
func (m *Charmap) DecodeByte(b byte) rune {
|
||||
switch x := &m.decode[b]; x.len {
|
||||
case 1:
|
||||
return rune(x.data[0])
|
||||
case 2:
|
||||
return rune(x.data[0]&0x1f)<<6 | rune(x.data[1]&0x3f)
|
||||
default:
|
||||
return rune(x.data[0]&0x0f)<<12 | rune(x.data[1]&0x3f)<<6 | rune(x.data[2]&0x3f)
|
||||
}
|
||||
}
|
||||
|
||||
// charmapEncoder implements transform.Transformer by encoding from UTF-8.
|
||||
type charmapEncoder struct {
|
||||
transform.NopResetter
|
||||
charmap *Charmap
|
||||
}
|
||||
|
||||
func (m charmapEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for nSrc < len(src) {
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
if m.charmap.asciiSuperset {
|
||||
nSrc++
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
}
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
} else {
|
||||
err = internal.RepertoireError(m.charmap.replacement)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Binary search in [low, high) for that rune in the m.charmap.encode table.
|
||||
for low, high := int(m.charmap.low), 0x100; ; {
|
||||
if low >= high {
|
||||
err = internal.RepertoireError(m.charmap.replacement)
|
||||
break loop
|
||||
}
|
||||
mid := (low + high) / 2
|
||||
got := m.charmap.encode[mid]
|
||||
gotRune := rune(got & (1<<24 - 1))
|
||||
if gotRune < r {
|
||||
low = mid + 1
|
||||
} else if gotRune > r {
|
||||
high = mid
|
||||
} else {
|
||||
dst[nDst] = byte(got >> 24)
|
||||
nDst++
|
||||
break
|
||||
}
|
||||
}
|
||||
nSrc += size
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// EncodeRune returns the Charmap's byte encoding of the rune r. ok is whether
|
||||
// r is in the Charmap's repertoire. If not, b is set to the Charmap's
|
||||
// replacement byte. This is often the ASCII substitute character '\x1a'.
|
||||
func (m *Charmap) EncodeRune(r rune) (b byte, ok bool) {
|
||||
if r < utf8.RuneSelf && m.asciiSuperset {
|
||||
return byte(r), true
|
||||
}
|
||||
for low, high := int(m.low), 0x100; ; {
|
||||
if low >= high {
|
||||
return m.replacement, false
|
||||
}
|
||||
mid := (low + high) / 2
|
||||
got := m.encode[mid]
|
||||
gotRune := rune(got & (1<<24 - 1))
|
||||
if gotRune < r {
|
||||
low = mid + 1
|
||||
} else if gotRune > r {
|
||||
high = mid
|
||||
} else {
|
||||
return byte(got >> 24), true
|
||||
}
|
||||
}
|
||||
}
|
||||
258
vendor/golang.org/x/text/encoding/charmap/charmap_test.go
generated
vendored
258
vendor/golang.org/x/text/encoding/charmap/charmap_test.go
generated
vendored
|
|
@ -1,258 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package charmap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/enctest"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Decode", e.NewDecoder(), nil
|
||||
}
|
||||
|
||||
func encASCIISuperset(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
|
||||
}
|
||||
|
||||
func encEBCDIC(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.RepertoireError(0x3f)
|
||||
}
|
||||
|
||||
func TestNonRepertoire(t *testing.T) {
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{dec, Windows1252, "\x81", "\ufffd"},
|
||||
|
||||
{encEBCDIC, CodePage037, "갂", ""},
|
||||
|
||||
{encEBCDIC, CodePage1047, "갂", ""},
|
||||
{encEBCDIC, CodePage1047, "a¤갂", "\x81\x9F"},
|
||||
|
||||
{encEBCDIC, CodePage1140, "갂", ""},
|
||||
{encEBCDIC, CodePage1140, "a€갂", "\x81\x9F"},
|
||||
|
||||
{encASCIISuperset, Windows1252, "갂", ""},
|
||||
{encASCIISuperset, Windows1252, "a갂", "a"},
|
||||
{encASCIISuperset, Windows1252, "\u00E9갂", "\xE9"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, wantErr := tc.init(tc.e)
|
||||
|
||||
dst, _, err := transform.String(tr, tc.src)
|
||||
if err != wantErr {
|
||||
t.Errorf("%s %v(%q): got %v; want %v", dir, tc.e, tc.src, err, wantErr)
|
||||
}
|
||||
if got := string(dst); got != tc.want {
|
||||
t.Errorf("%s %v(%q):\ngot %q\nwant %q", dir, tc.e, tc.src, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
testCases := []struct {
|
||||
e encoding.Encoding
|
||||
encoded string
|
||||
utf8 string
|
||||
}{{
|
||||
e: CodePage037,
|
||||
encoded: "\xc8\x51\xba\x93\xcf",
|
||||
utf8: "Hé[lõ",
|
||||
}, {
|
||||
e: CodePage437,
|
||||
encoded: "H\x82ll\x93 \x9d\xa7\xf4\x9c\xbe",
|
||||
utf8: "Héllô ¥º⌠£╛",
|
||||
}, {
|
||||
e: CodePage866,
|
||||
encoded: "H\xf3\xd3o \x98\xfd\x9f\xdd\xa1",
|
||||
utf8: "Hє╙o Ш¤Я▌б",
|
||||
}, {
|
||||
e: CodePage1047,
|
||||
encoded: "\xc8\x54\x93\x93\x9f",
|
||||
utf8: "Hèll¤",
|
||||
}, {
|
||||
e: CodePage1140,
|
||||
encoded: "\xc8\x9f\x93\x93\xcf",
|
||||
utf8: "H€llõ",
|
||||
}, {
|
||||
e: ISO8859_2,
|
||||
encoded: "Hel\xe5\xf5",
|
||||
utf8: "Helĺő",
|
||||
}, {
|
||||
e: ISO8859_3,
|
||||
encoded: "He\xbd\xd4",
|
||||
utf8: "He½Ô",
|
||||
}, {
|
||||
e: ISO8859_4,
|
||||
encoded: "Hel\xb6\xf8",
|
||||
utf8: "Helļø",
|
||||
}, {
|
||||
e: ISO8859_5,
|
||||
encoded: "H\xd7\xc6o",
|
||||
utf8: "HзЦo",
|
||||
}, {
|
||||
e: ISO8859_6,
|
||||
encoded: "Hel\xc2\xc9",
|
||||
utf8: "Helآة",
|
||||
}, {
|
||||
e: ISO8859_7,
|
||||
encoded: "H\xeel\xebo",
|
||||
utf8: "Hξlλo",
|
||||
}, {
|
||||
e: ISO8859_8,
|
||||
encoded: "Hel\xf5\xed",
|
||||
utf8: "Helץם",
|
||||
}, {
|
||||
e: ISO8859_9,
|
||||
encoded: "\xdeayet",
|
||||
utf8: "Şayet",
|
||||
}, {
|
||||
e: ISO8859_10,
|
||||
encoded: "H\xea\xbfo",
|
||||
utf8: "Hęŋo",
|
||||
}, {
|
||||
e: ISO8859_13,
|
||||
encoded: "H\xe6l\xf9o",
|
||||
utf8: "Hęlło",
|
||||
}, {
|
||||
e: ISO8859_14,
|
||||
encoded: "He\xfe\xd0o",
|
||||
utf8: "HeŷŴo",
|
||||
}, {
|
||||
e: ISO8859_15,
|
||||
encoded: "H\xa4ll\xd8",
|
||||
utf8: "H€llØ",
|
||||
}, {
|
||||
e: ISO8859_16,
|
||||
encoded: "H\xe6ll\xbd",
|
||||
utf8: "Hællœ",
|
||||
}, {
|
||||
e: KOI8R,
|
||||
encoded: "He\x93\xad\x9c",
|
||||
utf8: "He⌠╜°",
|
||||
}, {
|
||||
e: KOI8U,
|
||||
encoded: "He\x93\xad\x9c",
|
||||
utf8: "He⌠ґ°",
|
||||
}, {
|
||||
e: Macintosh,
|
||||
encoded: "He\xdf\xd7",
|
||||
utf8: "Hefl◊",
|
||||
}, {
|
||||
e: MacintoshCyrillic,
|
||||
encoded: "He\xbe\x94",
|
||||
utf8: "HeЊФ",
|
||||
}, {
|
||||
e: Windows874,
|
||||
encoded: "He\xb7\xf0",
|
||||
utf8: "Heท๐",
|
||||
}, {
|
||||
e: Windows1250,
|
||||
encoded: "He\xe5\xe5o",
|
||||
utf8: "Heĺĺo",
|
||||
}, {
|
||||
e: Windows1251,
|
||||
encoded: "H\xball\xfe",
|
||||
utf8: "Hєllю",
|
||||
}, {
|
||||
e: Windows1252,
|
||||
encoded: "H\xe9ll\xf4 \xa5\xbA\xae\xa3\xd0",
|
||||
utf8: "Héllô ¥º®£Ð",
|
||||
}, {
|
||||
e: Windows1253,
|
||||
encoded: "H\xe5ll\xd6",
|
||||
utf8: "HεllΦ",
|
||||
}, {
|
||||
e: Windows1254,
|
||||
encoded: "\xd0ello",
|
||||
utf8: "Ğello",
|
||||
}, {
|
||||
e: Windows1255,
|
||||
encoded: "He\xd4o",
|
||||
utf8: "Heװo",
|
||||
}, {
|
||||
e: Windows1256,
|
||||
encoded: "H\xdbllo",
|
||||
utf8: "Hغllo",
|
||||
}, {
|
||||
e: Windows1257,
|
||||
encoded: "He\xeflo",
|
||||
utf8: "Heļlo",
|
||||
}, {
|
||||
e: Windows1258,
|
||||
encoded: "Hell\xf5",
|
||||
utf8: "Hellơ",
|
||||
}, {
|
||||
e: XUserDefined,
|
||||
encoded: "\x00\x40\x7f\x80\xab\xff",
|
||||
utf8: "\u0000\u0040\u007f\uf780\uf7ab\uf7ff",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, "", "")
|
||||
}
|
||||
}
|
||||
|
||||
var windows1255TestCases = []struct {
|
||||
b byte
|
||||
ok bool
|
||||
r rune
|
||||
}{
|
||||
{'\x00', true, '\u0000'},
|
||||
{'\x1a', true, '\u001a'},
|
||||
{'\x61', true, '\u0061'},
|
||||
{'\x7f', true, '\u007f'},
|
||||
{'\x80', true, '\u20ac'},
|
||||
{'\x95', true, '\u2022'},
|
||||
{'\xa0', true, '\u00a0'},
|
||||
{'\xc0', true, '\u05b0'},
|
||||
{'\xfc', true, '\ufffd'},
|
||||
{'\xfd', true, '\u200e'},
|
||||
{'\xfe', true, '\u200f'},
|
||||
{'\xff', true, '\ufffd'},
|
||||
{encoding.ASCIISub, false, '\u0400'},
|
||||
{encoding.ASCIISub, false, '\u2603'},
|
||||
{encoding.ASCIISub, false, '\U0001f4a9'},
|
||||
}
|
||||
|
||||
func TestDecodeByte(t *testing.T) {
|
||||
for _, tc := range windows1255TestCases {
|
||||
if !tc.ok {
|
||||
continue
|
||||
}
|
||||
|
||||
got := Windows1255.DecodeByte(tc.b)
|
||||
want := tc.r
|
||||
if got != want {
|
||||
t.Errorf("DecodeByte(%#02x): got %#08x, want %#08x", tc.b, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeRune(t *testing.T) {
|
||||
for _, tc := range windows1255TestCases {
|
||||
// There can be multiple tc.b values that map to tc.r = '\ufffd'.
|
||||
if tc.r == '\ufffd' {
|
||||
continue
|
||||
}
|
||||
|
||||
gotB, gotOK := Windows1255.EncodeRune(tc.r)
|
||||
wantB, wantOK := tc.b, tc.ok
|
||||
if gotB != wantB || gotOK != wantOK {
|
||||
t.Errorf("EncodeRune(%#08x): got (%#02x, %t), want (%#02x, %t)", tc.r, gotB, gotOK, wantB, wantOK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFiles(t *testing.T) { enctest.TestFile(t, Windows1252) }
|
||||
|
||||
func BenchmarkEncoding(b *testing.B) { enctest.Benchmark(b, Windows1252) }
|
||||
556
vendor/golang.org/x/text/encoding/charmap/maketables.go
generated
vendored
556
vendor/golang.org/x/text/encoding/charmap/maketables.go
generated
vendored
|
|
@ -1,556 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
const ascii = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" +
|
||||
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
|
||||
` !"#$%&'()*+,-./0123456789:;<=>?` +
|
||||
`@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_` +
|
||||
"`abcdefghijklmnopqrstuvwxyz{|}~\u007f"
|
||||
|
||||
var encodings = []struct {
|
||||
name string
|
||||
mib string
|
||||
comment string
|
||||
varName string
|
||||
replacement byte
|
||||
mapping string
|
||||
}{
|
||||
{
|
||||
"IBM Code Page 037",
|
||||
"IBM037",
|
||||
"",
|
||||
"CodePage037",
|
||||
0x3f,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM037-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 437",
|
||||
"PC8CodePage437",
|
||||
"",
|
||||
"CodePage437",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM437-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 850",
|
||||
"PC850Multilingual",
|
||||
"",
|
||||
"CodePage850",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM850-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 852",
|
||||
"PCp852",
|
||||
"",
|
||||
"CodePage852",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM852-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 855",
|
||||
"IBM855",
|
||||
"",
|
||||
"CodePage855",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM855-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"Windows Code Page 858", // PC latin1 with Euro
|
||||
"IBM00858",
|
||||
"",
|
||||
"CodePage858",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-858-2000.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 860",
|
||||
"IBM860",
|
||||
"",
|
||||
"CodePage860",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM860-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 862",
|
||||
"PC862LatinHebrew",
|
||||
"",
|
||||
"CodePage862",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM862-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 863",
|
||||
"IBM863",
|
||||
"",
|
||||
"CodePage863",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM863-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 865",
|
||||
"IBM865",
|
||||
"",
|
||||
"CodePage865",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM865-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 866",
|
||||
"IBM866",
|
||||
"",
|
||||
"CodePage866",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-ibm866.txt",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 1047",
|
||||
"IBM1047",
|
||||
"",
|
||||
"CodePage1047",
|
||||
0x3f,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/glibc-IBM1047-2.1.2.ucm",
|
||||
},
|
||||
{
|
||||
"IBM Code Page 1140",
|
||||
"IBM01140",
|
||||
"",
|
||||
"CodePage1140",
|
||||
0x3f,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/ibm-1140_P100-1997.ucm",
|
||||
},
|
||||
{
|
||||
"ISO 8859-1",
|
||||
"ISOLatin1",
|
||||
"",
|
||||
"ISO8859_1",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_1-1998.ucm",
|
||||
},
|
||||
{
|
||||
"ISO 8859-2",
|
||||
"ISOLatin2",
|
||||
"",
|
||||
"ISO8859_2",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-2.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-3",
|
||||
"ISOLatin3",
|
||||
"",
|
||||
"ISO8859_3",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-3.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-4",
|
||||
"ISOLatin4",
|
||||
"",
|
||||
"ISO8859_4",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-4.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-5",
|
||||
"ISOLatinCyrillic",
|
||||
"",
|
||||
"ISO8859_5",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-5.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-6",
|
||||
"ISOLatinArabic",
|
||||
"",
|
||||
"ISO8859_6,ISO8859_6E,ISO8859_6I",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-6.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-7",
|
||||
"ISOLatinGreek",
|
||||
"",
|
||||
"ISO8859_7",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-7.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-8",
|
||||
"ISOLatinHebrew",
|
||||
"",
|
||||
"ISO8859_8,ISO8859_8E,ISO8859_8I",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-8.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-9",
|
||||
"ISOLatin5",
|
||||
"",
|
||||
"ISO8859_9",
|
||||
encoding.ASCIISub,
|
||||
"http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/iso-8859_9-1999.ucm",
|
||||
},
|
||||
{
|
||||
"ISO 8859-10",
|
||||
"ISOLatin6",
|
||||
"",
|
||||
"ISO8859_10",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-10.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-13",
|
||||
"ISO885913",
|
||||
"",
|
||||
"ISO8859_13",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-13.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-14",
|
||||
"ISO885914",
|
||||
"",
|
||||
"ISO8859_14",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-14.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-15",
|
||||
"ISO885915",
|
||||
"",
|
||||
"ISO8859_15",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-15.txt",
|
||||
},
|
||||
{
|
||||
"ISO 8859-16",
|
||||
"ISO885916",
|
||||
"",
|
||||
"ISO8859_16",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-iso-8859-16.txt",
|
||||
},
|
||||
{
|
||||
"KOI8-R",
|
||||
"KOI8R",
|
||||
"",
|
||||
"KOI8R",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-koi8-r.txt",
|
||||
},
|
||||
{
|
||||
"KOI8-U",
|
||||
"KOI8U",
|
||||
"",
|
||||
"KOI8U",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-koi8-u.txt",
|
||||
},
|
||||
{
|
||||
"Macintosh",
|
||||
"Macintosh",
|
||||
"",
|
||||
"Macintosh",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-macintosh.txt",
|
||||
},
|
||||
{
|
||||
"Macintosh Cyrillic",
|
||||
"MacintoshCyrillic",
|
||||
"",
|
||||
"MacintoshCyrillic",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-x-mac-cyrillic.txt",
|
||||
},
|
||||
{
|
||||
"Windows 874",
|
||||
"Windows874",
|
||||
"",
|
||||
"Windows874",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-874.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1250",
|
||||
"Windows1250",
|
||||
"",
|
||||
"Windows1250",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1250.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1251",
|
||||
"Windows1251",
|
||||
"",
|
||||
"Windows1251",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1251.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1252",
|
||||
"Windows1252",
|
||||
"",
|
||||
"Windows1252",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1252.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1253",
|
||||
"Windows1253",
|
||||
"",
|
||||
"Windows1253",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1253.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1254",
|
||||
"Windows1254",
|
||||
"",
|
||||
"Windows1254",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1254.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1255",
|
||||
"Windows1255",
|
||||
"",
|
||||
"Windows1255",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1255.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1256",
|
||||
"Windows1256",
|
||||
"",
|
||||
"Windows1256",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1256.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1257",
|
||||
"Windows1257",
|
||||
"",
|
||||
"Windows1257",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1257.txt",
|
||||
},
|
||||
{
|
||||
"Windows 1258",
|
||||
"Windows1258",
|
||||
"",
|
||||
"Windows1258",
|
||||
encoding.ASCIISub,
|
||||
"http://encoding.spec.whatwg.org/index-windows-1258.txt",
|
||||
},
|
||||
{
|
||||
"X-User-Defined",
|
||||
"XUserDefined",
|
||||
"It is defined at http://encoding.spec.whatwg.org/#x-user-defined",
|
||||
"XUserDefined",
|
||||
encoding.ASCIISub,
|
||||
ascii +
|
||||
"\uf780\uf781\uf782\uf783\uf784\uf785\uf786\uf787" +
|
||||
"\uf788\uf789\uf78a\uf78b\uf78c\uf78d\uf78e\uf78f" +
|
||||
"\uf790\uf791\uf792\uf793\uf794\uf795\uf796\uf797" +
|
||||
"\uf798\uf799\uf79a\uf79b\uf79c\uf79d\uf79e\uf79f" +
|
||||
"\uf7a0\uf7a1\uf7a2\uf7a3\uf7a4\uf7a5\uf7a6\uf7a7" +
|
||||
"\uf7a8\uf7a9\uf7aa\uf7ab\uf7ac\uf7ad\uf7ae\uf7af" +
|
||||
"\uf7b0\uf7b1\uf7b2\uf7b3\uf7b4\uf7b5\uf7b6\uf7b7" +
|
||||
"\uf7b8\uf7b9\uf7ba\uf7bb\uf7bc\uf7bd\uf7be\uf7bf" +
|
||||
"\uf7c0\uf7c1\uf7c2\uf7c3\uf7c4\uf7c5\uf7c6\uf7c7" +
|
||||
"\uf7c8\uf7c9\uf7ca\uf7cb\uf7cc\uf7cd\uf7ce\uf7cf" +
|
||||
"\uf7d0\uf7d1\uf7d2\uf7d3\uf7d4\uf7d5\uf7d6\uf7d7" +
|
||||
"\uf7d8\uf7d9\uf7da\uf7db\uf7dc\uf7dd\uf7de\uf7df" +
|
||||
"\uf7e0\uf7e1\uf7e2\uf7e3\uf7e4\uf7e5\uf7e6\uf7e7" +
|
||||
"\uf7e8\uf7e9\uf7ea\uf7eb\uf7ec\uf7ed\uf7ee\uf7ef" +
|
||||
"\uf7f0\uf7f1\uf7f2\uf7f3\uf7f4\uf7f5\uf7f6\uf7f7" +
|
||||
"\uf7f8\uf7f9\uf7fa\uf7fb\uf7fc\uf7fd\uf7fe\uf7ff",
|
||||
},
|
||||
}
|
||||
|
||||
func getWHATWG(url string) string {
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
log.Fatalf("%q: Get: %v", url, err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := make([]rune, 128)
|
||||
for i := range mapping {
|
||||
mapping[i] = '\ufffd'
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := 0, 0
|
||||
if _, err := fmt.Sscanf(s, "%d\t0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("could not parse %q", s)
|
||||
}
|
||||
if x < 0 || 128 <= x {
|
||||
log.Fatalf("code %d is out of range", x)
|
||||
}
|
||||
if 0x80 <= y && y < 0xa0 {
|
||||
// We diverge from the WHATWG spec by mapping control characters
|
||||
// in the range [0x80, 0xa0) to U+FFFD.
|
||||
continue
|
||||
}
|
||||
mapping[x] = rune(y)
|
||||
}
|
||||
return ascii + string(mapping)
|
||||
}
|
||||
|
||||
func getUCM(url string) string {
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
log.Fatalf("%q: Get: %v", url, err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := make([]rune, 256)
|
||||
for i := range mapping {
|
||||
mapping[i] = '\ufffd'
|
||||
}
|
||||
|
||||
charsFound := 0
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
var c byte
|
||||
var r rune
|
||||
if _, err := fmt.Sscanf(s, `<U%x> \x%x |0`, &r, &c); err != nil {
|
||||
continue
|
||||
}
|
||||
mapping[c] = r
|
||||
charsFound++
|
||||
}
|
||||
|
||||
if charsFound < 200 {
|
||||
log.Fatalf("%q: only %d characters found (wrong page format?)", url, charsFound)
|
||||
}
|
||||
|
||||
return string(mapping)
|
||||
}
|
||||
|
||||
func main() {
|
||||
mibs := map[string]bool{}
|
||||
all := []string{}
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
defer w.WriteGoFile("tables.go", "charmap")
|
||||
|
||||
printf := func(s string, a ...interface{}) { fmt.Fprintf(w, s, a...) }
|
||||
|
||||
printf("import (\n")
|
||||
printf("\t\"golang.org/x/text/encoding\"\n")
|
||||
printf("\t\"golang.org/x/text/encoding/internal/identifier\"\n")
|
||||
printf(")\n\n")
|
||||
for _, e := range encodings {
|
||||
varNames := strings.Split(e.varName, ",")
|
||||
all = append(all, varNames...)
|
||||
varName := varNames[0]
|
||||
switch {
|
||||
case strings.HasPrefix(e.mapping, "http://encoding.spec.whatwg.org/"):
|
||||
e.mapping = getWHATWG(e.mapping)
|
||||
case strings.HasPrefix(e.mapping, "http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/"):
|
||||
e.mapping = getUCM(e.mapping)
|
||||
}
|
||||
|
||||
asciiSuperset, low := strings.HasPrefix(e.mapping, ascii), 0x00
|
||||
if asciiSuperset {
|
||||
low = 0x80
|
||||
}
|
||||
lvn := 1
|
||||
if strings.HasPrefix(varName, "ISO") || strings.HasPrefix(varName, "KOI") {
|
||||
lvn = 3
|
||||
}
|
||||
lowerVarName := strings.ToLower(varName[:lvn]) + varName[lvn:]
|
||||
printf("// %s is the %s encoding.\n", varName, e.name)
|
||||
if e.comment != "" {
|
||||
printf("//\n// %s\n", e.comment)
|
||||
}
|
||||
printf("var %s *Charmap = &%s\n\nvar %s = Charmap{\nname: %q,\n",
|
||||
varName, lowerVarName, lowerVarName, e.name)
|
||||
if mibs[e.mib] {
|
||||
log.Fatalf("MIB type %q declared multiple times.", e.mib)
|
||||
}
|
||||
printf("mib: identifier.%s,\n", e.mib)
|
||||
printf("asciiSuperset: %t,\n", asciiSuperset)
|
||||
printf("low: 0x%02x,\n", low)
|
||||
printf("replacement: 0x%02x,\n", e.replacement)
|
||||
|
||||
printf("decode: [256]utf8Enc{\n")
|
||||
i, backMapping := 0, map[rune]byte{}
|
||||
for _, c := range e.mapping {
|
||||
if _, ok := backMapping[c]; !ok && c != utf8.RuneError {
|
||||
backMapping[c] = byte(i)
|
||||
}
|
||||
var buf [8]byte
|
||||
n := utf8.EncodeRune(buf[:], c)
|
||||
if n > 3 {
|
||||
panic(fmt.Sprintf("rune %q (%U) is too long", c, c))
|
||||
}
|
||||
printf("{%d,[3]byte{0x%02x,0x%02x,0x%02x}},", n, buf[0], buf[1], buf[2])
|
||||
if i%2 == 1 {
|
||||
printf("\n")
|
||||
}
|
||||
i++
|
||||
}
|
||||
printf("},\n")
|
||||
|
||||
printf("encode: [256]uint32{\n")
|
||||
encode := make([]uint32, 0, 256)
|
||||
for c, i := range backMapping {
|
||||
encode = append(encode, uint32(i)<<24|uint32(c))
|
||||
}
|
||||
sort.Sort(byRune(encode))
|
||||
for len(encode) < cap(encode) {
|
||||
encode = append(encode, encode[len(encode)-1])
|
||||
}
|
||||
for i, enc := range encode {
|
||||
printf("0x%08x,", enc)
|
||||
if i%8 == 7 {
|
||||
printf("\n")
|
||||
}
|
||||
}
|
||||
printf("},\n}\n")
|
||||
|
||||
// Add an estimate of the size of a single Charmap{} struct value, which
|
||||
// includes two 256 elem arrays of 4 bytes and some extra fields, which
|
||||
// align to 3 uint64s on 64-bit architectures.
|
||||
w.Size += 2*4*256 + 3*8
|
||||
}
|
||||
// TODO: add proper line breaking.
|
||||
printf("var listAll = []encoding.Encoding{\n%s,\n}\n\n", strings.Join(all, ",\n"))
|
||||
}
|
||||
|
||||
type byRune []uint32
|
||||
|
||||
func (b byRune) Len() int { return len(b) }
|
||||
func (b byRune) Less(i, j int) bool { return b[i]&0xffffff < b[j]&0xffffff }
|
||||
func (b byRune) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
7410
vendor/golang.org/x/text/encoding/charmap/tables.go
generated
vendored
7410
vendor/golang.org/x/text/encoding/charmap/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
335
vendor/golang.org/x/text/encoding/encoding.go
generated
vendored
335
vendor/golang.org/x/text/encoding/encoding.go
generated
vendored
|
|
@ -1,335 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package encoding defines an interface for character encodings, such as Shift
|
||||
// JIS and Windows 1252, that can convert to and from UTF-8.
|
||||
//
|
||||
// Encoding implementations are provided in other packages, such as
|
||||
// golang.org/x/text/encoding/charmap and
|
||||
// golang.org/x/text/encoding/japanese.
|
||||
package encoding // import "golang.org/x/text/encoding"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - There seems to be some inconsistency in when decoders return errors
|
||||
// and when not. Also documentation seems to suggest they shouldn't return
|
||||
// errors at all (except for UTF-16).
|
||||
// - Encoders seem to rely on or at least benefit from the input being in NFC
|
||||
// normal form. Perhaps add an example how users could prepare their output.
|
||||
|
||||
// Encoding is a character set encoding that can be transformed to and from
|
||||
// UTF-8.
|
||||
type Encoding interface {
|
||||
// NewDecoder returns a Decoder.
|
||||
NewDecoder() *Decoder
|
||||
|
||||
// NewEncoder returns an Encoder.
|
||||
NewEncoder() *Encoder
|
||||
}
|
||||
|
||||
// A Decoder converts bytes to UTF-8. It implements transform.Transformer.
|
||||
//
|
||||
// Transforming source bytes that are not of that encoding will not result in an
|
||||
// error per se. Each byte that cannot be transcoded will be represented in the
|
||||
// output by the UTF-8 encoding of '\uFFFD', the replacement rune.
|
||||
type Decoder struct {
|
||||
transform.Transformer
|
||||
|
||||
// This forces external creators of Decoders to use names in struct
|
||||
// initializers, allowing for future extendibility without having to break
|
||||
// code.
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// Bytes converts the given encoded bytes to UTF-8. It returns the converted
|
||||
// bytes or nil, err if any error occurred.
|
||||
func (d *Decoder) Bytes(b []byte) ([]byte, error) {
|
||||
b, _, err := transform.Bytes(d, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// String converts the given encoded string to UTF-8. It returns the converted
|
||||
// string or "", err if any error occurred.
|
||||
func (d *Decoder) String(s string) (string, error) {
|
||||
s, _, err := transform.String(d, s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Reader wraps another Reader to decode its bytes.
|
||||
//
|
||||
// The Decoder may not be used for any other operation as long as the returned
|
||||
// Reader is in use.
|
||||
func (d *Decoder) Reader(r io.Reader) io.Reader {
|
||||
return transform.NewReader(r, d)
|
||||
}
|
||||
|
||||
// An Encoder converts bytes from UTF-8. It implements transform.Transformer.
|
||||
//
|
||||
// Each rune that cannot be transcoded will result in an error. In this case,
|
||||
// the transform will consume all source byte up to, not including the offending
|
||||
// rune. Transforming source bytes that are not valid UTF-8 will be replaced by
|
||||
// `\uFFFD`. To return early with an error instead, use transform.Chain to
|
||||
// preprocess the data with a UTF8Validator.
|
||||
type Encoder struct {
|
||||
transform.Transformer
|
||||
|
||||
// This forces external creators of Encoders to use names in struct
|
||||
// initializers, allowing for future extendibility without having to break
|
||||
// code.
|
||||
_ struct{}
|
||||
}
|
||||
|
||||
// Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if
|
||||
// any error occurred.
|
||||
func (e *Encoder) Bytes(b []byte) ([]byte, error) {
|
||||
b, _, err := transform.Bytes(e, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// String converts a string from UTF-8. It returns the converted string or
|
||||
// "", err if any error occurred.
|
||||
func (e *Encoder) String(s string) (string, error) {
|
||||
s, _, err := transform.String(e, s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Writer wraps another Writer to encode its UTF-8 output.
|
||||
//
|
||||
// The Encoder may not be used for any other operation as long as the returned
|
||||
// Writer is in use.
|
||||
func (e *Encoder) Writer(w io.Writer) io.Writer {
|
||||
return transform.NewWriter(w, e)
|
||||
}
|
||||
|
||||
// ASCIISub is the ASCII substitute character, as recommended by
|
||||
// http://unicode.org/reports/tr36/#Text_Comparison
|
||||
const ASCIISub = '\x1a'
|
||||
|
||||
// Nop is the nop encoding. Its transformed bytes are the same as the source
|
||||
// bytes; it does not replace invalid UTF-8 sequences.
|
||||
var Nop Encoding = nop{}
|
||||
|
||||
type nop struct{}
|
||||
|
||||
func (nop) NewDecoder() *Decoder {
|
||||
return &Decoder{Transformer: transform.Nop}
|
||||
}
|
||||
func (nop) NewEncoder() *Encoder {
|
||||
return &Encoder{Transformer: transform.Nop}
|
||||
}
|
||||
|
||||
// Replacement is the replacement encoding. Decoding from the replacement
|
||||
// encoding yields a single '\uFFFD' replacement rune. Encoding from UTF-8 to
|
||||
// the replacement encoding yields the same as the source bytes except that
|
||||
// invalid UTF-8 is converted to '\uFFFD'.
|
||||
//
|
||||
// It is defined at http://encoding.spec.whatwg.org/#replacement
|
||||
var Replacement Encoding = replacement{}
|
||||
|
||||
type replacement struct{}
|
||||
|
||||
func (replacement) NewDecoder() *Decoder {
|
||||
return &Decoder{Transformer: replacementDecoder{}}
|
||||
}
|
||||
|
||||
func (replacement) NewEncoder() *Encoder {
|
||||
return &Encoder{Transformer: replacementEncoder{}}
|
||||
}
|
||||
|
||||
func (replacement) ID() (mib identifier.MIB, other string) {
|
||||
return identifier.Replacement, ""
|
||||
}
|
||||
|
||||
type replacementDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (replacementDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if len(dst) < 3 {
|
||||
return 0, 0, transform.ErrShortDst
|
||||
}
|
||||
if atEOF {
|
||||
const fffd = "\ufffd"
|
||||
dst[0] = fffd[0]
|
||||
dst[1] = fffd[1]
|
||||
dst[2] = fffd[2]
|
||||
nDst = 3
|
||||
}
|
||||
return nDst, len(src), nil
|
||||
}
|
||||
|
||||
type replacementEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (replacementEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
// HTMLEscapeUnsupported wraps encoders to replace source runes outside the
|
||||
// repertoire of the destination encoding with HTML escape sequences.
|
||||
//
|
||||
// This wrapper exists to comply to URL and HTML forms requiring a
|
||||
// non-terminating legacy encoder. The produced sequences may lead to data
|
||||
// loss as they are indistinguishable from legitimate input. To avoid this
|
||||
// issue, use UTF-8 encodings whenever possible.
|
||||
func HTMLEscapeUnsupported(e *Encoder) *Encoder {
|
||||
return &Encoder{Transformer: &errorHandler{e, errorToHTML}}
|
||||
}
|
||||
|
||||
// ReplaceUnsupported wraps encoders to replace source runes outside the
|
||||
// repertoire of the destination encoding with an encoding-specific
|
||||
// replacement.
|
||||
//
|
||||
// This wrapper is only provided for backwards compatibility and legacy
|
||||
// handling. Its use is strongly discouraged. Use UTF-8 whenever possible.
|
||||
func ReplaceUnsupported(e *Encoder) *Encoder {
|
||||
return &Encoder{Transformer: &errorHandler{e, errorToReplacement}}
|
||||
}
|
||||
|
||||
type errorHandler struct {
|
||||
*Encoder
|
||||
handler func(dst []byte, r rune, err repertoireError) (n int, ok bool)
|
||||
}
|
||||
|
||||
// TODO: consider making this error public in some form.
|
||||
type repertoireError interface {
|
||||
Replacement() byte
|
||||
}
|
||||
|
||||
func (h errorHandler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
nDst, nSrc, err = h.Transformer.Transform(dst, src, atEOF)
|
||||
for err != nil {
|
||||
rerr, ok := err.(repertoireError)
|
||||
if !ok {
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
r, sz := utf8.DecodeRune(src[nSrc:])
|
||||
n, ok := h.handler(dst[nDst:], r, rerr)
|
||||
if !ok {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
err = nil
|
||||
nDst += n
|
||||
if nSrc += sz; nSrc < len(src) {
|
||||
var dn, sn int
|
||||
dn, sn, err = h.Transformer.Transform(dst[nDst:], src[nSrc:], atEOF)
|
||||
nDst += dn
|
||||
nSrc += sn
|
||||
}
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func errorToHTML(dst []byte, r rune, err repertoireError) (n int, ok bool) {
|
||||
buf := [8]byte{}
|
||||
b := strconv.AppendUint(buf[:0], uint64(r), 10)
|
||||
if n = len(b) + len("&#;"); n >= len(dst) {
|
||||
return 0, false
|
||||
}
|
||||
dst[0] = '&'
|
||||
dst[1] = '#'
|
||||
dst[copy(dst[2:], b)+2] = ';'
|
||||
return n, true
|
||||
}
|
||||
|
||||
func errorToReplacement(dst []byte, r rune, err repertoireError) (n int, ok bool) {
|
||||
if len(dst) == 0 {
|
||||
return 0, false
|
||||
}
|
||||
dst[0] = err.Replacement()
|
||||
return 1, true
|
||||
}
|
||||
|
||||
// ErrInvalidUTF8 means that a transformer encountered invalid UTF-8.
|
||||
var ErrInvalidUTF8 = errors.New("encoding: invalid UTF-8")
|
||||
|
||||
// UTF8Validator is a transformer that returns ErrInvalidUTF8 on the first
|
||||
// input byte that is not valid UTF-8.
|
||||
var UTF8Validator transform.Transformer = utf8Validator{}
|
||||
|
||||
type utf8Validator struct{ transform.NopResetter }
|
||||
|
||||
func (utf8Validator) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
n := len(src)
|
||||
if n > len(dst) {
|
||||
n = len(dst)
|
||||
}
|
||||
for i := 0; i < n; {
|
||||
if c := src[i]; c < utf8.RuneSelf {
|
||||
dst[i] = c
|
||||
i++
|
||||
continue
|
||||
}
|
||||
_, size := utf8.DecodeRune(src[i:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
err = ErrInvalidUTF8
|
||||
if !atEOF && !utf8.FullRune(src[i:]) {
|
||||
err = transform.ErrShortSrc
|
||||
}
|
||||
return i, i, err
|
||||
}
|
||||
if i+size > len(dst) {
|
||||
return i, i, transform.ErrShortDst
|
||||
}
|
||||
for ; size > 0; size-- {
|
||||
dst[i] = src[i]
|
||||
i++
|
||||
}
|
||||
}
|
||||
if len(src) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
}
|
||||
return n, n, err
|
||||
}
|
||||
290
vendor/golang.org/x/text/encoding/encoding_test.go
generated
vendored
290
vendor/golang.org/x/text/encoding/encoding_test.go
generated
vendored
|
|
@ -1,290 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package encoding_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func TestEncodeInvalidUTF8(t *testing.T) {
|
||||
inputs := []string{
|
||||
"hello.",
|
||||
"wo\ufffdld.",
|
||||
"ABC\xff\x80\x80", // Invalid UTF-8.
|
||||
"\x80\x80\x80\x80\x80",
|
||||
"\x80\x80D\x80\x80", // Valid rune at "D".
|
||||
"E\xed\xa0\x80\xed\xbf\xbfF", // Two invalid UTF-8 runes (surrogates).
|
||||
"G",
|
||||
"H\xe2\x82", // U+20AC in UTF-8 is "\xe2\x82\xac", which we split over two
|
||||
"\xacI\xe2\x82", // input lines. It maps to 0x80 in the Windows-1252 encoding.
|
||||
}
|
||||
// Each invalid source byte becomes '\x1a'.
|
||||
want := strings.Replace("hello.wo?ld.ABC??????????D??E??????FGH\x80I??", "?", "\x1a", -1)
|
||||
|
||||
transformer := encoding.ReplaceUnsupported(charmap.Windows1252.NewEncoder())
|
||||
gotBuf := make([]byte, 0, 1024)
|
||||
src := make([]byte, 0, 1024)
|
||||
for i, input := range inputs {
|
||||
dst := make([]byte, 1024)
|
||||
src = append(src, input...)
|
||||
atEOF := i == len(inputs)-1
|
||||
nDst, nSrc, err := transformer.Transform(dst, src, atEOF)
|
||||
gotBuf = append(gotBuf, dst[:nDst]...)
|
||||
src = src[nSrc:]
|
||||
if err != nil && err != transform.ErrShortSrc {
|
||||
t.Fatalf("i=%d: %v", i, err)
|
||||
}
|
||||
if atEOF && err != nil {
|
||||
t.Fatalf("i=%d: atEOF: %v", i, err)
|
||||
}
|
||||
}
|
||||
if got := string(gotBuf); got != want {
|
||||
t.Fatalf("\ngot %+q\nwant %+q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReplacement(t *testing.T) {
|
||||
for _, direction := range []string{"Decode", "Encode"} {
|
||||
enc, want := (transform.Transformer)(nil), ""
|
||||
if direction == "Decode" {
|
||||
enc = encoding.Replacement.NewDecoder()
|
||||
want = "\ufffd"
|
||||
} else {
|
||||
enc = encoding.Replacement.NewEncoder()
|
||||
want = "AB\x00CD\ufffdYZ"
|
||||
}
|
||||
sr := strings.NewReader("AB\x00CD\x80YZ")
|
||||
g, err := ioutil.ReadAll(transform.NewReader(sr, enc))
|
||||
if err != nil {
|
||||
t.Errorf("%s: ReadAll: %v", direction, err)
|
||||
continue
|
||||
}
|
||||
if got := string(g); got != want {
|
||||
t.Errorf("%s:\ngot %q\nwant %q", direction, got, want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUTF8Validator(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
dstSize int
|
||||
src string
|
||||
atEOF bool
|
||||
want string
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
"empty input",
|
||||
100,
|
||||
"",
|
||||
false,
|
||||
"",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid 1-byte 1-rune input",
|
||||
100,
|
||||
"a",
|
||||
false,
|
||||
"a",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid 3-byte 1-rune input",
|
||||
100,
|
||||
"\u1234",
|
||||
false,
|
||||
"\u1234",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid 5-byte 3-rune input",
|
||||
100,
|
||||
"a\u0100\u0101",
|
||||
false,
|
||||
"a\u0100\u0101",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"perfectly sized dst (non-ASCII)",
|
||||
5,
|
||||
"a\u0100\u0101",
|
||||
false,
|
||||
"a\u0100\u0101",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"short dst (non-ASCII)",
|
||||
4,
|
||||
"a\u0100\u0101",
|
||||
false,
|
||||
"a\u0100",
|
||||
transform.ErrShortDst,
|
||||
},
|
||||
{
|
||||
"perfectly sized dst (ASCII)",
|
||||
5,
|
||||
"abcde",
|
||||
false,
|
||||
"abcde",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"short dst (ASCII)",
|
||||
4,
|
||||
"abcde",
|
||||
false,
|
||||
"abcd",
|
||||
transform.ErrShortDst,
|
||||
},
|
||||
{
|
||||
"partial input (!EOF)",
|
||||
100,
|
||||
"a\u0100\xf1",
|
||||
false,
|
||||
"a\u0100",
|
||||
transform.ErrShortSrc,
|
||||
},
|
||||
{
|
||||
"invalid input (EOF)",
|
||||
100,
|
||||
"a\u0100\xf1",
|
||||
true,
|
||||
"a\u0100",
|
||||
encoding.ErrInvalidUTF8,
|
||||
},
|
||||
{
|
||||
"invalid input (!EOF)",
|
||||
100,
|
||||
"a\u0100\x80",
|
||||
false,
|
||||
"a\u0100",
|
||||
encoding.ErrInvalidUTF8,
|
||||
},
|
||||
{
|
||||
"invalid input (above U+10FFFF)",
|
||||
100,
|
||||
"a\u0100\xf7\xbf\xbf\xbf",
|
||||
false,
|
||||
"a\u0100",
|
||||
encoding.ErrInvalidUTF8,
|
||||
},
|
||||
{
|
||||
"invalid input (surrogate half)",
|
||||
100,
|
||||
"a\u0100\xed\xa0\x80",
|
||||
false,
|
||||
"a\u0100",
|
||||
encoding.ErrInvalidUTF8,
|
||||
},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dst := make([]byte, tc.dstSize)
|
||||
nDst, nSrc, err := encoding.UTF8Validator.Transform(dst, []byte(tc.src), tc.atEOF)
|
||||
if nDst < 0 || len(dst) < nDst {
|
||||
t.Errorf("%s: nDst=%d out of range", tc.desc, nDst)
|
||||
continue
|
||||
}
|
||||
got := string(dst[:nDst])
|
||||
if got != tc.want || nSrc != len(tc.want) || err != tc.wantErr {
|
||||
t.Errorf("%s:\ngot %+q, %d, %v\nwant %+q, %d, %v",
|
||||
tc.desc, got, nSrc, err, tc.want, len(tc.want), tc.wantErr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorHandler(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
handler func(*encoding.Encoder) *encoding.Encoder
|
||||
sizeDst int
|
||||
src, want string
|
||||
nSrc int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "one rune replacement",
|
||||
handler: encoding.ReplaceUnsupported,
|
||||
sizeDst: 100,
|
||||
src: "\uAC00",
|
||||
want: "\x1a",
|
||||
nSrc: 3,
|
||||
},
|
||||
{
|
||||
desc: "mid-stream rune replacement",
|
||||
handler: encoding.ReplaceUnsupported,
|
||||
sizeDst: 100,
|
||||
src: "a\uAC00bcd\u00e9",
|
||||
want: "a\x1abcd\xe9",
|
||||
nSrc: 9,
|
||||
},
|
||||
{
|
||||
desc: "at end rune replacement",
|
||||
handler: encoding.ReplaceUnsupported,
|
||||
sizeDst: 10,
|
||||
src: "\u00e9\uAC00",
|
||||
want: "\xe9\x1a",
|
||||
nSrc: 5,
|
||||
},
|
||||
{
|
||||
desc: "short buffer replacement",
|
||||
handler: encoding.ReplaceUnsupported,
|
||||
sizeDst: 1,
|
||||
src: "\u00e9\uAC00",
|
||||
want: "\xe9",
|
||||
nSrc: 2,
|
||||
err: transform.ErrShortDst,
|
||||
},
|
||||
{
|
||||
desc: "one rune html escape",
|
||||
handler: encoding.HTMLEscapeUnsupported,
|
||||
sizeDst: 100,
|
||||
src: "\uAC00",
|
||||
want: "가",
|
||||
nSrc: 3,
|
||||
},
|
||||
{
|
||||
desc: "mid-stream html escape",
|
||||
handler: encoding.HTMLEscapeUnsupported,
|
||||
sizeDst: 100,
|
||||
src: "\u00e9\uAC00dcba",
|
||||
want: "\xe9가dcba",
|
||||
nSrc: 9,
|
||||
},
|
||||
{
|
||||
desc: "short buffer html escape",
|
||||
handler: encoding.HTMLEscapeUnsupported,
|
||||
sizeDst: 9,
|
||||
src: "ab\uAC01",
|
||||
want: "ab",
|
||||
nSrc: 2,
|
||||
err: transform.ErrShortDst,
|
||||
},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
tr := tc.handler(charmap.Windows1250.NewEncoder())
|
||||
b := make([]byte, tc.sizeDst)
|
||||
nDst, nSrc, err := tr.Transform(b, []byte(tc.src), true)
|
||||
if err != tc.err {
|
||||
t.Errorf("%d:%s: error was %v; want %v", i, tc.desc, err, tc.err)
|
||||
}
|
||||
if got := string(b[:nDst]); got != tc.want {
|
||||
t.Errorf("%d:%s: result was %q: want %q", i, tc.desc, got, tc.want)
|
||||
}
|
||||
if nSrc != tc.nSrc {
|
||||
t.Errorf("%d:%s: nSrc was %d; want %d", i, tc.desc, nSrc, tc.nSrc)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
42
vendor/golang.org/x/text/encoding/example_test.go
generated
vendored
42
vendor/golang.org/x/text/encoding/example_test.go
generated
vendored
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package encoding_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func ExampleDecodeWindows1252() {
|
||||
sr := strings.NewReader("Gar\xe7on !")
|
||||
tr := charmap.Windows1252.NewDecoder().Reader(sr)
|
||||
io.Copy(os.Stdout, tr)
|
||||
// Output: Garçon !
|
||||
}
|
||||
|
||||
func ExampleUTF8Validator() {
|
||||
for i := 0; i < 2; i++ {
|
||||
var transformer transform.Transformer
|
||||
transformer = unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM).NewEncoder()
|
||||
if i == 1 {
|
||||
transformer = transform.Chain(encoding.UTF8Validator, transformer)
|
||||
}
|
||||
dst := make([]byte, 256)
|
||||
src := []byte("abc\xffxyz") // src is invalid UTF-8.
|
||||
nDst, nSrc, err := transformer.Transform(dst, src, true)
|
||||
fmt.Printf("i=%d: produced %q, consumed %q, error %v\n",
|
||||
i, dst[:nDst], src[:nSrc], err)
|
||||
}
|
||||
// Output:
|
||||
// i=0: produced "\x00a\x00b\x00c\xff\xfd\x00x\x00y\x00z", consumed "abc\xffxyz", error <nil>
|
||||
// i=1: produced "\x00a\x00b\x00c", consumed "abc", error encoding: invalid UTF-8
|
||||
}
|
||||
173
vendor/golang.org/x/text/encoding/htmlindex/gen.go
generated
vendored
173
vendor/golang.org/x/text/encoding/htmlindex/gen.go
generated
vendored
|
|
@ -1,173 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
type group struct {
|
||||
Encodings []struct {
|
||||
Labels []string
|
||||
Name string
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
gen.Init()
|
||||
|
||||
r := gen.Open("https://encoding.spec.whatwg.org", "whatwg", "encodings.json")
|
||||
var groups []group
|
||||
if err := json.NewDecoder(r).Decode(&groups); err != nil {
|
||||
log.Fatalf("Error reading encodings.json: %v", err)
|
||||
}
|
||||
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintln(w, "type htmlEncoding byte")
|
||||
fmt.Fprintln(w, "const (")
|
||||
for i, g := range groups {
|
||||
for _, e := range g.Encodings {
|
||||
key := strings.ToLower(e.Name)
|
||||
name := consts[key]
|
||||
if name == "" {
|
||||
log.Fatalf("No const defined for %s.", key)
|
||||
}
|
||||
if i == 0 {
|
||||
fmt.Fprintf(w, "%s htmlEncoding = iota\n", name)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s\n", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, "numEncodings")
|
||||
fmt.Fprint(w, ")\n\n")
|
||||
|
||||
fmt.Fprintln(w, "var canonical = [numEncodings]string{")
|
||||
for _, g := range groups {
|
||||
for _, e := range g.Encodings {
|
||||
fmt.Fprintf(w, "%q,\n", strings.ToLower(e.Name))
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "}\n\n")
|
||||
|
||||
fmt.Fprintln(w, "var nameMap = map[string]htmlEncoding{")
|
||||
for _, g := range groups {
|
||||
for _, e := range g.Encodings {
|
||||
for _, l := range e.Labels {
|
||||
key := strings.ToLower(e.Name)
|
||||
name := consts[key]
|
||||
fmt.Fprintf(w, "%q: %s,\n", l, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "}\n\n")
|
||||
|
||||
var tags []string
|
||||
fmt.Fprintln(w, "var localeMap = []htmlEncoding{")
|
||||
for _, loc := range locales {
|
||||
tags = append(tags, loc.tag)
|
||||
fmt.Fprintf(w, "%s, // %s \n", consts[loc.name], loc.tag)
|
||||
}
|
||||
fmt.Fprint(w, "}\n\n")
|
||||
|
||||
fmt.Fprintf(w, "const locales = %q\n", strings.Join(tags, " "))
|
||||
|
||||
gen.WriteGoFile("tables.go", "htmlindex", w.Bytes())
|
||||
}
|
||||
|
||||
// consts maps canonical encoding name to internal constant.
|
||||
var consts = map[string]string{
|
||||
"utf-8": "utf8",
|
||||
"ibm866": "ibm866",
|
||||
"iso-8859-2": "iso8859_2",
|
||||
"iso-8859-3": "iso8859_3",
|
||||
"iso-8859-4": "iso8859_4",
|
||||
"iso-8859-5": "iso8859_5",
|
||||
"iso-8859-6": "iso8859_6",
|
||||
"iso-8859-7": "iso8859_7",
|
||||
"iso-8859-8": "iso8859_8",
|
||||
"iso-8859-8-i": "iso8859_8I",
|
||||
"iso-8859-10": "iso8859_10",
|
||||
"iso-8859-13": "iso8859_13",
|
||||
"iso-8859-14": "iso8859_14",
|
||||
"iso-8859-15": "iso8859_15",
|
||||
"iso-8859-16": "iso8859_16",
|
||||
"koi8-r": "koi8r",
|
||||
"koi8-u": "koi8u",
|
||||
"macintosh": "macintosh",
|
||||
"windows-874": "windows874",
|
||||
"windows-1250": "windows1250",
|
||||
"windows-1251": "windows1251",
|
||||
"windows-1252": "windows1252",
|
||||
"windows-1253": "windows1253",
|
||||
"windows-1254": "windows1254",
|
||||
"windows-1255": "windows1255",
|
||||
"windows-1256": "windows1256",
|
||||
"windows-1257": "windows1257",
|
||||
"windows-1258": "windows1258",
|
||||
"x-mac-cyrillic": "macintoshCyrillic",
|
||||
"gbk": "gbk",
|
||||
"gb18030": "gb18030",
|
||||
// "hz-gb-2312": "hzgb2312", // Was removed from WhatWG
|
||||
"big5": "big5",
|
||||
"euc-jp": "eucjp",
|
||||
"iso-2022-jp": "iso2022jp",
|
||||
"shift_jis": "shiftJIS",
|
||||
"euc-kr": "euckr",
|
||||
"replacement": "replacement",
|
||||
"utf-16be": "utf16be",
|
||||
"utf-16le": "utf16le",
|
||||
"x-user-defined": "xUserDefined",
|
||||
}
|
||||
|
||||
// locales is taken from
|
||||
// https://html.spec.whatwg.org/multipage/syntax.html#encoding-sniffing-algorithm.
|
||||
var locales = []struct{ tag, name string }{
|
||||
// The default value. Explicitly state latin to benefit from the exact
|
||||
// script option, while still making 1252 the default encoding for languages
|
||||
// written in Latin script.
|
||||
{"und_Latn", "windows-1252"},
|
||||
{"ar", "windows-1256"},
|
||||
{"ba", "windows-1251"},
|
||||
{"be", "windows-1251"},
|
||||
{"bg", "windows-1251"},
|
||||
{"cs", "windows-1250"},
|
||||
{"el", "iso-8859-7"},
|
||||
{"et", "windows-1257"},
|
||||
{"fa", "windows-1256"},
|
||||
{"he", "windows-1255"},
|
||||
{"hr", "windows-1250"},
|
||||
{"hu", "iso-8859-2"},
|
||||
{"ja", "shift_jis"},
|
||||
{"kk", "windows-1251"},
|
||||
{"ko", "euc-kr"},
|
||||
{"ku", "windows-1254"},
|
||||
{"ky", "windows-1251"},
|
||||
{"lt", "windows-1257"},
|
||||
{"lv", "windows-1257"},
|
||||
{"mk", "windows-1251"},
|
||||
{"pl", "iso-8859-2"},
|
||||
{"ru", "windows-1251"},
|
||||
{"sah", "windows-1251"},
|
||||
{"sk", "windows-1250"},
|
||||
{"sl", "iso-8859-2"},
|
||||
{"sr", "windows-1251"},
|
||||
{"tg", "windows-1251"},
|
||||
{"th", "windows-874"},
|
||||
{"tr", "windows-1254"},
|
||||
{"tt", "windows-1251"},
|
||||
{"uk", "windows-1251"},
|
||||
{"vi", "windows-1258"},
|
||||
{"zh-hans", "gb18030"},
|
||||
{"zh-hant", "big5"},
|
||||
}
|
||||
86
vendor/golang.org/x/text/encoding/htmlindex/htmlindex.go
generated
vendored
86
vendor/golang.org/x/text/encoding/htmlindex/htmlindex.go
generated
vendored
|
|
@ -1,86 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// Package htmlindex maps character set encoding names to Encodings as
|
||||
// recommended by the W3C for use in HTML 5. See http://www.w3.org/TR/encoding.
|
||||
package htmlindex
|
||||
|
||||
// TODO: perhaps have a "bare" version of the index (used by this package) that
|
||||
// is not pre-loaded with all encodings. Global variables in encodings prevent
|
||||
// the linker from being able to purge unneeded tables. This means that
|
||||
// referencing all encodings, as this package does for the default index, links
|
||||
// in all encodings unconditionally.
|
||||
//
|
||||
// This issue can be solved by either solving the linking issue (see
|
||||
// https://github.com/golang/go/issues/6330) or refactoring the encoding tables
|
||||
// (e.g. moving the tables to internal packages that do not use global
|
||||
// variables).
|
||||
|
||||
// TODO: allow canonicalizing names
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidName = errors.New("htmlindex: invalid encoding name")
|
||||
errUnknown = errors.New("htmlindex: unknown Encoding")
|
||||
errUnsupported = errors.New("htmlindex: this encoding is not supported")
|
||||
)
|
||||
|
||||
var (
|
||||
matcherOnce sync.Once
|
||||
matcher language.Matcher
|
||||
)
|
||||
|
||||
// LanguageDefault returns the canonical name of the default encoding for a
|
||||
// given language.
|
||||
func LanguageDefault(tag language.Tag) string {
|
||||
matcherOnce.Do(func() {
|
||||
tags := []language.Tag{}
|
||||
for _, t := range strings.Split(locales, " ") {
|
||||
tags = append(tags, language.MustParse(t))
|
||||
}
|
||||
matcher = language.NewMatcher(tags, language.PreferSameScript(true))
|
||||
})
|
||||
_, i, _ := matcher.Match(tag)
|
||||
return canonical[localeMap[i]] // Default is Windows-1252.
|
||||
}
|
||||
|
||||
// Get returns an Encoding for one of the names listed in
|
||||
// http://www.w3.org/TR/encoding using the Default Index. Matching is case-
|
||||
// insensitive.
|
||||
func Get(name string) (encoding.Encoding, error) {
|
||||
x, ok := nameMap[strings.ToLower(strings.TrimSpace(name))]
|
||||
if !ok {
|
||||
return nil, errInvalidName
|
||||
}
|
||||
return encodings[x], nil
|
||||
}
|
||||
|
||||
// Name reports the canonical name of the given Encoding. It will return
|
||||
// an error if e is not associated with a supported encoding scheme.
|
||||
func Name(e encoding.Encoding) (string, error) {
|
||||
id, ok := e.(identifier.Interface)
|
||||
if !ok {
|
||||
return "", errUnknown
|
||||
}
|
||||
mib, _ := id.ID()
|
||||
if mib == 0 {
|
||||
return "", errUnknown
|
||||
}
|
||||
v, ok := mibMap[mib]
|
||||
if !ok {
|
||||
return "", errUnsupported
|
||||
}
|
||||
return canonical[v], nil
|
||||
}
|
||||
144
vendor/golang.org/x/text/encoding/htmlindex/htmlindex_test.go
generated
vendored
144
vendor/golang.org/x/text/encoding/htmlindex/htmlindex_test.go
generated
vendored
|
|
@ -1,144 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package htmlindex
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
for i, tc := range []struct {
|
||||
name string
|
||||
canonical string
|
||||
err error
|
||||
}{
|
||||
{"utf-8", "utf-8", nil},
|
||||
{" utf-8 ", "utf-8", nil},
|
||||
{" l5 ", "windows-1254", nil},
|
||||
{"latin5 ", "windows-1254", nil},
|
||||
{"latin 5", "", errInvalidName},
|
||||
{"latin-5", "", errInvalidName},
|
||||
} {
|
||||
enc, err := Get(tc.name)
|
||||
if err != tc.err {
|
||||
t.Errorf("%d: error was %v; want %v", i, err, tc.err)
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if got, err := Name(enc); got != tc.canonical {
|
||||
t.Errorf("%d: Name(Get(%q)) = %q; want %q (%v)", i, tc.name, got, tc.canonical, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTables(t *testing.T) {
|
||||
for name, index := range nameMap {
|
||||
got, err := Get(name)
|
||||
if err != nil {
|
||||
t.Errorf("%s:err: expected non-nil error", name)
|
||||
}
|
||||
if want := encodings[index]; got != want {
|
||||
t.Errorf("%s:encoding: got %v; want %v", name, got, want)
|
||||
}
|
||||
mib, _ := got.(identifier.Interface).ID()
|
||||
if mibMap[mib] != index {
|
||||
t.Errorf("%s:mibMab: got %d; want %d", name, mibMap[mib], index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
for i, tc := range []struct {
|
||||
desc string
|
||||
enc encoding.Encoding
|
||||
name string
|
||||
err error
|
||||
}{{
|
||||
"defined encoding",
|
||||
charmap.ISO8859_2,
|
||||
"iso-8859-2",
|
||||
nil,
|
||||
}, {
|
||||
"defined Unicode encoding",
|
||||
unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
|
||||
"utf-16be",
|
||||
nil,
|
||||
}, {
|
||||
"undefined Unicode encoding in HTML standard",
|
||||
unicode.UTF16(unicode.BigEndian, unicode.UseBOM),
|
||||
"",
|
||||
errUnsupported,
|
||||
}, {
|
||||
"undefined other encoding in HTML standard",
|
||||
charmap.CodePage437,
|
||||
"",
|
||||
errUnsupported,
|
||||
}, {
|
||||
"unknown encoding",
|
||||
encoding.Nop,
|
||||
"",
|
||||
errUnknown,
|
||||
}} {
|
||||
name, err := Name(tc.enc)
|
||||
if name != tc.name || err != tc.err {
|
||||
t.Errorf("%d:%s: got %q, %v; want %q, %v", i, tc.desc, name, err, tc.name, tc.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLanguageDefault(t *testing.T) {
|
||||
for _, tc := range []struct{ tag, want string }{
|
||||
{"und", "windows-1252"}, // The default value.
|
||||
{"ar", "windows-1256"},
|
||||
{"ba", "windows-1251"},
|
||||
{"be", "windows-1251"},
|
||||
{"bg", "windows-1251"},
|
||||
{"cs", "windows-1250"},
|
||||
{"el", "iso-8859-7"},
|
||||
{"et", "windows-1257"},
|
||||
{"fa", "windows-1256"},
|
||||
{"he", "windows-1255"},
|
||||
{"hr", "windows-1250"},
|
||||
{"hu", "iso-8859-2"},
|
||||
{"ja", "shift_jis"},
|
||||
{"kk", "windows-1251"},
|
||||
{"ko", "euc-kr"},
|
||||
{"ku", "windows-1254"},
|
||||
{"ky", "windows-1251"},
|
||||
{"lt", "windows-1257"},
|
||||
{"lv", "windows-1257"},
|
||||
{"mk", "windows-1251"},
|
||||
{"pl", "iso-8859-2"},
|
||||
{"ru", "windows-1251"},
|
||||
{"sah", "windows-1251"},
|
||||
{"sk", "windows-1250"},
|
||||
{"sl", "iso-8859-2"},
|
||||
{"sr", "windows-1251"},
|
||||
{"tg", "windows-1251"},
|
||||
{"th", "windows-874"},
|
||||
{"tr", "windows-1254"},
|
||||
{"tt", "windows-1251"},
|
||||
{"uk", "windows-1251"},
|
||||
{"vi", "windows-1258"},
|
||||
{"zh-hans", "gb18030"},
|
||||
{"zh-hant", "big5"},
|
||||
// Variants and close approximates of the above.
|
||||
{"ar_EG", "windows-1256"},
|
||||
{"bs", "windows-1250"}, // Bosnian Latin maps to Croatian.
|
||||
// Use default fallback in case of miss.
|
||||
{"nl", "windows-1252"},
|
||||
} {
|
||||
if got := LanguageDefault(language.MustParse(tc.tag)); got != tc.want {
|
||||
t.Errorf("LanguageDefault(%s) = %s; want %s", tc.tag, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
105
vendor/golang.org/x/text/encoding/htmlindex/map.go
generated
vendored
105
vendor/golang.org/x/text/encoding/htmlindex/map.go
generated
vendored
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package htmlindex
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/encoding/traditionalchinese"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
// mibMap maps a MIB identifier to an htmlEncoding index.
|
||||
var mibMap = map[identifier.MIB]htmlEncoding{
|
||||
identifier.UTF8: utf8,
|
||||
identifier.UTF16BE: utf16be,
|
||||
identifier.UTF16LE: utf16le,
|
||||
identifier.IBM866: ibm866,
|
||||
identifier.ISOLatin2: iso8859_2,
|
||||
identifier.ISOLatin3: iso8859_3,
|
||||
identifier.ISOLatin4: iso8859_4,
|
||||
identifier.ISOLatinCyrillic: iso8859_5,
|
||||
identifier.ISOLatinArabic: iso8859_6,
|
||||
identifier.ISOLatinGreek: iso8859_7,
|
||||
identifier.ISOLatinHebrew: iso8859_8,
|
||||
identifier.ISO88598I: iso8859_8I,
|
||||
identifier.ISOLatin6: iso8859_10,
|
||||
identifier.ISO885913: iso8859_13,
|
||||
identifier.ISO885914: iso8859_14,
|
||||
identifier.ISO885915: iso8859_15,
|
||||
identifier.ISO885916: iso8859_16,
|
||||
identifier.KOI8R: koi8r,
|
||||
identifier.KOI8U: koi8u,
|
||||
identifier.Macintosh: macintosh,
|
||||
identifier.MacintoshCyrillic: macintoshCyrillic,
|
||||
identifier.Windows874: windows874,
|
||||
identifier.Windows1250: windows1250,
|
||||
identifier.Windows1251: windows1251,
|
||||
identifier.Windows1252: windows1252,
|
||||
identifier.Windows1253: windows1253,
|
||||
identifier.Windows1254: windows1254,
|
||||
identifier.Windows1255: windows1255,
|
||||
identifier.Windows1256: windows1256,
|
||||
identifier.Windows1257: windows1257,
|
||||
identifier.Windows1258: windows1258,
|
||||
identifier.XUserDefined: xUserDefined,
|
||||
identifier.GBK: gbk,
|
||||
identifier.GB18030: gb18030,
|
||||
identifier.Big5: big5,
|
||||
identifier.EUCPkdFmtJapanese: eucjp,
|
||||
identifier.ISO2022JP: iso2022jp,
|
||||
identifier.ShiftJIS: shiftJIS,
|
||||
identifier.EUCKR: euckr,
|
||||
identifier.Replacement: replacement,
|
||||
}
|
||||
|
||||
// encodings maps the internal htmlEncoding to an Encoding.
|
||||
// TODO: consider using a reusable index in encoding/internal.
|
||||
var encodings = [numEncodings]encoding.Encoding{
|
||||
utf8: unicode.UTF8,
|
||||
ibm866: charmap.CodePage866,
|
||||
iso8859_2: charmap.ISO8859_2,
|
||||
iso8859_3: charmap.ISO8859_3,
|
||||
iso8859_4: charmap.ISO8859_4,
|
||||
iso8859_5: charmap.ISO8859_5,
|
||||
iso8859_6: charmap.ISO8859_6,
|
||||
iso8859_7: charmap.ISO8859_7,
|
||||
iso8859_8: charmap.ISO8859_8,
|
||||
iso8859_8I: charmap.ISO8859_8I,
|
||||
iso8859_10: charmap.ISO8859_10,
|
||||
iso8859_13: charmap.ISO8859_13,
|
||||
iso8859_14: charmap.ISO8859_14,
|
||||
iso8859_15: charmap.ISO8859_15,
|
||||
iso8859_16: charmap.ISO8859_16,
|
||||
koi8r: charmap.KOI8R,
|
||||
koi8u: charmap.KOI8U,
|
||||
macintosh: charmap.Macintosh,
|
||||
windows874: charmap.Windows874,
|
||||
windows1250: charmap.Windows1250,
|
||||
windows1251: charmap.Windows1251,
|
||||
windows1252: charmap.Windows1252,
|
||||
windows1253: charmap.Windows1253,
|
||||
windows1254: charmap.Windows1254,
|
||||
windows1255: charmap.Windows1255,
|
||||
windows1256: charmap.Windows1256,
|
||||
windows1257: charmap.Windows1257,
|
||||
windows1258: charmap.Windows1258,
|
||||
macintoshCyrillic: charmap.MacintoshCyrillic,
|
||||
gbk: simplifiedchinese.GBK,
|
||||
gb18030: simplifiedchinese.GB18030,
|
||||
big5: traditionalchinese.Big5,
|
||||
eucjp: japanese.EUCJP,
|
||||
iso2022jp: japanese.ISO2022JP,
|
||||
shiftJIS: japanese.ShiftJIS,
|
||||
euckr: korean.EUCKR,
|
||||
replacement: encoding.Replacement,
|
||||
utf16be: unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
|
||||
utf16le: unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM),
|
||||
xUserDefined: charmap.XUserDefined,
|
||||
}
|
||||
352
vendor/golang.org/x/text/encoding/htmlindex/tables.go
generated
vendored
352
vendor/golang.org/x/text/encoding/htmlindex/tables.go
generated
vendored
|
|
@ -1,352 +0,0 @@
|
|||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
package htmlindex
|
||||
|
||||
type htmlEncoding byte
|
||||
|
||||
const (
|
||||
utf8 htmlEncoding = iota
|
||||
ibm866
|
||||
iso8859_2
|
||||
iso8859_3
|
||||
iso8859_4
|
||||
iso8859_5
|
||||
iso8859_6
|
||||
iso8859_7
|
||||
iso8859_8
|
||||
iso8859_8I
|
||||
iso8859_10
|
||||
iso8859_13
|
||||
iso8859_14
|
||||
iso8859_15
|
||||
iso8859_16
|
||||
koi8r
|
||||
koi8u
|
||||
macintosh
|
||||
windows874
|
||||
windows1250
|
||||
windows1251
|
||||
windows1252
|
||||
windows1253
|
||||
windows1254
|
||||
windows1255
|
||||
windows1256
|
||||
windows1257
|
||||
windows1258
|
||||
macintoshCyrillic
|
||||
gbk
|
||||
gb18030
|
||||
big5
|
||||
eucjp
|
||||
iso2022jp
|
||||
shiftJIS
|
||||
euckr
|
||||
replacement
|
||||
utf16be
|
||||
utf16le
|
||||
xUserDefined
|
||||
numEncodings
|
||||
)
|
||||
|
||||
var canonical = [numEncodings]string{
|
||||
"utf-8",
|
||||
"ibm866",
|
||||
"iso-8859-2",
|
||||
"iso-8859-3",
|
||||
"iso-8859-4",
|
||||
"iso-8859-5",
|
||||
"iso-8859-6",
|
||||
"iso-8859-7",
|
||||
"iso-8859-8",
|
||||
"iso-8859-8-i",
|
||||
"iso-8859-10",
|
||||
"iso-8859-13",
|
||||
"iso-8859-14",
|
||||
"iso-8859-15",
|
||||
"iso-8859-16",
|
||||
"koi8-r",
|
||||
"koi8-u",
|
||||
"macintosh",
|
||||
"windows-874",
|
||||
"windows-1250",
|
||||
"windows-1251",
|
||||
"windows-1252",
|
||||
"windows-1253",
|
||||
"windows-1254",
|
||||
"windows-1255",
|
||||
"windows-1256",
|
||||
"windows-1257",
|
||||
"windows-1258",
|
||||
"x-mac-cyrillic",
|
||||
"gbk",
|
||||
"gb18030",
|
||||
"big5",
|
||||
"euc-jp",
|
||||
"iso-2022-jp",
|
||||
"shift_jis",
|
||||
"euc-kr",
|
||||
"replacement",
|
||||
"utf-16be",
|
||||
"utf-16le",
|
||||
"x-user-defined",
|
||||
}
|
||||
|
||||
var nameMap = map[string]htmlEncoding{
|
||||
"unicode-1-1-utf-8": utf8,
|
||||
"utf-8": utf8,
|
||||
"utf8": utf8,
|
||||
"866": ibm866,
|
||||
"cp866": ibm866,
|
||||
"csibm866": ibm866,
|
||||
"ibm866": ibm866,
|
||||
"csisolatin2": iso8859_2,
|
||||
"iso-8859-2": iso8859_2,
|
||||
"iso-ir-101": iso8859_2,
|
||||
"iso8859-2": iso8859_2,
|
||||
"iso88592": iso8859_2,
|
||||
"iso_8859-2": iso8859_2,
|
||||
"iso_8859-2:1987": iso8859_2,
|
||||
"l2": iso8859_2,
|
||||
"latin2": iso8859_2,
|
||||
"csisolatin3": iso8859_3,
|
||||
"iso-8859-3": iso8859_3,
|
||||
"iso-ir-109": iso8859_3,
|
||||
"iso8859-3": iso8859_3,
|
||||
"iso88593": iso8859_3,
|
||||
"iso_8859-3": iso8859_3,
|
||||
"iso_8859-3:1988": iso8859_3,
|
||||
"l3": iso8859_3,
|
||||
"latin3": iso8859_3,
|
||||
"csisolatin4": iso8859_4,
|
||||
"iso-8859-4": iso8859_4,
|
||||
"iso-ir-110": iso8859_4,
|
||||
"iso8859-4": iso8859_4,
|
||||
"iso88594": iso8859_4,
|
||||
"iso_8859-4": iso8859_4,
|
||||
"iso_8859-4:1988": iso8859_4,
|
||||
"l4": iso8859_4,
|
||||
"latin4": iso8859_4,
|
||||
"csisolatincyrillic": iso8859_5,
|
||||
"cyrillic": iso8859_5,
|
||||
"iso-8859-5": iso8859_5,
|
||||
"iso-ir-144": iso8859_5,
|
||||
"iso8859-5": iso8859_5,
|
||||
"iso88595": iso8859_5,
|
||||
"iso_8859-5": iso8859_5,
|
||||
"iso_8859-5:1988": iso8859_5,
|
||||
"arabic": iso8859_6,
|
||||
"asmo-708": iso8859_6,
|
||||
"csiso88596e": iso8859_6,
|
||||
"csiso88596i": iso8859_6,
|
||||
"csisolatinarabic": iso8859_6,
|
||||
"ecma-114": iso8859_6,
|
||||
"iso-8859-6": iso8859_6,
|
||||
"iso-8859-6-e": iso8859_6,
|
||||
"iso-8859-6-i": iso8859_6,
|
||||
"iso-ir-127": iso8859_6,
|
||||
"iso8859-6": iso8859_6,
|
||||
"iso88596": iso8859_6,
|
||||
"iso_8859-6": iso8859_6,
|
||||
"iso_8859-6:1987": iso8859_6,
|
||||
"csisolatingreek": iso8859_7,
|
||||
"ecma-118": iso8859_7,
|
||||
"elot_928": iso8859_7,
|
||||
"greek": iso8859_7,
|
||||
"greek8": iso8859_7,
|
||||
"iso-8859-7": iso8859_7,
|
||||
"iso-ir-126": iso8859_7,
|
||||
"iso8859-7": iso8859_7,
|
||||
"iso88597": iso8859_7,
|
||||
"iso_8859-7": iso8859_7,
|
||||
"iso_8859-7:1987": iso8859_7,
|
||||
"sun_eu_greek": iso8859_7,
|
||||
"csiso88598e": iso8859_8,
|
||||
"csisolatinhebrew": iso8859_8,
|
||||
"hebrew": iso8859_8,
|
||||
"iso-8859-8": iso8859_8,
|
||||
"iso-8859-8-e": iso8859_8,
|
||||
"iso-ir-138": iso8859_8,
|
||||
"iso8859-8": iso8859_8,
|
||||
"iso88598": iso8859_8,
|
||||
"iso_8859-8": iso8859_8,
|
||||
"iso_8859-8:1988": iso8859_8,
|
||||
"visual": iso8859_8,
|
||||
"csiso88598i": iso8859_8I,
|
||||
"iso-8859-8-i": iso8859_8I,
|
||||
"logical": iso8859_8I,
|
||||
"csisolatin6": iso8859_10,
|
||||
"iso-8859-10": iso8859_10,
|
||||
"iso-ir-157": iso8859_10,
|
||||
"iso8859-10": iso8859_10,
|
||||
"iso885910": iso8859_10,
|
||||
"l6": iso8859_10,
|
||||
"latin6": iso8859_10,
|
||||
"iso-8859-13": iso8859_13,
|
||||
"iso8859-13": iso8859_13,
|
||||
"iso885913": iso8859_13,
|
||||
"iso-8859-14": iso8859_14,
|
||||
"iso8859-14": iso8859_14,
|
||||
"iso885914": iso8859_14,
|
||||
"csisolatin9": iso8859_15,
|
||||
"iso-8859-15": iso8859_15,
|
||||
"iso8859-15": iso8859_15,
|
||||
"iso885915": iso8859_15,
|
||||
"iso_8859-15": iso8859_15,
|
||||
"l9": iso8859_15,
|
||||
"iso-8859-16": iso8859_16,
|
||||
"cskoi8r": koi8r,
|
||||
"koi": koi8r,
|
||||
"koi8": koi8r,
|
||||
"koi8-r": koi8r,
|
||||
"koi8_r": koi8r,
|
||||
"koi8-ru": koi8u,
|
||||
"koi8-u": koi8u,
|
||||
"csmacintosh": macintosh,
|
||||
"mac": macintosh,
|
||||
"macintosh": macintosh,
|
||||
"x-mac-roman": macintosh,
|
||||
"dos-874": windows874,
|
||||
"iso-8859-11": windows874,
|
||||
"iso8859-11": windows874,
|
||||
"iso885911": windows874,
|
||||
"tis-620": windows874,
|
||||
"windows-874": windows874,
|
||||
"cp1250": windows1250,
|
||||
"windows-1250": windows1250,
|
||||
"x-cp1250": windows1250,
|
||||
"cp1251": windows1251,
|
||||
"windows-1251": windows1251,
|
||||
"x-cp1251": windows1251,
|
||||
"ansi_x3.4-1968": windows1252,
|
||||
"ascii": windows1252,
|
||||
"cp1252": windows1252,
|
||||
"cp819": windows1252,
|
||||
"csisolatin1": windows1252,
|
||||
"ibm819": windows1252,
|
||||
"iso-8859-1": windows1252,
|
||||
"iso-ir-100": windows1252,
|
||||
"iso8859-1": windows1252,
|
||||
"iso88591": windows1252,
|
||||
"iso_8859-1": windows1252,
|
||||
"iso_8859-1:1987": windows1252,
|
||||
"l1": windows1252,
|
||||
"latin1": windows1252,
|
||||
"us-ascii": windows1252,
|
||||
"windows-1252": windows1252,
|
||||
"x-cp1252": windows1252,
|
||||
"cp1253": windows1253,
|
||||
"windows-1253": windows1253,
|
||||
"x-cp1253": windows1253,
|
||||
"cp1254": windows1254,
|
||||
"csisolatin5": windows1254,
|
||||
"iso-8859-9": windows1254,
|
||||
"iso-ir-148": windows1254,
|
||||
"iso8859-9": windows1254,
|
||||
"iso88599": windows1254,
|
||||
"iso_8859-9": windows1254,
|
||||
"iso_8859-9:1989": windows1254,
|
||||
"l5": windows1254,
|
||||
"latin5": windows1254,
|
||||
"windows-1254": windows1254,
|
||||
"x-cp1254": windows1254,
|
||||
"cp1255": windows1255,
|
||||
"windows-1255": windows1255,
|
||||
"x-cp1255": windows1255,
|
||||
"cp1256": windows1256,
|
||||
"windows-1256": windows1256,
|
||||
"x-cp1256": windows1256,
|
||||
"cp1257": windows1257,
|
||||
"windows-1257": windows1257,
|
||||
"x-cp1257": windows1257,
|
||||
"cp1258": windows1258,
|
||||
"windows-1258": windows1258,
|
||||
"x-cp1258": windows1258,
|
||||
"x-mac-cyrillic": macintoshCyrillic,
|
||||
"x-mac-ukrainian": macintoshCyrillic,
|
||||
"chinese": gbk,
|
||||
"csgb2312": gbk,
|
||||
"csiso58gb231280": gbk,
|
||||
"gb2312": gbk,
|
||||
"gb_2312": gbk,
|
||||
"gb_2312-80": gbk,
|
||||
"gbk": gbk,
|
||||
"iso-ir-58": gbk,
|
||||
"x-gbk": gbk,
|
||||
"gb18030": gb18030,
|
||||
"big5": big5,
|
||||
"big5-hkscs": big5,
|
||||
"cn-big5": big5,
|
||||
"csbig5": big5,
|
||||
"x-x-big5": big5,
|
||||
"cseucpkdfmtjapanese": eucjp,
|
||||
"euc-jp": eucjp,
|
||||
"x-euc-jp": eucjp,
|
||||
"csiso2022jp": iso2022jp,
|
||||
"iso-2022-jp": iso2022jp,
|
||||
"csshiftjis": shiftJIS,
|
||||
"ms932": shiftJIS,
|
||||
"ms_kanji": shiftJIS,
|
||||
"shift-jis": shiftJIS,
|
||||
"shift_jis": shiftJIS,
|
||||
"sjis": shiftJIS,
|
||||
"windows-31j": shiftJIS,
|
||||
"x-sjis": shiftJIS,
|
||||
"cseuckr": euckr,
|
||||
"csksc56011987": euckr,
|
||||
"euc-kr": euckr,
|
||||
"iso-ir-149": euckr,
|
||||
"korean": euckr,
|
||||
"ks_c_5601-1987": euckr,
|
||||
"ks_c_5601-1989": euckr,
|
||||
"ksc5601": euckr,
|
||||
"ksc_5601": euckr,
|
||||
"windows-949": euckr,
|
||||
"csiso2022kr": replacement,
|
||||
"hz-gb-2312": replacement,
|
||||
"iso-2022-cn": replacement,
|
||||
"iso-2022-cn-ext": replacement,
|
||||
"iso-2022-kr": replacement,
|
||||
"utf-16be": utf16be,
|
||||
"utf-16": utf16le,
|
||||
"utf-16le": utf16le,
|
||||
"x-user-defined": xUserDefined,
|
||||
}
|
||||
|
||||
var localeMap = []htmlEncoding{
|
||||
windows1252, // und_Latn
|
||||
windows1256, // ar
|
||||
windows1251, // ba
|
||||
windows1251, // be
|
||||
windows1251, // bg
|
||||
windows1250, // cs
|
||||
iso8859_7, // el
|
||||
windows1257, // et
|
||||
windows1256, // fa
|
||||
windows1255, // he
|
||||
windows1250, // hr
|
||||
iso8859_2, // hu
|
||||
shiftJIS, // ja
|
||||
windows1251, // kk
|
||||
euckr, // ko
|
||||
windows1254, // ku
|
||||
windows1251, // ky
|
||||
windows1257, // lt
|
||||
windows1257, // lv
|
||||
windows1251, // mk
|
||||
iso8859_2, // pl
|
||||
windows1251, // ru
|
||||
windows1251, // sah
|
||||
windows1250, // sk
|
||||
iso8859_2, // sl
|
||||
windows1251, // sr
|
||||
windows1251, // tg
|
||||
windows874, // th
|
||||
windows1254, // tr
|
||||
windows1251, // tt
|
||||
windows1251, // uk
|
||||
windows1258, // vi
|
||||
gb18030, // zh-hans
|
||||
big5, // zh-hant
|
||||
}
|
||||
|
||||
const locales = "und_Latn ar ba be bg cs el et fa he hr hu ja kk ko ku ky lt lv mk pl ru sah sk sl sr tg th tr tt uk vi zh-hans zh-hant"
|
||||
27
vendor/golang.org/x/text/encoding/ianaindex/example_test.go
generated
vendored
27
vendor/golang.org/x/text/encoding/ianaindex/example_test.go
generated
vendored
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ianaindex_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/ianaindex"
|
||||
)
|
||||
|
||||
func ExampleIndex() {
|
||||
fmt.Println(ianaindex.MIME.Name(charmap.ISO8859_7))
|
||||
fmt.Println(ianaindex.IANA.Name(charmap.ISO8859_7))
|
||||
fmt.Println(ianaindex.MIB.Name(charmap.ISO8859_7))
|
||||
|
||||
e, _ := ianaindex.IANA.Encoding("cp437")
|
||||
fmt.Println(ianaindex.IANA.Name(e))
|
||||
|
||||
// Output:
|
||||
// ISO-8859-7 <nil>
|
||||
// ISO_8859-7:1987 <nil>
|
||||
// ISOLatinGreek <nil>
|
||||
// IBM437 <nil>
|
||||
}
|
||||
192
vendor/golang.org/x/text/encoding/ianaindex/gen.go
generated
vendored
192
vendor/golang.org/x/text/encoding/ianaindex/gen.go
generated
vendored
|
|
@ -1,192 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
type registry struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Updated string `xml:"updated"`
|
||||
Registry []struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Record []struct {
|
||||
Name string `xml:"name"`
|
||||
Xref []struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Data string `xml:"data,attr"`
|
||||
} `xml:"xref"`
|
||||
Desc struct {
|
||||
Data string `xml:",innerxml"`
|
||||
} `xml:"description,"`
|
||||
MIB string `xml:"value"`
|
||||
Alias []string `xml:"alias"`
|
||||
MIME string `xml:"preferred_alias"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml")
|
||||
reg := ®istry{}
|
||||
if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF {
|
||||
log.Fatalf("Error decoding charset registry: %v", err)
|
||||
}
|
||||
if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" {
|
||||
log.Fatalf("Unexpected ID %s", reg.Registry[0].ID)
|
||||
}
|
||||
|
||||
x := &indexInfo{}
|
||||
|
||||
for _, rec := range reg.Registry[0].Record {
|
||||
mib := identifier.MIB(parseInt(rec.MIB))
|
||||
x.addEntry(mib, rec.Name)
|
||||
for _, a := range rec.Alias {
|
||||
a = strings.Split(a, " ")[0] // strip comments.
|
||||
x.addAlias(a, mib)
|
||||
// MIB name aliases are prefixed with a "cs" (character set) in the
|
||||
// registry to identify them as display names and to ensure that
|
||||
// the name starts with a lowercase letter in case it is used as
|
||||
// an identifier. We remove it to be left with a nice clean name.
|
||||
if strings.HasPrefix(a, "cs") {
|
||||
x.setName(2, a[2:])
|
||||
}
|
||||
}
|
||||
if rec.MIME != "" {
|
||||
x.addAlias(rec.MIME, mib)
|
||||
x.setName(1, rec.MIME)
|
||||
}
|
||||
}
|
||||
|
||||
w := gen.NewCodeWriter()
|
||||
|
||||
fmt.Fprintln(w, `import "golang.org/x/text/encoding/internal/identifier"`)
|
||||
|
||||
writeIndex(w, x)
|
||||
|
||||
w.WriteGoFile("tables.go", "ianaindex")
|
||||
}
|
||||
|
||||
type alias struct {
|
||||
name string
|
||||
mib identifier.MIB
|
||||
}
|
||||
|
||||
type indexInfo struct {
|
||||
// compacted index from code to MIB
|
||||
codeToMIB []identifier.MIB
|
||||
alias []alias
|
||||
names [][3]string
|
||||
}
|
||||
|
||||
func (ii *indexInfo) Len() int {
|
||||
return len(ii.codeToMIB)
|
||||
}
|
||||
|
||||
func (ii *indexInfo) Less(a, b int) bool {
|
||||
return ii.codeToMIB[a] < ii.codeToMIB[b]
|
||||
}
|
||||
|
||||
func (ii *indexInfo) Swap(a, b int) {
|
||||
ii.codeToMIB[a], ii.codeToMIB[b] = ii.codeToMIB[b], ii.codeToMIB[a]
|
||||
// Co-sort the names.
|
||||
ii.names[a], ii.names[b] = ii.names[b], ii.names[a]
|
||||
}
|
||||
|
||||
func (ii *indexInfo) setName(i int, name string) {
|
||||
ii.names[len(ii.names)-1][i] = name
|
||||
}
|
||||
|
||||
func (ii *indexInfo) addEntry(mib identifier.MIB, name string) {
|
||||
ii.names = append(ii.names, [3]string{name, name, name})
|
||||
ii.addAlias(name, mib)
|
||||
ii.codeToMIB = append(ii.codeToMIB, mib)
|
||||
}
|
||||
|
||||
func (ii *indexInfo) addAlias(name string, mib identifier.MIB) {
|
||||
// Don't add duplicates for the same mib. Adding duplicate aliases for
|
||||
// different MIBs will cause the compiler to barf on an invalid map: great!.
|
||||
for i := len(ii.alias) - 1; i >= 0 && ii.alias[i].mib == mib; i-- {
|
||||
if ii.alias[i].name == name {
|
||||
return
|
||||
}
|
||||
}
|
||||
ii.alias = append(ii.alias, alias{name, mib})
|
||||
lower := strings.ToLower(name)
|
||||
if lower != name {
|
||||
ii.addAlias(lower, mib)
|
||||
}
|
||||
}
|
||||
|
||||
const maxMIMENameLen = '0' - 1 // officially 40, but we leave some buffer.
|
||||
|
||||
func writeIndex(w *gen.CodeWriter, x *indexInfo) {
|
||||
sort.Stable(x)
|
||||
|
||||
// Write constants.
|
||||
fmt.Fprintln(w, "const (")
|
||||
for i, m := range x.codeToMIB {
|
||||
if i == 0 {
|
||||
fmt.Fprintf(w, "enc%d = iota\n", m)
|
||||
} else {
|
||||
fmt.Fprintf(w, "enc%d\n", m)
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, "numIANA")
|
||||
fmt.Fprintln(w, ")")
|
||||
|
||||
w.WriteVar("ianaToMIB", x.codeToMIB)
|
||||
|
||||
var ianaNames, mibNames []string
|
||||
for _, names := range x.names {
|
||||
n := names[0]
|
||||
if names[0] != names[1] {
|
||||
// MIME names are mostly identical to IANA names. We share the
|
||||
// tables by setting the first byte of the string to an index into
|
||||
// the string itself (< maxMIMENameLen) to the IANA name. The MIME
|
||||
// name immediately follows the index.
|
||||
x := len(names[1]) + 1
|
||||
if x > maxMIMENameLen {
|
||||
log.Fatalf("MIME name length (%d) > %d", x, maxMIMENameLen)
|
||||
}
|
||||
n = string(x) + names[1] + names[0]
|
||||
}
|
||||
ianaNames = append(ianaNames, n)
|
||||
mibNames = append(mibNames, names[2])
|
||||
}
|
||||
|
||||
w.WriteVar("ianaNames", ianaNames)
|
||||
w.WriteVar("mibNames", mibNames)
|
||||
|
||||
w.WriteComment(`
|
||||
TODO: Instead of using a map, we could use binary search strings doing
|
||||
on-the fly lower-casing per character. This allows to always avoid
|
||||
allocation and will be considerably more compact.`)
|
||||
fmt.Fprintln(w, "var ianaAliases = map[string]int{")
|
||||
for _, a := range x.alias {
|
||||
fmt.Fprintf(w, "%q: enc%d,\n", a.name, a.mib)
|
||||
}
|
||||
fmt.Fprintln(w, "}")
|
||||
}
|
||||
|
||||
func parseInt(s string) int {
|
||||
x, err := strconv.ParseInt(s, 10, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse integer: %v", err)
|
||||
}
|
||||
return int(x)
|
||||
}
|
||||
209
vendor/golang.org/x/text/encoding/ianaindex/ianaindex.go
generated
vendored
209
vendor/golang.org/x/text/encoding/ianaindex/ianaindex.go
generated
vendored
|
|
@ -1,209 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// Package ianaindex maps names to Encodings as specified by the IANA registry.
|
||||
// This includes both the MIME and IANA names.
|
||||
//
|
||||
// See http://www.iana.org/assignments/character-sets/character-sets.xhtml for
|
||||
// more details.
|
||||
package ianaindex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/encoding/traditionalchinese"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
// TODO: remove the "Status... incomplete" in the package doc comment.
|
||||
// TODO: allow users to specify their own aliases?
|
||||
// TODO: allow users to specify their own indexes?
|
||||
// TODO: allow canonicalizing names
|
||||
|
||||
// NOTE: only use these top-level variables if we can get the linker to drop
|
||||
// the indexes when they are not used. Make them a function or perhaps only
|
||||
// support MIME otherwise.
|
||||
|
||||
var (
|
||||
// MIME is an index to map MIME names.
|
||||
MIME *Index = mime
|
||||
|
||||
// IANA is an index that supports all names and aliases using IANA names as
|
||||
// the canonical identifier.
|
||||
IANA *Index = iana
|
||||
|
||||
// MIB is an index that associates the MIB display name with an Encoding.
|
||||
MIB *Index = mib
|
||||
|
||||
mime = &Index{mimeName, ianaToMIB, ianaAliases, encodings[:]}
|
||||
iana = &Index{ianaName, ianaToMIB, ianaAliases, encodings[:]}
|
||||
mib = &Index{mibName, ianaToMIB, ianaAliases, encodings[:]}
|
||||
)
|
||||
|
||||
// Index maps names registered by IANA to Encodings.
|
||||
// Currently different Indexes only differ in the names they return for
|
||||
// encodings. In the future they may also differ in supported aliases.
|
||||
type Index struct {
|
||||
names func(i int) string
|
||||
toMIB []identifier.MIB // Sorted slice of supported MIBs
|
||||
alias map[string]int
|
||||
enc []encoding.Encoding
|
||||
}
|
||||
|
||||
var (
|
||||
errInvalidName = errors.New("ianaindex: invalid encoding name")
|
||||
errUnknown = errors.New("ianaindex: unknown Encoding")
|
||||
errUnsupported = errors.New("ianaindex: unsupported Encoding")
|
||||
)
|
||||
|
||||
// Encoding returns an Encoding for IANA-registered names. Matching is
|
||||
// case-insensitive.
|
||||
func (x *Index) Encoding(name string) (encoding.Encoding, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
// First try without lowercasing (possibly creating an allocation).
|
||||
i, ok := x.alias[name]
|
||||
if !ok {
|
||||
i, ok = x.alias[strings.ToLower(name)]
|
||||
if !ok {
|
||||
return nil, errInvalidName
|
||||
}
|
||||
}
|
||||
return x.enc[i], nil
|
||||
}
|
||||
|
||||
// Name reports the canonical name of the given Encoding. It will return an
|
||||
// error if the e is not associated with a known encoding scheme.
|
||||
func (x *Index) Name(e encoding.Encoding) (string, error) {
|
||||
id, ok := e.(identifier.Interface)
|
||||
if !ok {
|
||||
return "", errUnknown
|
||||
}
|
||||
mib, _ := id.ID()
|
||||
if mib == 0 {
|
||||
return "", errUnknown
|
||||
}
|
||||
v := findMIB(x.toMIB, mib)
|
||||
if v == -1 {
|
||||
return "", errUnsupported
|
||||
}
|
||||
return x.names(v), nil
|
||||
}
|
||||
|
||||
// TODO: the coverage of this index is rather spotty. Allowing users to set
|
||||
// encodings would allow:
|
||||
// - users to increase coverage
|
||||
// - allow a partially loaded set of encodings in case the user doesn't need to
|
||||
// them all.
|
||||
// - write an OS-specific wrapper for supported encodings and set them.
|
||||
// The exact definition of Set depends a bit on if and how we want to let users
|
||||
// write their own Encoding implementations. Also, it is not possible yet to
|
||||
// only partially load the encodings without doing some refactoring. Until this
|
||||
// is solved, we might as well not support Set.
|
||||
// // Set sets the e to be used for the encoding scheme identified by name. Only
|
||||
// // canonical names may be used. An empty name assigns e to its internally
|
||||
// // associated encoding scheme.
|
||||
// func (x *Index) Set(name string, e encoding.Encoding) error {
|
||||
// panic("TODO: implement")
|
||||
// }
|
||||
|
||||
func findMIB(x []identifier.MIB, mib identifier.MIB) int {
|
||||
i := sort.Search(len(x), func(i int) bool { return x[i] >= mib })
|
||||
if i < len(x) && x[i] == mib {
|
||||
return i
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
const maxMIMENameLen = '0' - 1 // officially 40, but we leave some buffer.
|
||||
|
||||
func mimeName(x int) string {
|
||||
n := ianaNames[x]
|
||||
// See gen.go for a description of the encoding.
|
||||
if n[0] <= maxMIMENameLen {
|
||||
return n[1:n[0]]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func ianaName(x int) string {
|
||||
n := ianaNames[x]
|
||||
// See gen.go for a description of the encoding.
|
||||
if n[0] <= maxMIMENameLen {
|
||||
return n[n[0]:]
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func mibName(x int) string {
|
||||
return mibNames[x]
|
||||
}
|
||||
|
||||
var encodings = [numIANA]encoding.Encoding{
|
||||
enc106: unicode.UTF8,
|
||||
enc1015: unicode.UTF16(unicode.BigEndian, unicode.UseBOM),
|
||||
enc1013: unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
|
||||
enc1014: unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM),
|
||||
enc2028: charmap.CodePage037,
|
||||
enc2011: charmap.CodePage437,
|
||||
enc2009: charmap.CodePage850,
|
||||
enc2010: charmap.CodePage852,
|
||||
enc2046: charmap.CodePage855,
|
||||
enc2089: charmap.CodePage858,
|
||||
enc2048: charmap.CodePage860,
|
||||
enc2013: charmap.CodePage862,
|
||||
enc2050: charmap.CodePage863,
|
||||
enc2052: charmap.CodePage865,
|
||||
enc2086: charmap.CodePage866,
|
||||
enc2102: charmap.CodePage1047,
|
||||
enc2091: charmap.CodePage1140,
|
||||
enc4: charmap.ISO8859_1,
|
||||
enc5: charmap.ISO8859_2,
|
||||
enc6: charmap.ISO8859_3,
|
||||
enc7: charmap.ISO8859_4,
|
||||
enc8: charmap.ISO8859_5,
|
||||
enc9: charmap.ISO8859_6,
|
||||
enc81: charmap.ISO8859_6E,
|
||||
enc82: charmap.ISO8859_6I,
|
||||
enc10: charmap.ISO8859_7,
|
||||
enc11: charmap.ISO8859_8,
|
||||
enc84: charmap.ISO8859_8E,
|
||||
enc85: charmap.ISO8859_8I,
|
||||
enc12: charmap.ISO8859_9,
|
||||
enc13: charmap.ISO8859_10,
|
||||
enc109: charmap.ISO8859_13,
|
||||
enc110: charmap.ISO8859_14,
|
||||
enc111: charmap.ISO8859_15,
|
||||
enc112: charmap.ISO8859_16,
|
||||
enc2084: charmap.KOI8R,
|
||||
enc2088: charmap.KOI8U,
|
||||
enc2027: charmap.Macintosh,
|
||||
enc2109: charmap.Windows874,
|
||||
enc2250: charmap.Windows1250,
|
||||
enc2251: charmap.Windows1251,
|
||||
enc2252: charmap.Windows1252,
|
||||
enc2253: charmap.Windows1253,
|
||||
enc2254: charmap.Windows1254,
|
||||
enc2255: charmap.Windows1255,
|
||||
enc2256: charmap.Windows1256,
|
||||
enc2257: charmap.Windows1257,
|
||||
enc2258: charmap.Windows1258,
|
||||
enc18: japanese.EUCJP,
|
||||
enc39: japanese.ISO2022JP,
|
||||
enc17: japanese.ShiftJIS,
|
||||
enc38: korean.EUCKR,
|
||||
enc114: simplifiedchinese.GB18030,
|
||||
enc113: simplifiedchinese.GBK,
|
||||
enc2085: simplifiedchinese.HZGB2312,
|
||||
enc2026: traditionalchinese.Big5,
|
||||
}
|
||||
192
vendor/golang.org/x/text/encoding/ianaindex/ianaindex_test.go
generated
vendored
192
vendor/golang.org/x/text/encoding/ianaindex/ianaindex_test.go
generated
vendored
|
|
@ -1,192 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ianaindex
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/charmap"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/encoding/japanese"
|
||||
"golang.org/x/text/encoding/korean"
|
||||
"golang.org/x/text/encoding/simplifiedchinese"
|
||||
"golang.org/x/text/encoding/traditionalchinese"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
)
|
||||
|
||||
var All = [][]encoding.Encoding{
|
||||
unicode.All,
|
||||
charmap.All,
|
||||
japanese.All,
|
||||
korean.All,
|
||||
simplifiedchinese.All,
|
||||
traditionalchinese.All,
|
||||
}
|
||||
|
||||
// TestAllIANA tests whether an Encoding supported in x/text is defined by IANA but
|
||||
// not supported by this package.
|
||||
func TestAllIANA(t *testing.T) {
|
||||
for _, ea := range All {
|
||||
for _, e := range ea {
|
||||
mib, _ := e.(identifier.Interface).ID()
|
||||
if x := findMIB(ianaToMIB, mib); x != -1 && encodings[x] == nil {
|
||||
t.Errorf("supported MIB %v (%v) not in index", mib, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNotSupported reports the encodings in IANA, but not by x/text.
|
||||
func TestNotSupported(t *testing.T) {
|
||||
mibs := map[identifier.MIB]bool{}
|
||||
for _, ea := range All {
|
||||
for _, e := range ea {
|
||||
mib, _ := e.(identifier.Interface).ID()
|
||||
mibs[mib] = true
|
||||
}
|
||||
}
|
||||
|
||||
// Many encodings in the IANA index will likely not be suppored by the
|
||||
// Go encodings. That is fine.
|
||||
// TODO: consider wheter we should add this test.
|
||||
// for code, mib := range ianaToMIB {
|
||||
// t.Run(fmt.Sprint("IANA:", mib), func(t *testing.T) {
|
||||
// if !mibs[mib] {
|
||||
// t.Skipf("IANA encoding %s (MIB %v) not supported",
|
||||
// ianaNames[code], mib)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
||||
func TestEncoding(t *testing.T) {
|
||||
testCases := []struct {
|
||||
index *Index
|
||||
name string
|
||||
canonical string
|
||||
err error
|
||||
}{
|
||||
{MIME, "utf-8", "UTF-8", nil},
|
||||
{MIME, " utf-8 ", "UTF-8", nil},
|
||||
{MIME, " l5 ", "ISO-8859-9", nil},
|
||||
{MIME, "latin5 ", "ISO-8859-9", nil},
|
||||
{MIME, "LATIN5 ", "ISO-8859-9", nil},
|
||||
{MIME, "latin 5", "", errInvalidName},
|
||||
{MIME, "latin-5", "", errInvalidName},
|
||||
|
||||
{IANA, "utf-8", "UTF-8", nil},
|
||||
{IANA, " utf-8 ", "UTF-8", nil},
|
||||
{IANA, " l5 ", "ISO_8859-9:1989", nil},
|
||||
{IANA, "latin5 ", "ISO_8859-9:1989", nil},
|
||||
{IANA, "LATIN5 ", "ISO_8859-9:1989", nil},
|
||||
{IANA, "latin 5", "", errInvalidName},
|
||||
{IANA, "latin-5", "", errInvalidName},
|
||||
|
||||
{MIB, "utf-8", "UTF8", nil},
|
||||
{MIB, " utf-8 ", "UTF8", nil},
|
||||
{MIB, " l5 ", "ISOLatin5", nil},
|
||||
{MIB, "latin5 ", "ISOLatin5", nil},
|
||||
{MIB, "LATIN5 ", "ISOLatin5", nil},
|
||||
{MIB, "latin 5", "", errInvalidName},
|
||||
{MIB, "latin-5", "", errInvalidName},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
enc, err := tc.index.Encoding(tc.name)
|
||||
if err != tc.err {
|
||||
t.Errorf("%d: error was %v; want %v", i, err, tc.err)
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if got, err := tc.index.Name(enc); got != tc.canonical {
|
||||
t.Errorf("%d: Name(Encoding(%q)) = %q; want %q (%v)", i, tc.name, got, tc.canonical, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTables(t *testing.T) {
|
||||
for i, x := range []*Index{MIME, IANA} {
|
||||
for name, index := range x.alias {
|
||||
got, err := x.Encoding(name)
|
||||
if err != nil {
|
||||
t.Errorf("%d%s:err: unexpected error %v", i, name, err)
|
||||
}
|
||||
if want := x.enc[index]; got != want {
|
||||
t.Errorf("%d%s:encoding: got %v; want %v", i, name, got, want)
|
||||
}
|
||||
if got != nil {
|
||||
mib, _ := got.(identifier.Interface).ID()
|
||||
if i := findMIB(x.toMIB, mib); i != index {
|
||||
t.Errorf("%d%s:mib: got %d; want %d", i, name, i, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type unsupported struct {
|
||||
encoding.Encoding
|
||||
}
|
||||
|
||||
func (unsupported) ID() (identifier.MIB, string) { return 9999, "" }
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
enc encoding.Encoding
|
||||
f func(e encoding.Encoding) (string, error)
|
||||
name string
|
||||
err error
|
||||
}{{
|
||||
"defined encoding",
|
||||
charmap.ISO8859_2,
|
||||
MIME.Name,
|
||||
"ISO-8859-2",
|
||||
nil,
|
||||
}, {
|
||||
"defined Unicode encoding",
|
||||
unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
|
||||
IANA.Name,
|
||||
"UTF-16BE",
|
||||
nil,
|
||||
}, {
|
||||
"another defined Unicode encoding",
|
||||
unicode.UTF16(unicode.BigEndian, unicode.UseBOM),
|
||||
MIME.Name,
|
||||
"UTF-16",
|
||||
nil,
|
||||
}, {
|
||||
"unknown Unicode encoding",
|
||||
unicode.UTF16(unicode.BigEndian, unicode.ExpectBOM),
|
||||
MIME.Name,
|
||||
"",
|
||||
errUnknown,
|
||||
}, {
|
||||
"undefined encoding",
|
||||
unsupported{},
|
||||
MIME.Name,
|
||||
"",
|
||||
errUnsupported,
|
||||
}, {
|
||||
"undefined other encoding in HTML standard",
|
||||
charmap.CodePage437,
|
||||
IANA.Name,
|
||||
"IBM437",
|
||||
nil,
|
||||
}, {
|
||||
"unknown encoding",
|
||||
encoding.Nop,
|
||||
IANA.Name,
|
||||
"",
|
||||
errUnknown,
|
||||
}}
|
||||
for i, tc := range testCases {
|
||||
name, err := tc.f(tc.enc)
|
||||
if name != tc.name || err != tc.err {
|
||||
t.Errorf("%d:%s: got %q, %v; want %q, %v", i, tc.desc, name, err, tc.name, tc.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
2348
vendor/golang.org/x/text/encoding/ianaindex/tables.go
generated
vendored
2348
vendor/golang.org/x/text/encoding/ianaindex/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
180
vendor/golang.org/x/text/encoding/internal/enctest/enctest.go
generated
vendored
180
vendor/golang.org/x/text/encoding/internal/enctest/enctest.go
generated
vendored
|
|
@ -1,180 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package enctest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// Encoder or Decoder
|
||||
type Transcoder interface {
|
||||
transform.Transformer
|
||||
Bytes([]byte) ([]byte, error)
|
||||
String(string) (string, error)
|
||||
}
|
||||
|
||||
func TestEncoding(t *testing.T, e encoding.Encoding, encoded, utf8, prefix, suffix string) {
|
||||
for _, direction := range []string{"Decode", "Encode"} {
|
||||
t.Run(fmt.Sprintf("%v/%s", e, direction), func(t *testing.T) {
|
||||
|
||||
var coder Transcoder
|
||||
var want, src, wPrefix, sPrefix, wSuffix, sSuffix string
|
||||
if direction == "Decode" {
|
||||
coder, want, src = e.NewDecoder(), utf8, encoded
|
||||
wPrefix, sPrefix, wSuffix, sSuffix = "", prefix, "", suffix
|
||||
} else {
|
||||
coder, want, src = e.NewEncoder(), encoded, utf8
|
||||
wPrefix, sPrefix, wSuffix, sSuffix = prefix, "", suffix, ""
|
||||
}
|
||||
|
||||
dst := make([]byte, len(wPrefix)+len(want)+len(wSuffix))
|
||||
nDst, nSrc, err := coder.Transform(dst, []byte(sPrefix+src+sSuffix), true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if nDst != len(wPrefix)+len(want)+len(wSuffix) {
|
||||
t.Fatalf("nDst got %d, want %d",
|
||||
nDst, len(wPrefix)+len(want)+len(wSuffix))
|
||||
}
|
||||
if nSrc != len(sPrefix)+len(src)+len(sSuffix) {
|
||||
t.Fatalf("nSrc got %d, want %d",
|
||||
nSrc, len(sPrefix)+len(src)+len(sSuffix))
|
||||
}
|
||||
if got := string(dst); got != wPrefix+want+wSuffix {
|
||||
t.Fatalf("\ngot %q\nwant %q", got, wPrefix+want+wSuffix)
|
||||
}
|
||||
|
||||
for _, n := range []int{0, 1, 2, 10, 123, 4567} {
|
||||
input := sPrefix + strings.Repeat(src, n) + sSuffix
|
||||
g, err := coder.String(input)
|
||||
if err != nil {
|
||||
t.Fatalf("Bytes: n=%d: %v", n, err)
|
||||
}
|
||||
if len(g) == 0 && len(input) == 0 {
|
||||
// If the input is empty then the output can be empty,
|
||||
// regardless of whatever wPrefix is.
|
||||
continue
|
||||
}
|
||||
got1, want1 := string(g), wPrefix+strings.Repeat(want, n)+wSuffix
|
||||
if got1 != want1 {
|
||||
t.Fatalf("ReadAll: n=%d\ngot %q\nwant %q",
|
||||
n, trim(got1), trim(want1))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFile(t *testing.T, e encoding.Encoding) {
|
||||
for _, dir := range []string{"Decode", "Encode"} {
|
||||
t.Run(fmt.Sprintf("%s/%s", e, dir), func(t *testing.T) {
|
||||
dst, src, transformer, err := load(dir, e)
|
||||
if err != nil {
|
||||
t.Fatalf("load: %v", err)
|
||||
}
|
||||
buf, err := transformer.Bytes(src)
|
||||
if err != nil {
|
||||
t.Fatalf("transform: %v", err)
|
||||
}
|
||||
if !bytes.Equal(buf, dst) {
|
||||
t.Error("transformed bytes did not match golden file")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark(b *testing.B, enc encoding.Encoding) {
|
||||
for _, direction := range []string{"Decode", "Encode"} {
|
||||
b.Run(fmt.Sprintf("%s/%s", enc, direction), func(b *testing.B) {
|
||||
_, src, transformer, err := load(direction, enc)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.SetBytes(int64(len(src)))
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
r := transform.NewReader(bytes.NewReader(src), transformer)
|
||||
io.Copy(ioutil.Discard, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// testdataFiles are files in testdata/*.txt.
|
||||
var testdataFiles = []struct {
|
||||
mib identifier.MIB
|
||||
basename, ext string
|
||||
}{
|
||||
{identifier.Windows1252, "candide", "windows-1252"},
|
||||
{identifier.EUCPkdFmtJapanese, "rashomon", "euc-jp"},
|
||||
{identifier.ISO2022JP, "rashomon", "iso-2022-jp"},
|
||||
{identifier.ShiftJIS, "rashomon", "shift-jis"},
|
||||
{identifier.EUCKR, "unsu-joh-eun-nal", "euc-kr"},
|
||||
{identifier.GBK, "sunzi-bingfa-simplified", "gbk"},
|
||||
{identifier.HZGB2312, "sunzi-bingfa-gb-levels-1-and-2", "hz-gb2312"},
|
||||
{identifier.Big5, "sunzi-bingfa-traditional", "big5"},
|
||||
{identifier.UTF16LE, "candide", "utf-16le"},
|
||||
{identifier.UTF8, "candide", "utf-8"},
|
||||
{identifier.UTF32BE, "candide", "utf-32be"},
|
||||
|
||||
// GB18030 is a superset of GBK and is nominally a Simplified Chinese
|
||||
// encoding, but it can also represent the entire Basic Multilingual
|
||||
// Plane, including codepoints like 'â' that aren't encodable by GBK.
|
||||
// GB18030 on Simplified Chinese should perform similarly to GBK on
|
||||
// Simplified Chinese. GB18030 on "candide" is more interesting.
|
||||
{identifier.GB18030, "candide", "gb18030"},
|
||||
}
|
||||
|
||||
func load(direction string, enc encoding.Encoding) ([]byte, []byte, Transcoder, error) {
|
||||
basename, ext, count := "", "", 0
|
||||
for _, tf := range testdataFiles {
|
||||
if mib, _ := enc.(identifier.Interface).ID(); tf.mib == mib {
|
||||
basename, ext = tf.basename, tf.ext
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count != 1 {
|
||||
if count == 0 {
|
||||
return nil, nil, nil, fmt.Errorf("no testdataFiles for %s", enc)
|
||||
}
|
||||
return nil, nil, nil, fmt.Errorf("too many testdataFiles for %s", enc)
|
||||
}
|
||||
dstFile := fmt.Sprintf("../testdata/%s-%s.txt", basename, ext)
|
||||
srcFile := fmt.Sprintf("../testdata/%s-utf-8.txt", basename)
|
||||
var coder Transcoder = encoding.ReplaceUnsupported(enc.NewEncoder())
|
||||
if direction == "Decode" {
|
||||
dstFile, srcFile = srcFile, dstFile
|
||||
coder = enc.NewDecoder()
|
||||
}
|
||||
dst, err := ioutil.ReadFile(dstFile)
|
||||
if err != nil {
|
||||
if dst, err = ioutil.ReadFile("../" + dstFile); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
src, err := ioutil.ReadFile(srcFile)
|
||||
if err != nil {
|
||||
if src, err = ioutil.ReadFile("../" + srcFile); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
return dst, src, coder, nil
|
||||
}
|
||||
|
||||
func trim(s string) string {
|
||||
if len(s) < 120 {
|
||||
return s
|
||||
}
|
||||
return s[:50] + "..." + s[len(s)-50:]
|
||||
}
|
||||
137
vendor/golang.org/x/text/encoding/internal/identifier/gen.go
generated
vendored
137
vendor/golang.org/x/text/encoding/internal/identifier/gen.go
generated
vendored
|
|
@ -1,137 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
type registry struct {
|
||||
XMLName xml.Name `xml:"registry"`
|
||||
Updated string `xml:"updated"`
|
||||
Registry []struct {
|
||||
ID string `xml:"id,attr"`
|
||||
Record []struct {
|
||||
Name string `xml:"name"`
|
||||
Xref []struct {
|
||||
Type string `xml:"type,attr"`
|
||||
Data string `xml:"data,attr"`
|
||||
} `xml:"xref"`
|
||||
Desc struct {
|
||||
Data string `xml:",innerxml"`
|
||||
// Any []struct {
|
||||
// Data string `xml:",chardata"`
|
||||
// } `xml:",any"`
|
||||
// Data string `xml:",chardata"`
|
||||
} `xml:"description,"`
|
||||
MIB string `xml:"value"`
|
||||
Alias []string `xml:"alias"`
|
||||
MIME string `xml:"preferred_alias"`
|
||||
} `xml:"record"`
|
||||
} `xml:"registry"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
r := gen.OpenIANAFile("assignments/character-sets/character-sets.xml")
|
||||
reg := ®istry{}
|
||||
if err := xml.NewDecoder(r).Decode(®); err != nil && err != io.EOF {
|
||||
log.Fatalf("Error decoding charset registry: %v", err)
|
||||
}
|
||||
if len(reg.Registry) == 0 || reg.Registry[0].ID != "character-sets-1" {
|
||||
log.Fatalf("Unexpected ID %s", reg.Registry[0].ID)
|
||||
}
|
||||
|
||||
w := &bytes.Buffer{}
|
||||
fmt.Fprintf(w, "const (\n")
|
||||
for _, rec := range reg.Registry[0].Record {
|
||||
constName := ""
|
||||
for _, a := range rec.Alias {
|
||||
if strings.HasPrefix(a, "cs") && strings.IndexByte(a, '-') == -1 {
|
||||
// Some of the constant definitions have comments in them. Strip those.
|
||||
constName = strings.Title(strings.SplitN(a[2:], "\n", 2)[0])
|
||||
}
|
||||
}
|
||||
if constName == "" {
|
||||
switch rec.MIB {
|
||||
case "2085":
|
||||
constName = "HZGB2312" // Not listed as alias for some reason.
|
||||
default:
|
||||
log.Fatalf("No cs alias defined for %s.", rec.MIB)
|
||||
}
|
||||
}
|
||||
if rec.MIME != "" {
|
||||
rec.MIME = fmt.Sprintf(" (MIME: %s)", rec.MIME)
|
||||
}
|
||||
fmt.Fprintf(w, "// %s is the MIB identifier with IANA name %s%s.\n//\n", constName, rec.Name, rec.MIME)
|
||||
if len(rec.Desc.Data) > 0 {
|
||||
fmt.Fprint(w, "// ")
|
||||
d := xml.NewDecoder(strings.NewReader(rec.Desc.Data))
|
||||
inElem := true
|
||||
attr := ""
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
log.Fatal(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
switch x := t.(type) {
|
||||
case xml.CharData:
|
||||
attr = "" // Don't need attribute info.
|
||||
a := bytes.Split([]byte(x), []byte("\n"))
|
||||
for i, b := range a {
|
||||
if b = bytes.TrimSpace(b); len(b) != 0 {
|
||||
if !inElem && i > 0 {
|
||||
fmt.Fprint(w, "\n// ")
|
||||
}
|
||||
inElem = false
|
||||
fmt.Fprintf(w, "%s ", string(b))
|
||||
}
|
||||
}
|
||||
case xml.StartElement:
|
||||
if x.Name.Local == "xref" {
|
||||
inElem = true
|
||||
use := false
|
||||
for _, a := range x.Attr {
|
||||
if a.Name.Local == "type" {
|
||||
use = use || a.Value != "person"
|
||||
}
|
||||
if a.Name.Local == "data" && use {
|
||||
attr = a.Value + " "
|
||||
}
|
||||
}
|
||||
}
|
||||
case xml.EndElement:
|
||||
inElem = false
|
||||
fmt.Fprint(w, attr)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
}
|
||||
for _, x := range rec.Xref {
|
||||
switch x.Type {
|
||||
case "rfc":
|
||||
fmt.Fprintf(w, "// Reference: %s\n", strings.ToUpper(x.Data))
|
||||
case "uri":
|
||||
fmt.Fprintf(w, "// Reference: %s\n", x.Data)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "%s MIB = %s\n", constName, rec.MIB)
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
fmt.Fprintln(w, ")")
|
||||
|
||||
gen.WriteGoFile("mib.go", "identifier", w.Bytes())
|
||||
}
|
||||
81
vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
generated
vendored
81
vendor/golang.org/x/text/encoding/internal/identifier/identifier.go
generated
vendored
|
|
@ -1,81 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run gen.go
|
||||
|
||||
// Package identifier defines the contract between implementations of Encoding
|
||||
// and Index by defining identifiers that uniquely identify standardized coded
|
||||
// character sets (CCS) and character encoding schemes (CES), which we will
|
||||
// together refer to as encodings, for which Encoding implementations provide
|
||||
// converters to and from UTF-8. This package is typically only of concern to
|
||||
// implementers of Indexes and Encodings.
|
||||
//
|
||||
// One part of the identifier is the MIB code, which is defined by IANA and
|
||||
// uniquely identifies a CCS or CES. Each code is associated with data that
|
||||
// references authorities, official documentation as well as aliases and MIME
|
||||
// names.
|
||||
//
|
||||
// Not all CESs are covered by the IANA registry. The "other" string that is
|
||||
// returned by ID can be used to identify other character sets or versions of
|
||||
// existing ones.
|
||||
//
|
||||
// It is recommended that each package that provides a set of Encodings provide
|
||||
// the All and Common variables to reference all supported encodings and
|
||||
// commonly used subset. This allows Index implementations to include all
|
||||
// available encodings without explicitly referencing or knowing about them.
|
||||
package identifier
|
||||
|
||||
// Note: this package is internal, but could be made public if there is a need
|
||||
// for writing third-party Indexes and Encodings.
|
||||
|
||||
// References:
|
||||
// - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt
|
||||
// - http://www.iana.org/assignments/character-sets/character-sets.xhtml
|
||||
// - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib
|
||||
// - http://www.ietf.org/rfc/rfc2978.txt
|
||||
// - http://www.unicode.org/reports/tr22/
|
||||
// - http://www.w3.org/TR/encoding/
|
||||
// - https://encoding.spec.whatwg.org/
|
||||
// - https://encoding.spec.whatwg.org/encodings.json
|
||||
// - https://tools.ietf.org/html/rfc6657#section-5
|
||||
|
||||
// Interface can be implemented by Encodings to define the CCS or CES for which
|
||||
// it implements conversions.
|
||||
type Interface interface {
|
||||
// ID returns an encoding identifier. Exactly one of the mib and other
|
||||
// values should be non-zero.
|
||||
//
|
||||
// In the usual case it is only necessary to indicate the MIB code. The
|
||||
// other string can be used to specify encodings for which there is no MIB,
|
||||
// such as "x-mac-dingbat".
|
||||
//
|
||||
// The other string may only contain the characters a-z, A-Z, 0-9, - and _.
|
||||
ID() (mib MIB, other string)
|
||||
|
||||
// NOTE: the restrictions on the encoding are to allow extending the syntax
|
||||
// with additional information such as versions, vendors and other variants.
|
||||
}
|
||||
|
||||
// A MIB identifies an encoding. It is derived from the IANA MIB codes and adds
|
||||
// some identifiers for some encodings that are not covered by the IANA
|
||||
// standard.
|
||||
//
|
||||
// See http://www.iana.org/assignments/ianacharset-mib.
|
||||
type MIB uint16
|
||||
|
||||
// These additional MIB types are not defined in IANA. They are added because
|
||||
// they are common and defined within the text repo.
|
||||
const (
|
||||
// Unofficial marks the start of encodings not registered by IANA.
|
||||
Unofficial MIB = 10000 + iota
|
||||
|
||||
// Replacement is the WhatWG replacement encoding.
|
||||
Replacement
|
||||
|
||||
// XUserDefined is the code for x-user-defined.
|
||||
XUserDefined
|
||||
|
||||
// MacintoshCyrillic is the code for x-mac-cyrillic.
|
||||
MacintoshCyrillic
|
||||
)
|
||||
1621
vendor/golang.org/x/text/encoding/internal/identifier/mib.go
generated
vendored
1621
vendor/golang.org/x/text/encoding/internal/identifier/mib.go
generated
vendored
File diff suppressed because it is too large
Load diff
75
vendor/golang.org/x/text/encoding/internal/internal.go
generated
vendored
75
vendor/golang.org/x/text/encoding/internal/internal.go
generated
vendored
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package internal contains code that is shared among encoding implementations.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// Encoding is an implementation of the Encoding interface that adds the String
|
||||
// and ID methods to an existing encoding.
|
||||
type Encoding struct {
|
||||
encoding.Encoding
|
||||
Name string
|
||||
MIB identifier.MIB
|
||||
}
|
||||
|
||||
// _ verifies that Encoding implements identifier.Interface.
|
||||
var _ identifier.Interface = (*Encoding)(nil)
|
||||
|
||||
func (e *Encoding) String() string {
|
||||
return e.Name
|
||||
}
|
||||
|
||||
func (e *Encoding) ID() (mib identifier.MIB, other string) {
|
||||
return e.MIB, ""
|
||||
}
|
||||
|
||||
// SimpleEncoding is an Encoding that combines two Transformers.
|
||||
type SimpleEncoding struct {
|
||||
Decoder transform.Transformer
|
||||
Encoder transform.Transformer
|
||||
}
|
||||
|
||||
func (e *SimpleEncoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: e.Decoder}
|
||||
}
|
||||
|
||||
func (e *SimpleEncoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: e.Encoder}
|
||||
}
|
||||
|
||||
// FuncEncoding is an Encoding that combines two functions returning a new
|
||||
// Transformer.
|
||||
type FuncEncoding struct {
|
||||
Decoder func() transform.Transformer
|
||||
Encoder func() transform.Transformer
|
||||
}
|
||||
|
||||
func (e FuncEncoding) NewDecoder() *encoding.Decoder {
|
||||
return &encoding.Decoder{Transformer: e.Decoder()}
|
||||
}
|
||||
|
||||
func (e FuncEncoding) NewEncoder() *encoding.Encoder {
|
||||
return &encoding.Encoder{Transformer: e.Encoder()}
|
||||
}
|
||||
|
||||
// A RepertoireError indicates a rune is not in the repertoire of a destination
|
||||
// encoding. It is associated with an encoding-specific suggested replacement
|
||||
// byte.
|
||||
type RepertoireError byte
|
||||
|
||||
// Error implements the error interrface.
|
||||
func (r RepertoireError) Error() string {
|
||||
return "encoding: rune not supported by encoding."
|
||||
}
|
||||
|
||||
// Replacement returns the replacement string associated with this error.
|
||||
func (r RepertoireError) Replacement() byte { return byte(r) }
|
||||
|
||||
var ErrASCIIReplacement = RepertoireError(encoding.ASCIISub)
|
||||
12
vendor/golang.org/x/text/encoding/japanese/all.go
generated
vendored
12
vendor/golang.org/x/text/encoding/japanese/all.go
generated
vendored
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{EUCJP, ISO2022JP, ShiftJIS}
|
||||
248
vendor/golang.org/x/text/encoding/japanese/all_test.go
generated
vendored
248
vendor/golang.org/x/text/encoding/japanese/all_test.go
generated
vendored
|
|
@ -1,248 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/enctest"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Decode", e.NewDecoder(), nil
|
||||
}
|
||||
func enc(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
|
||||
}
|
||||
|
||||
func TestNonRepertoire(t *testing.T) {
|
||||
// Pick n to cause the destination buffer in transform.String to overflow.
|
||||
const n = 100
|
||||
long := strings.Repeat(".", n)
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{enc, EUCJP, "갂", ""},
|
||||
{enc, EUCJP, "a갂", "a"},
|
||||
{enc, EUCJP, "丌갂", "\x8f\xb0\xa4"},
|
||||
|
||||
{enc, ISO2022JP, "갂", ""},
|
||||
{enc, ISO2022JP, "a갂", "a"},
|
||||
{enc, ISO2022JP, "朗갂", "\x1b$BzF\x1b(B"}, // switch back to ASCII mode at end
|
||||
|
||||
{enc, ShiftJIS, "갂", ""},
|
||||
{enc, ShiftJIS, "a갂", "a"},
|
||||
{enc, ShiftJIS, "\u2190갂", "\x81\xa9"},
|
||||
|
||||
// Continue correctly after errors
|
||||
{dec, EUCJP, "\x8e\xa0", "\ufffd\ufffd"},
|
||||
{dec, EUCJP, "\x8e\xe0", "\ufffd"},
|
||||
{dec, EUCJP, "\x8e\xff", "\ufffd\ufffd"},
|
||||
{dec, EUCJP, "\x8ea", "\ufffda"},
|
||||
{dec, EUCJP, "\x8f\xa0", "\ufffd\ufffd"},
|
||||
{dec, EUCJP, "\x8f\xa1\xa0", "\ufffd\ufffd"},
|
||||
{dec, EUCJP, "\x8f\xa1a", "\ufffda"},
|
||||
{dec, EUCJP, "\x8f\xa1a", "\ufffda"},
|
||||
{dec, EUCJP, "\x8f\xa1a", "\ufffda"},
|
||||
{dec, EUCJP, "\x8f\xa2\xa2", "\ufffd"},
|
||||
{dec, EUCJP, "\xfe", "\ufffd"},
|
||||
{dec, EUCJP, "\xfe\xfc", "\ufffd"},
|
||||
{dec, EUCJP, "\xfe\xff", "\ufffd\ufffd"},
|
||||
// Correct handling of end of source
|
||||
{dec, EUCJP, strings.Repeat("\x8e", n), strings.Repeat("\ufffd", n)},
|
||||
{dec, EUCJP, strings.Repeat("\x8f", n), strings.Repeat("\ufffd", n)},
|
||||
{dec, EUCJP, strings.Repeat("\x8f\xa0", n), strings.Repeat("\ufffd", 2*n)},
|
||||
{dec, EUCJP, "a" + strings.Repeat("\x8f\xa1", n), "a" + strings.Repeat("\ufffd", n)},
|
||||
{dec, EUCJP, "a" + strings.Repeat("\x8f\xa1\xff", n), "a" + strings.Repeat("\ufffd", 2*n)},
|
||||
|
||||
// Continue correctly after errors
|
||||
{dec, ShiftJIS, "\x80", "\u0080"}, // It's what the spec says.
|
||||
{dec, ShiftJIS, "\x81", "\ufffd"},
|
||||
{dec, ShiftJIS, "\x81\x7f", "\ufffd\u007f"},
|
||||
{dec, ShiftJIS, "\xe0", "\ufffd"},
|
||||
{dec, ShiftJIS, "\xe0\x39", "\ufffd\u0039"},
|
||||
{dec, ShiftJIS, "\xe0\x9f", "燹"},
|
||||
{dec, ShiftJIS, "\xe0\xfd", "\ufffd"},
|
||||
{dec, ShiftJIS, "\xef\xfc", "\ufffd"},
|
||||
{dec, ShiftJIS, "\xfc\xfc", "\ufffd"},
|
||||
{dec, ShiftJIS, "\xfc\xfd", "\ufffd"},
|
||||
{dec, ShiftJIS, "\xfdaa", "\ufffdaa"},
|
||||
|
||||
{dec, ShiftJIS, strings.Repeat("\x81\x81", n), strings.Repeat("=", n)},
|
||||
{dec, ShiftJIS, strings.Repeat("\xe0\xfd", n), strings.Repeat("\ufffd", n)},
|
||||
{dec, ShiftJIS, "a" + strings.Repeat("\xe0\xfd", n), "a" + strings.Repeat("\ufffd", n)},
|
||||
|
||||
{dec, ISO2022JP, "\x1b$", "\ufffd$"},
|
||||
{dec, ISO2022JP, "\x1b(", "\ufffd("},
|
||||
{dec, ISO2022JP, "\x1b@", "\ufffd@"},
|
||||
{dec, ISO2022JP, "\x1bZ", "\ufffdZ"},
|
||||
// incomplete escapes
|
||||
{dec, ISO2022JP, "\x1b$", "\ufffd$"},
|
||||
{dec, ISO2022JP, "\x1b$J.", "\ufffd$J."}, // illegal
|
||||
{dec, ISO2022JP, "\x1b$B.", "\ufffd"}, // JIS208
|
||||
{dec, ISO2022JP, "\x1b$(", "\ufffd$("}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b$(..", "\ufffd$(.."}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b$(" + long, "\ufffd$(" + long}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b$(D.", "\ufffd"}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b$(D..", "\ufffd"}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b$(D...", "\ufffd\ufffd"}, // JIS212
|
||||
{dec, ISO2022JP, "\x1b(B.", "."}, // ascii
|
||||
{dec, ISO2022JP, "\x1b(B..", ".."}, // ascii
|
||||
{dec, ISO2022JP, "\x1b(J.", "."}, // roman
|
||||
{dec, ISO2022JP, "\x1b(J..", ".."}, // roman
|
||||
{dec, ISO2022JP, "\x1b(I\x20", "\ufffd"}, // katakana
|
||||
{dec, ISO2022JP, "\x1b(I\x20\x20", "\ufffd\ufffd"}, // katakana
|
||||
// recover to same state
|
||||
{dec, ISO2022JP, "\x1b(B\x1b.", "\ufffd."},
|
||||
{dec, ISO2022JP, "\x1b(I\x1b.", "\ufffdョ"},
|
||||
{dec, ISO2022JP, "\x1b(I\x1b$.", "\ufffd、ョ"},
|
||||
{dec, ISO2022JP, "\x1b(I\x1b(.", "\ufffdィョ"},
|
||||
{dec, ISO2022JP, "\x1b$B\x7e\x7e", "\ufffd"},
|
||||
{dec, ISO2022JP, "\x1b$@\x0a.", "\x0a."},
|
||||
{dec, ISO2022JP, "\x1b$B\x0a.", "\x0a."},
|
||||
{dec, ISO2022JP, "\x1b$(D\x0a.", "\x0a."},
|
||||
{dec, ISO2022JP, "\x1b$(D\x7e\x7e", "\ufffd"},
|
||||
{dec, ISO2022JP, "\x80", "\ufffd"},
|
||||
|
||||
// TODO: according to https://encoding.spec.whatwg.org/#iso-2022-jp,
|
||||
// these should all be correct.
|
||||
// {dec, ISO2022JP, "\x1b(B\x0E", "\ufffd"},
|
||||
// {dec, ISO2022JP, "\x1b(B\x0F", "\ufffd"},
|
||||
{dec, ISO2022JP, "\x1b(B\x5C", "\u005C"},
|
||||
{dec, ISO2022JP, "\x1b(B\x7E", "\u007E"},
|
||||
// {dec, ISO2022JP, "\x1b(J\x0E", "\ufffd"},
|
||||
// {dec, ISO2022JP, "\x1b(J\x0F", "\ufffd"},
|
||||
// {dec, ISO2022JP, "\x1b(J\x5C", "\u00A5"},
|
||||
// {dec, ISO2022JP, "\x1b(J\x7E", "\u203E"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, wantErr := tc.init(tc.e)
|
||||
t.Run(fmt.Sprintf("%s/%v/%q", dir, tc.e, tc.src), func(t *testing.T) {
|
||||
dst := make([]byte, 100000)
|
||||
src := []byte(tc.src)
|
||||
for i := 0; i <= len(tc.src); i++ {
|
||||
nDst, nSrc, err := tr.Transform(dst, src[:i], false)
|
||||
if err != nil && err != transform.ErrShortSrc && err != wantErr {
|
||||
t.Fatalf("error on first call to Transform: %v", err)
|
||||
}
|
||||
n, _, err := tr.Transform(dst[nDst:], src[nSrc:], true)
|
||||
nDst += n
|
||||
if err != wantErr {
|
||||
t.Fatalf("(%q|%q): got %v; want %v", tc.src[:i], tc.src[i:], err, wantErr)
|
||||
}
|
||||
if got := string(dst[:nDst]); got != tc.want {
|
||||
t.Errorf("(%q|%q):\ngot %q\nwant %q", tc.src[:i], tc.src[i:], got, tc.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCorrect(t *testing.T) {
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{dec, ShiftJIS, "\x9f\xfc", "滌"},
|
||||
{dec, ShiftJIS, "\xfb\xfc", "髙"},
|
||||
{dec, ShiftJIS, "\xfa\xb1", "﨑"},
|
||||
{enc, ShiftJIS, "滌", "\x9f\xfc"},
|
||||
{enc, ShiftJIS, "﨑", "\xed\x95"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, _ := tc.init(tc.e)
|
||||
|
||||
dst, _, err := transform.String(tr, tc.src)
|
||||
if err != nil {
|
||||
t.Errorf("%s %v(%q): got %v; want %v", dir, tc.e, tc.src, err, nil)
|
||||
}
|
||||
if got := string(dst); got != tc.want {
|
||||
t.Errorf("%s %v(%q):\ngot %q\nwant %q", dir, tc.e, tc.src, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
// The encoded forms can be verified by the iconv program:
|
||||
// $ echo 月日は百代 | iconv -f UTF-8 -t SHIFT-JIS | xxd
|
||||
testCases := []struct {
|
||||
e encoding.Encoding
|
||||
encPrefix string
|
||||
encSuffix string
|
||||
encoded string
|
||||
utf8 string
|
||||
}{{
|
||||
// "A。カ゚ 0208: etc 0212: etc" is a nonsense string that contains ASCII, half-width
|
||||
// kana, JIS X 0208 (including two near the kink in the Shift JIS second byte
|
||||
// encoding) and JIS X 0212 encodable codepoints.
|
||||
//
|
||||
// "月日は百代の過客にして、行かふ年も又旅人也。" is from the 17th century poem
|
||||
// "Oku no Hosomichi" and contains both hiragana and kanji.
|
||||
e: EUCJP,
|
||||
encoded: "A\x8e\xa1\x8e\xb6\x8e\xdf " +
|
||||
"0208: \xa1\xa1\xa1\xa2\xa1\xdf\xa1\xe0\xa1\xfd\xa1\xfe\xa2\xa1\xa2\xa2\xf4\xa6 " +
|
||||
"0212: \x8f\xa2\xaf\x8f\xed\xe3",
|
||||
utf8: "A。カ゚ " +
|
||||
"0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199 " +
|
||||
"0212: \u02d8\u9fa5",
|
||||
}, {
|
||||
e: EUCJP,
|
||||
encoded: "\xb7\xee\xc6\xfc\xa4\xcf\xc9\xb4\xc2\xe5\xa4\xce\xb2\xe1\xb5\xd2" +
|
||||
"\xa4\xcb\xa4\xb7\xa4\xc6\xa1\xa2\xb9\xd4\xa4\xab\xa4\xd5\xc7\xaf" +
|
||||
"\xa4\xe2\xcb\xf4\xce\xb9\xbf\xcd\xcc\xe9\xa1\xa3",
|
||||
utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
|
||||
}, {
|
||||
e: ISO2022JP,
|
||||
encSuffix: "\x1b\x28\x42",
|
||||
encoded: "\x1b\x28\x49\x21\x36\x5f\x1b\x28\x42 " +
|
||||
"0208: \x1b\x24\x42\x21\x21\x21\x22\x21\x5f\x21\x60\x21\x7d\x21\x7e\x22\x21\x22\x22\x74\x26",
|
||||
utf8: "。カ゚ " +
|
||||
"0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199",
|
||||
}, {
|
||||
e: ISO2022JP,
|
||||
encPrefix: "\x1b\x24\x42",
|
||||
encSuffix: "\x1b\x28\x42",
|
||||
encoded: "\x37\x6e\x46\x7c\x24\x4f\x49\x34\x42\x65\x24\x4e\x32\x61\x35\x52" +
|
||||
"\x24\x4b\x24\x37\x24\x46\x21\x22\x39\x54\x24\x2b\x24\x55\x47\x2f" +
|
||||
"\x24\x62\x4b\x74\x4e\x39\x3f\x4d\x4c\x69\x21\x23",
|
||||
utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
|
||||
}, {
|
||||
e: ShiftJIS,
|
||||
encoded: "A\xa1\xb6\xdf " +
|
||||
"0208: \x81\x40\x81\x41\x81\x7e\x81\x80\x81\x9d\x81\x9e\x81\x9f\x81\xa0\xea\xa4",
|
||||
utf8: "A。カ゚ " +
|
||||
"0208: \u3000\u3001\u00d7\u00f7\u25ce\u25c7\u25c6\u25a1\u7199",
|
||||
}, {
|
||||
e: ShiftJIS,
|
||||
encoded: "\x8c\x8e\x93\xfa\x82\xcd\x95\x53\x91\xe3\x82\xcc\x89\xdf\x8b\x71" +
|
||||
"\x82\xc9\x82\xb5\x82\xc4\x81\x41\x8d\x73\x82\xa9\x82\xd3\x94\x4e" +
|
||||
"\x82\xe0\x96\x94\x97\xb7\x90\x6c\x96\xe7\x81\x42",
|
||||
utf8: "月日は百代の過客にして、行かふ年も又旅人也。",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, tc.encPrefix, tc.encSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFiles(t *testing.T) {
|
||||
enctest.TestFile(t, EUCJP)
|
||||
enctest.TestFile(t, ISO2022JP)
|
||||
enctest.TestFile(t, ShiftJIS)
|
||||
}
|
||||
|
||||
func BenchmarkEncoding(b *testing.B) {
|
||||
enctest.Benchmark(b, EUCJP)
|
||||
enctest.Benchmark(b, ISO2022JP)
|
||||
enctest.Benchmark(b, ShiftJIS)
|
||||
}
|
||||
225
vendor/golang.org/x/text/encoding/japanese/eucjp.go
generated
vendored
225
vendor/golang.org/x/text/encoding/japanese/eucjp.go
generated
vendored
|
|
@ -1,225 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// EUCJP is the EUC-JP encoding.
|
||||
var EUCJP encoding.Encoding = &eucJP
|
||||
|
||||
var eucJP = internal.Encoding{
|
||||
&internal.SimpleEncoding{eucJPDecoder{}, eucJPEncoder{}},
|
||||
"EUC-JP",
|
||||
identifier.EUCPkdFmtJapanese,
|
||||
}
|
||||
|
||||
type eucJPDecoder struct{ transform.NopResetter }
|
||||
|
||||
// See https://encoding.spec.whatwg.org/#euc-jp-decoder.
|
||||
func (eucJPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case c0 == 0x8e:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case c1 < 0xa1:
|
||||
r, size = utf8.RuneError, 1
|
||||
case c1 > 0xdf:
|
||||
r, size = utf8.RuneError, 2
|
||||
if c1 == 0xff {
|
||||
size = 1
|
||||
}
|
||||
default:
|
||||
r, size = rune(c1)+(0xff61-0xa1), 2
|
||||
}
|
||||
case c0 == 0x8f:
|
||||
if nSrc+2 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
if p := nSrc + 1; p < len(src) && 0xa1 <= src[p] && src[p] < 0xfe {
|
||||
size = 2
|
||||
}
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
if c1 < 0xa1 || 0xfe < c1 {
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c2 := src[nSrc+2]
|
||||
if c2 < 0xa1 || 0xfe < c2 {
|
||||
r, size = utf8.RuneError, 2
|
||||
break
|
||||
}
|
||||
r, size = utf8.RuneError, 3
|
||||
if i := int(c1-0xa1)*94 + int(c2-0xa1); i < len(jis0212Decode) {
|
||||
r = rune(jis0212Decode[i])
|
||||
if r == 0 {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
}
|
||||
|
||||
case 0xa1 <= c0 && c0 <= 0xfe:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
if c1 < 0xa1 || 0xfe < c1 {
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
r, size = utf8.RuneError, 2
|
||||
if i := int(c0-0xa1)*94 + int(c1-0xa1); i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
if r == 0 {
|
||||
r = utf8.RuneError
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type eucJPEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucJPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
goto write2
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2or3
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2or3:
|
||||
if r>>tableShift == jis0208 {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = 0x8f
|
||||
nDst++
|
||||
}
|
||||
dst[nDst+0] = 0xa1 + uint8(r>>codeShift)&codeMask
|
||||
dst[nDst+1] = 0xa1 + uint8(r)&codeMask
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = 0x8e
|
||||
dst[nDst+1] = uint8(r - (0xff61 - 0xa1))
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 6 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
||||
299
vendor/golang.org/x/text/encoding/japanese/iso2022jp.go
generated
vendored
299
vendor/golang.org/x/text/encoding/japanese/iso2022jp.go
generated
vendored
|
|
@ -1,299 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ISO2022JP is the ISO-2022-JP encoding.
|
||||
var ISO2022JP encoding.Encoding = &iso2022JP
|
||||
|
||||
var iso2022JP = internal.Encoding{
|
||||
internal.FuncEncoding{iso2022JPNewDecoder, iso2022JPNewEncoder},
|
||||
"ISO-2022-JP",
|
||||
identifier.ISO2022JP,
|
||||
}
|
||||
|
||||
func iso2022JPNewDecoder() transform.Transformer {
|
||||
return new(iso2022JPDecoder)
|
||||
}
|
||||
|
||||
func iso2022JPNewEncoder() transform.Transformer {
|
||||
return new(iso2022JPEncoder)
|
||||
}
|
||||
|
||||
const (
|
||||
asciiState = iota
|
||||
katakanaState
|
||||
jis0208State
|
||||
jis0212State
|
||||
)
|
||||
|
||||
const asciiEsc = 0x1b
|
||||
|
||||
type iso2022JPDecoder int
|
||||
|
||||
func (d *iso2022JPDecoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (d *iso2022JPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
c0 := src[nSrc]
|
||||
if c0 >= utf8.RuneSelf {
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
|
||||
if c0 == asciiEsc {
|
||||
if nSrc+2 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
// TODO: is it correct to only skip 1??
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 3
|
||||
c1 := src[nSrc+1]
|
||||
c2 := src[nSrc+2]
|
||||
switch {
|
||||
case c1 == '$' && (c2 == '@' || c2 == 'B'): // 0x24 {0x40, 0x42}
|
||||
*d = jis0208State
|
||||
continue
|
||||
case c1 == '$' && c2 == '(': // 0x24 0x28
|
||||
if nSrc+3 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 4
|
||||
if src[nSrc+3] == 'D' {
|
||||
*d = jis0212State
|
||||
continue
|
||||
}
|
||||
case c1 == '(' && (c2 == 'B' || c2 == 'J'): // 0x28 {0x42, 0x4A}
|
||||
*d = asciiState
|
||||
continue
|
||||
case c1 == '(' && c2 == 'I': // 0x28 0x49
|
||||
*d = katakanaState
|
||||
continue
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
|
||||
switch *d {
|
||||
case asciiState:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case katakanaState:
|
||||
if c0 < 0x21 || 0x60 <= c0 {
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
r, size = rune(c0)+(0xff61-0x21), 1
|
||||
|
||||
default:
|
||||
if c0 == 0x0a {
|
||||
*d = asciiState
|
||||
r, size = rune(c0), 1
|
||||
goto write
|
||||
}
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
return nDst, nSrc, transform.ErrShortSrc
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
c1 := src[nSrc+1]
|
||||
i := int(c0-0x21)*94 + int(c1-0x21)
|
||||
if *d == jis0208State && i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
} else if *d == jis0212State && i < len(jis0212Decode) {
|
||||
r = rune(jis0212Decode[i])
|
||||
} else {
|
||||
r = '\ufffd'
|
||||
goto write
|
||||
}
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
return nDst, nSrc, transform.ErrShortDst
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type iso2022JPEncoder int
|
||||
|
||||
func (e *iso2022JPEncoder) Reset() {
|
||||
*e = asciiState
|
||||
}
|
||||
|
||||
func (e *iso2022JPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
//
|
||||
// http://encoding.spec.whatwg.org/#iso-2022-jp says that "the index jis0212
|
||||
// is not used by the iso-2022-jp encoder due to lack of widespread support".
|
||||
//
|
||||
// TODO: do we have to special-case U+00A5 and U+203E, as per
|
||||
// http://encoding.spec.whatwg.org/#iso-2022-jp
|
||||
// Doing so would mean that "\u00a5" would not be preserved
|
||||
// after an encode-decode round trip.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
goto writeKatakana
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
|
||||
goto writeJIS
|
||||
}
|
||||
}
|
||||
|
||||
// Switch back to ASCII state in case of error so that an ASCII
|
||||
// replacement character can be written in the correct state.
|
||||
if *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
if *e != asciiState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
writeJIS:
|
||||
if *e != jis0208State {
|
||||
if nDst+5 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = jis0208State
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '$'
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
} else if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = 0x21 + uint8(r>>codeShift)&codeMask
|
||||
dst[nDst+1] = 0x21 + uint8(r)&codeMask
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
writeKatakana:
|
||||
if *e != katakanaState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = katakanaState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'I'
|
||||
nDst += 3
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r - (0xff61 - 0x21))
|
||||
nDst++
|
||||
continue
|
||||
}
|
||||
if atEOF && err == nil && *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
} else {
|
||||
*e = asciiState
|
||||
dst[nDst+0] = asciiEsc
|
||||
dst[nDst+1] = '('
|
||||
dst[nDst+2] = 'B'
|
||||
nDst += 3
|
||||
}
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
161
vendor/golang.org/x/text/encoding/japanese/maketables.go
generated
vendored
161
vendor/golang.org/x/text/encoding/japanese/maketables.go
generated
vendored
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This program generates tables.go:
|
||||
// go run maketables.go | gofmt > tables.go
|
||||
|
||||
// TODO: Emoji extensions?
|
||||
// http://www.unicode.org/faq/emoji_dingbats.html
|
||||
// http://www.unicode.org/Public/UNIDATA/EmojiSources.txt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type entry struct {
|
||||
jisCode, table int
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n")
|
||||
fmt.Printf("// Package japanese provides Japanese encodings such as EUC-JP and Shift JIS.\n")
|
||||
fmt.Printf(`package japanese // import "golang.org/x/text/encoding/japanese"` + "\n\n")
|
||||
|
||||
reverse := [65536]entry{}
|
||||
for i := range reverse {
|
||||
reverse[i].table = -1
|
||||
}
|
||||
|
||||
tables := []struct {
|
||||
url string
|
||||
name string
|
||||
}{
|
||||
{"http://encoding.spec.whatwg.org/index-jis0208.txt", "0208"},
|
||||
{"http://encoding.spec.whatwg.org/index-jis0212.txt", "0212"},
|
||||
}
|
||||
for i, table := range tables {
|
||||
res, err := http.Get(table.url)
|
||||
if err != nil {
|
||||
log.Fatalf("%q: Get: %v", table.url, err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := [65536]uint16{}
|
||||
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := 0, uint16(0)
|
||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("%q: could not parse %q", table.url, s)
|
||||
}
|
||||
if x < 0 || 120*94 <= x {
|
||||
log.Fatalf("%q: JIS code %d is out of range", table.url, x)
|
||||
}
|
||||
mapping[x] = y
|
||||
if reverse[y].table == -1 {
|
||||
reverse[y] = entry{jisCode: x, table: i}
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatalf("%q: scanner error: %v", table.url, err)
|
||||
}
|
||||
|
||||
fmt.Printf("// jis%sDecode is the decoding table from JIS %s code to Unicode.\n// It is defined at %s\n",
|
||||
table.name, table.name, table.url)
|
||||
fmt.Printf("var jis%sDecode = [...]uint16{\n", table.name)
|
||||
for i, m := range mapping {
|
||||
if m != 0 {
|
||||
fmt.Printf("\t%d: 0x%04X,\n", i, m)
|
||||
}
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
|
||||
// Any run of at least separation continuous zero entries in the reverse map will
|
||||
// be a separate encode table.
|
||||
const separation = 1024
|
||||
|
||||
intervals := []interval(nil)
|
||||
low, high := -1, -1
|
||||
for i, v := range reverse {
|
||||
if v.table == -1 {
|
||||
continue
|
||||
}
|
||||
if low < 0 {
|
||||
low = i
|
||||
} else if i-high >= separation {
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
low = i
|
||||
}
|
||||
high = i + 1
|
||||
}
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
sort.Sort(byDecreasingLength(intervals))
|
||||
|
||||
fmt.Printf("const (\n")
|
||||
fmt.Printf("\tjis0208 = 1\n")
|
||||
fmt.Printf("\tjis0212 = 2\n")
|
||||
fmt.Printf("\tcodeMask = 0x7f\n")
|
||||
fmt.Printf("\tcodeShift = 7\n")
|
||||
fmt.Printf("\ttableShift = 14\n")
|
||||
fmt.Printf(")\n\n")
|
||||
|
||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals))
|
||||
fmt.Printf("// encodeX are the encoding tables from Unicode to JIS code,\n")
|
||||
fmt.Printf("// sorted by decreasing length.\n")
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high)
|
||||
}
|
||||
fmt.Printf("//\n")
|
||||
fmt.Printf("// The high two bits of the value record whether the JIS code comes from the\n")
|
||||
fmt.Printf("// JIS0208 table (high bits == 1) or the JIS0212 table (high bits == 2).\n")
|
||||
fmt.Printf("// The low 14 bits are two 7-bit unsigned integers j1 and j2 that form the\n")
|
||||
fmt.Printf("// JIS code (94*j1 + j2) within that table.\n")
|
||||
fmt.Printf("\n")
|
||||
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high)
|
||||
fmt.Printf("var encode%d = [...]uint16{\n", i)
|
||||
for j := v.low; j < v.high; j++ {
|
||||
x := reverse[j]
|
||||
if x.table == -1 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("\t%d - %d: jis%s<<14 | 0x%02X<<7 | 0x%02X,\n",
|
||||
j, v.low, tables[x.table].name, x.jisCode/94, x.jisCode%94)
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
// interval is a half-open interval [low, high).
|
||||
type interval struct {
|
||||
low, high int
|
||||
}
|
||||
|
||||
func (i interval) len() int { return i.high - i.low }
|
||||
|
||||
// byDecreasingLength sorts intervals by decreasing length.
|
||||
type byDecreasingLength []interval
|
||||
|
||||
func (b byDecreasingLength) Len() int { return len(b) }
|
||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() }
|
||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
189
vendor/golang.org/x/text/encoding/japanese/shiftjis.go
generated
vendored
189
vendor/golang.org/x/text/encoding/japanese/shiftjis.go
generated
vendored
|
|
@ -1,189 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package japanese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// ShiftJIS is the Shift JIS encoding, also known as Code Page 932 and
|
||||
// Windows-31J.
|
||||
var ShiftJIS encoding.Encoding = &shiftJIS
|
||||
|
||||
var shiftJIS = internal.Encoding{
|
||||
&internal.SimpleEncoding{shiftJISDecoder{}, shiftJISEncoder{}},
|
||||
"Shift JIS",
|
||||
identifier.ShiftJIS,
|
||||
}
|
||||
|
||||
type shiftJISDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (shiftJISDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0xa1 <= c0 && c0 < 0xe0:
|
||||
r, size = rune(c0)+(0xff61-0xa1), 1
|
||||
|
||||
case (0x81 <= c0 && c0 < 0xa0) || (0xe0 <= c0 && c0 < 0xfd):
|
||||
if c0 <= 0x9f {
|
||||
c0 -= 0x70
|
||||
} else {
|
||||
c0 -= 0xb0
|
||||
}
|
||||
c0 = 2*c0 - 0x21
|
||||
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = '\ufffd', 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case c1 < 0x40:
|
||||
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
|
||||
goto write
|
||||
case c1 < 0x7f:
|
||||
c0--
|
||||
c1 -= 0x40
|
||||
case c1 == 0x7f:
|
||||
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
|
||||
goto write
|
||||
case c1 < 0x9f:
|
||||
c0--
|
||||
c1 -= 0x41
|
||||
case c1 < 0xfd:
|
||||
c1 -= 0x9f
|
||||
default:
|
||||
r, size = '\ufffd', 2
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0)*94 + int(c1); i < len(jis0208Decode) {
|
||||
r = rune(jis0208Decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
case c0 == 0x80:
|
||||
r, size = 0x80, 1
|
||||
|
||||
default:
|
||||
r, size = '\ufffd', 1
|
||||
}
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type shiftJISEncoder struct{ transform.NopResetter }
|
||||
|
||||
func (shiftJISEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if 0xff61 <= r && r < 0xffa0 {
|
||||
r -= 0xff61 - 0xa1
|
||||
goto write1
|
||||
}
|
||||
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write1:
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2:
|
||||
j1 := uint8(r>>codeShift) & codeMask
|
||||
j2 := uint8(r) & codeMask
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
if j1 <= 61 {
|
||||
dst[nDst+0] = 129 + j1/2
|
||||
} else {
|
||||
dst[nDst+0] = 193 + j1/2
|
||||
}
|
||||
if j1&1 == 0 {
|
||||
dst[nDst+1] = j2 + j2/63 + 64
|
||||
} else {
|
||||
dst[nDst+1] = j2 + 159
|
||||
}
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
26971
vendor/golang.org/x/text/encoding/japanese/tables.go
generated
vendored
26971
vendor/golang.org/x/text/encoding/japanese/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
94
vendor/golang.org/x/text/encoding/korean/all_test.go
generated
vendored
94
vendor/golang.org/x/text/encoding/korean/all_test.go
generated
vendored
|
|
@ -1,94 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package korean
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/enctest"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Decode", e.NewDecoder(), nil
|
||||
}
|
||||
func enc(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
|
||||
}
|
||||
|
||||
func TestNonRepertoire(t *testing.T) {
|
||||
// Pick n large enough to cause an overflow in the destination buffer of
|
||||
// transform.String.
|
||||
const n = 10000
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{dec, EUCKR, "\xfe\xfe", "\ufffd"},
|
||||
// {dec, EUCKR, "א", "\ufffd"}, // TODO: why is this different?
|
||||
|
||||
{enc, EUCKR, "א", ""},
|
||||
{enc, EUCKR, "aא", "a"},
|
||||
{enc, EUCKR, "\uac00א", "\xb0\xa1"},
|
||||
// TODO: should we also handle Jamo?
|
||||
|
||||
{dec, EUCKR, "\x80", "\ufffd"},
|
||||
{dec, EUCKR, "\xff", "\ufffd"},
|
||||
{dec, EUCKR, "\x81", "\ufffd"},
|
||||
{dec, EUCKR, "\xb0\x40", "\ufffd@"},
|
||||
{dec, EUCKR, "\xb0\xff", "\ufffd"},
|
||||
{dec, EUCKR, "\xd0\x20", "\ufffd "},
|
||||
{dec, EUCKR, "\xd0\xff", "\ufffd"},
|
||||
|
||||
{dec, EUCKR, strings.Repeat("\x81", n), strings.Repeat("걖", n/2)},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, wantErr := tc.init(tc.e)
|
||||
|
||||
dst, _, err := transform.String(tr, tc.src)
|
||||
if err != wantErr {
|
||||
t.Errorf("%s %v(%q): got %v; want %v", dir, tc.e, tc.src, err, wantErr)
|
||||
}
|
||||
if got := string(dst); got != tc.want {
|
||||
t.Errorf("%s %v(%q):\ngot %q\nwant %q", dir, tc.e, tc.src, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
// The encoded forms can be verified by the iconv program:
|
||||
// $ echo 月日は百代 | iconv -f UTF-8 -t SHIFT-JIS | xxd
|
||||
testCases := []struct {
|
||||
e encoding.Encoding
|
||||
encoded string
|
||||
utf8 string
|
||||
}{{
|
||||
// Korean tests.
|
||||
//
|
||||
// "A\uac02\uac35\uac56\ud401B\ud408\ud620\ud624C\u4f3d\u8a70D" is a
|
||||
// nonsense string that contains ASCII, Hangul and CJK ideographs.
|
||||
//
|
||||
// "세계야, 안녕" translates as "Hello, world".
|
||||
e: EUCKR,
|
||||
encoded: "A\x81\x41\x81\x61\x81\x81\xc6\xfeB\xc7\xa1\xc7\xfe\xc8\xa1C\xca\xa1\xfd\xfeD",
|
||||
utf8: "A\uac02\uac35\uac56\ud401B\ud408\ud620\ud624C\u4f3d\u8a70D",
|
||||
}, {
|
||||
e: EUCKR,
|
||||
encoded: "\xbc\xbc\xb0\xe8\xbe\xdf\x2c\x20\xbe\xc8\xb3\xe7",
|
||||
utf8: "세계야, 안녕",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, "", "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFiles(t *testing.T) { enctest.TestFile(t, EUCKR) }
|
||||
|
||||
func BenchmarkEncoding(b *testing.B) { enctest.Benchmark(b, EUCKR) }
|
||||
177
vendor/golang.org/x/text/encoding/korean/euckr.go
generated
vendored
177
vendor/golang.org/x/text/encoding/korean/euckr.go
generated
vendored
|
|
@ -1,177 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package korean
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{EUCKR}
|
||||
|
||||
// EUCKR is the EUC-KR encoding, also known as Code Page 949.
|
||||
var EUCKR encoding.Encoding = &eucKR
|
||||
|
||||
var eucKR = internal.Encoding{
|
||||
&internal.SimpleEncoding{eucKRDecoder{}, eucKREncoder{}},
|
||||
"EUC-KR",
|
||||
identifier.EUCKR,
|
||||
}
|
||||
|
||||
type eucKRDecoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucKRDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0x81 <= c0 && c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
size = 2
|
||||
if c0 < 0xc7 {
|
||||
r = 178 * rune(c0-0x81)
|
||||
switch {
|
||||
case 0x41 <= c1 && c1 < 0x5b:
|
||||
r += rune(c1) - (0x41 - 0*26)
|
||||
case 0x61 <= c1 && c1 < 0x7b:
|
||||
r += rune(c1) - (0x61 - 1*26)
|
||||
case 0x81 <= c1 && c1 < 0xff:
|
||||
r += rune(c1) - (0x81 - 2*26)
|
||||
default:
|
||||
goto decError
|
||||
}
|
||||
} else if 0xa1 <= c1 && c1 < 0xff {
|
||||
r = 178*(0xc7-0x81) + rune(c0-0xc7)*94 + rune(c1-0xa1)
|
||||
} else {
|
||||
goto decError
|
||||
}
|
||||
if int(r) < len(decode) {
|
||||
r = rune(decode[r])
|
||||
if r != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
decError:
|
||||
r = utf8.RuneError
|
||||
if c1 < utf8.RuneSelf {
|
||||
size = 1
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
break
|
||||
}
|
||||
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type eucKREncoder struct{ transform.NopResetter }
|
||||
|
||||
func (eucKREncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode6Low <= r && r < encode6High:
|
||||
if r = rune(encode6[r-encode6Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r >> 8)
|
||||
dst[nDst+1] = uint8(r)
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 7 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
||||
143
vendor/golang.org/x/text/encoding/korean/maketables.go
generated
vendored
143
vendor/golang.org/x/text/encoding/korean/maketables.go
generated
vendored
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This program generates tables.go:
|
||||
// go run maketables.go | gofmt > tables.go
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n")
|
||||
fmt.Printf("// Package korean provides Korean encodings such as EUC-KR.\n")
|
||||
fmt.Printf(`package korean // import "golang.org/x/text/encoding/korean"` + "\n\n")
|
||||
|
||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-euc-kr.txt")
|
||||
if err != nil {
|
||||
log.Fatalf("Get: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := [65536]uint16{}
|
||||
reverse := [65536]uint16{}
|
||||
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := uint16(0), uint16(0)
|
||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("could not parse %q", s)
|
||||
}
|
||||
if x < 0 || 178*(0xc7-0x81)+(0xfe-0xc7)*94+(0xff-0xa1) <= x {
|
||||
log.Fatalf("EUC-KR code %d is out of range", x)
|
||||
}
|
||||
mapping[x] = y
|
||||
if reverse[y] == 0 {
|
||||
c0, c1 := uint16(0), uint16(0)
|
||||
if x < 178*(0xc7-0x81) {
|
||||
c0 = uint16(x/178) + 0x81
|
||||
c1 = uint16(x % 178)
|
||||
switch {
|
||||
case c1 < 1*26:
|
||||
c1 += 0x41
|
||||
case c1 < 2*26:
|
||||
c1 += 0x47
|
||||
default:
|
||||
c1 += 0x4d
|
||||
}
|
||||
} else {
|
||||
x -= 178 * (0xc7 - 0x81)
|
||||
c0 = uint16(x/94) + 0xc7
|
||||
c1 = uint16(x%94) + 0xa1
|
||||
}
|
||||
reverse[y] = c0<<8 | c1
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatalf("scanner error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("// decode is the decoding table from EUC-KR code to Unicode.\n")
|
||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-euc-kr.txt\n")
|
||||
fmt.Printf("var decode = [...]uint16{\n")
|
||||
for i, v := range mapping {
|
||||
if v != 0 {
|
||||
fmt.Printf("\t%d: 0x%04X,\n", i, v)
|
||||
}
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
|
||||
// Any run of at least separation continuous zero entries in the reverse map will
|
||||
// be a separate encode table.
|
||||
const separation = 1024
|
||||
|
||||
intervals := []interval(nil)
|
||||
low, high := -1, -1
|
||||
for i, v := range reverse {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
if low < 0 {
|
||||
low = i
|
||||
} else if i-high >= separation {
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
low = i
|
||||
}
|
||||
high = i + 1
|
||||
}
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
sort.Sort(byDecreasingLength(intervals))
|
||||
|
||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals))
|
||||
fmt.Printf("// encodeX are the encoding tables from Unicode to EUC-KR code,\n")
|
||||
fmt.Printf("// sorted by decreasing length.\n")
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high)
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high)
|
||||
fmt.Printf("var encode%d = [...]uint16{\n", i)
|
||||
for j := v.low; j < v.high; j++ {
|
||||
x := reverse[j]
|
||||
if x == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x)
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
// interval is a half-open interval [low, high).
|
||||
type interval struct {
|
||||
low, high int
|
||||
}
|
||||
|
||||
func (i interval) len() int { return i.high - i.low }
|
||||
|
||||
// byDecreasingLength sorts intervals by decreasing length.
|
||||
type byDecreasingLength []interval
|
||||
|
||||
func (b byDecreasingLength) Len() int { return len(b) }
|
||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() }
|
||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
34152
vendor/golang.org/x/text/encoding/korean/tables.go
generated
vendored
34152
vendor/golang.org/x/text/encoding/korean/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
12
vendor/golang.org/x/text/encoding/simplifiedchinese/all.go
generated
vendored
12
vendor/golang.org/x/text/encoding/simplifiedchinese/all.go
generated
vendored
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"golang.org/x/text/encoding"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{GB18030, GBK, HZGB2312}
|
||||
143
vendor/golang.org/x/text/encoding/simplifiedchinese/all_test.go
generated
vendored
143
vendor/golang.org/x/text/encoding/simplifiedchinese/all_test.go
generated
vendored
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/enctest"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Decode", e.NewDecoder(), nil
|
||||
}
|
||||
func enc(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
|
||||
}
|
||||
|
||||
func TestNonRepertoire(t *testing.T) {
|
||||
// Pick n large enough to overflow the destination buffer of transform.String.
|
||||
const n = 10000
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{dec, GBK, "a\xfe\xfeb", "a\ufffdb"},
|
||||
{dec, HZGB2312, "~{z~", "\ufffd"},
|
||||
|
||||
{enc, GBK, "갂", ""},
|
||||
{enc, GBK, "a갂", "a"},
|
||||
{enc, GBK, "\u4e02갂", "\x81@"},
|
||||
|
||||
{enc, HZGB2312, "갂", ""},
|
||||
{enc, HZGB2312, "a갂", "a"},
|
||||
{enc, HZGB2312, "\u6cf5갂", "~{1C~}"},
|
||||
|
||||
{dec, GB18030, "\x80", "€"},
|
||||
{dec, GB18030, "\x81", "\ufffd"},
|
||||
{dec, GB18030, "\x81\x20", "\ufffd "},
|
||||
{dec, GB18030, "\xfe\xfe", "\ufffd"},
|
||||
{dec, GB18030, "\xfe\xff", "\ufffd\ufffd"},
|
||||
{dec, GB18030, "\xfe\x30", "\ufffd0"},
|
||||
{dec, GB18030, "\xfe\x30\x30 ", "\ufffd00 "},
|
||||
{dec, GB18030, "\xfe\x30\xff ", "\ufffd0\ufffd "},
|
||||
{dec, GB18030, "\xfe\x30\x81\x21", "\ufffd0\ufffd!"},
|
||||
|
||||
{dec, GB18030, strings.Repeat("\xfe\x30", n), strings.Repeat("\ufffd0", n)},
|
||||
|
||||
{dec, HZGB2312, "~/", "\ufffd"},
|
||||
{dec, HZGB2312, "~{a\x80", "\ufffd"},
|
||||
{dec, HZGB2312, "~{a\x80", "\ufffd"},
|
||||
{dec, HZGB2312, "~{" + strings.Repeat("z~", n), strings.Repeat("\ufffd", n)},
|
||||
{dec, HZGB2312, "~{" + strings.Repeat("\xfe\x30", n), strings.Repeat("\ufffd", n*2)},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, wantErr := tc.init(tc.e)
|
||||
|
||||
dst, _, err := transform.String(tr, tc.src)
|
||||
if err != wantErr {
|
||||
t.Errorf("%s %v(%q): got %v; want %v", dir, tc.e, tc.src, err, wantErr)
|
||||
}
|
||||
if got := string(dst); got != tc.want {
|
||||
t.Errorf("%s %v(%q):\ngot %q\nwant %q", dir, tc.e, tc.src, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
// The encoded forms can be verified by the iconv program:
|
||||
// $ echo 月日は百代 | iconv -f UTF-8 -t SHIFT-JIS | xxd
|
||||
testCases := []struct {
|
||||
e encoding.Encoding
|
||||
encPrefix string
|
||||
encoded string
|
||||
utf8 string
|
||||
}{{
|
||||
// "\u0081\u00de\u00df\u00e0\u00e1\u00e2\u00e3\uffff\U00010000" is a
|
||||
// nonsense string that contains GB18030 encodable codepoints of which
|
||||
// only U+00E0 and U+00E1 are GBK encodable.
|
||||
//
|
||||
// "A\u3000\u554a\u4e02\u4e90\u72dc\u7349\u02ca\u2588Z€" is a nonsense
|
||||
// string that contains ASCII and GBK encodable codepoints from Levels
|
||||
// 1-5 as well as the Euro sign.
|
||||
//
|
||||
// "A\u43f0\u4c32\U00027267\u3000\U0002910d\u79d4Z€" is a nonsense string
|
||||
// that contains ASCII and Big5 encodable codepoints from the Basic
|
||||
// Multilingual Plane and the Supplementary Ideographic Plane as well as
|
||||
// the Euro sign.
|
||||
//
|
||||
// "花间一壶酒,独酌无相亲。" (simplified) and
|
||||
// "花間一壺酒,獨酌無相親。" (traditional)
|
||||
// are from the 8th century poem "Yuè Xià Dú Zhuó".
|
||||
e: GB18030,
|
||||
encoded: "\x81\x30\x81\x31\x81\x30\x89\x37\x81\x30\x89\x38\xa8\xa4\xa8\xa2" +
|
||||
"\x81\x30\x89\x39\x81\x30\x8a\x30\x84\x31\xa4\x39\x90\x30\x81\x30",
|
||||
utf8: "\u0081\u00de\u00df\u00e0\u00e1\u00e2\u00e3\uffff\U00010000",
|
||||
}, {
|
||||
e: GB18030,
|
||||
encoded: "\xbb\xa8\xbc\xe4\xd2\xbb\xba\xf8\xbe\xc6\xa3\xac\xb6\xc0\xd7\xc3" +
|
||||
"\xce\xde\xcf\xe0\xc7\xd7\xa1\xa3",
|
||||
utf8: "花间一壶酒,独酌无相亲。",
|
||||
}, {
|
||||
e: GBK,
|
||||
encoded: "A\xa1\xa1\xb0\xa1\x81\x40\x81\x80\xaa\x40\xaa\x80\xa8\x40\xa8\x80Z\x80",
|
||||
utf8: "A\u3000\u554a\u4e02\u4e90\u72dc\u7349\u02ca\u2588Z€",
|
||||
}, {
|
||||
e: GBK,
|
||||
encoded: "\xbb\xa8\xbc\xe4\xd2\xbb\xba\xf8\xbe\xc6\xa3\xac\xb6\xc0\xd7\xc3" +
|
||||
"\xce\xde\xcf\xe0\xc7\xd7\xa1\xa3",
|
||||
utf8: "花间一壶酒,独酌无相亲。",
|
||||
}, {
|
||||
e: HZGB2312,
|
||||
encoded: "A~{\x21\x21~~\x30\x21~}Z~~",
|
||||
utf8: "A\u3000~\u554aZ~",
|
||||
}, {
|
||||
e: HZGB2312,
|
||||
encPrefix: "~{",
|
||||
encoded: ";(<dR;:x>F#,6@WCN^O`GW!#",
|
||||
utf8: "花间一壶酒,独酌无相亲。",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, tc.encPrefix, "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFiles(t *testing.T) {
|
||||
enctest.TestFile(t, GB18030)
|
||||
enctest.TestFile(t, GBK)
|
||||
enctest.TestFile(t, HZGB2312)
|
||||
}
|
||||
|
||||
func BenchmarkEncoding(b *testing.B) {
|
||||
enctest.Benchmark(b, GB18030)
|
||||
enctest.Benchmark(b, GBK)
|
||||
enctest.Benchmark(b, HZGB2312)
|
||||
}
|
||||
269
vendor/golang.org/x/text/encoding/simplifiedchinese/gbk.go
generated
vendored
269
vendor/golang.org/x/text/encoding/simplifiedchinese/gbk.go
generated
vendored
|
|
@ -1,269 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
var (
|
||||
// GB18030 is the GB18030 encoding.
|
||||
GB18030 encoding.Encoding = &gbk18030
|
||||
// GBK is the GBK encoding. It encodes an extension of the GB2312 character set
|
||||
// and is also known as Code Page 936.
|
||||
GBK encoding.Encoding = &gbk
|
||||
)
|
||||
|
||||
var gbk = internal.Encoding{
|
||||
&internal.SimpleEncoding{
|
||||
gbkDecoder{gb18030: false},
|
||||
gbkEncoder{gb18030: false},
|
||||
},
|
||||
"GBK",
|
||||
identifier.GBK,
|
||||
}
|
||||
|
||||
var gbk18030 = internal.Encoding{
|
||||
&internal.SimpleEncoding{
|
||||
gbkDecoder{gb18030: true},
|
||||
gbkEncoder{gb18030: true},
|
||||
},
|
||||
"GB18030",
|
||||
identifier.GB18030,
|
||||
}
|
||||
|
||||
type gbkDecoder struct {
|
||||
transform.NopResetter
|
||||
gb18030 bool
|
||||
}
|
||||
|
||||
func (d gbkDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
|
||||
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
|
||||
// says to treat "gbk" as Code Page 936.
|
||||
case c0 == 0x80:
|
||||
r, size = '€', 1
|
||||
|
||||
case c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case 0x40 <= c1 && c1 < 0x7f:
|
||||
c1 -= 0x40
|
||||
case 0x80 <= c1 && c1 < 0xff:
|
||||
c1 -= 0x41
|
||||
case d.gb18030 && 0x30 <= c1 && c1 < 0x40:
|
||||
if nSrc+3 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
// The second byte here is always ASCII, so we can set size
|
||||
// to 1 in all cases.
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c2 := src[nSrc+2]
|
||||
if c2 < 0x81 || 0xff <= c2 {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c3 := src[nSrc+3]
|
||||
if c3 < 0x30 || 0x3a <= c3 {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
size = 4
|
||||
r = ((rune(c0-0x81)*10+rune(c1-0x30))*126+rune(c2-0x81))*10 + rune(c3-0x30)
|
||||
if r < 39420 {
|
||||
i, j := 0, len(gb18030)
|
||||
for i < j {
|
||||
h := i + (j-i)/2
|
||||
if r >= rune(gb18030[h][0]) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
dec := &gb18030[i-1]
|
||||
r += rune(dec[1]) - rune(dec[0])
|
||||
goto write
|
||||
}
|
||||
r -= 189000
|
||||
if 0 <= r && r < 0x100000 {
|
||||
r += 0x10000
|
||||
} else {
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
goto write
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0-0x81)*190 + int(c1); i < len(decode) {
|
||||
r = rune(decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type gbkEncoder struct {
|
||||
transform.NopResetter
|
||||
gb18030 bool
|
||||
}
|
||||
|
||||
func (e gbkEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, r2, size := rune(0), rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r2 = rune(encode0[r-encode0Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
|
||||
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
|
||||
// says to treat "gbk" as Code Page 936.
|
||||
if r == '€' {
|
||||
r = 0x80
|
||||
goto write1
|
||||
}
|
||||
if r2 = rune(encode1[r-encode1Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r2 = rune(encode2[r-encode2Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r2 = rune(encode3[r-encode3Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r2 = rune(encode4[r-encode4Low]); r2 != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
|
||||
if e.gb18030 {
|
||||
if r < 0x10000 {
|
||||
i, j := 0, len(gb18030)
|
||||
for i < j {
|
||||
h := i + (j-i)/2
|
||||
if r >= rune(gb18030[h][1]) {
|
||||
i = h + 1
|
||||
} else {
|
||||
j = h
|
||||
}
|
||||
}
|
||||
dec := &gb18030[i-1]
|
||||
r += rune(dec[0]) - rune(dec[1])
|
||||
goto write4
|
||||
} else if r < 0x110000 {
|
||||
r += 189000 - 0x10000
|
||||
goto write4
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write1:
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r2 >> 8)
|
||||
dst[nDst+1] = uint8(r2)
|
||||
nDst += 2
|
||||
continue
|
||||
|
||||
write4:
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+3] = uint8(r%10 + 0x30)
|
||||
r /= 10
|
||||
dst[nDst+2] = uint8(r%126 + 0x81)
|
||||
r /= 126
|
||||
dst[nDst+1] = uint8(r%10 + 0x30)
|
||||
r /= 10
|
||||
dst[nDst+0] = uint8(r + 0x81)
|
||||
nDst += 4
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 5 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
||||
245
vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go
generated
vendored
245
vendor/golang.org/x/text/encoding/simplifiedchinese/hzgb2312.go
generated
vendored
|
|
@ -1,245 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package simplifiedchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// HZGB2312 is the HZ-GB2312 encoding.
|
||||
var HZGB2312 encoding.Encoding = &hzGB2312
|
||||
|
||||
var hzGB2312 = internal.Encoding{
|
||||
internal.FuncEncoding{hzGB2312NewDecoder, hzGB2312NewEncoder},
|
||||
"HZ-GB2312",
|
||||
identifier.HZGB2312,
|
||||
}
|
||||
|
||||
func hzGB2312NewDecoder() transform.Transformer {
|
||||
return new(hzGB2312Decoder)
|
||||
}
|
||||
|
||||
func hzGB2312NewEncoder() transform.Transformer {
|
||||
return new(hzGB2312Encoder)
|
||||
}
|
||||
|
||||
const (
|
||||
asciiState = iota
|
||||
gbState
|
||||
)
|
||||
|
||||
type hzGB2312Decoder int
|
||||
|
||||
func (d *hzGB2312Decoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (d *hzGB2312Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
c0 := src[nSrc]
|
||||
if c0 >= utf8.RuneSelf {
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
|
||||
if c0 == '~' {
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r = utf8.RuneError
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
switch src[nSrc+1] {
|
||||
case '{':
|
||||
*d = gbState
|
||||
continue
|
||||
case '}':
|
||||
*d = asciiState
|
||||
continue
|
||||
case '~':
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
dst[nDst] = '~'
|
||||
nDst++
|
||||
continue
|
||||
case '\n':
|
||||
continue
|
||||
default:
|
||||
r = utf8.RuneError
|
||||
goto write
|
||||
}
|
||||
}
|
||||
|
||||
if *d == asciiState {
|
||||
r, size = rune(c0), 1
|
||||
} else {
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
size = 2
|
||||
c1 := src[nSrc+1]
|
||||
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
|
||||
// error
|
||||
} else if i := int(c0-0x01)*190 + int(c1+0x3f); i < len(decode) {
|
||||
r = rune(decode[i])
|
||||
if r != 0 {
|
||||
goto write
|
||||
}
|
||||
}
|
||||
if c1 > utf8.RuneSelf {
|
||||
// Be consistent and always treat non-ASCII as a single error.
|
||||
size = 1
|
||||
}
|
||||
r = utf8.RuneError
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type hzGB2312Encoder int
|
||||
|
||||
func (d *hzGB2312Encoder) Reset() {
|
||||
*d = asciiState
|
||||
}
|
||||
|
||||
func (e *hzGB2312Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
if r == '~' {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '~'
|
||||
nDst += 2
|
||||
continue
|
||||
} else if *e != asciiState {
|
||||
if nDst+3 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = asciiState
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '}'
|
||||
nDst += 2
|
||||
} else if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst += 1
|
||||
continue
|
||||
|
||||
}
|
||||
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto writeGB
|
||||
}
|
||||
}
|
||||
|
||||
terminateInASCIIState:
|
||||
// Switch back to ASCII state in case of error so that an ASCII
|
||||
// replacement character can be written in the correct state.
|
||||
if *e != asciiState {
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '}'
|
||||
nDst += 2
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
|
||||
writeGB:
|
||||
c0 := uint8(r>>8) - 0x80
|
||||
c1 := uint8(r) - 0x80
|
||||
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
|
||||
goto terminateInASCIIState
|
||||
}
|
||||
if *e == asciiState {
|
||||
if nDst+4 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
*e = gbState
|
||||
dst[nDst+0] = '~'
|
||||
dst[nDst+1] = '{'
|
||||
nDst += 2
|
||||
} else if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = c0
|
||||
dst[nDst+1] = c1
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
// TODO: should one always terminate in ASCII state to make it safe to
|
||||
// concatenate two HZ-GB2312-encoded strings?
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
161
vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go
generated
vendored
161
vendor/golang.org/x/text/encoding/simplifiedchinese/maketables.go
generated
vendored
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This program generates tables.go:
|
||||
// go run maketables.go | gofmt > tables.go
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n")
|
||||
fmt.Printf("// Package simplifiedchinese provides Simplified Chinese encodings such as GBK.\n")
|
||||
fmt.Printf(`package simplifiedchinese // import "golang.org/x/text/encoding/simplifiedchinese"` + "\n\n")
|
||||
|
||||
printGB18030()
|
||||
printGBK()
|
||||
}
|
||||
|
||||
func printGB18030() {
|
||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-gb18030.txt")
|
||||
if err != nil {
|
||||
log.Fatalf("Get: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
fmt.Printf("// gb18030 is the table from http://encoding.spec.whatwg.org/index-gb18030.txt\n")
|
||||
fmt.Printf("var gb18030 = [...][2]uint16{\n")
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := uint32(0), uint32(0)
|
||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("could not parse %q", s)
|
||||
}
|
||||
if x < 0x10000 && y < 0x10000 {
|
||||
fmt.Printf("\t{0x%04x, 0x%04x},\n", x, y)
|
||||
}
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func printGBK() {
|
||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-gbk.txt")
|
||||
if err != nil {
|
||||
log.Fatalf("Get: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := [65536]uint16{}
|
||||
reverse := [65536]uint16{}
|
||||
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := uint16(0), uint16(0)
|
||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("could not parse %q", s)
|
||||
}
|
||||
if x < 0 || 126*190 <= x {
|
||||
log.Fatalf("GBK code %d is out of range", x)
|
||||
}
|
||||
mapping[x] = y
|
||||
if reverse[y] == 0 {
|
||||
c0, c1 := x/190, x%190
|
||||
if c1 >= 0x3f {
|
||||
c1++
|
||||
}
|
||||
reverse[y] = (0x81+c0)<<8 | (0x40 + c1)
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatalf("scanner error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("// decode is the decoding table from GBK code to Unicode.\n")
|
||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-gbk.txt\n")
|
||||
fmt.Printf("var decode = [...]uint16{\n")
|
||||
for i, v := range mapping {
|
||||
if v != 0 {
|
||||
fmt.Printf("\t%d: 0x%04X,\n", i, v)
|
||||
}
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
|
||||
// Any run of at least separation continuous zero entries in the reverse map will
|
||||
// be a separate encode table.
|
||||
const separation = 1024
|
||||
|
||||
intervals := []interval(nil)
|
||||
low, high := -1, -1
|
||||
for i, v := range reverse {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
if low < 0 {
|
||||
low = i
|
||||
} else if i-high >= separation {
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
low = i
|
||||
}
|
||||
high = i + 1
|
||||
}
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
sort.Sort(byDecreasingLength(intervals))
|
||||
|
||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals))
|
||||
fmt.Printf("// encodeX are the encoding tables from Unicode to GBK code,\n")
|
||||
fmt.Printf("// sorted by decreasing length.\n")
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("// encode%d: %5d entries for runes in [%5d, %5d).\n", i, v.len(), v.low, v.high)
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high)
|
||||
fmt.Printf("var encode%d = [...]uint16{\n", i)
|
||||
for j := v.low; j < v.high; j++ {
|
||||
x := reverse[j]
|
||||
if x == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x)
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
// interval is a half-open interval [low, high).
|
||||
type interval struct {
|
||||
low, high int
|
||||
}
|
||||
|
||||
func (i interval) len() int { return i.high - i.low }
|
||||
|
||||
// byDecreasingLength sorts intervals by decreasing length.
|
||||
type byDecreasingLength []interval
|
||||
|
||||
func (b byDecreasingLength) Len() int { return len(b) }
|
||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() }
|
||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
43999
vendor/golang.org/x/text/encoding/simplifiedchinese/tables.go
generated
vendored
43999
vendor/golang.org/x/text/encoding/simplifiedchinese/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
510
vendor/golang.org/x/text/encoding/testdata/candide-gb18030.txt
generated
vendored
510
vendor/golang.org/x/text/encoding/testdata/candide-gb18030.txt
generated
vendored
|
|
@ -1,510 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/4650/pg4650.txt
|
||||
--------
|
||||
|
||||
CANDIDE,
|
||||
|
||||
ou
|
||||
|
||||
L'OPTIMISME,
|
||||
|
||||
TRADUIT DE L'ALLEMAND
|
||||
|
||||
DE M. LE DOCTEUR RALPH,
|
||||
|
||||
AVEC LES ADDITIONS
|
||||
|
||||
QU'ON A TROUV<55>0‡7ES DANS LA POCHE DU DOCTEUR, LORSQU'IL MOURUT
|
||||
|
||||
<20>0†8 MINDEN, L'AN DE GR<47>0‡0CE 1759
|
||||
|
||||
1759
|
||||
|
||||
|
||||
|
||||
CHAPITRE I.
|
||||
|
||||
Comment Candide fut ¨¦lev¨¦ dans un beau ch<63>0‰9teau, et comment il fut
|
||||
chass¨¦ d'icelui.
|
||||
|
||||
Il y avait en Vestphalie, dans le ch<63>0‰9teau de M. le baron de
|
||||
Thunder-ten-tronckh, un jeune gar<61>0Š4on ¨¤ qui la nature avait donn¨¦
|
||||
les moeurs les plus douces. Sa physionomie annon<6F>0Š4ait son <20>0‰9me.
|
||||
Il avait le jugement assez droit, avec l'esprit le plus simple;
|
||||
c'est, je crois, pour cette raison qu'on le nommait Candide. Les
|
||||
anciens domestiques de la maison soup<75>0Š4onnaient qu'il ¨¦tait fils
|
||||
de la soeur de monsieur le baron et d'un bon et honn¨ºte
|
||||
gentilhomme du voisinage, que cette demoiselle ne voulut jamais
|
||||
¨¦pouser parce qu'il n'avait pu prouver que soixante et onze
|
||||
quartiers, et que le reste de son arbre g¨¦n¨¦alogique avait ¨¦t¨¦
|
||||
perdu par l'injure du temps.
|
||||
|
||||
Monsieur le baron ¨¦tait un des plus puissants seigneurs de la
|
||||
Westphalie, car son ch<63>0‰9teau avait une porte et des fen¨ºtres. Sa
|
||||
grande salle m¨ºme ¨¦tait orn¨¦e d'une tapisserie. Tous les chiens
|
||||
de ses basses-cours composaient une meute dans le besoin; ses
|
||||
palefreniers ¨¦taient ses piqueurs; le vicaire du village ¨¦tait
|
||||
son grand-aum<75>0‹0nier. Ils l'appelaient tous monseigneur, et ils
|
||||
riaient quand il fesait des contes.
|
||||
|
||||
Madame la baronne, qui pesait environ trois cent cinquante
|
||||
livres, s'attirait par l¨¤ une tr¨¨s grande consid¨¦ration, et
|
||||
fesait les honneurs de la maison avec une dignit¨¦ qui la rendait
|
||||
encore plus respectable. Sa fille Cun¨¦gonde, <20>0‰9g¨¦e de dix-sept
|
||||
ans, ¨¦tait haute en couleur, fra<72>0Š6che, grasse, app¨¦tissante. Le
|
||||
fils du baron paraissait en tout digne de son p¨¨re. Le
|
||||
pr¨¦cepteur Pangloss[1] ¨¦tait l'oracle de la maison, et le petit
|
||||
Candide ¨¦coutait ses le<6C>0Š4ons avec toute la bonne foi de son <20>0‰9ge et
|
||||
de son caract¨¨re.
|
||||
|
||||
[1] De _pan_, tout, et _glossa_, langue. B.
|
||||
|
||||
|
||||
Pangloss enseignait la m¨¦taphysico-th¨¦ologo-cosmolonigologie. Il
|
||||
prouvait admirablement qu'il n'y a point d'effet sans cause, et
|
||||
que, dans ce meilleur des mondes possibles, le ch<63>0‰9teau de
|
||||
monseigneur le baron ¨¦tait le plus beau des ch<63>0‰9teaux, et madame
|
||||
la meilleure des baronnes possibles.
|
||||
|
||||
Il est d¨¦montr¨¦, disait-il, que les choses ne peuvent ¨ºtre
|
||||
autrement; car tout ¨¦tant fait pour une fin, tout est
|
||||
n¨¦cessairement pour la meilleure fin. Remarquez bien que les nez
|
||||
ont ¨¦t¨¦ faits pour porter des lunettes; aussi avons-nous des
|
||||
lunettes[2]. Les jambes sont visiblement institu¨¦es pour ¨ºtre
|
||||
chauss¨¦es, et nous avons des chausses. Les pierres ont ¨¦t¨¦
|
||||
form¨¦es pour ¨ºtre taill¨¦es et pour en faire des ch<63>0‰9teaux; aussi
|
||||
monseigneur a un tr¨¨s beau ch<63>0‰9teau: le plus grand baron de la
|
||||
province doit ¨ºtre le mieux log¨¦; et les cochons ¨¦tant faits pour
|
||||
¨ºtre mang¨¦s, nous mangeons du porc toute l'ann¨¦e: par cons¨¦quent,
|
||||
ceux qui ont avanc¨¦ que tout est bien ont dit une sottise; il
|
||||
fallait dire que tout est au mieux.
|
||||
|
||||
[2] Voyez tome XXVII, page 528; et dans les _M¨¦langes_, ann¨¦e
|
||||
1738, le chapitre XI de la troisi¨¨me partie des _<>0‡7l¨¦ments de la
|
||||
philosophie de Newton_; et ann¨¦e 1768, le chapitre X des
|
||||
_Singularit¨¦s de la nature_. B.
|
||||
|
||||
|
||||
Candide ¨¦coutait attentivement, et croyait innocemment; car il
|
||||
trouvait mademoiselle Cun¨¦gonde extr¨ºmement belle, quoiqu'il ne
|
||||
pr<EFBFBD>0Š6t jamais la hardiesse de le lui dire. Il concluait qu'apr¨¨s
|
||||
le bonheur d'¨ºtre n¨¦ baron de Thunder-ten-tronckh, le second
|
||||
degr¨¦ de bonheur ¨¦tait d'¨ºtre mademoiselle Cun¨¦gonde; le
|
||||
troisi¨¨me, de la voir tous les jours; et le quatri¨¨me, d'entendre
|
||||
ma<EFBFBD>0Š6tre Pangloss, le plus grand philosophe de la province, et par
|
||||
cons¨¦quent de toute la terre.
|
||||
|
||||
Un jour Cun¨¦gonde, en se promenant aupr¨¨s du ch<63>0‰9teau, dans le
|
||||
petit bois qu'on appelait parc, vit entre des broussailles le
|
||||
docteur Pangloss qui donnait une le<6C>0Š4on de physique exp¨¦rimentale
|
||||
¨¤ la femme de chambre de sa m¨¨re, petite brune tr¨¨s jolie et tr¨¨s
|
||||
docile. Comme mademoiselle Cun¨¦gonde avait beaucoup de
|
||||
disposition pour les sciences, elle observa, sans souffler, les
|
||||
exp¨¦riences r¨¦it¨¦r¨¦es dont elle fut t¨¦moin; elle vit clairement
|
||||
la raison suffisante du docteur, les effets et les causes, et
|
||||
s'en retourna tout agit¨¦e, toute pensive, toute remplie du d¨¦sir
|
||||
d'¨ºtre savante, songeant qu'elle pourrait bien ¨ºtre la raison
|
||||
suffisante du jeune Candide, qui pouvait aussi ¨ºtre la sienne.
|
||||
|
||||
Elle rencontra Candide en revenant au ch<63>0‰9teau, et rougit: Candide
|
||||
rougit aussi . Elle lui dit bonjour d'une voix entrecoup¨¦e; et
|
||||
Candide lui parla sans savoir ce qu'il disait. Le lendemain,
|
||||
apr¨¨s le d<>0Š6ner, comme on sortait de table, Cun¨¦gonde et Candide
|
||||
se trouv¨¨rent derri¨¨re un paravent; Cun¨¦gonde laissa tomber son
|
||||
mouchoir, Candide le ramassa; elle lui prit innocemment la main;
|
||||
le jeune homme baisa innocemment la main de la jeune demoiselle
|
||||
avec une vivacit¨¦, une sensibilit¨¦, une gr<67>0‰9ce toute particuli¨¨re;
|
||||
leurs bouches se rencontr¨¨rent, leurs yeux s'enflamm¨¨rent, leurs
|
||||
genoux trembl¨¨rent, leurs mains s'¨¦gar¨¨rent. M. le baron de
|
||||
Thunder-ten-tronckh passa aupr¨¨s du paravent, et voyant cette
|
||||
cause et cet effet, chassa Candide du ch<63>0‰9teau ¨¤ grands coups de
|
||||
pied dans le derri¨¨re. Cun¨¦gonde s'¨¦vanouit: elle fut soufflet¨¦e
|
||||
par madame la baronne d¨¨s qu'elle fut revenue ¨¤ elle-m¨ºme; et
|
||||
tout fut constern¨¦ dans le plus beau et le plus agr¨¦able des
|
||||
ch<EFBFBD>0‰9teaux possibles.
|
||||
|
||||
|
||||
|
||||
CHAPITRE II
|
||||
|
||||
Ce que devint Candide parmi les Bulgares.
|
||||
|
||||
|
||||
Candide, chass¨¦ du paradis terrestre, marcha longtemps sans
|
||||
savoir o¨´, pleurant, levant les yeux au ciel, les tournant
|
||||
souvent vers le plus beau des ch<63>0‰9teaux qui renfermait la plus
|
||||
belle des baronnettes; il se coucha sans souper au milieu des
|
||||
champs entre deux sillons; la neige tombait ¨¤ gros flocons.
|
||||
Candide, tout transi, se tra<72>0Š6na le lendemain vers la ville
|
||||
voisine, qui s'appelle _Valdberghoff-trarbk-dikdorff_, n'ayant
|
||||
point d'argent, mourant de faim et de lassitude. Il s'arr¨ºta
|
||||
tristement ¨¤ la porte d'un cabaret. Deux hommes habill¨¦s de bleu
|
||||
le remarqu¨¨rent: Camarade, dit l'un, voil¨¤ un jeune homme tr¨¨s
|
||||
bien fait, et qui a la taille requise; ils s'avanc¨¨rent vers
|
||||
Candide et le pri¨¨rent ¨¤ d<>0Š6ner tr¨¨s civilement.--Messieurs, leur
|
||||
dit Candide avec une modestie charmante, vous me faites beaucoup
|
||||
d'honneur, mais je n'ai pas de quoi payer mon ¨¦cot.--Ah!
|
||||
monsieur, lui dit un des bleus, les personnes de votre figure et
|
||||
de votre m¨¦rite ne paient jamais rien: n'avez-vous pas cinq pieds
|
||||
cinq pouces de haut?--Oui, messieurs, c'est ma taille, dit-il en
|
||||
fesant la r¨¦v¨¦rence.--Ah! monsieur, mettez-vous ¨¤ table; non
|
||||
seulement nous vous d¨¦fraierons, mais nous ne souffrirons jamais
|
||||
qu'un homme comme vous manque d'argent; les hommes ne sont faits
|
||||
que pour se secourir les uns les autres.--Vous avez raison, dit
|
||||
Candide; c'est ce que M. Pangloss m'a toujours dit, et je vois
|
||||
bien que tout est au mieux. On le prie d'accepter quelques ¨¦cus,
|
||||
il les prend et veut faire son billet; on n'en veut point, on se
|
||||
met ¨¤ table. N'aimez-vous pas tendrement?....--Oh! oui,
|
||||
r¨¦pond-il, j'aime tendrement mademoiselle Cun¨¦gonde.--Non, dit
|
||||
l'un de ces messieurs, nous vous demandons si vous n'aimez pas
|
||||
tendrement le roi des Bulgares?--Point du tout, dit-il, car je ne
|
||||
l'ai jamais vu.--Comment! c'est le plus charmant des rois, et il
|
||||
faut boire ¨¤ sa sant¨¦.--Oh! tr¨¨s volontiers, messieurs. Et il
|
||||
boit. C'en est assez, lui dit-on, vous voil¨¤ l'appui, le
|
||||
soutien, le d¨¦fenseur, le h¨¦ros des Bulgares; votre fortune est
|
||||
faite, et votre gloire est assur¨¦e. On lui met sur-le-champ les
|
||||
fers aux pieds, et on le m¨¨ne au r¨¦giment. On le fait tourner ¨¤
|
||||
droite, ¨¤ gauche, hausser la baguette, remettre la baguette,
|
||||
coucher en joue, tirer, doubler le pas, et on lui donne trente
|
||||
coups de b<>0‰9ton; le lendemain, il fait l'exercice un peu moins
|
||||
mal, et il ne re<72>0Š4oit que vingt coups; le surlendemain, on ne lui
|
||||
en donne que dix, et il est regard¨¦ par ses camarades comme un
|
||||
prodige.
|
||||
|
||||
Candide, tout stup¨¦fait, ne d¨¦m¨ºlait pas encore trop bien comment
|
||||
il ¨¦tait un h¨¦ros. Il s'avisa un beau jour de printemps de
|
||||
s'aller promener, marchant tout droit devant lui, croyant que
|
||||
c'¨¦tait un privil¨¨ge de l'esp¨¨ce humaine, comme de l'esp¨¨ce
|
||||
animale, de se servir de ses jambes ¨¤ son plaisir. Il n'eut pas
|
||||
fait deux lieues que voil¨¤ quatre autres h¨¦ros de six pieds qui
|
||||
l'atteignent, qui le lient, qui le m¨¨nent dans un cachot. On lui
|
||||
demanda juridiquement ce qu'il aimait le mieux d'¨ºtre fustig¨¦
|
||||
trente-six fois par tout le r¨¦giment, ou de recevoir ¨¤-la-fois
|
||||
douze balles de plomb dans la cervelle. Il eut beau dire que les
|
||||
volont¨¦s sont libres, et qu'il ne voulait ni l'un ni l'autre, il
|
||||
fallut faire un choix; il se d¨¦termina, en vertu du don de Dieu
|
||||
qu'on nomme _libert¨¦_, ¨¤ passer trente-six fois par les
|
||||
baguettes; il essuya deux promenades. Le r¨¦giment ¨¦tait compos¨¦
|
||||
de deux mille hommes; cela lui composa quatre mille coups de
|
||||
baguette, qui, depuis la nuque du cou jusqu'au cul, lui
|
||||
d¨¦couvrirent les muscles et les nerfs. Comme on allait proc¨¦der
|
||||
¨¤ la troisi¨¨me course, Candide, n'en pouvant plus, demanda en
|
||||
gr<EFBFBD>0‰9ce qu'on voul<75>0‹4t bien avoir la bont¨¦ de lui casser la t¨ºte; il
|
||||
obtint cette faveur; on lui bande les yeux; on le fait mettre ¨¤
|
||||
genoux. Le roi des Bulgares passe dans ce moment, s'informe du
|
||||
crime du patient; et comme ce roi avait un grand g¨¦nie, il
|
||||
comprit, par tout ce qu'il apprit de Candide, que c'¨¦tait un
|
||||
jeune m¨¦taphysicien fort ignorant des choses de ce monde, et il
|
||||
lui accorda sa gr<67>0‰9ce avec une cl¨¦mence qui sera lou¨¦e dans tous
|
||||
les journaux et dans tous les si¨¨cles. Un brave chirurgien
|
||||
gu¨¦rit Candide en trois semaines avec les ¨¦mollients enseign¨¦s
|
||||
par Dioscoride. Il avait d¨¦j¨¤ un peu de peau et pouvait marcher,
|
||||
quand le roi des Bulgares livra bataille au roi des Abares.
|
||||
|
||||
|
||||
|
||||
CHAPITRE III.
|
||||
|
||||
Comment Candide se sauva d'entre les Bulgares, et ce qu'il
|
||||
devint.
|
||||
|
||||
|
||||
Rien n'¨¦tait si beau, si leste, si brillant, si bien ordonn¨¦ que
|
||||
les deux arm¨¦es. Les trompettes, les fifres, les hautbois, les
|
||||
tambours, les canons; formaient une harmonie telle qu'il n'y en
|
||||
eut jamais en enfer. Les canons renvers¨¨rent d'abord ¨¤ peu pr¨¨s
|
||||
six mille hommes de chaque c<>0‹0t¨¦; ensuite la mousqueterie <20>0‹0ta du
|
||||
meilleur des mondes environ neuf ¨¤ dix mille coquins qui en
|
||||
infectaient la surface. La ba<62>0Š7onnette fut aussi la raison
|
||||
suffisante de la mort de quelques milliers d'hommes. Le tout
|
||||
pouvait bien se monter ¨¤ une trentaine de mille <20>0‰9mes. Candide,
|
||||
qui tremblait comme un philosophe, se cacha du mieux qu'il put
|
||||
pendant cette boucherie h¨¦ro<72>0Š7que.
|
||||
|
||||
Enfin, tandis que les deux rois fesaient chanter des _Te Deum_,
|
||||
chacun dans son camp, il prit le parti d'aller raisonner ailleurs
|
||||
des effets et des causes. Il passa par-dessus des tas de morts
|
||||
et de mourants, et gagna d'abord un village voisin; il ¨¦tait en
|
||||
cendres: c'¨¦tait un village abare que les Bulgares avaient br<62>0‹4l¨¦,
|
||||
selon les lois du droit public. Ici des vieillards cribl¨¦s de
|
||||
coups regardaient mourir leurs femmes ¨¦gorg¨¦es, qui tenaient
|
||||
leurs enfants ¨¤ leurs mamelles sanglantes; l¨¤ des filles
|
||||
¨¦ventr¨¦es apr¨¨s avoir assouvi les besoins naturels de quelques
|
||||
h¨¦ros, rendaient les derniers soupirs; d'autres ¨¤ demi br<62>0‹4l¨¦es
|
||||
criaient qu'on achev<65>0‰9t de leur donner la mort. Des cervelles
|
||||
¨¦taient r¨¦pandues sur la terre ¨¤ c<>0‹0t¨¦ de bras et de jambes
|
||||
coup¨¦s.
|
||||
|
||||
Candide s'enfuit au plus vite dans un autre village: il
|
||||
appartenait ¨¤ des Bulgares, et les h¨¦ros abares l'avaient trait¨¦
|
||||
de m¨ºme. Candide, toujours marchant sur des membres palpitants
|
||||
ou ¨¤ travers des ruines, arriva enfin hors du th¨¦<C2A8>0‰9tre de la
|
||||
guerre, portant quelques petites provisions dans son bissac, et
|
||||
n'oubliant jamais mademoiselle Cun¨¦gonde. Ses provisions lui
|
||||
manqu¨¨rent quand il fut en Hollande; mais ayant entendu dire que
|
||||
tout le monde ¨¦tait riche dans ce pays-l¨¤, et qu'on y ¨¦tait
|
||||
chr¨¦tien, il ne douta pas qu'on ne le trait<69>0‰9t aussi bien qu'il
|
||||
l'avait ¨¦t¨¦ dans le ch<63>0‰9teau de M. le baron, avant qu'il en e<>0‹4t
|
||||
¨¦t¨¦ chass¨¦ pour les beaux yeux de mademoiselle Cun¨¦gonde.
|
||||
|
||||
Il demanda l'aum<75>0‹0ne ¨¤ plusieurs graves personnages, qui lui
|
||||
r¨¦pondirent tous que, s'il continuait ¨¤ faire ce m¨¦tier, on
|
||||
l'enfermerait dans une maison de correction pour lui apprendre ¨¤
|
||||
vivre.
|
||||
|
||||
Il s'adressa ensuite ¨¤ un homme qui venait de parler tout seul
|
||||
une heure de suite sur la charit¨¦ dans une grande assembl¨¦e. Cet
|
||||
orateur le regardant de travers lui dit: Que venez-vous faire
|
||||
ici? y ¨ºtes-vous pour la bonne cause? Il n'y a point d'effet sans
|
||||
cause, r¨¦pondit modestement Candide; tout est encha<68>0Š6n¨¦
|
||||
n¨¦cessairement et arrang¨¦ pour le mieux. Il a fallu que je fusse
|
||||
chass¨¦ d'aupr¨¨s de mademoiselle Cun¨¦gonde, que j'aie pass¨¦ par
|
||||
les baguettes, et il faut que je demande mon pain, jusqu'¨¤ ce que
|
||||
je puisse en gagner; tout cela ne pouvait ¨ºtre autrement. Mon
|
||||
ami, lui dit l'orateur, croyez-vous que le pape soit
|
||||
l'antechrist? Je ne l'avais pas encore entendu dire, r¨¦pondit
|
||||
Candide: mais qu'il le soit, ou qu'il ne le soit pas, je manque
|
||||
de pain. Tu ne m¨¦rites pas d'en manger, dit l'autre: va, coquin,
|
||||
va, mis¨¦rable, ne m'approche de ta vie. La femme de l'orateur
|
||||
ayant mis la t¨ºte ¨¤ la fen¨ºtre, et avisant un homme qui doutait
|
||||
que le pape f<>0‹4t antechrist, lui r¨¦pandit sur le chef un
|
||||
plein..... O ciel! ¨¤ quel exc¨¨s se porte le z¨¨le de la religion
|
||||
dans les dames!
|
||||
|
||||
Un homme qui n'avait point ¨¦t¨¦ baptis¨¦, un bon anabaptiste, nomm¨¦
|
||||
Jacques, vit la mani¨¨re cruelle et ignominieuse dont on traitait
|
||||
ainsi un de ses fr¨¨res, un ¨ºtre ¨¤ deux pieds sans plumes, qui
|
||||
avait une <20>0‰9me; il l'amena chez lui, le nettoya, lui donna du pain
|
||||
et de la bi¨¨re, lui fit pr¨¦sent de deux florins, et voulut m¨ºme
|
||||
lui apprendre ¨¤ travailler dans ses manufactures aux ¨¦toffes de
|
||||
Perse qu'on fabrique en Hollande. Candide se prosternant presque
|
||||
devant lui, s'¨¦criait: Ma<4D>0Š6tre Pangloss me l'avait bien dit que
|
||||
tout est au mieux dans ce monde, car je suis infiniment plus
|
||||
touch¨¦ de votre extr¨ºme g¨¦n¨¦rosit¨¦ que de la duret¨¦ de ce
|
||||
monsieur ¨¤ manteau noir, et de madame son ¨¦pouse.
|
||||
|
||||
Le lendemain, en se promenant, il rencontra un gueux tout couvert
|
||||
de pustules, les yeux morts, le bout du nez rong¨¦, la bouche de
|
||||
travers, les dents noires, et parlant de la gorge, tourment¨¦
|
||||
d'une toux violente, et crachant une dent ¨¤ chaque effort.
|
||||
|
||||
|
||||
|
||||
CHAPITRE IV.
|
||||
|
||||
Comment Candide rencontra son ancien ma<6D>0Š6tre de philosophie, le
|
||||
docteur Pangloss, et ce qui en advint.
|
||||
|
||||
|
||||
Candide, plus ¨¦mu encore de compassion que d'horreur, donna ¨¤ cet
|
||||
¨¦pouvantable gueux les deux florins qu'il avait re<72>0Š4us de son
|
||||
honn¨ºte anabaptiste Jacques. Le fant<6E>0‹0me le regarda fixement,
|
||||
versa des larmes, et sauta ¨¤ son cou. Candide effray¨¦ recule.
|
||||
H¨¦las! dit le mis¨¦rable ¨¤ l'autre mis¨¦rable, ne reconnaissez-vous
|
||||
plus votre cher Pangloss? Qu'entends-je? vous, mon cher ma<6D>0Š6tre!
|
||||
vous, dans cet ¨¦tat horrible! quel malheur vous est-il donc
|
||||
arriv¨¦? pourquoi n'¨ºtes-vous plus dans le plus beau des ch<63>0‰9teaux?
|
||||
qu'est devenue mademoiselle Cun¨¦gonde, la perle des filles, le
|
||||
chef-d'oeuvre de la nature? Je n'en peux plus, dit Pangloss.
|
||||
Aussit<EFBFBD>0‹0t Candide le mena dans l'¨¦table de l'anabaptiste, o¨´ il
|
||||
lui fit manger un peu de pain; et quand Pangloss fut refait: Eh
|
||||
bien! lui dit-il, Cun¨¦gonde? Elle est morte, reprit l'autre.
|
||||
Candide s'¨¦vanouit ¨¤ ce mot: son ami rappela ses sens avec un peu
|
||||
de mauvais vinaigre qui se trouva par hasard dans l'¨¦table.
|
||||
Candide rouvre les yeux. Cun¨¦gonde est morte! Ah! meilleur des
|
||||
mondes, o¨´ ¨ºtes-vous? Mais de quelle maladie est-elle morte? ne
|
||||
serait-ce point de m'avoir vu chasser du beau ch<63>0‰9teau de monsieur
|
||||
son p¨¨re ¨¤ grands coups de pied? Non, dit Pangloss, elle a ¨¦t¨¦
|
||||
¨¦ventr¨¦e par des soldats bulgares, apr¨¨s avoir ¨¦t¨¦ viol¨¦e autant
|
||||
qu'on peut l'¨ºtre; ils ont cass¨¦ la t¨ºte ¨¤ monsieur le baron qui
|
||||
voulait la d¨¦fendre; madame la baronne a ¨¦t¨¦ coup¨¦e en morceaux;
|
||||
mon pauvre pupille trait¨¦ pr¨¦cis¨¦ment comme sa soeur; et quant au
|
||||
ch<EFBFBD>0‰9teau, il n'est pas rest¨¦ pierre sur pierre, pas une grange,
|
||||
pas un mouton, pas un canard, pas un arbre; mais nous avons ¨¦t¨¦
|
||||
bien veng¨¦s, car les Abares en ont fait autant dans une baronnie
|
||||
voisine qui appartenait ¨¤ un seigneur bulgare.
|
||||
|
||||
A ce discours, Candide s'¨¦vanouit encore; mais revenu ¨¤ soi, et
|
||||
ayant dit tout ce qu'il devait dire, il s'enquit de la cause et
|
||||
de l'effet, et de la raison suffisante qui avait mis Pangloss
|
||||
dans un si piteux ¨¦tat. H¨¦las! dit l'autre, c'est l'amour:
|
||||
l'amour, le consolateur du genre humain, le conservateur de
|
||||
l'univers, l'<27>0‰9me de tous les ¨ºtres sensibles, le tendre amour.
|
||||
H¨¦las! dit Candide, je l'ai connu cet amour, ce souverain des
|
||||
coeurs, cette <20>0‰9me de notre <20>0‰9me; il ne m'a jamais valu qu'un
|
||||
baiser et vingt coups de pied au cul. Comment cette belle cause
|
||||
a-t-elle pu produire en vous un effet si abominable?
|
||||
|
||||
Pangloss r¨¦pondit en ces termes: O mon cher Candide! vous avez
|
||||
connu Paquette, cette jolie suivante de notre auguste baronne:
|
||||
j'ai go<67>0‹4t¨¦ dans ses bras les d¨¦lices du paradis, qui ont produit
|
||||
ces tourments d'enfer dont vous me voyez d¨¦vor¨¦; elle en ¨¦tait
|
||||
infect¨¦e, elle en est peut-¨ºtre morte. Paquette tenait ce
|
||||
pr¨¦sent d'un cordelier tr¨¨s savant qui avait remont¨¦ ¨¤ la source,
|
||||
car il l'avait eu d'une vieille comtesse, qui l'avait re<72>0Š4u d'un
|
||||
capitaine de cavalerie, qui le devait ¨¤ une marquise, qui le
|
||||
tenait d'un page, qui l'avait re<72>0Š4u d'un j¨¦suite, qui, ¨¦tant
|
||||
novice, l'avait eu en droite ligne d'un des compagnons de
|
||||
Christophe Colomb. Pour moi, je ne le donnerai ¨¤ personne, car
|
||||
je me meurs.
|
||||
|
||||
O Pangloss! s'¨¦cria Candide, voil¨¤ une ¨¦trange g¨¦n¨¦alogie!
|
||||
n'est-ce pas le diable qui en fut la souche? Point du tout,
|
||||
r¨¦pliqua ce grand homme; c'¨¦tait une chose indispensable dans le
|
||||
meilleur des mondes, un ingr¨¦dient n¨¦cessaire; car si Colomb
|
||||
n'avait pas attrap¨¦ dans une <20>0Š6le de l'Am¨¦rique cette maladie[1]
|
||||
qui empoisonne la source de la g¨¦n¨¦ration, qui souvent m¨ºme
|
||||
emp¨ºche la g¨¦n¨¦ration, et qui est ¨¦videmment l'oppos¨¦ du grand
|
||||
but de la nature, nous n'aurions ni le chocolat ni la cochenille;
|
||||
il faut encore observer que jusqu'aujourd'hui, dans notre
|
||||
continent, cette maladie nous est particuli¨¨re, comme la
|
||||
controverse. Les Turcs, les Indiens, les Persans, les Chinois,
|
||||
les Siamois, les Japonais, ne la connaissent pas encore; mais il
|
||||
y a une raison suffisante pour qu'ils la connaissent ¨¤ leur tour
|
||||
dans quelques si¨¨cles. En attendant elle a fait un merveilleux
|
||||
progr¨¨s parmi nous, et surtout dans ces grandes arm¨¦es compos¨¦es
|
||||
d'honn¨ºtes stipendiaires bien ¨¦lev¨¦s, qui d¨¦cident du destin des
|
||||
¨¦tats; on peut assurer que, quand trente mille hommes combattent
|
||||
en bataille rang¨¦e contre des troupes ¨¦gales en nombre, il y a
|
||||
environ vingt mille v¨¦rol¨¦s de chaque c<>0‹0t¨¦.
|
||||
|
||||
[1] Voyez tome XXXI, page 7. B.
|
||||
|
||||
|
||||
Voil¨¤ qui est admirable, dit Candide; mais il faut vous faire
|
||||
gu¨¦rir. Et comment le puis-je? dit Pangloss; je n'ai pas le sou,
|
||||
mon ami, et dans toute l'¨¦tendue de ce globe on ne peut ni se
|
||||
faire saigner, ni prendre un lavement sans payer, ou sans qu'il y
|
||||
ait quelqu'un qui paie pour nous.
|
||||
|
||||
Ce dernier discours d¨¦termina Candide; il alla se jeter aux pieds
|
||||
de son charitable anabaptiste Jacques, et lui fit une peinture si
|
||||
touchante de l'¨¦tat o¨´ son ami ¨¦tait r¨¦duit, que le bon-homme
|
||||
n'h¨¦sita pas ¨¤ recueillir le docteur Pangloss; il le fit gu¨¦rir ¨¤
|
||||
ses d¨¦pens. Pangloss, dans la cure, ne perdit qu'un oeil et une
|
||||
oreille. Il ¨¦crivait bien, et savait parfaitement
|
||||
l'arithm¨¦tique. L'anabaptiste Jacques en fit son teneur de
|
||||
livres. Au bout de deux mois, ¨¦tant oblig¨¦ d'aller ¨¤ Lisbonne
|
||||
pour les affaires de son commerce, il mena dans son vaisseau ses
|
||||
deux philosophes. Pangloss lui expliqua comment tout ¨¦tait on ne
|
||||
peut mieux. Jacques n'¨¦tait pas de cet avis. Il faut bien,
|
||||
disait-il, que les hommes aient un peu corrompu la nature, car
|
||||
ils ne sont point n¨¦s loups, et ils sont devenus loups. Dieu ne
|
||||
leur a donn¨¦ ni canons de vingt-quatre, ni ba<62>0Š7onnettes, et ils se
|
||||
sont fait des ba<62>0Š7onnettes et des canons pour se d¨¦truire. Je
|
||||
pourrais mettre en ligne de compte les banqueroutes, et la
|
||||
justice qui s'empare des biens des banqueroutiers pour en
|
||||
frustrer les cr¨¦anciers. Tout cela ¨¦tait indispensable,
|
||||
r¨¦pliquait le docteur borgne, et les malheurs particuliers font
|
||||
le bien g¨¦n¨¦ral; de sorte que plus il y a de malheurs
|
||||
particuliers, et plus tout est bien. Tandis qu'il raisonnait,
|
||||
l'air s'obscurcit, les vents souffl¨¨rent des quatre coins du
|
||||
monde, et le vaisseau fut assailli de la plus horrible temp¨ºte, ¨¤
|
||||
la vue du port de Lisbonne.
|
||||
|
||||
|
||||
CHAPITRE V.
|
||||
|
||||
Temp¨ºte, naufrage, tremblement de terre, et ce qui advint du
|
||||
docteur Pangloss, de Candide, et de l'anabaptiste Jacques.
|
||||
|
||||
La moiti¨¦ des passagers affaiblis, expirants de ces angoisses
|
||||
inconcevables que le roulis d'un vaisseau porte dans les nerfs et
|
||||
dans toutes les humeurs du corps agit¨¦es en sens contraires,
|
||||
n'avait pas m¨ºme la force de s'inqui¨¦ter du danger. L'autre
|
||||
moiti¨¦ jetait des cris et fesait des pri¨¨res; les voiles ¨¦taient
|
||||
d¨¦chir¨¦es, les m<>0‰9ts bris¨¦s, le vaisseau entr'ouvert. Travaillait
|
||||
qui pouvait, personne ne s'entendait, personne ne commandait.
|
||||
L'anabaptiste aidait un peu ¨¤ la manoeuvre; il ¨¦tait sur le
|
||||
tillac; un matelot furieux le frappe rudement et l'¨¦tend sur les
|
||||
planches; mais du coup qu'il lui donna, il eut lui-m¨ºme une si
|
||||
violente secousse, qu'il tomba hors du vaisseau, la t¨ºte la
|
||||
premi¨¨re. Il restait suspendu et accroch¨¦ ¨¤ une partie de m<>0‰9t
|
||||
rompu. Le bon Jacques court ¨¤ son secours, l'aide ¨¤ remonter, et
|
||||
de l'effort qu'il fait, il est pr¨¦cipit¨¦ dans la mer ¨¤ la vue du
|
||||
matelot, qui le laissa p¨¦rir sans daigner seulement le regarder.
|
||||
Candide approche, voit son bienfaiteur qui repara<72>0Š6t un moment, et
|
||||
qui est englouti pour jamais. Il veut se jeter apr¨¨s lui dans la
|
||||
mer: le philosophe Pangloss l'en emp¨ºche, en lui prouvant que la
|
||||
rade de Lisbonne avait ¨¦t¨¦ form¨¦e expr¨¨s pour que cet anabaptiste
|
||||
s'y noy<6F>0‰9t. Tandis qu'il le prouvait _¨¤ priori_, le vaisseau
|
||||
s'entr'ouvre, tout p¨¦rit ¨¤ la r¨¦serve de Pangloss, de Candide, et
|
||||
de ce brutal de matelot qui avait noy¨¦ le vertueux anabaptiste;
|
||||
le coquin nagea heureusement jusqu'au rivage, o¨´ Pangloss et
|
||||
Candide furent port¨¦s sur une planche.
|
||||
|
||||
Quand ils furent revenus un peu ¨¤ eux, ils march¨¨rent vers
|
||||
Lisbonne; il leur restait quelque argent, avec lequel ils
|
||||
esp¨¦raient se sauver de la faim apr¨¨s avoir ¨¦chapp¨¦ ¨¤ la temp¨ºte.
|
||||
|
||||
A peine ont-ils mis le pied dans la ville, en pleurant la mort de
|
||||
leur bienfaiteur, qu'ils sentent la terre trembler sous leurs
|
||||
pas[1]; la mer s'¨¦l¨¨ve en bouillonnant dans le port, et brise les
|
||||
vaisseaux qui sont ¨¤ l'ancre. Des tourbillons de flammes et de
|
||||
cendres couvrent les rues et les places publiques; les maisons
|
||||
s'¨¦croulent, les toits sont renvers¨¦s sur les fondements, et les
|
||||
fondements se dispersent; trente mille habitants de tout <20>0‰9ge et
|
||||
de tout sexe sont ¨¦cras¨¦s sous des ruines. Le matelot disait en
|
||||
sifflant et en jurant: il y aura quelque chose ¨¤ gagner ici.
|
||||
Quelle peut ¨ºtre la raison suffisante de ce ph¨¦nom¨¨ne? disait
|
||||
Pangloss. Voici le dernier jour du monde! s'¨¦criait Candide.
|
||||
Le matelot court incontinent au milieu des d¨¦bris, affronte la
|
||||
mort pour trouver de l'argent, en trouve, s'en empare, s'enivre,
|
||||
et ayant cuv¨¦ son vin, ach¨¨te les faveurs de la premi¨¨re fille de
|
||||
bonne volont¨¦ qu'il rencontre sur les ruines des maisons
|
||||
d¨¦truites, et au milieu des mourants et des morts. Pangloss le
|
||||
tirait cependant par la manche: Mon ami, lui disait-il, cela
|
||||
n'est pas bien, vous manquez ¨¤ la raison universelle, vous prenez
|
||||
mal votre temps. T¨ºte et sang, r¨¦pondit l'autre, je suis matelot
|
||||
et n¨¦ ¨¤ Batavia; j'ai march¨¦ quatre fois sur le crucifix dans
|
||||
quatre voyages au Japon[2]; tu as bien trouv¨¦ ton homme avec ta
|
||||
raison universelle!
|
||||
|
||||
|
||||
[1] Le tremblement de terre de Lisbonne est du 1er novembre 1755.
|
||||
B.
|
||||
|
||||
[2] Voyez tome XVIII, page 470. B.
|
||||
|
||||
|
||||
Quelques ¨¦clats de pierre avaient bless¨¦ Candide; il ¨¦tait ¨¦tendu
|
||||
dans la rue et couvert de d¨¦bris. Il disait ¨¤ Pangloss: H¨¦las!
|
||||
procure-moi un peu de vin et d'huile; je me meurs. Ce
|
||||
tremblement de terre n'est pas une chose nouvelle, r¨¦pondit
|
||||
Pangloss; la ville de Lima ¨¦prouva les m¨ºmes secousses en
|
||||
Am¨¦rique l'ann¨¦e pass¨¦e; m¨ºmes causes, m¨ºmes effets; il y a
|
||||
certainement une tra<72>0Š6n¨¦e de soufre sous terre depuis Lima jusqu'¨¤
|
||||
Lisbonne. Rien n'est plus probable, dit Candide; mais, pour
|
||||
Dieu, un peu d'huile et de vin. Comment probable? r¨¦pliqua le
|
||||
philosophe, je soutiens que la chose est d¨¦montr¨¦e. Candide
|
||||
perdit connaissance, et Pangloss lui apporta un peu d'eau d'une
|
||||
fontaine voisine.
|
||||
|
||||
Le lendemain, ayant trouv¨¦ quelques provisions de bouche en se
|
||||
glissant ¨¤ travers des d¨¦combres, ils r¨¦par¨¨rent un peu leurs
|
||||
forces. Ensuite ils travaill¨¨rent comme les autres ¨¤ soulager
|
||||
les habitants ¨¦chapp¨¦s ¨¤ la mort. Quelques citoyens, secourus
|
||||
par eux, leur donn¨¨rent un aussi bon d<>0Š6ner qu'on le pouvait dans
|
||||
un tel d¨¦sastre: il est vrai que le repas ¨¦tait triste; les
|
||||
convives arrosaient leur pain de leurs larmes; mais Pangloss les
|
||||
consola, en les assurant que les choses ne pouvaient ¨ºtre
|
||||
autrement: Car, dit-il, tout ceci est ce qu'il y a de mieux; car
|
||||
s'il y a un volcan ¨¤ Lisbonne, il ne pouvait ¨ºtre ailleurs; car
|
||||
il est impossible que les choses ne soient pas o¨´ elles sont, car
|
||||
tout est bien.
|
||||
|
||||
Un petit homme noir, familier de l'inquisition, lequel ¨¦tait ¨¤
|
||||
c<EFBFBD>0‹0t¨¦ de lui, prit poliment la parole et dit: Apparemment que
|
||||
monsieur ne croit pas au p¨¦ch¨¦ originel; car si tout est au
|
||||
mieux, il n'y a donc eu ni chute ni punition.
|
||||
|
||||
Je demande tr¨¨s humblement pardon ¨¤ votre excellence, r¨¦pondit
|
||||
Pangloss encore plus poliment, car la chute de l'homme et la
|
||||
mal¨¦diction entraient n¨¦cessairement dans le meilleur des mondes
|
||||
possibles. Monsieur ne croit donc pas ¨¤ la libert¨¦? dit le
|
||||
familier. Votre excellence m'excusera, dit Pangloss; la libert¨¦
|
||||
peut subsister avec la n¨¦cessit¨¦ absolue; car il ¨¦tait n¨¦cessaire
|
||||
que nous fussions libres; car enfin la volont¨¦ d¨¦termin¨¦e......
|
||||
Pangloss ¨¦tait au milieu de sa phrase, quand Je familier fit un
|
||||
signe de t¨ºte ¨¤ son estafier qui lui servait ¨¤ boire du vin de
|
||||
Porto ou d'Oporto.
|
||||
BIN
vendor/golang.org/x/text/encoding/testdata/candide-utf-16le.txt
generated
vendored
BIN
vendor/golang.org/x/text/encoding/testdata/candide-utf-16le.txt
generated
vendored
Binary file not shown.
BIN
vendor/golang.org/x/text/encoding/testdata/candide-utf-32be.txt
generated
vendored
BIN
vendor/golang.org/x/text/encoding/testdata/candide-utf-32be.txt
generated
vendored
Binary file not shown.
510
vendor/golang.org/x/text/encoding/testdata/candide-utf-8.txt
generated
vendored
510
vendor/golang.org/x/text/encoding/testdata/candide-utf-8.txt
generated
vendored
|
|
@ -1,510 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/4650/pg4650.txt
|
||||
--------
|
||||
|
||||
CANDIDE,
|
||||
|
||||
ou
|
||||
|
||||
L'OPTIMISME,
|
||||
|
||||
TRADUIT DE L'ALLEMAND
|
||||
|
||||
DE M. LE DOCTEUR RALPH,
|
||||
|
||||
AVEC LES ADDITIONS
|
||||
|
||||
QU'ON A TROUVÉES DANS LA POCHE DU DOCTEUR, LORSQU'IL MOURUT
|
||||
|
||||
À MINDEN, L'AN DE GRÂCE 1759
|
||||
|
||||
1759
|
||||
|
||||
|
||||
|
||||
CHAPITRE I.
|
||||
|
||||
Comment Candide fut élevé dans un beau château, et comment il fut
|
||||
chassé d'icelui.
|
||||
|
||||
Il y avait en Vestphalie, dans le château de M. le baron de
|
||||
Thunder-ten-tronckh, un jeune garçon à qui la nature avait donné
|
||||
les moeurs les plus douces. Sa physionomie annonçait son âme.
|
||||
Il avait le jugement assez droit, avec l'esprit le plus simple;
|
||||
c'est, je crois, pour cette raison qu'on le nommait Candide. Les
|
||||
anciens domestiques de la maison soupçonnaient qu'il était fils
|
||||
de la soeur de monsieur le baron et d'un bon et honnête
|
||||
gentilhomme du voisinage, que cette demoiselle ne voulut jamais
|
||||
épouser parce qu'il n'avait pu prouver que soixante et onze
|
||||
quartiers, et que le reste de son arbre généalogique avait été
|
||||
perdu par l'injure du temps.
|
||||
|
||||
Monsieur le baron était un des plus puissants seigneurs de la
|
||||
Westphalie, car son château avait une porte et des fenêtres. Sa
|
||||
grande salle même était ornée d'une tapisserie. Tous les chiens
|
||||
de ses basses-cours composaient une meute dans le besoin; ses
|
||||
palefreniers étaient ses piqueurs; le vicaire du village était
|
||||
son grand-aumônier. Ils l'appelaient tous monseigneur, et ils
|
||||
riaient quand il fesait des contes.
|
||||
|
||||
Madame la baronne, qui pesait environ trois cent cinquante
|
||||
livres, s'attirait par là une très grande considération, et
|
||||
fesait les honneurs de la maison avec une dignité qui la rendait
|
||||
encore plus respectable. Sa fille Cunégonde, âgée de dix-sept
|
||||
ans, était haute en couleur, fraîche, grasse, appétissante. Le
|
||||
fils du baron paraissait en tout digne de son père. Le
|
||||
précepteur Pangloss[1] était l'oracle de la maison, et le petit
|
||||
Candide écoutait ses leçons avec toute la bonne foi de son âge et
|
||||
de son caractère.
|
||||
|
||||
[1] De _pan_, tout, et _glossa_, langue. B.
|
||||
|
||||
|
||||
Pangloss enseignait la métaphysico-théologo-cosmolonigologie. Il
|
||||
prouvait admirablement qu'il n'y a point d'effet sans cause, et
|
||||
que, dans ce meilleur des mondes possibles, le château de
|
||||
monseigneur le baron était le plus beau des châteaux, et madame
|
||||
la meilleure des baronnes possibles.
|
||||
|
||||
Il est démontré, disait-il, que les choses ne peuvent être
|
||||
autrement; car tout étant fait pour une fin, tout est
|
||||
nécessairement pour la meilleure fin. Remarquez bien que les nez
|
||||
ont été faits pour porter des lunettes; aussi avons-nous des
|
||||
lunettes[2]. Les jambes sont visiblement instituées pour être
|
||||
chaussées, et nous avons des chausses. Les pierres ont été
|
||||
formées pour être taillées et pour en faire des châteaux; aussi
|
||||
monseigneur a un très beau château: le plus grand baron de la
|
||||
province doit être le mieux logé; et les cochons étant faits pour
|
||||
être mangés, nous mangeons du porc toute l'année: par conséquent,
|
||||
ceux qui ont avancé que tout est bien ont dit une sottise; il
|
||||
fallait dire que tout est au mieux.
|
||||
|
||||
[2] Voyez tome XXVII, page 528; et dans les _Mélanges_, année
|
||||
1738, le chapitre XI de la troisième partie des _Éléments de la
|
||||
philosophie de Newton_; et année 1768, le chapitre X des
|
||||
_Singularités de la nature_. B.
|
||||
|
||||
|
||||
Candide écoutait attentivement, et croyait innocemment; car il
|
||||
trouvait mademoiselle Cunégonde extrêmement belle, quoiqu'il ne
|
||||
prît jamais la hardiesse de le lui dire. Il concluait qu'après
|
||||
le bonheur d'être né baron de Thunder-ten-tronckh, le second
|
||||
degré de bonheur était d'être mademoiselle Cunégonde; le
|
||||
troisième, de la voir tous les jours; et le quatrième, d'entendre
|
||||
maître Pangloss, le plus grand philosophe de la province, et par
|
||||
conséquent de toute la terre.
|
||||
|
||||
Un jour Cunégonde, en se promenant auprès du château, dans le
|
||||
petit bois qu'on appelait parc, vit entre des broussailles le
|
||||
docteur Pangloss qui donnait une leçon de physique expérimentale
|
||||
à la femme de chambre de sa mère, petite brune très jolie et très
|
||||
docile. Comme mademoiselle Cunégonde avait beaucoup de
|
||||
disposition pour les sciences, elle observa, sans souffler, les
|
||||
expériences réitérées dont elle fut témoin; elle vit clairement
|
||||
la raison suffisante du docteur, les effets et les causes, et
|
||||
s'en retourna tout agitée, toute pensive, toute remplie du désir
|
||||
d'être savante, songeant qu'elle pourrait bien être la raison
|
||||
suffisante du jeune Candide, qui pouvait aussi être la sienne.
|
||||
|
||||
Elle rencontra Candide en revenant au château, et rougit: Candide
|
||||
rougit aussi . Elle lui dit bonjour d'une voix entrecoupée; et
|
||||
Candide lui parla sans savoir ce qu'il disait. Le lendemain,
|
||||
après le dîner, comme on sortait de table, Cunégonde et Candide
|
||||
se trouvèrent derrière un paravent; Cunégonde laissa tomber son
|
||||
mouchoir, Candide le ramassa; elle lui prit innocemment la main;
|
||||
le jeune homme baisa innocemment la main de la jeune demoiselle
|
||||
avec une vivacité, une sensibilité, une grâce toute particulière;
|
||||
leurs bouches se rencontrèrent, leurs yeux s'enflammèrent, leurs
|
||||
genoux tremblèrent, leurs mains s'égarèrent. M. le baron de
|
||||
Thunder-ten-tronckh passa auprès du paravent, et voyant cette
|
||||
cause et cet effet, chassa Candide du château à grands coups de
|
||||
pied dans le derrière. Cunégonde s'évanouit: elle fut souffletée
|
||||
par madame la baronne dès qu'elle fut revenue à elle-même; et
|
||||
tout fut consterné dans le plus beau et le plus agréable des
|
||||
châteaux possibles.
|
||||
|
||||
|
||||
|
||||
CHAPITRE II
|
||||
|
||||
Ce que devint Candide parmi les Bulgares.
|
||||
|
||||
|
||||
Candide, chassé du paradis terrestre, marcha longtemps sans
|
||||
savoir où, pleurant, levant les yeux au ciel, les tournant
|
||||
souvent vers le plus beau des châteaux qui renfermait la plus
|
||||
belle des baronnettes; il se coucha sans souper au milieu des
|
||||
champs entre deux sillons; la neige tombait à gros flocons.
|
||||
Candide, tout transi, se traîna le lendemain vers la ville
|
||||
voisine, qui s'appelle _Valdberghoff-trarbk-dikdorff_, n'ayant
|
||||
point d'argent, mourant de faim et de lassitude. Il s'arrêta
|
||||
tristement à la porte d'un cabaret. Deux hommes habillés de bleu
|
||||
le remarquèrent: Camarade, dit l'un, voilà un jeune homme très
|
||||
bien fait, et qui a la taille requise; ils s'avancèrent vers
|
||||
Candide et le prièrent à dîner très civilement.--Messieurs, leur
|
||||
dit Candide avec une modestie charmante, vous me faites beaucoup
|
||||
d'honneur, mais je n'ai pas de quoi payer mon écot.--Ah!
|
||||
monsieur, lui dit un des bleus, les personnes de votre figure et
|
||||
de votre mérite ne paient jamais rien: n'avez-vous pas cinq pieds
|
||||
cinq pouces de haut?--Oui, messieurs, c'est ma taille, dit-il en
|
||||
fesant la révérence.--Ah! monsieur, mettez-vous à table; non
|
||||
seulement nous vous défraierons, mais nous ne souffrirons jamais
|
||||
qu'un homme comme vous manque d'argent; les hommes ne sont faits
|
||||
que pour se secourir les uns les autres.--Vous avez raison, dit
|
||||
Candide; c'est ce que M. Pangloss m'a toujours dit, et je vois
|
||||
bien que tout est au mieux. On le prie d'accepter quelques écus,
|
||||
il les prend et veut faire son billet; on n'en veut point, on se
|
||||
met à table. N'aimez-vous pas tendrement?....--Oh! oui,
|
||||
répond-il, j'aime tendrement mademoiselle Cunégonde.--Non, dit
|
||||
l'un de ces messieurs, nous vous demandons si vous n'aimez pas
|
||||
tendrement le roi des Bulgares?--Point du tout, dit-il, car je ne
|
||||
l'ai jamais vu.--Comment! c'est le plus charmant des rois, et il
|
||||
faut boire à sa santé.--Oh! très volontiers, messieurs. Et il
|
||||
boit. C'en est assez, lui dit-on, vous voilà l'appui, le
|
||||
soutien, le défenseur, le héros des Bulgares; votre fortune est
|
||||
faite, et votre gloire est assurée. On lui met sur-le-champ les
|
||||
fers aux pieds, et on le mène au régiment. On le fait tourner à
|
||||
droite, à gauche, hausser la baguette, remettre la baguette,
|
||||
coucher en joue, tirer, doubler le pas, et on lui donne trente
|
||||
coups de bâton; le lendemain, il fait l'exercice un peu moins
|
||||
mal, et il ne reçoit que vingt coups; le surlendemain, on ne lui
|
||||
en donne que dix, et il est regardé par ses camarades comme un
|
||||
prodige.
|
||||
|
||||
Candide, tout stupéfait, ne démêlait pas encore trop bien comment
|
||||
il était un héros. Il s'avisa un beau jour de printemps de
|
||||
s'aller promener, marchant tout droit devant lui, croyant que
|
||||
c'était un privilège de l'espèce humaine, comme de l'espèce
|
||||
animale, de se servir de ses jambes à son plaisir. Il n'eut pas
|
||||
fait deux lieues que voilà quatre autres héros de six pieds qui
|
||||
l'atteignent, qui le lient, qui le mènent dans un cachot. On lui
|
||||
demanda juridiquement ce qu'il aimait le mieux d'être fustigé
|
||||
trente-six fois par tout le régiment, ou de recevoir à-la-fois
|
||||
douze balles de plomb dans la cervelle. Il eut beau dire que les
|
||||
volontés sont libres, et qu'il ne voulait ni l'un ni l'autre, il
|
||||
fallut faire un choix; il se détermina, en vertu du don de Dieu
|
||||
qu'on nomme _liberté_, à passer trente-six fois par les
|
||||
baguettes; il essuya deux promenades. Le régiment était composé
|
||||
de deux mille hommes; cela lui composa quatre mille coups de
|
||||
baguette, qui, depuis la nuque du cou jusqu'au cul, lui
|
||||
découvrirent les muscles et les nerfs. Comme on allait procéder
|
||||
à la troisième course, Candide, n'en pouvant plus, demanda en
|
||||
grâce qu'on voulût bien avoir la bonté de lui casser la tête; il
|
||||
obtint cette faveur; on lui bande les yeux; on le fait mettre à
|
||||
genoux. Le roi des Bulgares passe dans ce moment, s'informe du
|
||||
crime du patient; et comme ce roi avait un grand génie, il
|
||||
comprit, par tout ce qu'il apprit de Candide, que c'était un
|
||||
jeune métaphysicien fort ignorant des choses de ce monde, et il
|
||||
lui accorda sa grâce avec une clémence qui sera louée dans tous
|
||||
les journaux et dans tous les siècles. Un brave chirurgien
|
||||
guérit Candide en trois semaines avec les émollients enseignés
|
||||
par Dioscoride. Il avait déjà un peu de peau et pouvait marcher,
|
||||
quand le roi des Bulgares livra bataille au roi des Abares.
|
||||
|
||||
|
||||
|
||||
CHAPITRE III.
|
||||
|
||||
Comment Candide se sauva d'entre les Bulgares, et ce qu'il
|
||||
devint.
|
||||
|
||||
|
||||
Rien n'était si beau, si leste, si brillant, si bien ordonné que
|
||||
les deux armées. Les trompettes, les fifres, les hautbois, les
|
||||
tambours, les canons; formaient une harmonie telle qu'il n'y en
|
||||
eut jamais en enfer. Les canons renversèrent d'abord à peu près
|
||||
six mille hommes de chaque côté; ensuite la mousqueterie ôta du
|
||||
meilleur des mondes environ neuf à dix mille coquins qui en
|
||||
infectaient la surface. La baïonnette fut aussi la raison
|
||||
suffisante de la mort de quelques milliers d'hommes. Le tout
|
||||
pouvait bien se monter à une trentaine de mille âmes. Candide,
|
||||
qui tremblait comme un philosophe, se cacha du mieux qu'il put
|
||||
pendant cette boucherie héroïque.
|
||||
|
||||
Enfin, tandis que les deux rois fesaient chanter des _Te Deum_,
|
||||
chacun dans son camp, il prit le parti d'aller raisonner ailleurs
|
||||
des effets et des causes. Il passa par-dessus des tas de morts
|
||||
et de mourants, et gagna d'abord un village voisin; il était en
|
||||
cendres: c'était un village abare que les Bulgares avaient brûlé,
|
||||
selon les lois du droit public. Ici des vieillards criblés de
|
||||
coups regardaient mourir leurs femmes égorgées, qui tenaient
|
||||
leurs enfants à leurs mamelles sanglantes; là des filles
|
||||
éventrées après avoir assouvi les besoins naturels de quelques
|
||||
héros, rendaient les derniers soupirs; d'autres à demi brûlées
|
||||
criaient qu'on achevât de leur donner la mort. Des cervelles
|
||||
étaient répandues sur la terre à côté de bras et de jambes
|
||||
coupés.
|
||||
|
||||
Candide s'enfuit au plus vite dans un autre village: il
|
||||
appartenait à des Bulgares, et les héros abares l'avaient traité
|
||||
de même. Candide, toujours marchant sur des membres palpitants
|
||||
ou à travers des ruines, arriva enfin hors du théâtre de la
|
||||
guerre, portant quelques petites provisions dans son bissac, et
|
||||
n'oubliant jamais mademoiselle Cunégonde. Ses provisions lui
|
||||
manquèrent quand il fut en Hollande; mais ayant entendu dire que
|
||||
tout le monde était riche dans ce pays-là, et qu'on y était
|
||||
chrétien, il ne douta pas qu'on ne le traitât aussi bien qu'il
|
||||
l'avait été dans le château de M. le baron, avant qu'il en eût
|
||||
été chassé pour les beaux yeux de mademoiselle Cunégonde.
|
||||
|
||||
Il demanda l'aumône à plusieurs graves personnages, qui lui
|
||||
répondirent tous que, s'il continuait à faire ce métier, on
|
||||
l'enfermerait dans une maison de correction pour lui apprendre à
|
||||
vivre.
|
||||
|
||||
Il s'adressa ensuite à un homme qui venait de parler tout seul
|
||||
une heure de suite sur la charité dans une grande assemblée. Cet
|
||||
orateur le regardant de travers lui dit: Que venez-vous faire
|
||||
ici? y êtes-vous pour la bonne cause? Il n'y a point d'effet sans
|
||||
cause, répondit modestement Candide; tout est enchaîné
|
||||
nécessairement et arrangé pour le mieux. Il a fallu que je fusse
|
||||
chassé d'auprès de mademoiselle Cunégonde, que j'aie passé par
|
||||
les baguettes, et il faut que je demande mon pain, jusqu'à ce que
|
||||
je puisse en gagner; tout cela ne pouvait être autrement. Mon
|
||||
ami, lui dit l'orateur, croyez-vous que le pape soit
|
||||
l'antechrist? Je ne l'avais pas encore entendu dire, répondit
|
||||
Candide: mais qu'il le soit, ou qu'il ne le soit pas, je manque
|
||||
de pain. Tu ne mérites pas d'en manger, dit l'autre: va, coquin,
|
||||
va, misérable, ne m'approche de ta vie. La femme de l'orateur
|
||||
ayant mis la tête à la fenêtre, et avisant un homme qui doutait
|
||||
que le pape fût antechrist, lui répandit sur le chef un
|
||||
plein..... O ciel! à quel excès se porte le zèle de la religion
|
||||
dans les dames!
|
||||
|
||||
Un homme qui n'avait point été baptisé, un bon anabaptiste, nommé
|
||||
Jacques, vit la manière cruelle et ignominieuse dont on traitait
|
||||
ainsi un de ses frères, un être à deux pieds sans plumes, qui
|
||||
avait une âme; il l'amena chez lui, le nettoya, lui donna du pain
|
||||
et de la bière, lui fit présent de deux florins, et voulut même
|
||||
lui apprendre à travailler dans ses manufactures aux étoffes de
|
||||
Perse qu'on fabrique en Hollande. Candide se prosternant presque
|
||||
devant lui, s'écriait: Maître Pangloss me l'avait bien dit que
|
||||
tout est au mieux dans ce monde, car je suis infiniment plus
|
||||
touché de votre extrême générosité que de la dureté de ce
|
||||
monsieur à manteau noir, et de madame son épouse.
|
||||
|
||||
Le lendemain, en se promenant, il rencontra un gueux tout couvert
|
||||
de pustules, les yeux morts, le bout du nez rongé, la bouche de
|
||||
travers, les dents noires, et parlant de la gorge, tourmenté
|
||||
d'une toux violente, et crachant une dent à chaque effort.
|
||||
|
||||
|
||||
|
||||
CHAPITRE IV.
|
||||
|
||||
Comment Candide rencontra son ancien maître de philosophie, le
|
||||
docteur Pangloss, et ce qui en advint.
|
||||
|
||||
|
||||
Candide, plus ému encore de compassion que d'horreur, donna à cet
|
||||
épouvantable gueux les deux florins qu'il avait reçus de son
|
||||
honnête anabaptiste Jacques. Le fantôme le regarda fixement,
|
||||
versa des larmes, et sauta à son cou. Candide effrayé recule.
|
||||
Hélas! dit le misérable à l'autre misérable, ne reconnaissez-vous
|
||||
plus votre cher Pangloss? Qu'entends-je? vous, mon cher maître!
|
||||
vous, dans cet état horrible! quel malheur vous est-il donc
|
||||
arrivé? pourquoi n'êtes-vous plus dans le plus beau des châteaux?
|
||||
qu'est devenue mademoiselle Cunégonde, la perle des filles, le
|
||||
chef-d'oeuvre de la nature? Je n'en peux plus, dit Pangloss.
|
||||
Aussitôt Candide le mena dans l'étable de l'anabaptiste, où il
|
||||
lui fit manger un peu de pain; et quand Pangloss fut refait: Eh
|
||||
bien! lui dit-il, Cunégonde? Elle est morte, reprit l'autre.
|
||||
Candide s'évanouit à ce mot: son ami rappela ses sens avec un peu
|
||||
de mauvais vinaigre qui se trouva par hasard dans l'étable.
|
||||
Candide rouvre les yeux. Cunégonde est morte! Ah! meilleur des
|
||||
mondes, où êtes-vous? Mais de quelle maladie est-elle morte? ne
|
||||
serait-ce point de m'avoir vu chasser du beau château de monsieur
|
||||
son père à grands coups de pied? Non, dit Pangloss, elle a été
|
||||
éventrée par des soldats bulgares, après avoir été violée autant
|
||||
qu'on peut l'être; ils ont cassé la tête à monsieur le baron qui
|
||||
voulait la défendre; madame la baronne a été coupée en morceaux;
|
||||
mon pauvre pupille traité précisément comme sa soeur; et quant au
|
||||
château, il n'est pas resté pierre sur pierre, pas une grange,
|
||||
pas un mouton, pas un canard, pas un arbre; mais nous avons été
|
||||
bien vengés, car les Abares en ont fait autant dans une baronnie
|
||||
voisine qui appartenait à un seigneur bulgare.
|
||||
|
||||
A ce discours, Candide s'évanouit encore; mais revenu à soi, et
|
||||
ayant dit tout ce qu'il devait dire, il s'enquit de la cause et
|
||||
de l'effet, et de la raison suffisante qui avait mis Pangloss
|
||||
dans un si piteux état. Hélas! dit l'autre, c'est l'amour:
|
||||
l'amour, le consolateur du genre humain, le conservateur de
|
||||
l'univers, l'âme de tous les êtres sensibles, le tendre amour.
|
||||
Hélas! dit Candide, je l'ai connu cet amour, ce souverain des
|
||||
coeurs, cette âme de notre âme; il ne m'a jamais valu qu'un
|
||||
baiser et vingt coups de pied au cul. Comment cette belle cause
|
||||
a-t-elle pu produire en vous un effet si abominable?
|
||||
|
||||
Pangloss répondit en ces termes: O mon cher Candide! vous avez
|
||||
connu Paquette, cette jolie suivante de notre auguste baronne:
|
||||
j'ai goûté dans ses bras les délices du paradis, qui ont produit
|
||||
ces tourments d'enfer dont vous me voyez dévoré; elle en était
|
||||
infectée, elle en est peut-être morte. Paquette tenait ce
|
||||
présent d'un cordelier très savant qui avait remonté à la source,
|
||||
car il l'avait eu d'une vieille comtesse, qui l'avait reçu d'un
|
||||
capitaine de cavalerie, qui le devait à une marquise, qui le
|
||||
tenait d'un page, qui l'avait reçu d'un jésuite, qui, étant
|
||||
novice, l'avait eu en droite ligne d'un des compagnons de
|
||||
Christophe Colomb. Pour moi, je ne le donnerai à personne, car
|
||||
je me meurs.
|
||||
|
||||
O Pangloss! s'écria Candide, voilà une étrange généalogie!
|
||||
n'est-ce pas le diable qui en fut la souche? Point du tout,
|
||||
répliqua ce grand homme; c'était une chose indispensable dans le
|
||||
meilleur des mondes, un ingrédient nécessaire; car si Colomb
|
||||
n'avait pas attrapé dans une île de l'Amérique cette maladie[1]
|
||||
qui empoisonne la source de la génération, qui souvent même
|
||||
empêche la génération, et qui est évidemment l'opposé du grand
|
||||
but de la nature, nous n'aurions ni le chocolat ni la cochenille;
|
||||
il faut encore observer que jusqu'aujourd'hui, dans notre
|
||||
continent, cette maladie nous est particulière, comme la
|
||||
controverse. Les Turcs, les Indiens, les Persans, les Chinois,
|
||||
les Siamois, les Japonais, ne la connaissent pas encore; mais il
|
||||
y a une raison suffisante pour qu'ils la connaissent à leur tour
|
||||
dans quelques siècles. En attendant elle a fait un merveilleux
|
||||
progrès parmi nous, et surtout dans ces grandes armées composées
|
||||
d'honnêtes stipendiaires bien élevés, qui décident du destin des
|
||||
états; on peut assurer que, quand trente mille hommes combattent
|
||||
en bataille rangée contre des troupes égales en nombre, il y a
|
||||
environ vingt mille vérolés de chaque côté.
|
||||
|
||||
[1] Voyez tome XXXI, page 7. B.
|
||||
|
||||
|
||||
Voilà qui est admirable, dit Candide; mais il faut vous faire
|
||||
guérir. Et comment le puis-je? dit Pangloss; je n'ai pas le sou,
|
||||
mon ami, et dans toute l'étendue de ce globe on ne peut ni se
|
||||
faire saigner, ni prendre un lavement sans payer, ou sans qu'il y
|
||||
ait quelqu'un qui paie pour nous.
|
||||
|
||||
Ce dernier discours détermina Candide; il alla se jeter aux pieds
|
||||
de son charitable anabaptiste Jacques, et lui fit une peinture si
|
||||
touchante de l'état où son ami était réduit, que le bon-homme
|
||||
n'hésita pas à recueillir le docteur Pangloss; il le fit guérir à
|
||||
ses dépens. Pangloss, dans la cure, ne perdit qu'un oeil et une
|
||||
oreille. Il écrivait bien, et savait parfaitement
|
||||
l'arithmétique. L'anabaptiste Jacques en fit son teneur de
|
||||
livres. Au bout de deux mois, étant obligé d'aller à Lisbonne
|
||||
pour les affaires de son commerce, il mena dans son vaisseau ses
|
||||
deux philosophes. Pangloss lui expliqua comment tout était on ne
|
||||
peut mieux. Jacques n'était pas de cet avis. Il faut bien,
|
||||
disait-il, que les hommes aient un peu corrompu la nature, car
|
||||
ils ne sont point nés loups, et ils sont devenus loups. Dieu ne
|
||||
leur a donné ni canons de vingt-quatre, ni baïonnettes, et ils se
|
||||
sont fait des baïonnettes et des canons pour se détruire. Je
|
||||
pourrais mettre en ligne de compte les banqueroutes, et la
|
||||
justice qui s'empare des biens des banqueroutiers pour en
|
||||
frustrer les créanciers. Tout cela était indispensable,
|
||||
répliquait le docteur borgne, et les malheurs particuliers font
|
||||
le bien général; de sorte que plus il y a de malheurs
|
||||
particuliers, et plus tout est bien. Tandis qu'il raisonnait,
|
||||
l'air s'obscurcit, les vents soufflèrent des quatre coins du
|
||||
monde, et le vaisseau fut assailli de la plus horrible tempête, à
|
||||
la vue du port de Lisbonne.
|
||||
|
||||
|
||||
CHAPITRE V.
|
||||
|
||||
Tempête, naufrage, tremblement de terre, et ce qui advint du
|
||||
docteur Pangloss, de Candide, et de l'anabaptiste Jacques.
|
||||
|
||||
La moitié des passagers affaiblis, expirants de ces angoisses
|
||||
inconcevables que le roulis d'un vaisseau porte dans les nerfs et
|
||||
dans toutes les humeurs du corps agitées en sens contraires,
|
||||
n'avait pas même la force de s'inquiéter du danger. L'autre
|
||||
moitié jetait des cris et fesait des prières; les voiles étaient
|
||||
déchirées, les mâts brisés, le vaisseau entr'ouvert. Travaillait
|
||||
qui pouvait, personne ne s'entendait, personne ne commandait.
|
||||
L'anabaptiste aidait un peu à la manoeuvre; il était sur le
|
||||
tillac; un matelot furieux le frappe rudement et l'étend sur les
|
||||
planches; mais du coup qu'il lui donna, il eut lui-même une si
|
||||
violente secousse, qu'il tomba hors du vaisseau, la tête la
|
||||
première. Il restait suspendu et accroché à une partie de mât
|
||||
rompu. Le bon Jacques court à son secours, l'aide à remonter, et
|
||||
de l'effort qu'il fait, il est précipité dans la mer à la vue du
|
||||
matelot, qui le laissa périr sans daigner seulement le regarder.
|
||||
Candide approche, voit son bienfaiteur qui reparaît un moment, et
|
||||
qui est englouti pour jamais. Il veut se jeter après lui dans la
|
||||
mer: le philosophe Pangloss l'en empêche, en lui prouvant que la
|
||||
rade de Lisbonne avait été formée exprès pour que cet anabaptiste
|
||||
s'y noyât. Tandis qu'il le prouvait _à priori_, le vaisseau
|
||||
s'entr'ouvre, tout périt à la réserve de Pangloss, de Candide, et
|
||||
de ce brutal de matelot qui avait noyé le vertueux anabaptiste;
|
||||
le coquin nagea heureusement jusqu'au rivage, où Pangloss et
|
||||
Candide furent portés sur une planche.
|
||||
|
||||
Quand ils furent revenus un peu à eux, ils marchèrent vers
|
||||
Lisbonne; il leur restait quelque argent, avec lequel ils
|
||||
espéraient se sauver de la faim après avoir échappé à la tempête.
|
||||
|
||||
A peine ont-ils mis le pied dans la ville, en pleurant la mort de
|
||||
leur bienfaiteur, qu'ils sentent la terre trembler sous leurs
|
||||
pas[1]; la mer s'élève en bouillonnant dans le port, et brise les
|
||||
vaisseaux qui sont à l'ancre. Des tourbillons de flammes et de
|
||||
cendres couvrent les rues et les places publiques; les maisons
|
||||
s'écroulent, les toits sont renversés sur les fondements, et les
|
||||
fondements se dispersent; trente mille habitants de tout âge et
|
||||
de tout sexe sont écrasés sous des ruines. Le matelot disait en
|
||||
sifflant et en jurant: il y aura quelque chose à gagner ici.
|
||||
Quelle peut être la raison suffisante de ce phénomène? disait
|
||||
Pangloss. Voici le dernier jour du monde! s'écriait Candide.
|
||||
Le matelot court incontinent au milieu des débris, affronte la
|
||||
mort pour trouver de l'argent, en trouve, s'en empare, s'enivre,
|
||||
et ayant cuvé son vin, achète les faveurs de la première fille de
|
||||
bonne volonté qu'il rencontre sur les ruines des maisons
|
||||
détruites, et au milieu des mourants et des morts. Pangloss le
|
||||
tirait cependant par la manche: Mon ami, lui disait-il, cela
|
||||
n'est pas bien, vous manquez à la raison universelle, vous prenez
|
||||
mal votre temps. Tête et sang, répondit l'autre, je suis matelot
|
||||
et né à Batavia; j'ai marché quatre fois sur le crucifix dans
|
||||
quatre voyages au Japon[2]; tu as bien trouvé ton homme avec ta
|
||||
raison universelle!
|
||||
|
||||
|
||||
[1] Le tremblement de terre de Lisbonne est du 1er novembre 1755.
|
||||
B.
|
||||
|
||||
[2] Voyez tome XVIII, page 470. B.
|
||||
|
||||
|
||||
Quelques éclats de pierre avaient blessé Candide; il était étendu
|
||||
dans la rue et couvert de débris. Il disait à Pangloss: Hélas!
|
||||
procure-moi un peu de vin et d'huile; je me meurs. Ce
|
||||
tremblement de terre n'est pas une chose nouvelle, répondit
|
||||
Pangloss; la ville de Lima éprouva les mêmes secousses en
|
||||
Amérique l'année passée; mêmes causes, mêmes effets; il y a
|
||||
certainement une traînée de soufre sous terre depuis Lima jusqu'à
|
||||
Lisbonne. Rien n'est plus probable, dit Candide; mais, pour
|
||||
Dieu, un peu d'huile et de vin. Comment probable? répliqua le
|
||||
philosophe, je soutiens que la chose est démontrée. Candide
|
||||
perdit connaissance, et Pangloss lui apporta un peu d'eau d'une
|
||||
fontaine voisine.
|
||||
|
||||
Le lendemain, ayant trouvé quelques provisions de bouche en se
|
||||
glissant à travers des décombres, ils réparèrent un peu leurs
|
||||
forces. Ensuite ils travaillèrent comme les autres à soulager
|
||||
les habitants échappés à la mort. Quelques citoyens, secourus
|
||||
par eux, leur donnèrent un aussi bon dîner qu'on le pouvait dans
|
||||
un tel désastre: il est vrai que le repas était triste; les
|
||||
convives arrosaient leur pain de leurs larmes; mais Pangloss les
|
||||
consola, en les assurant que les choses ne pouvaient être
|
||||
autrement: Car, dit-il, tout ceci est ce qu'il y a de mieux; car
|
||||
s'il y a un volcan à Lisbonne, il ne pouvait être ailleurs; car
|
||||
il est impossible que les choses ne soient pas où elles sont, car
|
||||
tout est bien.
|
||||
|
||||
Un petit homme noir, familier de l'inquisition, lequel était à
|
||||
côté de lui, prit poliment la parole et dit: Apparemment que
|
||||
monsieur ne croit pas au péché originel; car si tout est au
|
||||
mieux, il n'y a donc eu ni chute ni punition.
|
||||
|
||||
Je demande très humblement pardon à votre excellence, répondit
|
||||
Pangloss encore plus poliment, car la chute de l'homme et la
|
||||
malédiction entraient nécessairement dans le meilleur des mondes
|
||||
possibles. Monsieur ne croit donc pas à la liberté? dit le
|
||||
familier. Votre excellence m'excusera, dit Pangloss; la liberté
|
||||
peut subsister avec la nécessité absolue; car il était nécessaire
|
||||
que nous fussions libres; car enfin la volonté déterminée......
|
||||
Pangloss était au milieu de sa phrase, quand Je familier fit un
|
||||
signe de tête à son estafier qui lui servait à boire du vin de
|
||||
Porto ou d'Oporto.
|
||||
510
vendor/golang.org/x/text/encoding/testdata/candide-windows-1252.txt
generated
vendored
510
vendor/golang.org/x/text/encoding/testdata/candide-windows-1252.txt
generated
vendored
|
|
@ -1,510 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/4650/pg4650.txt
|
||||
--------
|
||||
|
||||
CANDIDE,
|
||||
|
||||
ou
|
||||
|
||||
L'OPTIMISME,
|
||||
|
||||
TRADUIT DE L'ALLEMAND
|
||||
|
||||
DE M. LE DOCTEUR RALPH,
|
||||
|
||||
AVEC LES ADDITIONS
|
||||
|
||||
QU'ON A TROUVÉES DANS LA POCHE DU DOCTEUR, LORSQU'IL MOURUT
|
||||
|
||||
À MINDEN, L'AN DE GRÂCE 1759
|
||||
|
||||
1759
|
||||
|
||||
|
||||
|
||||
CHAPITRE I.
|
||||
|
||||
Comment Candide fut élevé dans un beau château, et comment il fut
|
||||
chassé d'icelui.
|
||||
|
||||
Il y avait en Vestphalie, dans le château de M. le baron de
|
||||
Thunder-ten-tronckh, un jeune garçon à qui la nature avait donné
|
||||
les moeurs les plus douces. Sa physionomie annonçait son âme.
|
||||
Il avait le jugement assez droit, avec l'esprit le plus simple;
|
||||
c'est, je crois, pour cette raison qu'on le nommait Candide. Les
|
||||
anciens domestiques de la maison soupçonnaient qu'il était fils
|
||||
de la soeur de monsieur le baron et d'un bon et honnête
|
||||
gentilhomme du voisinage, que cette demoiselle ne voulut jamais
|
||||
épouser parce qu'il n'avait pu prouver que soixante et onze
|
||||
quartiers, et que le reste de son arbre généalogique avait été
|
||||
perdu par l'injure du temps.
|
||||
|
||||
Monsieur le baron était un des plus puissants seigneurs de la
|
||||
Westphalie, car son château avait une porte et des fenêtres. Sa
|
||||
grande salle même était ornée d'une tapisserie. Tous les chiens
|
||||
de ses basses-cours composaient une meute dans le besoin; ses
|
||||
palefreniers étaient ses piqueurs; le vicaire du village était
|
||||
son grand-aumônier. Ils l'appelaient tous monseigneur, et ils
|
||||
riaient quand il fesait des contes.
|
||||
|
||||
Madame la baronne, qui pesait environ trois cent cinquante
|
||||
livres, s'attirait par là une très grande considération, et
|
||||
fesait les honneurs de la maison avec une dignité qui la rendait
|
||||
encore plus respectable. Sa fille Cunégonde, âgée de dix-sept
|
||||
ans, était haute en couleur, fraîche, grasse, appétissante. Le
|
||||
fils du baron paraissait en tout digne de son père. Le
|
||||
précepteur Pangloss[1] était l'oracle de la maison, et le petit
|
||||
Candide écoutait ses leçons avec toute la bonne foi de son âge et
|
||||
de son caractère.
|
||||
|
||||
[1] De _pan_, tout, et _glossa_, langue. B.
|
||||
|
||||
|
||||
Pangloss enseignait la métaphysico-théologo-cosmolonigologie. Il
|
||||
prouvait admirablement qu'il n'y a point d'effet sans cause, et
|
||||
que, dans ce meilleur des mondes possibles, le château de
|
||||
monseigneur le baron était le plus beau des châteaux, et madame
|
||||
la meilleure des baronnes possibles.
|
||||
|
||||
Il est démontré, disait-il, que les choses ne peuvent être
|
||||
autrement; car tout étant fait pour une fin, tout est
|
||||
nécessairement pour la meilleure fin. Remarquez bien que les nez
|
||||
ont été faits pour porter des lunettes; aussi avons-nous des
|
||||
lunettes[2]. Les jambes sont visiblement instituées pour être
|
||||
chaussées, et nous avons des chausses. Les pierres ont été
|
||||
formées pour être taillées et pour en faire des châteaux; aussi
|
||||
monseigneur a un très beau château: le plus grand baron de la
|
||||
province doit être le mieux logé; et les cochons étant faits pour
|
||||
être mangés, nous mangeons du porc toute l'année: par conséquent,
|
||||
ceux qui ont avancé que tout est bien ont dit une sottise; il
|
||||
fallait dire que tout est au mieux.
|
||||
|
||||
[2] Voyez tome XXVII, page 528; et dans les _Mélanges_, année
|
||||
1738, le chapitre XI de la troisième partie des _Éléments de la
|
||||
philosophie de Newton_; et année 1768, le chapitre X des
|
||||
_Singularités de la nature_. B.
|
||||
|
||||
|
||||
Candide écoutait attentivement, et croyait innocemment; car il
|
||||
trouvait mademoiselle Cunégonde extrêmement belle, quoiqu'il ne
|
||||
prît jamais la hardiesse de le lui dire. Il concluait qu'après
|
||||
le bonheur d'être né baron de Thunder-ten-tronckh, le second
|
||||
degré de bonheur était d'être mademoiselle Cunégonde; le
|
||||
troisième, de la voir tous les jours; et le quatrième, d'entendre
|
||||
maître Pangloss, le plus grand philosophe de la province, et par
|
||||
conséquent de toute la terre.
|
||||
|
||||
Un jour Cunégonde, en se promenant auprès du château, dans le
|
||||
petit bois qu'on appelait parc, vit entre des broussailles le
|
||||
docteur Pangloss qui donnait une leçon de physique expérimentale
|
||||
à la femme de chambre de sa mère, petite brune très jolie et très
|
||||
docile. Comme mademoiselle Cunégonde avait beaucoup de
|
||||
disposition pour les sciences, elle observa, sans souffler, les
|
||||
expériences réitérées dont elle fut témoin; elle vit clairement
|
||||
la raison suffisante du docteur, les effets et les causes, et
|
||||
s'en retourna tout agitée, toute pensive, toute remplie du désir
|
||||
d'être savante, songeant qu'elle pourrait bien être la raison
|
||||
suffisante du jeune Candide, qui pouvait aussi être la sienne.
|
||||
|
||||
Elle rencontra Candide en revenant au château, et rougit: Candide
|
||||
rougit aussi . Elle lui dit bonjour d'une voix entrecoupée; et
|
||||
Candide lui parla sans savoir ce qu'il disait. Le lendemain,
|
||||
après le dîner, comme on sortait de table, Cunégonde et Candide
|
||||
se trouvèrent derrière un paravent; Cunégonde laissa tomber son
|
||||
mouchoir, Candide le ramassa; elle lui prit innocemment la main;
|
||||
le jeune homme baisa innocemment la main de la jeune demoiselle
|
||||
avec une vivacité, une sensibilité, une grâce toute particulière;
|
||||
leurs bouches se rencontrèrent, leurs yeux s'enflammèrent, leurs
|
||||
genoux tremblèrent, leurs mains s'égarèrent. M. le baron de
|
||||
Thunder-ten-tronckh passa auprès du paravent, et voyant cette
|
||||
cause et cet effet, chassa Candide du château à grands coups de
|
||||
pied dans le derrière. Cunégonde s'évanouit: elle fut souffletée
|
||||
par madame la baronne dès qu'elle fut revenue à elle-même; et
|
||||
tout fut consterné dans le plus beau et le plus agréable des
|
||||
châteaux possibles.
|
||||
|
||||
|
||||
|
||||
CHAPITRE II
|
||||
|
||||
Ce que devint Candide parmi les Bulgares.
|
||||
|
||||
|
||||
Candide, chassé du paradis terrestre, marcha longtemps sans
|
||||
savoir où, pleurant, levant les yeux au ciel, les tournant
|
||||
souvent vers le plus beau des châteaux qui renfermait la plus
|
||||
belle des baronnettes; il se coucha sans souper au milieu des
|
||||
champs entre deux sillons; la neige tombait à gros flocons.
|
||||
Candide, tout transi, se traîna le lendemain vers la ville
|
||||
voisine, qui s'appelle _Valdberghoff-trarbk-dikdorff_, n'ayant
|
||||
point d'argent, mourant de faim et de lassitude. Il s'arrêta
|
||||
tristement à la porte d'un cabaret. Deux hommes habillés de bleu
|
||||
le remarquèrent: Camarade, dit l'un, voilà un jeune homme très
|
||||
bien fait, et qui a la taille requise; ils s'avancèrent vers
|
||||
Candide et le prièrent à dîner très civilement.--Messieurs, leur
|
||||
dit Candide avec une modestie charmante, vous me faites beaucoup
|
||||
d'honneur, mais je n'ai pas de quoi payer mon écot.--Ah!
|
||||
monsieur, lui dit un des bleus, les personnes de votre figure et
|
||||
de votre mérite ne paient jamais rien: n'avez-vous pas cinq pieds
|
||||
cinq pouces de haut?--Oui, messieurs, c'est ma taille, dit-il en
|
||||
fesant la révérence.--Ah! monsieur, mettez-vous à table; non
|
||||
seulement nous vous défraierons, mais nous ne souffrirons jamais
|
||||
qu'un homme comme vous manque d'argent; les hommes ne sont faits
|
||||
que pour se secourir les uns les autres.--Vous avez raison, dit
|
||||
Candide; c'est ce que M. Pangloss m'a toujours dit, et je vois
|
||||
bien que tout est au mieux. On le prie d'accepter quelques écus,
|
||||
il les prend et veut faire son billet; on n'en veut point, on se
|
||||
met à table. N'aimez-vous pas tendrement?....--Oh! oui,
|
||||
répond-il, j'aime tendrement mademoiselle Cunégonde.--Non, dit
|
||||
l'un de ces messieurs, nous vous demandons si vous n'aimez pas
|
||||
tendrement le roi des Bulgares?--Point du tout, dit-il, car je ne
|
||||
l'ai jamais vu.--Comment! c'est le plus charmant des rois, et il
|
||||
faut boire à sa santé.--Oh! très volontiers, messieurs. Et il
|
||||
boit. C'en est assez, lui dit-on, vous voilà l'appui, le
|
||||
soutien, le défenseur, le héros des Bulgares; votre fortune est
|
||||
faite, et votre gloire est assurée. On lui met sur-le-champ les
|
||||
fers aux pieds, et on le mène au régiment. On le fait tourner à
|
||||
droite, à gauche, hausser la baguette, remettre la baguette,
|
||||
coucher en joue, tirer, doubler le pas, et on lui donne trente
|
||||
coups de bâton; le lendemain, il fait l'exercice un peu moins
|
||||
mal, et il ne reçoit que vingt coups; le surlendemain, on ne lui
|
||||
en donne que dix, et il est regardé par ses camarades comme un
|
||||
prodige.
|
||||
|
||||
Candide, tout stupéfait, ne démêlait pas encore trop bien comment
|
||||
il était un héros. Il s'avisa un beau jour de printemps de
|
||||
s'aller promener, marchant tout droit devant lui, croyant que
|
||||
c'était un privilège de l'espèce humaine, comme de l'espèce
|
||||
animale, de se servir de ses jambes à son plaisir. Il n'eut pas
|
||||
fait deux lieues que voilà quatre autres héros de six pieds qui
|
||||
l'atteignent, qui le lient, qui le mènent dans un cachot. On lui
|
||||
demanda juridiquement ce qu'il aimait le mieux d'être fustigé
|
||||
trente-six fois par tout le régiment, ou de recevoir à-la-fois
|
||||
douze balles de plomb dans la cervelle. Il eut beau dire que les
|
||||
volontés sont libres, et qu'il ne voulait ni l'un ni l'autre, il
|
||||
fallut faire un choix; il se détermina, en vertu du don de Dieu
|
||||
qu'on nomme _liberté_, à passer trente-six fois par les
|
||||
baguettes; il essuya deux promenades. Le régiment était composé
|
||||
de deux mille hommes; cela lui composa quatre mille coups de
|
||||
baguette, qui, depuis la nuque du cou jusqu'au cul, lui
|
||||
découvrirent les muscles et les nerfs. Comme on allait procéder
|
||||
à la troisième course, Candide, n'en pouvant plus, demanda en
|
||||
grâce qu'on voulût bien avoir la bonté de lui casser la tête; il
|
||||
obtint cette faveur; on lui bande les yeux; on le fait mettre à
|
||||
genoux. Le roi des Bulgares passe dans ce moment, s'informe du
|
||||
crime du patient; et comme ce roi avait un grand génie, il
|
||||
comprit, par tout ce qu'il apprit de Candide, que c'était un
|
||||
jeune métaphysicien fort ignorant des choses de ce monde, et il
|
||||
lui accorda sa grâce avec une clémence qui sera louée dans tous
|
||||
les journaux et dans tous les siècles. Un brave chirurgien
|
||||
guérit Candide en trois semaines avec les émollients enseignés
|
||||
par Dioscoride. Il avait déjà un peu de peau et pouvait marcher,
|
||||
quand le roi des Bulgares livra bataille au roi des Abares.
|
||||
|
||||
|
||||
|
||||
CHAPITRE III.
|
||||
|
||||
Comment Candide se sauva d'entre les Bulgares, et ce qu'il
|
||||
devint.
|
||||
|
||||
|
||||
Rien n'était si beau, si leste, si brillant, si bien ordonné que
|
||||
les deux armées. Les trompettes, les fifres, les hautbois, les
|
||||
tambours, les canons; formaient une harmonie telle qu'il n'y en
|
||||
eut jamais en enfer. Les canons renversèrent d'abord à peu près
|
||||
six mille hommes de chaque côté; ensuite la mousqueterie ôta du
|
||||
meilleur des mondes environ neuf à dix mille coquins qui en
|
||||
infectaient la surface. La baïonnette fut aussi la raison
|
||||
suffisante de la mort de quelques milliers d'hommes. Le tout
|
||||
pouvait bien se monter à une trentaine de mille âmes. Candide,
|
||||
qui tremblait comme un philosophe, se cacha du mieux qu'il put
|
||||
pendant cette boucherie héroïque.
|
||||
|
||||
Enfin, tandis que les deux rois fesaient chanter des _Te Deum_,
|
||||
chacun dans son camp, il prit le parti d'aller raisonner ailleurs
|
||||
des effets et des causes. Il passa par-dessus des tas de morts
|
||||
et de mourants, et gagna d'abord un village voisin; il était en
|
||||
cendres: c'était un village abare que les Bulgares avaient brûlé,
|
||||
selon les lois du droit public. Ici des vieillards criblés de
|
||||
coups regardaient mourir leurs femmes égorgées, qui tenaient
|
||||
leurs enfants à leurs mamelles sanglantes; là des filles
|
||||
éventrées après avoir assouvi les besoins naturels de quelques
|
||||
héros, rendaient les derniers soupirs; d'autres à demi brûlées
|
||||
criaient qu'on achevât de leur donner la mort. Des cervelles
|
||||
étaient répandues sur la terre à côté de bras et de jambes
|
||||
coupés.
|
||||
|
||||
Candide s'enfuit au plus vite dans un autre village: il
|
||||
appartenait à des Bulgares, et les héros abares l'avaient traité
|
||||
de même. Candide, toujours marchant sur des membres palpitants
|
||||
ou à travers des ruines, arriva enfin hors du théâtre de la
|
||||
guerre, portant quelques petites provisions dans son bissac, et
|
||||
n'oubliant jamais mademoiselle Cunégonde. Ses provisions lui
|
||||
manquèrent quand il fut en Hollande; mais ayant entendu dire que
|
||||
tout le monde était riche dans ce pays-là, et qu'on y était
|
||||
chrétien, il ne douta pas qu'on ne le traitât aussi bien qu'il
|
||||
l'avait été dans le château de M. le baron, avant qu'il en eût
|
||||
été chassé pour les beaux yeux de mademoiselle Cunégonde.
|
||||
|
||||
Il demanda l'aumône à plusieurs graves personnages, qui lui
|
||||
répondirent tous que, s'il continuait à faire ce métier, on
|
||||
l'enfermerait dans une maison de correction pour lui apprendre à
|
||||
vivre.
|
||||
|
||||
Il s'adressa ensuite à un homme qui venait de parler tout seul
|
||||
une heure de suite sur la charité dans une grande assemblée. Cet
|
||||
orateur le regardant de travers lui dit: Que venez-vous faire
|
||||
ici? y êtes-vous pour la bonne cause? Il n'y a point d'effet sans
|
||||
cause, répondit modestement Candide; tout est enchaîné
|
||||
nécessairement et arrangé pour le mieux. Il a fallu que je fusse
|
||||
chassé d'auprès de mademoiselle Cunégonde, que j'aie passé par
|
||||
les baguettes, et il faut que je demande mon pain, jusqu'à ce que
|
||||
je puisse en gagner; tout cela ne pouvait être autrement. Mon
|
||||
ami, lui dit l'orateur, croyez-vous que le pape soit
|
||||
l'antechrist? Je ne l'avais pas encore entendu dire, répondit
|
||||
Candide: mais qu'il le soit, ou qu'il ne le soit pas, je manque
|
||||
de pain. Tu ne mérites pas d'en manger, dit l'autre: va, coquin,
|
||||
va, misérable, ne m'approche de ta vie. La femme de l'orateur
|
||||
ayant mis la tête à la fenêtre, et avisant un homme qui doutait
|
||||
que le pape fût antechrist, lui répandit sur le chef un
|
||||
plein..... O ciel! à quel excès se porte le zèle de la religion
|
||||
dans les dames!
|
||||
|
||||
Un homme qui n'avait point été baptisé, un bon anabaptiste, nommé
|
||||
Jacques, vit la manière cruelle et ignominieuse dont on traitait
|
||||
ainsi un de ses frères, un être à deux pieds sans plumes, qui
|
||||
avait une âme; il l'amena chez lui, le nettoya, lui donna du pain
|
||||
et de la bière, lui fit présent de deux florins, et voulut même
|
||||
lui apprendre à travailler dans ses manufactures aux étoffes de
|
||||
Perse qu'on fabrique en Hollande. Candide se prosternant presque
|
||||
devant lui, s'écriait: Maître Pangloss me l'avait bien dit que
|
||||
tout est au mieux dans ce monde, car je suis infiniment plus
|
||||
touché de votre extrême générosité que de la dureté de ce
|
||||
monsieur à manteau noir, et de madame son épouse.
|
||||
|
||||
Le lendemain, en se promenant, il rencontra un gueux tout couvert
|
||||
de pustules, les yeux morts, le bout du nez rongé, la bouche de
|
||||
travers, les dents noires, et parlant de la gorge, tourmenté
|
||||
d'une toux violente, et crachant une dent à chaque effort.
|
||||
|
||||
|
||||
|
||||
CHAPITRE IV.
|
||||
|
||||
Comment Candide rencontra son ancien maître de philosophie, le
|
||||
docteur Pangloss, et ce qui en advint.
|
||||
|
||||
|
||||
Candide, plus ému encore de compassion que d'horreur, donna à cet
|
||||
épouvantable gueux les deux florins qu'il avait reçus de son
|
||||
honnête anabaptiste Jacques. Le fantôme le regarda fixement,
|
||||
versa des larmes, et sauta à son cou. Candide effrayé recule.
|
||||
Hélas! dit le misérable à l'autre misérable, ne reconnaissez-vous
|
||||
plus votre cher Pangloss? Qu'entends-je? vous, mon cher maître!
|
||||
vous, dans cet état horrible! quel malheur vous est-il donc
|
||||
arrivé? pourquoi n'êtes-vous plus dans le plus beau des châteaux?
|
||||
qu'est devenue mademoiselle Cunégonde, la perle des filles, le
|
||||
chef-d'oeuvre de la nature? Je n'en peux plus, dit Pangloss.
|
||||
Aussitôt Candide le mena dans l'étable de l'anabaptiste, où il
|
||||
lui fit manger un peu de pain; et quand Pangloss fut refait: Eh
|
||||
bien! lui dit-il, Cunégonde? Elle est morte, reprit l'autre.
|
||||
Candide s'évanouit à ce mot: son ami rappela ses sens avec un peu
|
||||
de mauvais vinaigre qui se trouva par hasard dans l'étable.
|
||||
Candide rouvre les yeux. Cunégonde est morte! Ah! meilleur des
|
||||
mondes, où êtes-vous? Mais de quelle maladie est-elle morte? ne
|
||||
serait-ce point de m'avoir vu chasser du beau château de monsieur
|
||||
son père à grands coups de pied? Non, dit Pangloss, elle a été
|
||||
éventrée par des soldats bulgares, après avoir été violée autant
|
||||
qu'on peut l'être; ils ont cassé la tête à monsieur le baron qui
|
||||
voulait la défendre; madame la baronne a été coupée en morceaux;
|
||||
mon pauvre pupille traité précisément comme sa soeur; et quant au
|
||||
château, il n'est pas resté pierre sur pierre, pas une grange,
|
||||
pas un mouton, pas un canard, pas un arbre; mais nous avons été
|
||||
bien vengés, car les Abares en ont fait autant dans une baronnie
|
||||
voisine qui appartenait à un seigneur bulgare.
|
||||
|
||||
A ce discours, Candide s'évanouit encore; mais revenu à soi, et
|
||||
ayant dit tout ce qu'il devait dire, il s'enquit de la cause et
|
||||
de l'effet, et de la raison suffisante qui avait mis Pangloss
|
||||
dans un si piteux état. Hélas! dit l'autre, c'est l'amour:
|
||||
l'amour, le consolateur du genre humain, le conservateur de
|
||||
l'univers, l'âme de tous les êtres sensibles, le tendre amour.
|
||||
Hélas! dit Candide, je l'ai connu cet amour, ce souverain des
|
||||
coeurs, cette âme de notre âme; il ne m'a jamais valu qu'un
|
||||
baiser et vingt coups de pied au cul. Comment cette belle cause
|
||||
a-t-elle pu produire en vous un effet si abominable?
|
||||
|
||||
Pangloss répondit en ces termes: O mon cher Candide! vous avez
|
||||
connu Paquette, cette jolie suivante de notre auguste baronne:
|
||||
j'ai goûté dans ses bras les délices du paradis, qui ont produit
|
||||
ces tourments d'enfer dont vous me voyez dévoré; elle en était
|
||||
infectée, elle en est peut-être morte. Paquette tenait ce
|
||||
présent d'un cordelier très savant qui avait remonté à la source,
|
||||
car il l'avait eu d'une vieille comtesse, qui l'avait reçu d'un
|
||||
capitaine de cavalerie, qui le devait à une marquise, qui le
|
||||
tenait d'un page, qui l'avait reçu d'un jésuite, qui, étant
|
||||
novice, l'avait eu en droite ligne d'un des compagnons de
|
||||
Christophe Colomb. Pour moi, je ne le donnerai à personne, car
|
||||
je me meurs.
|
||||
|
||||
O Pangloss! s'écria Candide, voilà une étrange généalogie!
|
||||
n'est-ce pas le diable qui en fut la souche? Point du tout,
|
||||
répliqua ce grand homme; c'était une chose indispensable dans le
|
||||
meilleur des mondes, un ingrédient nécessaire; car si Colomb
|
||||
n'avait pas attrapé dans une île de l'Amérique cette maladie[1]
|
||||
qui empoisonne la source de la génération, qui souvent même
|
||||
empêche la génération, et qui est évidemment l'opposé du grand
|
||||
but de la nature, nous n'aurions ni le chocolat ni la cochenille;
|
||||
il faut encore observer que jusqu'aujourd'hui, dans notre
|
||||
continent, cette maladie nous est particulière, comme la
|
||||
controverse. Les Turcs, les Indiens, les Persans, les Chinois,
|
||||
les Siamois, les Japonais, ne la connaissent pas encore; mais il
|
||||
y a une raison suffisante pour qu'ils la connaissent à leur tour
|
||||
dans quelques siècles. En attendant elle a fait un merveilleux
|
||||
progrès parmi nous, et surtout dans ces grandes armées composées
|
||||
d'honnêtes stipendiaires bien élevés, qui décident du destin des
|
||||
états; on peut assurer que, quand trente mille hommes combattent
|
||||
en bataille rangée contre des troupes égales en nombre, il y a
|
||||
environ vingt mille vérolés de chaque côté.
|
||||
|
||||
[1] Voyez tome XXXI, page 7. B.
|
||||
|
||||
|
||||
Voilà qui est admirable, dit Candide; mais il faut vous faire
|
||||
guérir. Et comment le puis-je? dit Pangloss; je n'ai pas le sou,
|
||||
mon ami, et dans toute l'étendue de ce globe on ne peut ni se
|
||||
faire saigner, ni prendre un lavement sans payer, ou sans qu'il y
|
||||
ait quelqu'un qui paie pour nous.
|
||||
|
||||
Ce dernier discours détermina Candide; il alla se jeter aux pieds
|
||||
de son charitable anabaptiste Jacques, et lui fit une peinture si
|
||||
touchante de l'état où son ami était réduit, que le bon-homme
|
||||
n'hésita pas à recueillir le docteur Pangloss; il le fit guérir à
|
||||
ses dépens. Pangloss, dans la cure, ne perdit qu'un oeil et une
|
||||
oreille. Il écrivait bien, et savait parfaitement
|
||||
l'arithmétique. L'anabaptiste Jacques en fit son teneur de
|
||||
livres. Au bout de deux mois, étant obligé d'aller à Lisbonne
|
||||
pour les affaires de son commerce, il mena dans son vaisseau ses
|
||||
deux philosophes. Pangloss lui expliqua comment tout était on ne
|
||||
peut mieux. Jacques n'était pas de cet avis. Il faut bien,
|
||||
disait-il, que les hommes aient un peu corrompu la nature, car
|
||||
ils ne sont point nés loups, et ils sont devenus loups. Dieu ne
|
||||
leur a donné ni canons de vingt-quatre, ni baïonnettes, et ils se
|
||||
sont fait des baïonnettes et des canons pour se détruire. Je
|
||||
pourrais mettre en ligne de compte les banqueroutes, et la
|
||||
justice qui s'empare des biens des banqueroutiers pour en
|
||||
frustrer les créanciers. Tout cela était indispensable,
|
||||
répliquait le docteur borgne, et les malheurs particuliers font
|
||||
le bien général; de sorte que plus il y a de malheurs
|
||||
particuliers, et plus tout est bien. Tandis qu'il raisonnait,
|
||||
l'air s'obscurcit, les vents soufflèrent des quatre coins du
|
||||
monde, et le vaisseau fut assailli de la plus horrible tempête, à
|
||||
la vue du port de Lisbonne.
|
||||
|
||||
|
||||
CHAPITRE V.
|
||||
|
||||
Tempête, naufrage, tremblement de terre, et ce qui advint du
|
||||
docteur Pangloss, de Candide, et de l'anabaptiste Jacques.
|
||||
|
||||
La moitié des passagers affaiblis, expirants de ces angoisses
|
||||
inconcevables que le roulis d'un vaisseau porte dans les nerfs et
|
||||
dans toutes les humeurs du corps agitées en sens contraires,
|
||||
n'avait pas même la force de s'inquiéter du danger. L'autre
|
||||
moitié jetait des cris et fesait des prières; les voiles étaient
|
||||
déchirées, les mâts brisés, le vaisseau entr'ouvert. Travaillait
|
||||
qui pouvait, personne ne s'entendait, personne ne commandait.
|
||||
L'anabaptiste aidait un peu à la manoeuvre; il était sur le
|
||||
tillac; un matelot furieux le frappe rudement et l'étend sur les
|
||||
planches; mais du coup qu'il lui donna, il eut lui-même une si
|
||||
violente secousse, qu'il tomba hors du vaisseau, la tête la
|
||||
première. Il restait suspendu et accroché à une partie de mât
|
||||
rompu. Le bon Jacques court à son secours, l'aide à remonter, et
|
||||
de l'effort qu'il fait, il est précipité dans la mer à la vue du
|
||||
matelot, qui le laissa périr sans daigner seulement le regarder.
|
||||
Candide approche, voit son bienfaiteur qui reparaît un moment, et
|
||||
qui est englouti pour jamais. Il veut se jeter après lui dans la
|
||||
mer: le philosophe Pangloss l'en empêche, en lui prouvant que la
|
||||
rade de Lisbonne avait été formée exprès pour que cet anabaptiste
|
||||
s'y noyât. Tandis qu'il le prouvait _à priori_, le vaisseau
|
||||
s'entr'ouvre, tout périt à la réserve de Pangloss, de Candide, et
|
||||
de ce brutal de matelot qui avait noyé le vertueux anabaptiste;
|
||||
le coquin nagea heureusement jusqu'au rivage, où Pangloss et
|
||||
Candide furent portés sur une planche.
|
||||
|
||||
Quand ils furent revenus un peu à eux, ils marchèrent vers
|
||||
Lisbonne; il leur restait quelque argent, avec lequel ils
|
||||
espéraient se sauver de la faim après avoir échappé à la tempête.
|
||||
|
||||
A peine ont-ils mis le pied dans la ville, en pleurant la mort de
|
||||
leur bienfaiteur, qu'ils sentent la terre trembler sous leurs
|
||||
pas[1]; la mer s'élève en bouillonnant dans le port, et brise les
|
||||
vaisseaux qui sont à l'ancre. Des tourbillons de flammes et de
|
||||
cendres couvrent les rues et les places publiques; les maisons
|
||||
s'écroulent, les toits sont renversés sur les fondements, et les
|
||||
fondements se dispersent; trente mille habitants de tout âge et
|
||||
de tout sexe sont écrasés sous des ruines. Le matelot disait en
|
||||
sifflant et en jurant: il y aura quelque chose à gagner ici.
|
||||
Quelle peut être la raison suffisante de ce phénomène? disait
|
||||
Pangloss. Voici le dernier jour du monde! s'écriait Candide.
|
||||
Le matelot court incontinent au milieu des débris, affronte la
|
||||
mort pour trouver de l'argent, en trouve, s'en empare, s'enivre,
|
||||
et ayant cuvé son vin, achète les faveurs de la première fille de
|
||||
bonne volonté qu'il rencontre sur les ruines des maisons
|
||||
détruites, et au milieu des mourants et des morts. Pangloss le
|
||||
tirait cependant par la manche: Mon ami, lui disait-il, cela
|
||||
n'est pas bien, vous manquez à la raison universelle, vous prenez
|
||||
mal votre temps. Tête et sang, répondit l'autre, je suis matelot
|
||||
et né à Batavia; j'ai marché quatre fois sur le crucifix dans
|
||||
quatre voyages au Japon[2]; tu as bien trouvé ton homme avec ta
|
||||
raison universelle!
|
||||
|
||||
|
||||
[1] Le tremblement de terre de Lisbonne est du 1er novembre 1755.
|
||||
B.
|
||||
|
||||
[2] Voyez tome XVIII, page 470. B.
|
||||
|
||||
|
||||
Quelques éclats de pierre avaient blessé Candide; il était étendu
|
||||
dans la rue et couvert de débris. Il disait à Pangloss: Hélas!
|
||||
procure-moi un peu de vin et d'huile; je me meurs. Ce
|
||||
tremblement de terre n'est pas une chose nouvelle, répondit
|
||||
Pangloss; la ville de Lima éprouva les mêmes secousses en
|
||||
Amérique l'année passée; mêmes causes, mêmes effets; il y a
|
||||
certainement une traînée de soufre sous terre depuis Lima jusqu'à
|
||||
Lisbonne. Rien n'est plus probable, dit Candide; mais, pour
|
||||
Dieu, un peu d'huile et de vin. Comment probable? répliqua le
|
||||
philosophe, je soutiens que la chose est démontrée. Candide
|
||||
perdit connaissance, et Pangloss lui apporta un peu d'eau d'une
|
||||
fontaine voisine.
|
||||
|
||||
Le lendemain, ayant trouvé quelques provisions de bouche en se
|
||||
glissant à travers des décombres, ils réparèrent un peu leurs
|
||||
forces. Ensuite ils travaillèrent comme les autres à soulager
|
||||
les habitants échappés à la mort. Quelques citoyens, secourus
|
||||
par eux, leur donnèrent un aussi bon dîner qu'on le pouvait dans
|
||||
un tel désastre: il est vrai que le repas était triste; les
|
||||
convives arrosaient leur pain de leurs larmes; mais Pangloss les
|
||||
consola, en les assurant que les choses ne pouvaient être
|
||||
autrement: Car, dit-il, tout ceci est ce qu'il y a de mieux; car
|
||||
s'il y a un volcan à Lisbonne, il ne pouvait être ailleurs; car
|
||||
il est impossible que les choses ne soient pas où elles sont, car
|
||||
tout est bien.
|
||||
|
||||
Un petit homme noir, familier de l'inquisition, lequel était à
|
||||
côté de lui, prit poliment la parole et dit: Apparemment que
|
||||
monsieur ne croit pas au péché originel; car si tout est au
|
||||
mieux, il n'y a donc eu ni chute ni punition.
|
||||
|
||||
Je demande très humblement pardon à votre excellence, répondit
|
||||
Pangloss encore plus poliment, car la chute de l'homme et la
|
||||
malédiction entraient nécessairement dans le meilleur des mondes
|
||||
possibles. Monsieur ne croit donc pas à la liberté? dit le
|
||||
familier. Votre excellence m'excusera, dit Pangloss; la liberté
|
||||
peut subsister avec la nécessité absolue; car il était nécessaire
|
||||
que nous fussions libres; car enfin la volonté déterminée......
|
||||
Pangloss était au milieu de sa phrase, quand Je familier fit un
|
||||
signe de tête à son estafier qui lui servait à boire du vin de
|
||||
Porto ou d'Oporto.
|
||||
178
vendor/golang.org/x/text/encoding/testdata/rashomon-euc-jp.txt
generated
vendored
178
vendor/golang.org/x/text/encoding/testdata/rashomon-euc-jp.txt
generated
vendored
|
|
@ -1,178 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/1982/pg1982.txt
|
||||
--------
|
||||
羅生門
|
||||
|
||||
芥川龍之介
|
||||
|
||||
或日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。 広い門
|
||||
の下には、この男の外に誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、きりぎ
|
||||
りすが一匹とまっている。羅生門が、朱雀大路にある以上は、この男の外にも、雨やみ
|
||||
をする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男の外
|
||||
に誰もいない。
|
||||
何故かと云うと、この二三年、京都には、地震とか辻風とか火事とか饑饉とか云う災
|
||||
いがつづいて起こった。そこで洛中のさびれ方は一通りでない。旧記によると、仏像や
|
||||
仏具を打砕いて、その丹がついたり、金銀の箔(はく)がついたりした木を、路ばたに
|
||||
つみ重ねて薪の料(しろ)に売っていたと云うことである。洛中がその始末であるから、
|
||||
羅生門の修理などは、元より誰も捨てて顧みる者がなかった。するとその荒れ果てたの
|
||||
をよい事にして、狐狸(こり)が棲む。盗人が棲む。とうとうしまいには、引取り手の
|
||||
ない死人を、この門へ持って来て、捨てて行くと云う習慣さえ出来た。そこで、日の目
|
||||
が見えなくなると、誰でも気味を悪がって、この門の近所へは足ぶみをしない事になっ
|
||||
てしまったのである。
|
||||
その代り又鴉が何処からか、たくさん集まって来た。昼間見ると、その鴉が何羽とな
|
||||
く輪を描いて、高い鴟尾(しび)のまわりを啼きながら、飛びまわっている。殊に門の
|
||||
上の空が、夕焼けであかくなる時には、それが胡麻をまいたようにはっきり見えた。鴉
|
||||
は、勿論、門の上にある死人の肉を、啄みに来るのである。ーー尤も今日は、刻限が遅
|
||||
いせいか、一羽も見えない。唯、所々、崩れかかった、そうしてその崩れ目に長い草の
|
||||
はえた石段の上に、鴉の糞(くそ)が、点々と白くこびりついているのが見える。下人
|
||||
は七段ある石段の一番上の段に洗いざらした紺の襖(あお)の尻を据えて、右の頬に出
|
||||
来た、大きな面皰(にきび)を気にしながら、ぼんやり、雨のふるのを眺めているので
|
||||
ある。
|
||||
作者はさっき、「下人が雨やみを待っていた」と書いた。しかし、下人は、雨がやん
|
||||
でも格別どうしようと云う当てはない。ふだんなら、勿論、主人の家へ帰る可き筈であ
|
||||
る。所がその主人からは、四五日前に暇を出された。前にも書いたように、当時京都の
|
||||
町は一通りならず衰微していた。今この下人が、永年、使われていた主人から暇を出さ
|
||||
れたのも、この衰微の小さな余波に外ならない。だから、「下人が雨やみを待っていた」
|
||||
と云うよりも、「雨にふりこめられた下人が、行き所がなくて、途方にくれていた」と
|
||||
云う方が、適当である。その上、今日の空模様も少なからずこの平安朝の下人の
|
||||
Sentimentalismeに影響した。申(さる)の刻下がりからふり出した雨は、未だに上
|
||||
がるけしきがない。そこで、下人は、何を措いても差当たり明日の暮しをどうにかしよ
|
||||
うとしてーー云わばどうにもならない事を、どうにかしようとして、とりとめもない考
|
||||
えをたどりながら、さっきから朱雀大路にふる雨の音を聞くともなく聞いていた。
|
||||
雨は羅生門をつつんで、遠くから、ざあっと云う音をあつめてくる。夕闇は次第に空
|
||||
を低くして、見上げると、門の屋根が、斜めにつき出した甍(いらか)の先に、重たく
|
||||
うす暗い雲を支えている。
|
||||
どうにもならない事を、どうにかする為には、手段を選んでいる遑(いとま)はない。
|
||||
選んでいれば、築地(ついじ)の下か、道ばたの土の上で、饑死(うえじに)をするば
|
||||
かりである。そうして、この門の上へ持って来て、犬のように捨てられてしまうばかり
|
||||
である。選ばないとすればーー下人の考えは、何度も同じ道を低徊した揚句に、やっと
|
||||
この局所へ逢着した。しかしこの「すれば」は、いつもでたっても、結局「すれば」で
|
||||
あった。下人は、手段を選ばないという事を肯定しながらも、この「すれば」のかたを
|
||||
つける為に、当然、この後に来る可き「盗人になるより外に仕方がない」と云う事を、
|
||||
積極的に肯定するだけの、勇気が出ずにいたのである。
|
||||
下人は大きな嚏(くさめ)をして、それから、大儀そうに立上がった。夕冷えのする
|
||||
京都は、もう火桶が欲しい程の寒さである。風は門の柱と柱との間を、夕闇と共に遠慮
|
||||
なく、吹きぬける。丹塗の柱にとまっていたきりぎりすも、もうどこかへ行ってしまっ
|
||||
た。
|
||||
下人は、頸をちぢめながら、山吹の汗衫(かざみ)に重ねた、紺の襖の肩を高くして
|
||||
門のまわりを見まわした。雨風の患のない、人目にかかる惧のない、一晩楽にねられそ
|
||||
うな所があれば、そこでともかくも、夜を明かそうと思ったからである。すると、幸門
|
||||
の上の楼へ上る、幅の広い、之も丹を塗った梯子が眼についた。上なら、人がいたにし
|
||||
ても、どうせ死人ばかりである。下人は、そこで腰にさげた聖柄(ひじりづか)の太刀
|
||||
が鞘走らないように気をつけながら、藁草履をはいた足を、その梯子の一番下の段へふ
|
||||
みかけた。
|
||||
それから、何分かの後である。羅生門の楼の上へ出る、幅の広い梯子の中段に、一人
|
||||
の男が、猫のように身をちぢめて、息を殺しながら、上の容子を窺っていた。楼の上か
|
||||
らさす火の光が、かすかに、その男の右の頬をぬらしている。短い鬚(ひげ)の中に、
|
||||
赤く膿を持った面皰のある頬である。下人は、始めから、この上にいる者は、死人ばか
|
||||
りだと高を括っていた。それが、梯子を二三段上って見ると、上では誰か火をとぼして、
|
||||
しかもその火を其処此処と動かしているらしい。これは、その濁った、黄いろい光が、
|
||||
隅々に蜘蛛の巣をかけた天井裏に、ゆれながら映ったので、すぐにそれと知れたのであ
|
||||
る。この雨の夜に、この羅生門の上で、火をともしているからは、どうせ唯の者ではな
|
||||
い。
|
||||
下人は、宮守(やもり)のように足音をぬすんで、やっと急な梯子を、一番上の段ま
|
||||
で這うようにして上りつめた。そうして体を出来るだけ、平にしながら、頸を出来るだ
|
||||
け、前へ出して、恐る恐る、楼の内を覗いて見た。
|
||||
見ると、楼の内には、噂に聞いた通り、幾つかの屍骸(しがい)が、無造作に棄てて
|
||||
あるが、火の光の及ぶ範囲が、思ったより狭いので、数は幾つともわからない。唯、お
|
||||
ぼろげながら、知れるのは、その中に裸の屍骸と、着物を着た屍骸とがあると云う事で
|
||||
ある。勿論、中には女も男もまじっているらしい。そうして、その屍骸は皆、それが、
|
||||
嘗(かつて)、生きていた人間だと云う事実さえ疑われる程、土を捏ねて造った人形の
|
||||
ように、口を開いたり、手を延ばしたりして、ごろごろ床の上にころがっていた。しか
|
||||
も、肩とか胸とかの高くなっている部分に、ぼんやりした火の光をうけて、低くなって
|
||||
いる部分の影を一層暗くしながら、永久に唖(おし)の如く黙っていた。
|
||||
下人は、それらの屍骸の腐爛した臭気に思わず、鼻を掩った(おおった)。しかし、
|
||||
その手は、次の瞬間には、もう鼻を掩う事を忘れていた。或る強い感情が殆悉(ほとん
|
||||
どことごとく)この男の嗅覚を奪ってしまったからである。
|
||||
下人の眼は、その時、はじめて、其屍骸の中に蹲っている(うずくまっている)人間
|
||||
を見た。檜肌色(ひはだいろ)の着物を著た、背の低い、痩せた、白髪頭の、猿のよう
|
||||
な老婆である。その老婆は、右の手に火をともした松の木片を持って、その屍骸の一つ
|
||||
の顔を覗きこむように眺めていた。髪の毛の長い所を見ると、多分女の屍骸であろう。
|
||||
下人は、六分の恐怖と四分の好奇心とに動かされて、暫時は呼吸(いき)をするのさ
|
||||
え忘れていた。旧記の記者の語を借りれば、「頭身(とうしん)の毛も太る」ように感
|
||||
じたのである。すると、老婆は、松の木片を、床板の間に挿して、それから、今まで眺
|
||||
めていた屍骸の首に両手をかけると、丁度、猿の親が猿の子の虱(しらみ)をとるよう
|
||||
に、その長い髪の毛を一本ずつ抜きはじめた。髪は手に従って抜けるらしい。
|
||||
その髪の毛が、一本ずつ抜けるのに従って下人の心からは、恐怖が少しずつ消えて行っ
|
||||
た。そうして、それと同時に、その老婆に対するはげしい憎悪が、少しずつ動いて来た。
|
||||
いや、この老婆に対すると云っては、語弊があるかも知れない。寧(むしろ)、あらゆ
|
||||
る悪に対する反感が、一分毎に強さを増して来たのである。この時、誰かがこの下人に、
|
||||
さっき門の下でこの男が考えていた、饑死(うえじに)をするか盗人になるかと云う問
|
||||
題を、改めて持出したら、恐らく下人は、何の未練もなく、饑死を選んだ事であろう。
|
||||
それほど、この男の悪を憎む心は、老婆の床に挿した松の木片のように、勢よく燃え上
|
||||
がりだしていたのである。
|
||||
下人には、勿論、何故老婆が死人の髪の毛を抜くかわからなかった。従って、合理的
|
||||
には、それを善悪の何れに片づけてよいか知らなかった。しかし下人にとっては、この
|
||||
雨の夜に、この羅生門の上で、死人の髪の毛を抜くと云う事が、それだけで既に許す可
|
||||
らざる悪であった。勿論 下人は さっき迄自分が、盗人になる気でいた事なぞは と
|
||||
うに忘れているのである。
|
||||
そこで、下人は、両足に力を入れて、いかなり、梯子から上へ飛び上がった そうし
|
||||
て聖柄(ひじりづか)の太刀に手をかけながら、大股に老婆の前へ歩みよった。老婆が
|
||||
驚いたのは 云う迄もない。
|
||||
老婆は、一目下人を見ると、まるで弩(いしゆみ)にでも弾かれたように 飛び上がっ
|
||||
た。
|
||||
「おのれ、どこへ行く。」
|
||||
下人は、老婆が屍骸につまづきながら、慌てふためいて逃げようとする行手を塞いで、
|
||||
こう罵った。老婆は、それでも下人をつきのけて行こうとする。下人は又、それを行か
|
||||
すまいとして、押しもどす。二人は屍骸の中で、暫、無言のまま、つかみ合った。しか
|
||||
し勝負は、はじめから、わかっている。下人はとうとう、老婆の腕をつかんで、無理に
|
||||
そこへねじ倒した。丁度、鶏(とり)の脚のような、骨と皮ばかりの腕である。
|
||||
「何をしていた。さあ何をしていた。云え。云わぬと これだぞよ。」
|
||||
下人は、老婆をつき放すと、いきなり、太刀の鞘を払って、白い鋼(はがね)の色を
|
||||
その眼の前へつきつけた。けれども、老婆は黙っている。両手をわなわなふるわせて、
|
||||
肩で息を切りながら、眼を、眼球がまぶたの外へ出そうになる程、見開いて、唖のよう
|
||||
に執拗(しゅうね)く黙っている。これを見ると、下人は始めて明白にこの老婆の生死
|
||||
が、全然、自分の意志に支配されていると云う事を意識した。そうして、この意識は、
|
||||
今まではげしく燃えていた憎悪の心を何時(いつ)の間にか冷ましてしまった。後に残っ
|
||||
たのは、唯、或仕事をして、それが円満に成就した時の、安らかな得意と満足とがある
|
||||
ばかりである。そこで、下人は、老婆を、見下げながら、少し声を柔げてこう云った。
|
||||
「己は検非違使(けびいし)の庁の役人などではない。今し方この門の下を通りかかっ
|
||||
た旅の者だ。だからお前に縄をかけて、どうしようと云うような事はない。唯今時分、
|
||||
この門の上で、何をしていたのだか、それを己に話さえすればいいのだ。」
|
||||
すると、老婆は、見開いた眼を、一層大きくして、じっとその下人の顔を見守った。
|
||||
まぶたの赤くなった、肉食鳥のような、鋭い眼で見たのである。それから、皺で、殆、
|
||||
鼻と一つになった唇を何か物でも噛んでいるように動かした。細い喉で、尖った喉仏の
|
||||
動いているのが見える。その時、その喉から、鴉(からす)の啼くような声が、喘ぎ喘
|
||||
ぎ、下人の耳へ伝わって来た。
|
||||
「この髪を抜いてな、この女の髪を抜いてな、鬘(かつら)にしようと思うたの
|
||||
じゃ。」
|
||||
下人は、老婆の答が存外、平凡なのに失望した。そうして失望すると同時に、又前の
|
||||
憎悪が、冷な侮蔑と一しょに、心の中へはいって来た。すると その気色(けしき)が、
|
||||
先方へも通じたのであろう。老婆は、片手に、まだ屍骸の頭から奪(と)った長い抜け
|
||||
毛を持ったなり、蟇(ひき)のつぶやくような声で、口ごもりながら、こんな事を云っ
|
||||
た。
|
||||
成程、死人の髪の毛を抜くと云う事は、悪い事かね知れぬ。しかし、こう云う死人の
|
||||
多くは、皆 その位な事を、されてもいい人間ばかりである。現に、自分が今、髪を抜
|
||||
いた女などは、蛇を四寸ばかりずつに切って干したのを、干魚(ほしうお)だと云って、
|
||||
太刀帯(たちはき)の陣へ売りに行った。疫病にかかって死ななかったなら、今でも売
|
||||
りに行っていたかもしれない。しかも、この女の売る干魚は、味がよいと云うので、太
|
||||
刀帯たちが、欠かさず菜料に買っていたのである。自分は、この女のした事が悪いとは
|
||||
思わない。しなければ、饑死(えうじに)をするので、仕方がなくした事だからである。
|
||||
だから、又今、自分のしていた事も悪い事とは思わない。これもやはりしなければ、饑
|
||||
死をするので、仕方がなくする事だからである。そうして、その仕方がない事を、よく
|
||||
知っていたこの女は、自分のする事を許してくれるのにちがいないと思うからであ
|
||||
る。ーー老婆は、大体こんな意味の事を云った。
|
||||
下人は、太刀を鞘におさめて、その太刀の柄を左の手でおさえながら、冷然として、
|
||||
この話を聞いていた。勿論、 右の手では、赤く頬に膿を持た大きな面皰(にきび)を
|
||||
気にしながら、聞いているのである。しかし、之を聞いている中に、下人の心には、或
|
||||
勇気が生まれて来た。それは さっき、門の下でこの男に欠けていた勇気である。そう
|
||||
して、又さっき、この門の上へ上(あが)って、その老婆を捕えた時の勇気とは、全然、
|
||||
反対な方向に動こうとする勇気である。下人は、饑死をするか盗人になるかに迷わなかっ
|
||||
たばかりではない。その時のこの男の心もちから云えば、饑死などと云う事は、殆、考
|
||||
える事さえ出来ない程、意識の外に追い出されていた。
|
||||
「きっと、そうか。」
|
||||
老婆の話が完ると、下人は嘲(あざけ)るような声で念を押した。そうして、一足前
|
||||
へ出ると、不意に、右の手を面皰から離して、老婆の襟上(えりがみ)をつかみながら、
|
||||
こう云った。
|
||||
「では、己が引剥(ひはぎ)をしようと恨むまいな。己もそうしなければ、饑死をす
|
||||
る体なのだ。」
|
||||
下人は、すばやく、老婆の着物を剥ぎとった。それから、足にしがみつこうとする老
|
||||
婆を、手荒く屍骸の上へ蹴倒した。梯子の口までは、僅に五歩を数えるばかりである。
|
||||
下人は、剥ぎとった桧肌色の着物をわきにかかえて、またたく間に急な梯子を夜の底へ
|
||||
かけ下りた。
|
||||
暫、死んだように倒れていた老婆が、屍骸の中から、その裸の体を起こしたのは、そ
|
||||
れから間もなくの事である。老婆は、つぶやくような、うめくような声を立てながら、
|
||||
まだ燃えている火の光をたよりに、梯子の口まで、這って行った。そうして、そこから、
|
||||
短い白髪を倒(さかさま)にして、門の下を覗きこんだ。外には、唯、黒洞々(こくと
|
||||
うとう)たる夜があるばかりである。
|
||||
下人は、既に、雨を冒して、京都の町へ強盗を働きに急いでいた。
|
||||
178
vendor/golang.org/x/text/encoding/testdata/rashomon-iso-2022-jp.txt
generated
vendored
178
vendor/golang.org/x/text/encoding/testdata/rashomon-iso-2022-jp.txt
generated
vendored
|
|
@ -1,178 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/1982/pg1982.txt
|
||||
--------
|
||||
$BMe@8Lg(B
|
||||
|
||||
$B3)@nN6G72p(B
|
||||
|
||||
$B!!0?F|$NJkJ}$N;v$G$"$k!#0l?M$N2<?M$,!"Me@8Lg$N2<$G1+$d$_$rBT$C$F$$$?!#!!9-$$Lg(B
|
||||
$B$N2<$K$O!"$3$NCK$N30$KC/$b$$$J$$!#$?$@!"=j!9C0EI$NGm$2$?!"Bg$-$J1_Cl$K!"$-$j$.(B
|
||||
$B$j$9$,0lI$$H$^$C$F$$$k!#Me@8Lg$,!"<k?}BgO)$K$"$k0J>e$O!"$3$NCK$N30$K$b!"1+$d$_(B
|
||||
$B$r$9$k;T=w3^$dYf1(K9;R$,!"$b$&Fs;0?M$O$"$j$=$&$J$b$N$G$"$k!#$=$l$,!"$3$NCK$N30(B
|
||||
$B$KC/$b$$$J$$!#(B
|
||||
$B!!2?8N$+$H1>$&$H!"$3$NFs;0G/!"5~ET$K$O!"CO?L$H$+DTIw$H$+2P;v$H$+q@q<$H$+1>$&:R(B
|
||||
$B$$$,$D$E$$$F5/$3$C$?!#$=$3$GMlCf$N$5$S$lJ}$O0lDL$j$G$J$$!#5l5-$K$h$k$H!"J)A|$d(B
|
||||
$BJ)6q$rBG:U$$$F!"$=$NC0$,$D$$$?$j!"6b6d$NGs!J$O$/!K$,$D$$$?$j$7$?LZ$r!"O)$P$?$K(B
|
||||
$B$D$_=E$M$F?E$NNA!J$7$m!K$KGd$C$F$$$?$H1>$&$3$H$G$"$k!#MlCf$,$=$N;OKv$G$"$k$+$i!"(B
|
||||
$BMe@8Lg$N=$M}$J$I$O!"85$h$jC/$b<N$F$F8\$_$k<T$,$J$+$C$?!#$9$k$H$=$N9S$l2L$F$?$N(B
|
||||
$B$r$h$$;v$K$7$F!"8QC,!J$3$j!K$,@3$`!#Ep?M$,@3$`!#$H$&$H$&$7$^$$$K$O!"0z<h$j<j$N(B
|
||||
$B$J$$;`?M$r!"$3$NLg$X;}$C$FMh$F!"<N$F$F9T$/$H1>$&=,47$5$(=PMh$?!#$=$3$G!"F|$NL\(B
|
||||
$B$,8+$($J$/$J$k$H!"C/$G$b5$L#$r0-$,$C$F!"$3$NLg$N6a=j$X$OB-$V$_$r$7$J$$;v$K$J$C(B
|
||||
$B$F$7$^$C$?$N$G$"$k!#(B
|
||||
$B!!$=$NBe$jKtrm$,2?=h$+$i$+!"$?$/$5$s=8$^$C$FMh$?!#Ck4V8+$k$H!"$=$Nrm$,2?1)$H$J(B
|
||||
$B$/NX$rIA$$$F!"9b$$rvHx!J$7$S!K$N$^$o$j$rSF$-$J$,$i!"Ht$S$^$o$C$F$$$k!#<l$KLg$N(B
|
||||
$B>e$N6u$,!"M<>F$1$G$"$+$/$J$k;~$K$O!"$=$l$,8UKc$r$^$$$?$h$&$K$O$C$-$j8+$($?!#rm(B
|
||||
$B$O!"L^O@!"Lg$N>e$K$"$k;`?M$NFy$r!"Bo$_$KMh$k$N$G$"$k!#!<!<L`$b:#F|$O!"9o8B$,CY(B
|
||||
$B$$$;$$$+!"0l1)$b8+$($J$$!#M#!"=j!9!"Jx$l$+$+$C$?!"$=$&$7$F$=$NJx$lL\$KD9$$Ap$N(B
|
||||
$B$O$($?@PCJ$N>e$K!"rm$NJ5!J$/$=!K$,!"E@!9$HGr$/$3$S$j$D$$$F$$$k$N$,8+$($k!#2<?M(B
|
||||
$B$O<7CJ$"$k@PCJ$N0lHV>e$NCJ$K@v$$$6$i$7$?:0$N2(!J$"$*!K$N?,$r?x$($F!"1&$NKK$K=P(B
|
||||
$BMh$?!"Bg$-$JLLb.!J$K$-$S!K$r5$$K$7$J$,$i!"$\$s$d$j!"1+$N$U$k$N$rD/$a$F$$$k$N$G(B
|
||||
$B$"$k!#(B
|
||||
$B!!:n<T$O$5$C$-!"!V2<?M$,1+$d$_$rBT$C$F$$$?!W$H=q$$$?!#$7$+$7!"2<?M$O!"1+$,$d$s(B
|
||||
$B$G$b3JJL$I$&$7$h$&$H1>$&Ev$F$O$J$$!#$U$@$s$J$i!"L^O@!"<g?M$N2H$X5"$k2D$-H&$G$"(B
|
||||
$B$k!#=j$,$=$N<g?M$+$i$O!";M8^F|A0$K2K$r=P$5$l$?!#A0$K$b=q$$$?$h$&$K!"Ev;~5~ET$N(B
|
||||
$BD.$O0lDL$j$J$i$:?jHy$7$F$$$?!#:#$3$N2<?M$,!"1JG/!";H$o$l$F$$$?<g?M$+$i2K$r=P$5(B
|
||||
$B$l$?$N$b!"$3$N?jHy$N>.$5$JM>GH$K30$J$i$J$$!#$@$+$i!"!V2<?M$,1+$d$_$rBT$C$F$$$?!W(B
|
||||
$B$H1>$&$h$j$b!"!V1+$K$U$j$3$a$i$l$?2<?M$,!"9T$-=j$,$J$/$F!"ESJ}$K$/$l$F$$$?!W$H(B
|
||||
$B1>$&J}$,!"E,Ev$G$"$k!#$=$N>e!":#F|$N6uLOMM$b>/$J$+$i$:$3$NJ?0BD+$N2<?M$N(B
|
||||
Sentimentalisme$B$K1F6A$7$?!#?=!J$5$k!K$N9o2<$,$j$+$i$U$j=P$7$?1+$O!"L$$@$K>e(B
|
||||
$B$,$k$1$7$-$,$J$$!#$=$3$G!"2<?M$O!"2?$rA<$$$F$b:9Ev$?$jL@F|$NJk$7$r$I$&$K$+$7$h(B
|
||||
$B$&$H$7$F!<!<1>$o$P$I$&$K$b$J$i$J$$;v$r!"$I$&$K$+$7$h$&$H$7$F!"$H$j$H$a$b$J$$9M(B
|
||||
$B$($r$?$I$j$J$,$i!"$5$C$-$+$i<k?}BgO)$K$U$k1+$N2;$rJ9$/$H$b$J$/J9$$$F$$$?!#(B
|
||||
$B!!1+$OMe@8Lg$r$D$D$s$G!"1s$/$+$i!"$6$"$C$H1>$&2;$r$"$D$a$F$/$k!#M<0G$O<!Bh$K6u(B
|
||||
$B$rDc$/$7$F!"8+>e$2$k$H!"Lg$N20:,$,!"<P$a$K$D$-=P$7$?a0!J$$$i$+!K$N@h$K!"=E$?$/(B
|
||||
$B$&$90E$$1@$r;Y$($F$$$k!#(B
|
||||
$B!!$I$&$K$b$J$i$J$$;v$r!"$I$&$K$+$9$k0Y$K$O!"<jCJ$rA*$s$G$$$kn#!J$$$H$^!K$O$J$$!#(B
|
||||
$BA*$s$G$$$l$P!"C[CO!J$D$$$8!K$N2<$+!"F;$P$?$NEZ$N>e$G!"q@;`!J$&$($8$K!K$r$9$k$P(B
|
||||
$B$+$j$G$"$k!#$=$&$7$F!"$3$NLg$N>e$X;}$C$FMh$F!"8$$N$h$&$K<N$F$i$l$F$7$^$&$P$+$j(B
|
||||
$B$G$"$k!#A*$P$J$$$H$9$l$P!<!<2<?M$N9M$($O!"2?EY$bF1$8F;$rDcWK$7$?MH6g$K!"$d$C$H(B
|
||||
$B$3$N6I=j$X0)Ce$7$?!#$7$+$7$3$N!V$9$l$P!W$O!"$$$D$b$G$?$C$F$b!"7k6I!V$9$l$P!W$G(B
|
||||
$B$"$C$?!#2<?M$O!"<jCJ$rA*$P$J$$$H$$$&;v$r9NDj$7$J$,$i$b!"$3$N!V$9$l$P!W$N$+$?$r(B
|
||||
$B$D$1$k0Y$K!"EvA3!"$3$N8e$KMh$k2D$-!VEp?M$K$J$k$h$j30$K;EJ}$,$J$$!W$H1>$&;v$r!"(B
|
||||
$B@Q6KE*$K9NDj$9$k$@$1$N!"M&5$$,=P$:$K$$$?$N$G$"$k!#(B
|
||||
$B!!2<?M$OBg$-$JSj!J$/$5$a!K$r$7$F!"$=$l$+$i!"Bg57$=$&$KN)>e$,$C$?!#M<Nd$($N$9$k(B
|
||||
$B5~ET$O!"$b$&2P23$,M_$7$$Dx$N4($5$G$"$k!#Iw$OLg$NCl$HCl$H$N4V$r!"M<0G$H6&$K1sN8(B
|
||||
$B$J$/!"?a$-$L$1$k!#C0EI$NCl$K$H$^$C$F$$$?$-$j$.$j$9$b!"$b$&$I$3$+$X9T$C$F$7$^$C(B
|
||||
$B$?!#(B
|
||||
$B!!2<?M$O!"pt$r$A$B$a$J$,$i!";3?a$N4@jN!J$+$6$_!K$K=E$M$?!":0$N2($N8*$r9b$/$7$F(B
|
||||
$BLg$N$^$o$j$r8+$^$o$7$?!#1+Iw$N45$N$J$$!"?ML\$K$+$+$kW|$N$J$$!"0lHU3Z$K$M$i$l$=(B
|
||||
$B$&$J=j$,$"$l$P!"$=$3$G$H$b$+$/$b!"Lk$rL@$+$=$&$H;W$C$?$+$i$G$"$k!#$9$k$H!"9,Lg(B
|
||||
$B$N>e$NO0$X>e$k!"I}$N9-$$!"G7$bC0$rEI$C$?Dt;R$,4c$K$D$$$?!#>e$J$i!"?M$,$$$?$K$7(B
|
||||
$B$F$b!"$I$&$;;`?M$P$+$j$G$"$k!#2<?M$O!"$=$3$G9x$K$5$2$?@;JA!J$R$8$j$E$+!K$NB@Ea(B
|
||||
$B$,>dAv$i$J$$$h$&$K5$$r$D$1$J$,$i!"ONApMz$r$O$$$?B-$r!"$=$NDt;R$N0lHV2<$NCJ$X$U(B
|
||||
$B$_$+$1$?!#(B
|
||||
$B!!$=$l$+$i!"2?J,$+$N8e$G$"$k!#Me@8Lg$NO0$N>e$X=P$k!"I}$N9-$$Dt;R$NCfCJ$K!"0l?M(B
|
||||
$B$NCK$,!"G-$N$h$&$K?H$r$A$B$a$F!"B)$r;&$7$J$,$i!">e$NMF;R$r1.$C$F$$$?!#O0$N>e$+(B
|
||||
$B$i$5$92P$N8w$,!"$+$9$+$K!"$=$NCK$N1&$NKK$r$L$i$7$F$$$k!#C;$$r$!J$R$2!K$NCf$K!"(B
|
||||
$B@V$/G?$r;}$C$?LLb.$N$"$kKK$G$"$k!#2<?M$O!";O$a$+$i!"$3$N>e$K$$$k<T$O!";`?M$P$+(B
|
||||
$B$j$@$H9b$r3g$C$F$$$?!#$=$l$,!"Dt;R$rFs;0CJ>e$C$F8+$k$H!">e$G$OC/$+2P$r$H$\$7$F!"(B
|
||||
$B$7$+$b$=$N2P$rB6=h:!=h$HF0$+$7$F$$$k$i$7$$!#$3$l$O!"$=$NBy$C$?!"2+$$$m$$8w$,!"(B
|
||||
$B6y!9$KCXia$NAc$r$+$1$?E70fN"$K!"$f$l$J$,$i1G$C$?$N$G!"$9$0$K$=$l$HCN$l$?$N$G$"(B
|
||||
$B$k!#$3$N1+$NLk$K!"$3$NMe@8Lg$N>e$G!"2P$r$H$b$7$F$$$k$+$i$O!"$I$&$;M#$N<T$G$O$J(B
|
||||
$B$$!#(B
|
||||
$B!!2<?M$O!"5\<i!J$d$b$j!K$N$h$&$KB-2;$r$L$9$s$G!"$d$C$H5^$JDt;R$r!"0lHV>e$NCJ$^(B
|
||||
$B$GGg$&$h$&$K$7$F>e$j$D$a$?!#$=$&$7$FBN$r=PMh$k$@$1!"J?$K$7$J$,$i!"pt$r=PMh$k$@(B
|
||||
$B$1!"A0$X=P$7$F!"62$k62$k!"O0$NFb$rGA$$$F8+$?!#(B
|
||||
$B!!8+$k$H!"O0$NFb$K$O!"1=$KJ9$$$?DL$j!"4v$D$+$N;S3<!J$7$,$$!K$,!"L5B$:n$K4~$F$F(B
|
||||
$B$"$k$,!"2P$N8w$N5Z$VHO0O$,!";W$C$?$h$j69$$$N$G!"?t$O4v$D$H$b$o$+$i$J$$!#M#!"$*(B
|
||||
$B$\$m$2$J$,$i!"CN$l$k$N$O!"$=$NCf$KMg$N;S3<$H!"CeJ*$rCe$?;S3<$H$,$"$k$H1>$&;v$G(B
|
||||
$B$"$k!#L^O@!"Cf$K$O=w$bCK$b$^$8$C$F$$$k$i$7$$!#$=$&$7$F!"$=$N;S3<$O3'!"$=$l$,!"(B
|
||||
$B>(!J$+$D$F!K!"@8$-$F$$$??M4V$@$H1>$&;v<B$5$(5?$o$l$kDx!"EZ$rYT$M$FB$$C$??M7A$N(B
|
||||
$B$h$&$K!"8}$r3+$$$?$j!"<j$r1d$P$7$?$j$7$F!"$4$m$4$m>2$N>e$K$3$m$,$C$F$$$?!#$7$+(B
|
||||
$B$b!"8*$H$+6;$H$+$N9b$/$J$C$F$$$kItJ,$K!"$\$s$d$j$7$?2P$N8w$r$&$1$F!"Dc$/$J$C$F(B
|
||||
$B$$$kItJ,$N1F$r0lAX0E$/$7$J$,$i!"1J5W$K0"!J$*$7!K$NG!$/L[$C$F$$$?!#(B
|
||||
$B!!2<?M$O!"$=$l$i$N;S3<$NIe`%$7$?=-5$$K;W$o$:!"I!$r1f$C$?!J$*$*$C$?!K!#$7$+$7!"(B
|
||||
$B$=$N<j$O!"<!$N=V4V$K$O!"$b$&I!$r1f$&;v$rK:$l$F$$$?!#0?$k6/$$46>p$,KX<=!J$[$H$s(B
|
||||
$B$I$3$H$4$H$/!K$3$NCK$NSL3P$rC%$C$F$7$^$C$?$+$i$G$"$k!#(B
|
||||
$B!!2<?M$N4c$O!"$=$N;~!"$O$8$a$F!"B6;S3<$NCf$Km-$C$F$$$k!J$&$:$/$^$C$F$$$k!K?M4V(B
|
||||
$B$r8+$?!#[XH)?'!J$R$O$@$$$m!K$NCeJ*$rCx$?!"GX$NDc$$!"Ai$;$?!"GrH1F,$N!"1n$N$h$&(B
|
||||
$B$JO7GL$G$"$k!#$=$NO7GL$O!"1&$N<j$K2P$r$H$b$7$?>>$NLZJR$r;}$C$F!"$=$N;S3<$N0l$D(B
|
||||
$B$N4i$rGA$-$3$`$h$&$KD/$a$F$$$?!#H1$NLS$ND9$$=j$r8+$k$H!"B?J,=w$N;S3<$G$"$m$&!#(B
|
||||
$B!!2<?M$O!"O;J,$N62I]$H;MJ,$N9%4q?4$H$KF0$+$5$l$F!";C;~$O8F5[!J$$$-!K$r$9$k$N$5(B
|
||||
$B$(K:$l$F$$$?!#5l5-$N5-<T$N8l$r<Z$j$l$P!"!VF,?H!J$H$&$7$s!K$NLS$bB@$k!W$h$&$K46(B
|
||||
$B$8$?$N$G$"$k!#$9$k$H!"O7GL$O!">>$NLZJR$r!">2HD$N4V$KA^$7$F!"$=$l$+$i!":#$^$GD/(B
|
||||
$B$a$F$$$?;S3<$N<s$KN><j$r$+$1$k$H!"CzEY!"1n$N?F$,1n$N;R$NiM!J$7$i$_!K$r$H$k$h$&(B
|
||||
$B$K!"$=$ND9$$H1$NLS$r0lK\$:$DH4$-$O$8$a$?!#H1$O<j$K=>$C$FH4$1$k$i$7$$!#(B
|
||||
$B!!$=$NH1$NLS$,!"0lK\$:$DH4$1$k$N$K=>$C$F2<?M$N?4$+$i$O!"62I]$,>/$7$:$D>C$($F9T$C(B
|
||||
$B$?!#$=$&$7$F!"$=$l$HF1;~$K!"$=$NO7GL$KBP$9$k$O$2$7$$A~0-$,!">/$7$:$DF0$$$FMh$?!#(B
|
||||
$B$$$d!"$3$NO7GL$KBP$9$k$H1>$C$F$O!"8lJ@$,$"$k$+$bCN$l$J$$!#G+!J$`$7$m!K!"$"$i$f(B
|
||||
$B$k0-$KBP$9$kH?46$,!"0lJ,Kh$K6/$5$rA}$7$FMh$?$N$G$"$k!#$3$N;~!"C/$+$,$3$N2<?M$K!"(B
|
||||
$B$5$C$-Lg$N2<$G$3$NCK$,9M$($F$$$?!"q@;`!J$&$($8$K!K$r$9$k$+Ep?M$K$J$k$+$H1>$&Ld(B
|
||||
$BBj$r!"2~$a$F;}=P$7$?$i!"62$i$/2<?M$O!"2?$NL$N}$b$J$/!"q@;`$rA*$s$@;v$G$"$m$&!#(B
|
||||
$B$=$l$[$I!"$3$NCK$N0-$rA~$`?4$O!"O7GL$N>2$KA^$7$?>>$NLZJR$N$h$&$K!"@*$h$/G3$(>e(B
|
||||
$B$,$j$@$7$F$$$?$N$G$"$k!#(B
|
||||
$B!!2<?M$K$O!"L^O@!"2?8NO7GL$,;`?M$NH1$NLS$rH4$/$+$o$+$i$J$+$C$?!#=>$C$F!"9gM}E*(B
|
||||
$B$K$O!"$=$l$rA10-$N2?$l$KJR$E$1$F$h$$$+CN$i$J$+$C$?!#$7$+$72<?M$K$H$C$F$O!"$3$N(B
|
||||
$B1+$NLk$K!"$3$NMe@8Lg$N>e$G!";`?M$NH1$NLS$rH4$/$H1>$&;v$,!"$=$l$@$1$G4{$K5v$92D(B
|
||||
$B$i$6$k0-$G$"$C$?!#L^O@!!2<?M$O!!$5$C$-Kx<+J,$,!"Ep?M$K$J$k5$$G$$$?;v$J$>$O!!$H(B
|
||||
$B$&$KK:$l$F$$$k$N$G$"$k!#(B
|
||||
$B!!$=$3$G!"2<?M$O!"N>B-$KNO$rF~$l$F!"$$$+$J$j!"Dt;R$+$i>e$XHt$S>e$,$C$?!!$=$&$7(B
|
||||
$B$F@;JA!J$R$8$j$E$+!K$NB@Ea$K<j$r$+$1$J$,$i!"Bg8T$KO7GL$NA0$XJb$_$h$C$?!#O7GL$,(B
|
||||
$B6C$$$?$N$O!!1>$&Kx$b$J$$!#(B
|
||||
$B!!O7GL$O!"0lL\2<?M$r8+$k$H!"$^$k$GW8!J$$$7$f$_!K$K$G$bCF$+$l$?$h$&$K!!Ht$S>e$,$C(B
|
||||
$B$?!#(B
|
||||
$B!!!V$*$N$l!"$I$3$X9T$/!#!W(B
|
||||
$B!!2<?M$O!"O7GL$,;S3<$K$D$^$E$-$J$,$i!"92$F$U$?$a$$$FF($2$h$&$H$9$k9T<j$r:I$$$G!"(B
|
||||
$B$3$&GM$C$?!#O7GL$O!"$=$l$G$b2<?M$r$D$-$N$1$F9T$3$&$H$9$k!#2<?M$OKt!"$=$l$r9T$+(B
|
||||
$B$9$^$$$H$7$F!"2!$7$b$I$9!#Fs?M$O;S3<$NCf$G!";C!"L58@$N$^$^!"$D$+$_9g$C$?!#$7$+(B
|
||||
$B$7>!Ii$O!"$O$8$a$+$i!"$o$+$C$F$$$k!#2<?M$O$H$&$H$&!"O7GL$NOS$r$D$+$s$G!"L5M}$K(B
|
||||
$B$=$3$X$M$8E]$7$?!#CzEY!"7\!J$H$j!K$N5S$N$h$&$J!"9|$HHi$P$+$j$NOS$G$"$k!#(B
|
||||
$B!!!V2?$r$7$F$$$?!#$5$"2?$r$7$F$$$?!#1>$(!#1>$o$L$H!!$3$l$@$>$h!#!W(B
|
||||
$B!!2<?M$O!"O7GL$r$D$-J|$9$H!"$$$-$J$j!"B@Ea$N>d$rJ'$C$F!"Gr$$9]!J$O$,$M!K$N?'$r(B
|
||||
$B$=$N4c$NA0$X$D$-$D$1$?!#$1$l$I$b!"O7GL$OL[$C$F$$$k!#N><j$r$o$J$o$J$U$k$o$;$F!"(B
|
||||
$B8*$GB)$r@Z$j$J$,$i!"4c$r!"4c5e$,$^$V$?$N30$X=P$=$&$K$J$kDx!"8+3+$$$F!"0"$N$h$&(B
|
||||
$B$K<9Y9!J$7$e$&$M!K$/L[$C$F$$$k!#$3$l$r8+$k$H!"2<?M$O;O$a$FL@Gr$K$3$NO7GL$N@8;`(B
|
||||
$B$,!"A4A3!"<+J,$N0U;V$K;YG[$5$l$F$$$k$H1>$&;v$r0U<1$7$?!#$=$&$7$F!"$3$N0U<1$O!"(B
|
||||
$B:#$^$G$O$2$7$/G3$($F$$$?A~0-$N?4$r2?;~!J$$$D!K$N4V$K$+Nd$^$7$F$7$^$C$?!#8e$K;D$C(B
|
||||
$B$?$N$O!"M#!"0?;E;v$r$7$F!"$=$l$,1_K~$K@.="$7$?;~$N!"0B$i$+$JF@0U$HK~B-$H$,$"$k(B
|
||||
$B$P$+$j$G$"$k!#$=$3$G!"2<?M$O!"O7GL$r!"8+2<$2$J$,$i!">/$7@<$r=@$2$F$3$&1>$C$?!#(B
|
||||
$B!!!V8J$O8!Hs0c;H!J$1$S$$$7!K$ND#$NLr?M$J$I$G$O$J$$!#:#$7J}$3$NLg$N2<$rDL$j$+$+$C(B
|
||||
$B$?N9$N<T$@!#$@$+$i$*A0$KFl$r$+$1$F!"$I$&$7$h$&$H1>$&$h$&$J;v$O$J$$!#M#:#;~J,!"(B
|
||||
$B$3$NLg$N>e$G!"2?$r$7$F$$$?$N$@$+!"$=$l$r8J$KOC$5$($9$l$P$$$$$N$@!#!W(B
|
||||
$B!!$9$k$H!"O7GL$O!"8+3+$$$?4c$r!"0lAXBg$-$/$7$F!"$8$C$H$=$N2<?M$N4i$r8+<i$C$?!#(B
|
||||
$B$^$V$?$N@V$/$J$C$?!"Fy?)D;$N$h$&$J!"1T$$4c$G8+$?$N$G$"$k!#$=$l$+$i!"b2$G!"KX!"(B
|
||||
$BI!$H0l$D$K$J$C$??0$r2?$+J*$G$b3z$s$G$$$k$h$&$KF0$+$7$?!#:Y$$9"$G!"@m$C$?9"J)$N(B
|
||||
$BF0$$$F$$$k$N$,8+$($k!#$=$N;~!"$=$N9"$+$i!"rm!J$+$i$9!K$NSF$/$h$&$J@<$,!"SC$.SC(B
|
||||
$B$.!"2<?M$N<*$XEA$o$C$FMh$?!#(B
|
||||
$B!!!V$3$NH1$rH4$$$F$J!"$3$N=w$NH1$rH4$$$F$J!"r#!J$+$D$i!K$K$7$h$&$H;W$&$?$N(B
|
||||
$B$8$c!#!W(B
|
||||
$B!!2<?M$O!"O7GL$NEz$,B830!"J?K^$J$N$K<:K>$7$?!#$=$&$7$F<:K>$9$k$HF1;~$K!"KtA0$N(B
|
||||
$BA~0-$,!"Nd$JInJN$H0l$7$g$K!"?4$NCf$X$O$$$C$FMh$?!#$9$k$H!!$=$N5$?'!J$1$7$-!K$,!"(B
|
||||
$B@hJ}$X$bDL$8$?$N$G$"$m$&!#O7GL$O!"JR<j$K!"$^$@;S3<$NF,$+$iC%!J$H!K$C$?D9$$H4$1(B
|
||||
$BLS$r;}$C$?$J$j!"j1!J$R$-!K$N$D$V$d$/$h$&$J@<$G!"8}$4$b$j$J$,$i!"$3$s$J;v$r1>$C(B
|
||||
$B$?!#(B
|
||||
$B!!@.Dx!";`?M$NH1$NLS$rH4$/$H1>$&;v$O!"0-$$;v$+$MCN$l$L!#$7$+$7!"$3$&1>$&;`?M$N(B
|
||||
$BB?$/$O!"3'!!$=$N0L$J;v$r!"$5$l$F$b$$$$?M4V$P$+$j$G$"$k!#8=$K!"<+J,$,:#!"H1$rH4(B
|
||||
$B$$$?=w$J$I$O!"<X$r;M@#$P$+$j$:$D$K@Z$C$F43$7$?$N$r!"435{!J$[$7$&$*!K$@$H1>$C$F!"(B
|
||||
$BB@EaBS!J$?$A$O$-!K$N?X$XGd$j$K9T$C$?!#1VIB$K$+$+$C$F;`$J$J$+$C$?$J$i!":#$G$bGd(B
|
||||
$B$j$K9T$C$F$$$?$+$b$7$l$J$$!#$7$+$b!"$3$N=w$NGd$k435{$O!"L#$,$h$$$H1>$&$N$G!"B@(B
|
||||
$BEaBS$?$A$,!"7g$+$5$::ZNA$KGc$C$F$$$?$N$G$"$k!#<+J,$O!"$3$N=w$N$7$?;v$,0-$$$H$O(B
|
||||
$B;W$o$J$$!#$7$J$1$l$P!"q@;`!J$($&$8$K!K$r$9$k$N$G!";EJ}$,$J$/$7$?;v$@$+$i$G$"$k!#(B
|
||||
$B$@$+$i!"Kt:#!"<+J,$N$7$F$$$?;v$b0-$$;v$H$O;W$o$J$$!#$3$l$b$d$O$j$7$J$1$l$P!"q@(B
|
||||
$B;`$r$9$k$N$G!";EJ}$,$J$/$9$k;v$@$+$i$G$"$k!#$=$&$7$F!"$=$N;EJ}$,$J$$;v$r!"$h$/(B
|
||||
$BCN$C$F$$$?$3$N=w$O!"<+J,$N$9$k;v$r5v$7$F$/$l$k$N$K$A$,$$$J$$$H;W$&$+$i$G$"(B
|
||||
$B$k!#!<!<O7GL$O!"BgBN$3$s$J0UL#$N;v$r1>$C$?!#(B
|
||||
$B!!2<?M$O!"B@Ea$r>d$K$*$5$a$F!"$=$NB@Ea$NJA$r:8$N<j$G$*$5$($J$,$i!"NdA3$H$7$F!"(B
|
||||
$B$3$NOC$rJ9$$$F$$$?!#L^O@!"!!1&$N<j$G$O!"@V$/KK$KG?$r;}$?Bg$-$JLLb.!J$K$-$S!K$r(B
|
||||
$B5$$K$7$J$,$i!"J9$$$F$$$k$N$G$"$k!#$7$+$7!"G7$rJ9$$$F$$$kCf$K!"2<?M$N?4$K$O!"0?(B
|
||||
$BM&5$$,@8$^$l$FMh$?!#$=$l$O!!$5$C$-!"Lg$N2<$G$3$NCK$K7g$1$F$$$?M&5$$G$"$k!#$=$&(B
|
||||
$B$7$F!"Kt$5$C$-!"$3$NLg$N>e$X>e!J$"$,!K$C$F!"$=$NO7GL$rJa$($?;~$NM&5$$H$O!"A4A3!"(B
|
||||
$BH?BP$JJ}8~$KF0$3$&$H$9$kM&5$$G$"$k!#2<?M$O!"q@;`$r$9$k$+Ep?M$K$J$k$+$KLB$o$J$+$C(B
|
||||
$B$?$P$+$j$G$O$J$$!#$=$N;~$N$3$NCK$N?4$b$A$+$i1>$($P!"q@;`$J$I$H1>$&;v$O!"KX!"9M(B
|
||||
$B$($k;v$5$(=PMh$J$$Dx!"0U<1$N30$KDI$$=P$5$l$F$$$?!#(B
|
||||
$B!!!V$-$C$H!"$=$&$+!#!W(B
|
||||
$B!!O7GL$NOC$,40$k$H!"2<?M$OS^!J$"$6$1!K$k$h$&$J@<$GG0$r2!$7$?!#$=$&$7$F!"0lB-A0(B
|
||||
$B$X=P$k$H!"IT0U$K!"1&$N<j$rLLb.$+$iN%$7$F!"O7GL$N6_>e!J$($j$,$_!K$r$D$+$_$J$,$i!"(B
|
||||
$B$3$&1>$C$?!#(B
|
||||
$B!!!V$G$O!"8J$,0zGm!J$R$O$.!K$r$7$h$&$H:($`$^$$$J!#8J$b$=$&$7$J$1$l$P!"q@;`$r$9(B
|
||||
$B$kBN$J$N$@!#!W(B
|
||||
$B!!2<?M$O!"$9$P$d$/!"O7GL$NCeJ*$rGm$.$H$C$?!#$=$l$+$i!"B-$K$7$,$_$D$3$&$H$9$kO7(B
|
||||
$BGL$r!"<j9S$/;S3<$N>e$X=3E]$7$?!#Dt;R$N8}$^$G$O!"6O$K8^Jb$r?t$($k$P$+$j$G$"$k!#(B
|
||||
$B2<?M$O!"Gm$.$H$C$?I0H)?'$NCeJ*$r$o$-$K$+$+$($F!"$^$?$?$/4V$K5^$JDt;R$rLk$NDl$X(B
|
||||
$B$+$12<$j$?!#(B
|
||||
$B!!;C!";`$s$@$h$&$KE]$l$F$$$?O7GL$,!";S3<$NCf$+$i!"$=$NMg$NBN$r5/$3$7$?$N$O!"$=(B
|
||||
$B$l$+$i4V$b$J$/$N;v$G$"$k!#O7GL$O!"$D$V$d$/$h$&$J!"$&$a$/$h$&$J@<$rN)$F$J$,$i!"(B
|
||||
$B$^$@G3$($F$$$k2P$N8w$r$?$h$j$K!"Dt;R$N8}$^$G!"Gg$C$F9T$C$?!#$=$&$7$F!"$=$3$+$i!"(B
|
||||
$BC;$$GrH1$rE]!J$5$+$5$^!K$K$7$F!"Lg$N2<$rGA$-$3$s$@!#30$K$O!"M#!"9uF6!9!J$3$/$H(B
|
||||
$B$&$H$&!K$?$kLk$,$"$k$P$+$j$G$"$k!#(B
|
||||
$B!!2<?M$O!"4{$K!"1+$rKA$7$F!"5~ET$ND.$X6/Ep$rF/$-$K5^$$$G$$$?!#(B
|
||||
178
vendor/golang.org/x/text/encoding/testdata/rashomon-shift-jis.txt
generated
vendored
178
vendor/golang.org/x/text/encoding/testdata/rashomon-shift-jis.txt
generated
vendored
|
|
@ -1,178 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/1982/pg1982.txt
|
||||
--------
|
||||
羅生門
|
||||
|
||||
芥川龍之介
|
||||
|
||||
或日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。 広い門
|
||||
の下には、この男の外に誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、きりぎ
|
||||
りすが一匹とまっている。羅生門が、朱雀大路にある以上は、この男の外にも、雨やみ
|
||||
をする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男の外
|
||||
に誰もいない。
|
||||
何故かと云うと、この二三年、京都には、地震とか辻風とか火事とか饑饉とか云う災
|
||||
いがつづいて起こった。そこで洛中のさびれ方は一通りでない。旧記によると、仏像や
|
||||
仏具を打砕いて、その丹がついたり、金銀の箔(はく)がついたりした木を、路ばたに
|
||||
つみ重ねて薪の料(しろ)に売っていたと云うことである。洛中がその始末であるから、
|
||||
羅生門の修理などは、元より誰も捨てて顧みる者がなかった。するとその荒れ果てたの
|
||||
をよい事にして、狐狸(こり)が棲む。盗人が棲む。とうとうしまいには、引取り手の
|
||||
ない死人を、この門へ持って来て、捨てて行くと云う習慣さえ出来た。そこで、日の目
|
||||
が見えなくなると、誰でも気味を悪がって、この門の近所へは足ぶみをしない事になっ
|
||||
てしまったのである。
|
||||
その代り又鴉が何処からか、たくさん集まって来た。昼間見ると、その鴉が何羽とな
|
||||
く輪を描いて、高い鴟尾(しび)のまわりを啼きながら、飛びまわっている。殊に門の
|
||||
上の空が、夕焼けであかくなる時には、それが胡麻をまいたようにはっきり見えた。鴉
|
||||
は、勿論、門の上にある死人の肉を、啄みに来るのである。ーー尤も今日は、刻限が遅
|
||||
いせいか、一羽も見えない。唯、所々、崩れかかった、そうしてその崩れ目に長い草の
|
||||
はえた石段の上に、鴉の糞(くそ)が、点々と白くこびりついているのが見える。下人
|
||||
は七段ある石段の一番上の段に洗いざらした紺の襖(あお)の尻を据えて、右の頬に出
|
||||
来た、大きな面皰(にきび)を気にしながら、ぼんやり、雨のふるのを眺めているので
|
||||
ある。
|
||||
作者はさっき、「下人が雨やみを待っていた」と書いた。しかし、下人は、雨がやん
|
||||
でも格別どうしようと云う当てはない。ふだんなら、勿論、主人の家へ帰る可き筈であ
|
||||
る。所がその主人からは、四五日前に暇を出された。前にも書いたように、当時京都の
|
||||
町は一通りならず衰微していた。今この下人が、永年、使われていた主人から暇を出さ
|
||||
れたのも、この衰微の小さな余波に外ならない。だから、「下人が雨やみを待っていた」
|
||||
と云うよりも、「雨にふりこめられた下人が、行き所がなくて、途方にくれていた」と
|
||||
云う方が、適当である。その上、今日の空模様も少なからずこの平安朝の下人の
|
||||
Sentimentalismeに影響した。申(さる)の刻下がりからふり出した雨は、未だに上
|
||||
がるけしきがない。そこで、下人は、何を措いても差当たり明日の暮しをどうにかしよ
|
||||
うとしてーー云わばどうにもならない事を、どうにかしようとして、とりとめもない考
|
||||
えをたどりながら、さっきから朱雀大路にふる雨の音を聞くともなく聞いていた。
|
||||
雨は羅生門をつつんで、遠くから、ざあっと云う音をあつめてくる。夕闇は次第に空
|
||||
を低くして、見上げると、門の屋根が、斜めにつき出した甍(いらか)の先に、重たく
|
||||
うす暗い雲を支えている。
|
||||
どうにもならない事を、どうにかする為には、手段を選んでいる遑(いとま)はない。
|
||||
選んでいれば、築地(ついじ)の下か、道ばたの土の上で、饑死(うえじに)をするば
|
||||
かりである。そうして、この門の上へ持って来て、犬のように捨てられてしまうばかり
|
||||
である。選ばないとすればーー下人の考えは、何度も同じ道を低徊した揚句に、やっと
|
||||
この局所へ逢着した。しかしこの「すれば」は、いつもでたっても、結局「すれば」で
|
||||
あった。下人は、手段を選ばないという事を肯定しながらも、この「すれば」のかたを
|
||||
つける為に、当然、この後に来る可き「盗人になるより外に仕方がない」と云う事を、
|
||||
積極的に肯定するだけの、勇気が出ずにいたのである。
|
||||
下人は大きな嚏(くさめ)をして、それから、大儀そうに立上がった。夕冷えのする
|
||||
京都は、もう火桶が欲しい程の寒さである。風は門の柱と柱との間を、夕闇と共に遠慮
|
||||
なく、吹きぬける。丹塗の柱にとまっていたきりぎりすも、もうどこかへ行ってしまっ
|
||||
た。
|
||||
下人は、頸をちぢめながら、山吹の汗衫(かざみ)に重ねた、紺の襖の肩を高くして
|
||||
門のまわりを見まわした。雨風の患のない、人目にかかる惧のない、一晩楽にねられそ
|
||||
うな所があれば、そこでともかくも、夜を明かそうと思ったからである。すると、幸門
|
||||
の上の楼へ上る、幅の広い、之も丹を塗った梯子が眼についた。上なら、人がいたにし
|
||||
ても、どうせ死人ばかりである。下人は、そこで腰にさげた聖柄(ひじりづか)の太刀
|
||||
が鞘走らないように気をつけながら、藁草履をはいた足を、その梯子の一番下の段へふ
|
||||
みかけた。
|
||||
それから、何分かの後である。羅生門の楼の上へ出る、幅の広い梯子の中段に、一人
|
||||
の男が、猫のように身をちぢめて、息を殺しながら、上の容子を窺っていた。楼の上か
|
||||
らさす火の光が、かすかに、その男の右の頬をぬらしている。短い鬚(ひげ)の中に、
|
||||
赤く膿を持った面皰のある頬である。下人は、始めから、この上にいる者は、死人ばか
|
||||
りだと高を括っていた。それが、梯子を二三段上って見ると、上では誰か火をとぼして、
|
||||
しかもその火を其処此処と動かしているらしい。これは、その濁った、黄いろい光が、
|
||||
隅々に蜘蛛の巣をかけた天井裏に、ゆれながら映ったので、すぐにそれと知れたのであ
|
||||
る。この雨の夜に、この羅生門の上で、火をともしているからは、どうせ唯の者ではな
|
||||
い。
|
||||
下人は、宮守(やもり)のように足音をぬすんで、やっと急な梯子を、一番上の段ま
|
||||
で這うようにして上りつめた。そうして体を出来るだけ、平にしながら、頸を出来るだ
|
||||
け、前へ出して、恐る恐る、楼の内を覗いて見た。
|
||||
見ると、楼の内には、噂に聞いた通り、幾つかの屍骸(しがい)が、無造作に棄てて
|
||||
あるが、火の光の及ぶ範囲が、思ったより狭いので、数は幾つともわからない。唯、お
|
||||
ぼろげながら、知れるのは、その中に裸の屍骸と、着物を着た屍骸とがあると云う事で
|
||||
ある。勿論、中には女も男もまじっているらしい。そうして、その屍骸は皆、それが、
|
||||
嘗(かつて)、生きていた人間だと云う事実さえ疑われる程、土を捏ねて造った人形の
|
||||
ように、口を開いたり、手を延ばしたりして、ごろごろ床の上にころがっていた。しか
|
||||
も、肩とか胸とかの高くなっている部分に、ぼんやりした火の光をうけて、低くなって
|
||||
いる部分の影を一層暗くしながら、永久に唖(おし)の如く黙っていた。
|
||||
下人は、それらの屍骸の腐爛した臭気に思わず、鼻を掩った(おおった)。しかし、
|
||||
その手は、次の瞬間には、もう鼻を掩う事を忘れていた。或る強い感情が殆悉(ほとん
|
||||
どことごとく)この男の嗅覚を奪ってしまったからである。
|
||||
下人の眼は、その時、はじめて、其屍骸の中に蹲っている(うずくまっている)人間
|
||||
を見た。檜肌色(ひはだいろ)の着物を著た、背の低い、痩せた、白髪頭の、猿のよう
|
||||
な老婆である。その老婆は、右の手に火をともした松の木片を持って、その屍骸の一つ
|
||||
の顔を覗きこむように眺めていた。髪の毛の長い所を見ると、多分女の屍骸であろう。
|
||||
下人は、六分の恐怖と四分の好奇心とに動かされて、暫時は呼吸(いき)をするのさ
|
||||
え忘れていた。旧記の記者の語を借りれば、「頭身(とうしん)の毛も太る」ように感
|
||||
じたのである。すると、老婆は、松の木片を、床板の間に挿して、それから、今まで眺
|
||||
めていた屍骸の首に両手をかけると、丁度、猿の親が猿の子の虱(しらみ)をとるよう
|
||||
に、その長い髪の毛を一本ずつ抜きはじめた。髪は手に従って抜けるらしい。
|
||||
その髪の毛が、一本ずつ抜けるのに従って下人の心からは、恐怖が少しずつ消えて行っ
|
||||
た。そうして、それと同時に、その老婆に対するはげしい憎悪が、少しずつ動いて来た。
|
||||
いや、この老婆に対すると云っては、語弊があるかも知れない。寧(むしろ)、あらゆ
|
||||
る悪に対する反感が、一分毎に強さを増して来たのである。この時、誰かがこの下人に、
|
||||
さっき門の下でこの男が考えていた、饑死(うえじに)をするか盗人になるかと云う問
|
||||
題を、改めて持出したら、恐らく下人は、何の未練もなく、饑死を選んだ事であろう。
|
||||
それほど、この男の悪を憎む心は、老婆の床に挿した松の木片のように、勢よく燃え上
|
||||
がりだしていたのである。
|
||||
下人には、勿論、何故老婆が死人の髪の毛を抜くかわからなかった。従って、合理的
|
||||
には、それを善悪の何れに片づけてよいか知らなかった。しかし下人にとっては、この
|
||||
雨の夜に、この羅生門の上で、死人の髪の毛を抜くと云う事が、それだけで既に許す可
|
||||
らざる悪であった。勿論 下人は さっき迄自分が、盗人になる気でいた事なぞは と
|
||||
うに忘れているのである。
|
||||
そこで、下人は、両足に力を入れて、いかなり、梯子から上へ飛び上がった そうし
|
||||
て聖柄(ひじりづか)の太刀に手をかけながら、大股に老婆の前へ歩みよった。老婆が
|
||||
驚いたのは 云う迄もない。
|
||||
老婆は、一目下人を見ると、まるで弩(いしゆみ)にでも弾かれたように 飛び上がっ
|
||||
た。
|
||||
「おのれ、どこへ行く。」
|
||||
下人は、老婆が屍骸につまづきながら、慌てふためいて逃げようとする行手を塞いで、
|
||||
こう罵った。老婆は、それでも下人をつきのけて行こうとする。下人は又、それを行か
|
||||
すまいとして、押しもどす。二人は屍骸の中で、暫、無言のまま、つかみ合った。しか
|
||||
し勝負は、はじめから、わかっている。下人はとうとう、老婆の腕をつかんで、無理に
|
||||
そこへねじ倒した。丁度、鶏(とり)の脚のような、骨と皮ばかりの腕である。
|
||||
「何をしていた。さあ何をしていた。云え。云わぬと これだぞよ。」
|
||||
下人は、老婆をつき放すと、いきなり、太刀の鞘を払って、白い鋼(はがね)の色を
|
||||
その眼の前へつきつけた。けれども、老婆は黙っている。両手をわなわなふるわせて、
|
||||
肩で息を切りながら、眼を、眼球がまぶたの外へ出そうになる程、見開いて、唖のよう
|
||||
に執拗(しゅうね)く黙っている。これを見ると、下人は始めて明白にこの老婆の生死
|
||||
が、全然、自分の意志に支配されていると云う事を意識した。そうして、この意識は、
|
||||
今まではげしく燃えていた憎悪の心を何時(いつ)の間にか冷ましてしまった。後に残っ
|
||||
たのは、唯、或仕事をして、それが円満に成就した時の、安らかな得意と満足とがある
|
||||
ばかりである。そこで、下人は、老婆を、見下げながら、少し声を柔げてこう云った。
|
||||
「己は検非違使(けびいし)の庁の役人などではない。今し方この門の下を通りかかっ
|
||||
た旅の者だ。だからお前に縄をかけて、どうしようと云うような事はない。唯今時分、
|
||||
この門の上で、何をしていたのだか、それを己に話さえすればいいのだ。」
|
||||
すると、老婆は、見開いた眼を、一層大きくして、じっとその下人の顔を見守った。
|
||||
まぶたの赤くなった、肉食鳥のような、鋭い眼で見たのである。それから、皺で、殆、
|
||||
鼻と一つになった唇を何か物でも噛んでいるように動かした。細い喉で、尖った喉仏の
|
||||
動いているのが見える。その時、その喉から、鴉(からす)の啼くような声が、喘ぎ喘
|
||||
ぎ、下人の耳へ伝わって来た。
|
||||
「この髪を抜いてな、この女の髪を抜いてな、鬘(かつら)にしようと思うたの
|
||||
じゃ。」
|
||||
下人は、老婆の答が存外、平凡なのに失望した。そうして失望すると同時に、又前の
|
||||
憎悪が、冷な侮蔑と一しょに、心の中へはいって来た。すると その気色(けしき)が、
|
||||
先方へも通じたのであろう。老婆は、片手に、まだ屍骸の頭から奪(と)った長い抜け
|
||||
毛を持ったなり、蟇(ひき)のつぶやくような声で、口ごもりながら、こんな事を云っ
|
||||
た。
|
||||
成程、死人の髪の毛を抜くと云う事は、悪い事かね知れぬ。しかし、こう云う死人の
|
||||
多くは、皆 その位な事を、されてもいい人間ばかりである。現に、自分が今、髪を抜
|
||||
いた女などは、蛇を四寸ばかりずつに切って干したのを、干魚(ほしうお)だと云って、
|
||||
太刀帯(たちはき)の陣へ売りに行った。疫病にかかって死ななかったなら、今でも売
|
||||
りに行っていたかもしれない。しかも、この女の売る干魚は、味がよいと云うので、太
|
||||
刀帯たちが、欠かさず菜料に買っていたのである。自分は、この女のした事が悪いとは
|
||||
思わない。しなければ、饑死(えうじに)をするので、仕方がなくした事だからである。
|
||||
だから、又今、自分のしていた事も悪い事とは思わない。これもやはりしなければ、饑
|
||||
死をするので、仕方がなくする事だからである。そうして、その仕方がない事を、よく
|
||||
知っていたこの女は、自分のする事を許してくれるのにちがいないと思うからであ
|
||||
る。ーー老婆は、大体こんな意味の事を云った。
|
||||
下人は、太刀を鞘におさめて、その太刀の柄を左の手でおさえながら、冷然として、
|
||||
この話を聞いていた。勿論、 右の手では、赤く頬に膿を持た大きな面皰(にきび)を
|
||||
気にしながら、聞いているのである。しかし、之を聞いている中に、下人の心には、或
|
||||
勇気が生まれて来た。それは さっき、門の下でこの男に欠けていた勇気である。そう
|
||||
して、又さっき、この門の上へ上(あが)って、その老婆を捕えた時の勇気とは、全然、
|
||||
反対な方向に動こうとする勇気である。下人は、饑死をするか盗人になるかに迷わなかっ
|
||||
たばかりではない。その時のこの男の心もちから云えば、饑死などと云う事は、殆、考
|
||||
える事さえ出来ない程、意識の外に追い出されていた。
|
||||
「きっと、そうか。」
|
||||
老婆の話が完ると、下人は嘲(あざけ)るような声で念を押した。そうして、一足前
|
||||
へ出ると、不意に、右の手を面皰から離して、老婆の襟上(えりがみ)をつかみながら、
|
||||
こう云った。
|
||||
「では、己が引剥(ひはぎ)をしようと恨むまいな。己もそうしなければ、饑死をす
|
||||
る体なのだ。」
|
||||
下人は、すばやく、老婆の着物を剥ぎとった。それから、足にしがみつこうとする老
|
||||
婆を、手荒く屍骸の上へ蹴倒した。梯子の口までは、僅に五歩を数えるばかりである。
|
||||
下人は、剥ぎとった桧肌色の着物をわきにかかえて、またたく間に急な梯子を夜の底へ
|
||||
かけ下りた。
|
||||
暫、死んだように倒れていた老婆が、屍骸の中から、その裸の体を起こしたのは、そ
|
||||
れから間もなくの事である。老婆は、つぶやくような、うめくような声を立てながら、
|
||||
まだ燃えている火の光をたよりに、梯子の口まで、這って行った。そうして、そこから、
|
||||
短い白髪を倒(さかさま)にして、門の下を覗きこんだ。外には、唯、黒洞々(こくと
|
||||
うとう)たる夜があるばかりである。
|
||||
下人は、既に、雨を冒して、京都の町へ強盗を働きに急いでいた。
|
||||
178
vendor/golang.org/x/text/encoding/testdata/rashomon-utf-8.txt
generated
vendored
178
vendor/golang.org/x/text/encoding/testdata/rashomon-utf-8.txt
generated
vendored
|
|
@ -1,178 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/cache/epub/1982/pg1982.txt
|
||||
--------
|
||||
羅生門
|
||||
|
||||
芥川龍之介
|
||||
|
||||
或日の暮方の事である。一人の下人が、羅生門の下で雨やみを待っていた。 広い門
|
||||
の下には、この男の外に誰もいない。ただ、所々丹塗の剥げた、大きな円柱に、きりぎ
|
||||
りすが一匹とまっている。羅生門が、朱雀大路にある以上は、この男の外にも、雨やみ
|
||||
をする市女笠や揉烏帽子が、もう二三人はありそうなものである。それが、この男の外
|
||||
に誰もいない。
|
||||
何故かと云うと、この二三年、京都には、地震とか辻風とか火事とか饑饉とか云う災
|
||||
いがつづいて起こった。そこで洛中のさびれ方は一通りでない。旧記によると、仏像や
|
||||
仏具を打砕いて、その丹がついたり、金銀の箔(はく)がついたりした木を、路ばたに
|
||||
つみ重ねて薪の料(しろ)に売っていたと云うことである。洛中がその始末であるから、
|
||||
羅生門の修理などは、元より誰も捨てて顧みる者がなかった。するとその荒れ果てたの
|
||||
をよい事にして、狐狸(こり)が棲む。盗人が棲む。とうとうしまいには、引取り手の
|
||||
ない死人を、この門へ持って来て、捨てて行くと云う習慣さえ出来た。そこで、日の目
|
||||
が見えなくなると、誰でも気味を悪がって、この門の近所へは足ぶみをしない事になっ
|
||||
てしまったのである。
|
||||
その代り又鴉が何処からか、たくさん集まって来た。昼間見ると、その鴉が何羽とな
|
||||
く輪を描いて、高い鴟尾(しび)のまわりを啼きながら、飛びまわっている。殊に門の
|
||||
上の空が、夕焼けであかくなる時には、それが胡麻をまいたようにはっきり見えた。鴉
|
||||
は、勿論、門の上にある死人の肉を、啄みに来るのである。ーー尤も今日は、刻限が遅
|
||||
いせいか、一羽も見えない。唯、所々、崩れかかった、そうしてその崩れ目に長い草の
|
||||
はえた石段の上に、鴉の糞(くそ)が、点々と白くこびりついているのが見える。下人
|
||||
は七段ある石段の一番上の段に洗いざらした紺の襖(あお)の尻を据えて、右の頬に出
|
||||
来た、大きな面皰(にきび)を気にしながら、ぼんやり、雨のふるのを眺めているので
|
||||
ある。
|
||||
作者はさっき、「下人が雨やみを待っていた」と書いた。しかし、下人は、雨がやん
|
||||
でも格別どうしようと云う当てはない。ふだんなら、勿論、主人の家へ帰る可き筈であ
|
||||
る。所がその主人からは、四五日前に暇を出された。前にも書いたように、当時京都の
|
||||
町は一通りならず衰微していた。今この下人が、永年、使われていた主人から暇を出さ
|
||||
れたのも、この衰微の小さな余波に外ならない。だから、「下人が雨やみを待っていた」
|
||||
と云うよりも、「雨にふりこめられた下人が、行き所がなくて、途方にくれていた」と
|
||||
云う方が、適当である。その上、今日の空模様も少なからずこの平安朝の下人の
|
||||
Sentimentalismeに影響した。申(さる)の刻下がりからふり出した雨は、未だに上
|
||||
がるけしきがない。そこで、下人は、何を措いても差当たり明日の暮しをどうにかしよ
|
||||
うとしてーー云わばどうにもならない事を、どうにかしようとして、とりとめもない考
|
||||
えをたどりながら、さっきから朱雀大路にふる雨の音を聞くともなく聞いていた。
|
||||
雨は羅生門をつつんで、遠くから、ざあっと云う音をあつめてくる。夕闇は次第に空
|
||||
を低くして、見上げると、門の屋根が、斜めにつき出した甍(いらか)の先に、重たく
|
||||
うす暗い雲を支えている。
|
||||
どうにもならない事を、どうにかする為には、手段を選んでいる遑(いとま)はない。
|
||||
選んでいれば、築地(ついじ)の下か、道ばたの土の上で、饑死(うえじに)をするば
|
||||
かりである。そうして、この門の上へ持って来て、犬のように捨てられてしまうばかり
|
||||
である。選ばないとすればーー下人の考えは、何度も同じ道を低徊した揚句に、やっと
|
||||
この局所へ逢着した。しかしこの「すれば」は、いつもでたっても、結局「すれば」で
|
||||
あった。下人は、手段を選ばないという事を肯定しながらも、この「すれば」のかたを
|
||||
つける為に、当然、この後に来る可き「盗人になるより外に仕方がない」と云う事を、
|
||||
積極的に肯定するだけの、勇気が出ずにいたのである。
|
||||
下人は大きな嚏(くさめ)をして、それから、大儀そうに立上がった。夕冷えのする
|
||||
京都は、もう火桶が欲しい程の寒さである。風は門の柱と柱との間を、夕闇と共に遠慮
|
||||
なく、吹きぬける。丹塗の柱にとまっていたきりぎりすも、もうどこかへ行ってしまっ
|
||||
た。
|
||||
下人は、頸をちぢめながら、山吹の汗衫(かざみ)に重ねた、紺の襖の肩を高くして
|
||||
門のまわりを見まわした。雨風の患のない、人目にかかる惧のない、一晩楽にねられそ
|
||||
うな所があれば、そこでともかくも、夜を明かそうと思ったからである。すると、幸門
|
||||
の上の楼へ上る、幅の広い、之も丹を塗った梯子が眼についた。上なら、人がいたにし
|
||||
ても、どうせ死人ばかりである。下人は、そこで腰にさげた聖柄(ひじりづか)の太刀
|
||||
が鞘走らないように気をつけながら、藁草履をはいた足を、その梯子の一番下の段へふ
|
||||
みかけた。
|
||||
それから、何分かの後である。羅生門の楼の上へ出る、幅の広い梯子の中段に、一人
|
||||
の男が、猫のように身をちぢめて、息を殺しながら、上の容子を窺っていた。楼の上か
|
||||
らさす火の光が、かすかに、その男の右の頬をぬらしている。短い鬚(ひげ)の中に、
|
||||
赤く膿を持った面皰のある頬である。下人は、始めから、この上にいる者は、死人ばか
|
||||
りだと高を括っていた。それが、梯子を二三段上って見ると、上では誰か火をとぼして、
|
||||
しかもその火を其処此処と動かしているらしい。これは、その濁った、黄いろい光が、
|
||||
隅々に蜘蛛の巣をかけた天井裏に、ゆれながら映ったので、すぐにそれと知れたのであ
|
||||
る。この雨の夜に、この羅生門の上で、火をともしているからは、どうせ唯の者ではな
|
||||
い。
|
||||
下人は、宮守(やもり)のように足音をぬすんで、やっと急な梯子を、一番上の段ま
|
||||
で這うようにして上りつめた。そうして体を出来るだけ、平にしながら、頸を出来るだ
|
||||
け、前へ出して、恐る恐る、楼の内を覗いて見た。
|
||||
見ると、楼の内には、噂に聞いた通り、幾つかの屍骸(しがい)が、無造作に棄てて
|
||||
あるが、火の光の及ぶ範囲が、思ったより狭いので、数は幾つともわからない。唯、お
|
||||
ぼろげながら、知れるのは、その中に裸の屍骸と、着物を着た屍骸とがあると云う事で
|
||||
ある。勿論、中には女も男もまじっているらしい。そうして、その屍骸は皆、それが、
|
||||
嘗(かつて)、生きていた人間だと云う事実さえ疑われる程、土を捏ねて造った人形の
|
||||
ように、口を開いたり、手を延ばしたりして、ごろごろ床の上にころがっていた。しか
|
||||
も、肩とか胸とかの高くなっている部分に、ぼんやりした火の光をうけて、低くなって
|
||||
いる部分の影を一層暗くしながら、永久に唖(おし)の如く黙っていた。
|
||||
下人は、それらの屍骸の腐爛した臭気に思わず、鼻を掩った(おおった)。しかし、
|
||||
その手は、次の瞬間には、もう鼻を掩う事を忘れていた。或る強い感情が殆悉(ほとん
|
||||
どことごとく)この男の嗅覚を奪ってしまったからである。
|
||||
下人の眼は、その時、はじめて、其屍骸の中に蹲っている(うずくまっている)人間
|
||||
を見た。檜肌色(ひはだいろ)の着物を著た、背の低い、痩せた、白髪頭の、猿のよう
|
||||
な老婆である。その老婆は、右の手に火をともした松の木片を持って、その屍骸の一つ
|
||||
の顔を覗きこむように眺めていた。髪の毛の長い所を見ると、多分女の屍骸であろう。
|
||||
下人は、六分の恐怖と四分の好奇心とに動かされて、暫時は呼吸(いき)をするのさ
|
||||
え忘れていた。旧記の記者の語を借りれば、「頭身(とうしん)の毛も太る」ように感
|
||||
じたのである。すると、老婆は、松の木片を、床板の間に挿して、それから、今まで眺
|
||||
めていた屍骸の首に両手をかけると、丁度、猿の親が猿の子の虱(しらみ)をとるよう
|
||||
に、その長い髪の毛を一本ずつ抜きはじめた。髪は手に従って抜けるらしい。
|
||||
その髪の毛が、一本ずつ抜けるのに従って下人の心からは、恐怖が少しずつ消えて行っ
|
||||
た。そうして、それと同時に、その老婆に対するはげしい憎悪が、少しずつ動いて来た。
|
||||
いや、この老婆に対すると云っては、語弊があるかも知れない。寧(むしろ)、あらゆ
|
||||
る悪に対する反感が、一分毎に強さを増して来たのである。この時、誰かがこの下人に、
|
||||
さっき門の下でこの男が考えていた、饑死(うえじに)をするか盗人になるかと云う問
|
||||
題を、改めて持出したら、恐らく下人は、何の未練もなく、饑死を選んだ事であろう。
|
||||
それほど、この男の悪を憎む心は、老婆の床に挿した松の木片のように、勢よく燃え上
|
||||
がりだしていたのである。
|
||||
下人には、勿論、何故老婆が死人の髪の毛を抜くかわからなかった。従って、合理的
|
||||
には、それを善悪の何れに片づけてよいか知らなかった。しかし下人にとっては、この
|
||||
雨の夜に、この羅生門の上で、死人の髪の毛を抜くと云う事が、それだけで既に許す可
|
||||
らざる悪であった。勿論 下人は さっき迄自分が、盗人になる気でいた事なぞは と
|
||||
うに忘れているのである。
|
||||
そこで、下人は、両足に力を入れて、いかなり、梯子から上へ飛び上がった そうし
|
||||
て聖柄(ひじりづか)の太刀に手をかけながら、大股に老婆の前へ歩みよった。老婆が
|
||||
驚いたのは 云う迄もない。
|
||||
老婆は、一目下人を見ると、まるで弩(いしゆみ)にでも弾かれたように 飛び上がっ
|
||||
た。
|
||||
「おのれ、どこへ行く。」
|
||||
下人は、老婆が屍骸につまづきながら、慌てふためいて逃げようとする行手を塞いで、
|
||||
こう罵った。老婆は、それでも下人をつきのけて行こうとする。下人は又、それを行か
|
||||
すまいとして、押しもどす。二人は屍骸の中で、暫、無言のまま、つかみ合った。しか
|
||||
し勝負は、はじめから、わかっている。下人はとうとう、老婆の腕をつかんで、無理に
|
||||
そこへねじ倒した。丁度、鶏(とり)の脚のような、骨と皮ばかりの腕である。
|
||||
「何をしていた。さあ何をしていた。云え。云わぬと これだぞよ。」
|
||||
下人は、老婆をつき放すと、いきなり、太刀の鞘を払って、白い鋼(はがね)の色を
|
||||
その眼の前へつきつけた。けれども、老婆は黙っている。両手をわなわなふるわせて、
|
||||
肩で息を切りながら、眼を、眼球がまぶたの外へ出そうになる程、見開いて、唖のよう
|
||||
に執拗(しゅうね)く黙っている。これを見ると、下人は始めて明白にこの老婆の生死
|
||||
が、全然、自分の意志に支配されていると云う事を意識した。そうして、この意識は、
|
||||
今まではげしく燃えていた憎悪の心を何時(いつ)の間にか冷ましてしまった。後に残っ
|
||||
たのは、唯、或仕事をして、それが円満に成就した時の、安らかな得意と満足とがある
|
||||
ばかりである。そこで、下人は、老婆を、見下げながら、少し声を柔げてこう云った。
|
||||
「己は検非違使(けびいし)の庁の役人などではない。今し方この門の下を通りかかっ
|
||||
た旅の者だ。だからお前に縄をかけて、どうしようと云うような事はない。唯今時分、
|
||||
この門の上で、何をしていたのだか、それを己に話さえすればいいのだ。」
|
||||
すると、老婆は、見開いた眼を、一層大きくして、じっとその下人の顔を見守った。
|
||||
まぶたの赤くなった、肉食鳥のような、鋭い眼で見たのである。それから、皺で、殆、
|
||||
鼻と一つになった唇を何か物でも噛んでいるように動かした。細い喉で、尖った喉仏の
|
||||
動いているのが見える。その時、その喉から、鴉(からす)の啼くような声が、喘ぎ喘
|
||||
ぎ、下人の耳へ伝わって来た。
|
||||
「この髪を抜いてな、この女の髪を抜いてな、鬘(かつら)にしようと思うたの
|
||||
じゃ。」
|
||||
下人は、老婆の答が存外、平凡なのに失望した。そうして失望すると同時に、又前の
|
||||
憎悪が、冷な侮蔑と一しょに、心の中へはいって来た。すると その気色(けしき)が、
|
||||
先方へも通じたのであろう。老婆は、片手に、まだ屍骸の頭から奪(と)った長い抜け
|
||||
毛を持ったなり、蟇(ひき)のつぶやくような声で、口ごもりながら、こんな事を云っ
|
||||
た。
|
||||
成程、死人の髪の毛を抜くと云う事は、悪い事かね知れぬ。しかし、こう云う死人の
|
||||
多くは、皆 その位な事を、されてもいい人間ばかりである。現に、自分が今、髪を抜
|
||||
いた女などは、蛇を四寸ばかりずつに切って干したのを、干魚(ほしうお)だと云って、
|
||||
太刀帯(たちはき)の陣へ売りに行った。疫病にかかって死ななかったなら、今でも売
|
||||
りに行っていたかもしれない。しかも、この女の売る干魚は、味がよいと云うので、太
|
||||
刀帯たちが、欠かさず菜料に買っていたのである。自分は、この女のした事が悪いとは
|
||||
思わない。しなければ、饑死(えうじに)をするので、仕方がなくした事だからである。
|
||||
だから、又今、自分のしていた事も悪い事とは思わない。これもやはりしなければ、饑
|
||||
死をするので、仕方がなくする事だからである。そうして、その仕方がない事を、よく
|
||||
知っていたこの女は、自分のする事を許してくれるのにちがいないと思うからであ
|
||||
る。ーー老婆は、大体こんな意味の事を云った。
|
||||
下人は、太刀を鞘におさめて、その太刀の柄を左の手でおさえながら、冷然として、
|
||||
この話を聞いていた。勿論、 右の手では、赤く頬に膿を持た大きな面皰(にきび)を
|
||||
気にしながら、聞いているのである。しかし、之を聞いている中に、下人の心には、或
|
||||
勇気が生まれて来た。それは さっき、門の下でこの男に欠けていた勇気である。そう
|
||||
して、又さっき、この門の上へ上(あが)って、その老婆を捕えた時の勇気とは、全然、
|
||||
反対な方向に動こうとする勇気である。下人は、饑死をするか盗人になるかに迷わなかっ
|
||||
たばかりではない。その時のこの男の心もちから云えば、饑死などと云う事は、殆、考
|
||||
える事さえ出来ない程、意識の外に追い出されていた。
|
||||
「きっと、そうか。」
|
||||
老婆の話が完ると、下人は嘲(あざけ)るような声で念を押した。そうして、一足前
|
||||
へ出ると、不意に、右の手を面皰から離して、老婆の襟上(えりがみ)をつかみながら、
|
||||
こう云った。
|
||||
「では、己が引剥(ひはぎ)をしようと恨むまいな。己もそうしなければ、饑死をす
|
||||
る体なのだ。」
|
||||
下人は、すばやく、老婆の着物を剥ぎとった。それから、足にしがみつこうとする老
|
||||
婆を、手荒く屍骸の上へ蹴倒した。梯子の口までは、僅に五歩を数えるばかりである。
|
||||
下人は、剥ぎとった桧肌色の着物をわきにかかえて、またたく間に急な梯子を夜の底へ
|
||||
かけ下りた。
|
||||
暫、死んだように倒れていた老婆が、屍骸の中から、その裸の体を起こしたのは、そ
|
||||
れから間もなくの事である。老婆は、つぶやくような、うめくような声を立てながら、
|
||||
まだ燃えている火の光をたよりに、梯子の口まで、這って行った。そうして、そこから、
|
||||
短い白髪を倒(さかさま)にして、門の下を覗きこんだ。外には、唯、黒洞々(こくと
|
||||
うとう)たる夜があるばかりである。
|
||||
下人は、既に、雨を冒して、京都の町へ強盗を働きに急いでいた。
|
||||
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-gb-levels-1-and-2-hz-gb2312.txt
generated
vendored
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-gb-levels-1-and-2-hz-gb2312.txt
generated
vendored
|
|
@ -1,107 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
after converting from Traditional Chinese to Simplified Chinese.
|
||||
--------
|
||||
~{J<<F5ZR;~}
|
||||
|
||||
~{KoWST;#:1xU_#,9zV.4sJB#,K@IzV.5X#,4fMvV.5@#,2;?I2;2lR2!#~}
|
||||
|
||||
~{9J>-V.RTNeJB#,P#V.RT<F#,6xKwFdGi#:R;T;5@#,6~T;Ll#,H}T;5X#,KDT;=+#,NeT;7(!#~}
|
||||
|
||||
~{5@U_#,AnCqSkIOM,Rb#,?ISkV.K@#,?ISkV.Iz#,6x2;N7N#R2#;LlU_#,RuQt!":.Jn!"J1VFR2#;5XU_#,T6=|!"OURW!"9cOA!"K@IzR2#;=+U_#,VG!"PE!"HJ!"SB!"QOR2#;7(U_#,GzVF!"9Y5@!"VwSCR2!#724KNeU_#,=+D*2;NE#,V*V.U_J$#,2;V*U_2;J$!#~}
|
||||
|
||||
~{9JP#V.RT<F#,6xKwFdGi#,T;#:VwJkSP5@#?=+JkSPD\#?Ll5XJk5C#?7(AnJkPP#?1x~}?~{JkG?#?J?WdJkA7#?IM7#JkCw#?NaRT4KV*J$8:RS!#~}
|
||||
|
||||
~{=+L}Na<F#,SCV.1XJ$#,AtV.#;=+2;L}Na<F#,SCV.1X0\#,H%V.!#~}
|
||||
|
||||
~{<F@{RTL}#,DK~}?~{V.JF#,RTWtFdMb!#JFU_#,Rr@{6xVFH(R2!#~}
|
||||
|
||||
~{1xU_#,9n5@R2!#9JD\6xJ>V.2;D\#,SC6xJ>V.2;SC#,=|6xJ>V.T6#,T66xJ>V.=|!#@{6xSUV.#,BR6xH!V.#,J56x18V.#,G?6x1\V.#,E-6xDSV.#,106x=>V.#,X}6x@MV.#,GW6x@kV.#,9%FdN^18#,3vFd2;Rb!#4K1x<RV.J$#,2;?IOH4+R2!#~}
|
||||
|
||||
~{7rN4U=6xCmKcJ$U_#,5CKc6`R2#;N4U=6xCmKc2;J$U_#,5CKcIYR2!#6`KcJ$#,IYKc2;J$#,6x?vN^Kc:u#!NaRT4K9[V.#,J$8:<{RS!#~}
|
||||
|
||||
~{WwU=5Z6~~}
|
||||
|
||||
~{KoWST;#:72SC1xV.7(#,3[35G'~}?~{#,8o35G'3K#,4x<WJ.Mr#,G'@o@!A8!#TrDZMbV.7Q#,1v?MV.SC#,=:FaV.2D#,35<WV.7n#,HU7QG'=p#,H;:sJ.MrV.J&>YRS!#~}
|
||||
|
||||
~{FdSCU=R2#,9sJ$#,>CTr6[1x4lHq#,9%3GTrA&G|#,>C1)J&Tr9zSC2;Wc!#7r6[1x4lHq#,G|A&~}?~{;u#,TrVn:n3KFd1W6xFp#,KdSPVGU_#,2;D\IFFd:sRS!#9J1xNEW>KY#,N46CGIV.>CR2!#7r1x>C6x9z@{U_#,N4V.SPR2!#9J2;>!V*SC1xV.:&U_#,Tr2;D\>!V*SC1xV.@{R2!#~}
|
||||
|
||||
~{IFSC1xU_#,R[2;TY<.#,A82;H}TX#,H!SCl69z#,RrA8l65P#,9J>|J3?IWcR2!#9zV.F6l6J&U_T6Jd#,T6JdTr0YPUF6#;=|l6J&U_9sBt#,9sBtTr0YPU=_#,2F=_Tr<1l6GpR[!#A&G|2F~}?~{#,VPT-DZPil6<R#,0YPUV.7Q#,J.H%FdF_#;9+<RV.7Q#,FF>|0UBm#,<WkPJ8es#,j*~}?~{C,~}?~{#,GpE#4s35#,J.H%FdAy!#~}
|
||||
|
||||
~{9JVG=+NqJ3l65P#,J35PR;VS#,51Na6~J.VS#;]=8QR;J/#,51Na6~J.J/!#9JI15PU_#,E-R2#;H!5PV.@{U_#,;uR2!#9J35U=#,5C35J.3KRTIO#,IMFdOH5CU_#,6x8|Fdl:Fl!#35TS6x3KV.#,WdIF6xQxV.#,JGN=J$5P6xRfG?!#~}
|
||||
|
||||
~{9J1x9sJ$#,2;9s>C!#9JV*1xV.=+#,CqV.K>C|!#9z<R02N#V.VwR2!#~}
|
||||
|
||||
~{D19%5ZH}~}
|
||||
|
||||
~{KoWST;#:72SC1xV.7(#,H+9z~}?~{IO#,FF9z4NV.#;H+>|~}?~{IO#,FF>|4NV.#;H+BC~}?~{IO#,FFBC4NV.#;H+Wd~}?~{IO#,FFWd4NV.#;H+Ni~}?~{IO#,FFNi4NV.!#JG9J0YU=0YJ$#,7GIFV.IFU_R2#;2;U=6xG|HKV.1x#,IFV.IFU_R2!#~}
|
||||
|
||||
~{9JIO1x7%D1#,Fd4N7%=;#,Fd4N7%1x#,FdOB9%3G!#9%3GV.7(#,~}?~{2;5CRQ!#P^~}???~{#,>_FwP5#,H}TB6x:s3I#;>`~}?~{#,SVH}TB6x:sRQ!#=+2;J$Fd7^#,6xRO8=V.#,I1J?H}7VV.R;#,6x3G2;0NU_#,4K9%V.TVR2!#~}
|
||||
|
||||
~{9JIFSC1xU_#,G|HKV.1x#,6x7GU=R2#,0NHKV.3G6x7G9%R2#,;YHKV.9z6x7G>CR2#,1XRTH+Uyl6LlOB#,9J1x2;6Y6x@{?IH+#,4KD19%V.7(R2!#~}
|
||||
|
||||
~{9JSC1xV.7(#,J.TrN'V.#,NeTr9%V.#,16Tr7VV.#,5PTrD\U=V.#,IYTrD\LSV.#,2;HtTrD\1\V.!#9JP!5PV.<a#,4s5PV.G\R2!#~}
|
||||
|
||||
~{7r=+U_#,9zV.8(R2!#8(V\Tr9z1XG?#,8(O6Tr9z1XHu!#9J>}V.KyRT;<l6>|U_H}#:2;V*>|V.2;?IRT=x6xN=V.=x#,2;V*>|V.2;?IRTMK6xN=V.MK#,JGN=wc>|#;2;V*H}>|V.JB#,6xM,H}>|V.U~#,Tr>|J?;sRS#;2;V*H}>|V.H(#,6xM,H}>|V.HN#,Tr>|J?RIRS!#H}>|<H;sGRRI#,TrVn:nV.DQVARS!#JGN=BR>|R}J$!#~}
|
||||
|
||||
~{9JV*J$SPNe#:V*?IRTU=Sk2;?IRTU=U_#,J$!#J6~}?~{9QV.SCU_#,J$!#IOOBM,S{U_#,J$!#RTS]4}2;S]U_#,J$!#=+D\6x>}2;SyU_#,J$!#4KNeU_#,V*J$V.5@R2!#~}
|
||||
|
||||
~{9JT;#:V*<:V*1K#,0YU=2;~}?~{#;2;V*1K6xV*<:#,R;J$R;8:#;2;V*1K2;V*<:#,C?U=1X0\!#~}
|
||||
|
||||
~{>|PN5ZKD~}
|
||||
|
||||
~{KoWST;#:NtV.IFU=U_#,OH~}?~{2;?IJ$#,RT4}5PV.?IJ$!#2;?IJ$TZ<:#,?IJ$TZ5P!#9JIFU=U_#,D\~}?~{2;?IJ$#,2;D\J95P1X?IJ$!#9JT;#:J$?IV*#,6x2;?I~}?~{!#~}
|
||||
|
||||
~{2;?IJ$U_#,JXR2#;?IJ$U_#,9%R2!#JXTr2;Wc#,9%TrSP~}?~{!#IFJXU_#,2Xl6>E5XV.OB#,IF9%U_#,6/l6>ELlV.IO#,9JD\WT1#6xH+J$R2!#~}
|
||||
|
||||
~{<{J$2;9}~}?~{HKV.KyV*#,7GIFV.IFU_R2#;U=J$6xLlOBT;IF#,7GIFV.IFU_R2!#9J>YGo:A2;~}?~{6`A&#,<{HUTB2;~}?~{CwD?#,NE@Wv*2;~}?~{4O6z!#9EV.IFU=U_#,J$l6RWJ$U_R2!#9JIFU=U_V.J$R2#,N^VGC{#,N^SB9&#,9JFdU=J$2;_/!#2;_/U_#,FdKy4k1XJ$#,J$RQ0\U_R2!#9JIFU=U_#,OHA"l62;0\V.5X#,6x2;J'5PV.0\R2!#JG9JJ$1xOHJ$#,6x:sGsU=#,0\1xOHU=6x:sGsJ$!#IFSC1xU_#,P^5@6x1#7(#,9JD\~}?~{J$0\V.U~!#~}
|
||||
|
||||
~{1x7(#:R;T;6H#,6~T;A?#,H}T;J}#,KDT;3F#,NeT;J$!#5XIz6H#,6HIzA?#,A?IzJ}#,J}Iz3F#,3FIzJ$!#9JJ$1xHtRT~}?~{3F~}?~{#,0\1xHtRT~}?~{3F~}?~{!#J$U_V.U=#,Ht>v;}K.l6G'XpV.~}?~{U_#,PNR2!#~}
|
||||
|
||||
~{1xJF5ZNe~}
|
||||
|
||||
~{KoWST;#:72VN~}?~{HgVN9Q#,7VJ}JGR2#;67~}?~{Hg679Q#,PNC{JGR2#;H}>|V.~}?~{#,?IJ91XJ\5P6xN^0\U_#,FfU}JGR2#;1xV.Ky<S#,HgRT~}?~{M6BQU_#,PiJ5JGR2!#~}
|
||||
|
||||
~{72U=U_#,RTU}:O#,RTFfJ$!#9JIF3vFfU_#,N^GnHgLl5X#,2;=_Hg=-:#!#VU6x84J<#,HUTBJGR2!#K@6x~}?~{Iz#,KDJ1JGR2!#Iy2;9}Ne#,NeIyV.1d#,2;?IJ$L}R2#;I+2;9}Ne#,NeI+V.1d#,2;?IJ$9[R2#;N62;9}Ne#,NeN6V.1d#,2;?IJ$3"R2#;U=JF#,2;9}FfU}#,FfU}V.1d#,2;?IJ$GnR2!#FfU}O`Iz#,HgQ-;7V.N^6K#,JlD\GnV.TU#?~}
|
||||
|
||||
~{<$K.V.<2#,VAl6F/J/U_#,JFR2#;~}?~{DqV.<2#,VAl6;YU[U_#,=ZR2!#JG9JIFU=U_#,FdJFOU#,Fd=Z6L!#JFHgUEes#,=ZHg7";z!#~}
|
||||
|
||||
~{7W7W~}??~{#,67BR6x2;?IBRR2#;;k;kcgcg#,PNT26x2;?I0\R2!#BRIzl6VN#,GSIzl6SB#,HuIzl6G?!#VNBR#,J}R2#;SBGS#,JFR2#;G?Hu#,PNR2!#9JIF6/5PU_#,PNV.#,5P1X4SV.#;ShV.#,5P1XH!V.!#RT@{6/V.#,RTWd4}V.!#~}
|
||||
|
||||
~{9JIFU=U_#,GsV.l6JF#,2;Tpl6HK#;9JD\TqHK6xHNJF!#HNJFU_#,FdU=HKR2#,HgW*D>J/!#D>J/V.PT#,02Tr>2#,N#Tr6/#,7=TrV9#,T2TrPP!#9JIFU=HKV.JF#,HgW*T2J/l6G'XpV.I=U_#,JFR2!#~}
|
||||
|
||||
~{PiJ55ZAy~}
|
||||
|
||||
~{KoWST;#:72OH4&U=5X6x4}5PU_X}#,:s4&U=5X6xGwU=U_@M!#~}
|
||||
|
||||
~{9JIFU=U_#,VBHK6x2;VBl6HK!#D\J95PHKWTVAU_#,@{V.R2#;D\J95PHK2;5CVAU_#,:&V.R2!#9J5PX}D\@MV.#,1%D\<"V.#,02D\6/V.!#3vFdKy1XGw#,GwFdKy2;Rb!#PPG'@o6x2;@MU_#,PPl6N^HKV.5XR2#;9%6x1XH!U_#,9%FdKy2;JXR2!#JX6x1X9LU_#,JXFdKy2;9%R2!#~}
|
||||
|
||||
~{9JIF9%U_#,5P2;V*FdKyJX#;IFJXU_#,5P2;V*FdKy9%!#N":uN":u#,VAl6N^PN#;Iq:uIq:u#,VAl6N^Iy#,9JD\~}?~{5PV.K>C|!#=x6x2;?ISyU_#,3eFdPiR2#;MK6x2;?IW7U_#,KY6x2;?I<0R2!#9JNRS{U=#,5PKd8_@]In95#,2;5C2;SkNRU=U_#,9%FdKy1X>HR2#;NR2;S{U=#,Kd;-5X6xJXV.#,5P2;5CSkNRU=U_#,9TFdKyV.R2!#9JPNHK6xNRN^PN#,TrNRW(6x5P7V!#NRW(~}?~{R;#,5P7V~}?~{J.#,JGRTJ.9%FdR;R2!#TrNR~}?~{5P9Q#,D\RT~}?~{;w9QU_#,TrNaV.KySkU=U_T<RS!#NaKySkU=V.5X2;?IV*#,2;?IV*Tr5PKy18U_6`#,5PKy18U_6`#,TrNaKySkU=U_9QRS!#9J18G0Tr:s9Q#,18:sTrG09Q#,18WsTrSR9Q#,18SRTrWs9Q#,N^Ky2;18#,TrN^Ky2;9Q!#9QU_#,18HKU_R2#;~}?~{U_#,J9HK18<:U_R2!#9JV*U=V.5X#,V*U=V.HU#,Tr?IG'@o6x;aU=#;2;V*U=V.5X#,2;V*U=HU#,TrWs2;D\>HSR#,SR2;D\>HWs#,G02;D\>H:s#,:s2;D\>HG0#,6x?vT6U_J}J.@o#,=|U_J}@o:u#!RTNa6HV.#,T=HKV.1xKd6`#,R`^IRfl6J$TU#!9JT;#:J$?I~}?~{R2!#5PKd~}?~{#,?IJ9N^67!#9J2_V.6xV*5CJ'V.<F#,:rV.6xV*6/>2V.@m#,PNV.6xV*K@IzV.5X#,=GV.6xV*SP~}?~{2;WcV.4&!#9JPN1xV.<+#,VAl6N^PN!#N^PNTrIn<d2;D\?z#,VGU_2;D\D1!#RrPN6x4kJ$l6~}?~{#,~}?~{2;D\V*!#HK=TV*NRKyRTJ$V.PN#,6xD*V*NaKyRTVFJ$V.PN!#9JFdU=J$2;~}?~{#,6xS&PNl6N^Gn!#7r1xPNOsK.#,K.V.PP1\8_6xGwOB#,1xV.PN1\J56x;wPi#;K.Rr5X6xVFAw#,1xRr5P6xVFJ$!#9J1xN^3#JF#,K.N^3#PN!#D\Rr5P1d;/6xH!J$U_#,N=V.Iq!#9JNePPN^3#J$#,KDJ1N^3#N;#,HUSP6L3$#,TBSPK@Iz!#~}
|
||||
|
||||
~{>|Uy5ZF_~}
|
||||
|
||||
~{KoWST;#:~} ~{72SC1xV.7(#,=+J\C|l6>}#,:O>|>[~}?~{#,=;:M6xIa#,D*DQl6>|Uy!#>|UyV.DQU_#,RTSX~}?~{V1#,RT;<~}?~{@{!#9JSXFdM>#,6xSUV.RT@{#,:sHK7"#,OHHKVA#,4KV*SXV1V.<FU_R2!#>|Uy~}?~{@{#,>|Uy~}?~{N#!#>Y>|6xUy@{Tr2;<0#,N/>|6xUy@{Tr~}?~{VX>h!#JG9J~}?~{<W6xGw#,HUR92;4&#,165@<fPP#,0Y~}?~{6xUy@{#,TrG\H}=+>|#,>"U_OH#,F#U_:s#,Fd7(J.R;6xVA#;NeJ.@o6xUy@{#,TrujIO=+>|#,Fd7(0kVA#;H}J.@o6xUy@{#,TrH}7VV.6~VA!#JG9J>|N^~}?~{VXTrMv#,N^A8J3TrMv#,N^N/;}TrMv!#9J2;V*Vn:nV.D1U_#,2;D\T%=;#;2;V*I=AV!"OUWh!">ZTsV.PNU_#,2;D\PP>|#;2;SCOg5<U_#,2;D\5C5X@{!#9J1xRTU)A"#,RT@{6/#,RT7V:M~}?~{1dU_R2!#9JFd<2Hg7g#,FdPlHgAV#,GVBSHg;p#,2;6/HgI=#,DQV*HgRu#,6/Hg@WUp!#BSOg7V~}?~{#,@*5X7V@{#,P|H(6x6/!#OHV*SXV1V.<FU_J$#,4K>|UyV.7(R2!#!6>|U~!7T;#:!0QT2;O`NE#,9J~}?~{V.=p9D#;JS2;O`<{#,9J~}?~{V.l:Fl!#!17r=p9Dl:FlU_#,KyRTR;CqV.6zD?R2!#Cq<HW(R;#,TrSBU_2;5C6@=x#,GSU_2;5C6@MK#,4KSC~}?~{V.7(R2!#9JR9U=6`=p9D#,VgU=6`l:Fl#,KyRT1dHKV.6zD?R2!#H}>|?I6aFx#,=+>|?I6aPD!#JG9J3/FxHq#,VgFx6h#,D:Fx9i!#IFSC1xU_#,1\FdHqFx#,;wFd6h9i#,4KVNFxU_R2!#RTVN4}BR#,RT>24};)#,4KVNPDU_R2!#RT=|4}T6#,RTX}4}@M#,RT1%4}<"#,4KVNA&U_R2!#N^Q{U}U}V.Fl#,N^;wLCLCV.3B#,4KVN1dU_R2!#9JSC1xV.7(#,8_AjNpOr#,13GpNpDf#,Qp11Np4S#,HqWdNp9%#,6|1xNpJ3#,9iJ&Np6t#,N'J&RE~}?~{#,Gn?\NpFH#,4KSC1xV.7(R2!#~}
|
||||
|
||||
~{>E1d5Z0K~}
|
||||
|
||||
~{KoWST;#:~} ~{72SC1xV.7(#,=+J\C|l6>}#,:O>|>[:O!#7:5XN^Ia#,ai5X:O=;#,>x5XN^At#,N'5XTrD1#,K@5XTrU=#,M>SPKy2;SI#,>|SPKy2;;w#,3GSPKy2;9%#,5XSPKy2;Uy#,>}C|SPKy2;J\!#9J=+M(l6>E1dV.@{U_#,V*SC1xRS#;=+2;M(>E1dV.@{#,KdV*5XPN#,2;D\5C5XV.@{RS#;VN1x2;V*>E1dV.Ju#,KdV*Ne@{#,2;D\5CHKV.SCRS!#JG9JVGU_V.BG#,1XTSl6@{:&#,TSl6@{6xNq?IPER2#,TSl6:&6x;<?I=bR2!#JG9JG|Vn:nU_RT:&#,R[Vn:nU_RTR5#,GwVn:nU_RT@{!#9JSC1xV.7(#,N^JQFd2;@4#,JQNaSPRT4}V.#;N^JQFd2;9%#,JQNaSPKy2;?I9%R2!#9J=+SPNeN##,1XK@?II1#,1XIz?IB2#,7^KY?INj#,A.=`?IHh#,0.Cq?I73!#724KNeU_#,=+V.9}R2#,SC1xV.TVR2!#82>|I1=+#,1XRTNeN##,2;?I2;2lR2!#~}
|
||||
|
||||
~{PP>|5Z>E~}
|
||||
|
||||
~{KoWST;#:724&>|O`5P#,>xI=R@~}?~{#,JSIz4&8_#,U=B!N^5G#,4K4&I=V.>|R2!#>xK.1XT6K.#,?M>xK.6x@4#,NpS-V.l6K.DZ#,An0k6I6x;wV.@{#,S{U=U_#,N^8=l6K.6xS-?M#,JSIz4&8_#,N^S-K.Aw#,4K4&K.IOV.>|R2!#>x3bTs#,N(X=H%N^At#,Ht=;>|l63bTsV.VP#,1XR@K.2]6x13~}?~{Jw#,4K4&3bTsV.>|R2!#F=B=4&RW#,SR138_#,G0K@:sIz#,4K4&F=B=V.>|R2!#724KKD>|V.@{#,;F5[V.KyRTJ$KD5[R2!#72>|:C8_6x6qOB#,9sQt6x<zRu#,QxIz6x4&J5#,>|N^0Y<2#,JGN=1XJ$!#GpAj5L7@#,1X4&FdQt6xSR13V.#,4K1xV.@{#,5XV.VzR2!#IOSjK.AwVA#,S{IfU_#,4}Fd6(R2!#725XSP>x='!"Ll>.!"Ll@N!"LlB^!"LlO]!"LlO6#,1XX=H%V.#,Np=|R2!#NaT6V.#,5P=|V.#;NaS-V.#,5P13V.!#>|ETSPOUWh!"dj>.!"]s]g!"P!AV!"~}??~{U_#,1X=w82KwV.#,4K7|~}?~{V.Ky4&R2!#5P=|6x>2U_#,JQFdOUR2#;T66xLtU=U_#,S{HKV.=xR2#;FdKy>SRWU_#,@{R2#;~}?~{Jw6/U_#,@4R2#;~}?~{2]6`UOU_#,RIR2#;DqFpU_#,7|R2#;J^:'U_#,82R2#;3>8_6xHqU_#,35@4R2#;106x9cU_#,M=@4R2#;I"6xLu4oU_#,iT~}?~{R2#;IY6xMy@4U_#,S*>|R2#;4G106x18U_#,=xR2#;4GG?6x=xG}U_#,MKR2#;Ga35OH3v>SFd2`U_#,3BR2#;N^T<6xGk:MU_#,D1R2#;1<W_6x3B1xU_#,FZR2#;0k=x0kMKU_#,SUR2#;UH6xA"U_#,<"R2#;<36xOHR{U_#,?JR2#;<{@{6x2;=xU_#,@MR2#;Dq</U_#,PiR2#;R9:tU_#,?VR2#;>|HEU_#,=+2;VXR2#;l:Fl6/U_#,BRR2#;@tE-U_#,>kR2#;I1BmHbJ3U_#,>|N^A8R2#;P|~}?~{2;75FdIaU_#,Gn?\R2#;W;W;tbtb#,PlSkHKQTU_#,J'~}?~{R2#;J}IMU_#,>=R2#;J}7#U_#,@'R2#;OH1)6x:sN7Fd~}?~{U_#,2;>+V.VAR2#;@4N/P;U_#,S{P]O"R2!#1xE-6xO`S-#,>C6x2;:O#,SV2;O`H%#,1X=w2lV.!#1x7G9sRf6`R2#,N)N^Nd=x#,WcRT2"A&AO5PH!HK6xRQ!#7rN)N^BG6xRW5PU_#,1XG\l6HK!#WdN4GW6x7#V.#,Tr2;7~#,2;7~TrDQSC!#WdRQGW8=6x7#2;PP#,Tr2;?ISC!#9J:OV.RTND#,FkV.RTNd#,JGN=1XH!!#AnKXPPRT=LFdCq#,TrCq7~#;AnKX2;PPRT=LFdCq#,TrCq2;7~!#AnKXPPU_#,Sk~}?~{O`5CR2!#~}
|
||||
|
||||
~{5XPN5ZJ.~}
|
||||
|
||||
~{KoWST;#:5XPNSPM(U_!"SP~}?~{U_!"SPV'U_!"SP0/U_!"SPOUU_!"SPT6U_!#NR?IRTMy#,1K?IRT@4#,T;M(!#M(PNU_#,OH>S8_Qt#,@{A85@#,RTU=Tr@{!#?IRTMy#,DQRT75#,T;~}?~{!#~}?~{PNU_#,5PN^18#,3v6xJ$V.#,5PHtSP18#,3v6x2;J$#,DQRT75#,2;@{!#NR3v6x2;@{#,1K3v6x2;@{#,T;V'!#V'PNU_#,5PKd@{NR#,NRN^3vR2#,R}6xH%V.#,An5P0k3v6x;wV.@{!#0/PNU_#,NROH>SV.#,1XS/V.RT4}5P!#Ht5POH>SV.#,S/6xNp4S#,2;S/6x4SV.!#OUPNU_#,NROH>SV.#,1X>S8_QtRT4}5P#;Ht5POH>SV.#,R}6xH%V.#,Np4SR2!#T6PNU_#,JF>yDQRTLtU=#,U=6x2;@{!#724KAyU_#,5XV.5@R2#,=+V.VAHN#,2;?I2;2lR2!#721xSPW_U_!"SP3[U_!"SPO]U_!"SP1@U_!"SPBRU_!"SP11U_!#724KAyU_#,7GLl5XV.TV#,=+V.9}R2!#7rJF>y#,RTR;;wJ.#,T;W_#;WdG?@tHu#,T;3[#;@tG?WdHu#,T;O]#;4s@tE-6x2;7~#,Sv5P~}?~{6xWTU=#,=+2;V*FdD\#,T;1@#;=+Hu2;QO#,=L5@2;Cw#,@tWdN^3##,3B1xW]:a#,T;BR#;=+2;D\AO5P#,RTIY:O~}?~{#,RTHu;wG?#,1xN^Q!7f#,T;11!#724KAyU_#,0\V.5@R2#,=+V.VAHN#,2;?I2;2lR2!#7r5XPNU_#,1xV.VzR2!#AO5PVFJ$#,<FOU0/T6=|#,IO=+V.5@R2!#V*4K6xSCU=U_1XJ$#,2;V*4K6xSCU=U_1X0\!#9JU=5@1XJ$#,VwT;N^U=#,1XU=?IR2#;U=5@2;J$#,VwT;1XU=#,N^U=?IR2!#9J=x2;GsC{#,MK2;1\Wo#,N(CqJG1##,6x@{l6Vw#,9zV.1&R2!#JSWdHgS$6y#,9J?IRTSkV.80InO*#;JSWdHg0.WS#,9J?ISkV.>cK@!#:q6x2;D\J9#,0.6x2;D\An#,BR6x2;D\VN#,F)Ht=>WS#,2;?ISCR2!#V*NaWdV.?IRT;w#,6x2;V*5PV.2;?I;w#,J$V.0kR2#;V*5PV.?I;w#,6x2;V*NaWdV.2;?IRT;w#,J$V.0kR2#;V*5PV.?I;w#,V*NaWdV.?IRT;w#,6x2;V*5XPNV.2;?IRTU=#,J$V.0kR2!#9JV*1xU_#,6/6x2;CT#,>Y6x2;Gn!#9JT;#:V*1KV*<:#,J$DK2;4y#;V*LlV*5X#,J$DK?IH+!#~}
|
||||
|
||||
~{>E5X5ZJ.R;~}
|
||||
|
||||
~{KoWST;#:SC1xV.7(#,SPI"5X#,SPGa5X#,SPUy5X#,SP=;5X#,SPai5X#,SPVX5X#,SP7:5X#,SPN'5X#,SPK@5X!#Vn:nWTU=Fd5XU_#,~}?~{I"5X#;HkHKV.5X2;InU_#,~}?~{Ga5X#;NR5CR`@{#,1K5CR`@{U_#,~}?~{Uy5X#;NR?IRTMy#,1K?IRT@4U_#,~}?~{=;5X#;Vn:nV.5XH}Jt#,OHVA6x5CLlOB~}?~{U_#,~}?~{ai5X#;HkHKV.5XIn#,133GRX6`U_#,~}?~{VX5X#;I=AV!"OUWh!">ZTs#,72DQPPV.5@U_#,~}?~{7:5X#;KySIHkU_0/#,Ky4S9iU_SX#,1K9Q?IRT;wNaV.~}?~{U_#,~}?~{N'5X#;<2U=Tr4f#,2;<2U=TrMvU_#,~}?~{K@5X!#JG9JI"5XTrN^U=#,Ga5XTrN^V9#,Uy5XTrN^9%#,=;5XTrN^>x#,ai5XTr:O=;#,VX5XTrBS#,7:5XTrPP#,N'5XTrD1#,K@5XTrU=!#9EV.IFSC1xU_#,D\J95PHKG0:s2;O`<0#,~}?~{9Q2;O`JQ#,9s<z2;O`>H#,IOOB2;O`JU#,Wd@k6x2;</#,1x:O6x2;Fk!#:Ol6@{6x6/#,2;:Ol6@{6xV9!#8RNJ5P~}?~{6xU{=+@4#,4}V.Ht:NT;#:OH6aFdKy0.TrL}RS!#1xV.GiVwKY#,3KHKV.2;<0!#SI2;S]V.5@#,9%FdKy2;=dR2!#72~}?~{?MV.5@#,InHkTrW(!#VwHK2;?K#,BSl6HDR0#,H}>|WcJ3!#=wQx6xNp@M#,2"Fx;}A&#,TK1x<FD1#,~}?~{2;?I2b!#M6V.N^KyMy#,K@GR2;11!#K@QI2;5C#,J?HK>!A&!#1xJ?IuO]Tr2;>e#,N^KyMyTr9L#,InHkTr>P#,2;5CRQTr67!#JG9JFd1x2;P^6x=d#,2;Gs6x5C#,2;T<6xGW#,2;An6xPE#,={OiH%RI#,VAK@N^KyV.!#NaJ?N^~}?~{2F#,7G6q;uR2#;N^~}?~{C|#,7G6qJYR2!#An7"V.HU#,J?WdWxU_LiU4=s#,YHNTU_Li=;RC#,M6V.N^KyMy#,Vn!"~}?~{V.SBR2!#9JIFSC1xU_#,F)HgBJH;!#BJH;U_#,3#I=V.I_R2!#;wFdJWTrN2VA#,;wFdN2TrJWVA#,;wFdVPTrJWN2>cVA!#8RNJ1x?IJ9HgBJH;:u#?T;?I!#7rNbHKSkT=HKO`6qR2#,51FdM,V[6x<C6xSv7g#,FdO`>HR2HgWsSRJV!#JG9J7=BmBqBV#,N4WcJQR2#;FkSBHgR;#,U~V.5@R2#;8UHa=T5C#,5XV.@mR2!#9JIFSC1xU_#,P/JVHtJ9R;HK#,2;5CRQR2!#=+>|V.JB#,>2RTSD#,U}RTVN#,D\S^J?WdV.6zD?#,J9V.N^V*#;RWFdJB#,8oFdD1#,J9HKN^J6#;RWFd>S#,SXFdM>#,J9Cq2;5CBG!#K'SkV.FZ#,Hg5G8_6xH%FdL]#;K'SkV.InHkVn:nV.5X#,6x7"Fd;z!#HtG}H:Qr#,G}6xMy#,G}6x@4#,D*V*KyV.!#>[H}>|V.~}?~{#,M6V.l6OU#,4KN==+>|V.JBR2!#>E5XV.1d#,G|IlV.A&#,HKGiV.@m#,2;?I2;2lR2!#72~}?~{?MV.5@#,InTrW(#,G3TrI"!#H%9zT=>36xJ&U_#,>x5XR2#;KD39U_#,ai5XR2#;HkInU_#,VX5XR2#;HkG3U_#,Ga5XR2#;139LG00/U_#,N'5XR2#;N^KyMyU_#,K@5XR2!#JG9JI"5XNa=+R;FdV>#,Ga5XNa=+J9V.Jt#,Uy5XNa=+GwFd:s#,=;5XNa=+=wFdJX#,=;5XNa=+9LFd=a#,ai5XNa=+=wFdJQ#,VX5XNa=+<LFdJ3#,7:5XNa=+=xFdM>#,N'5XNa=+H{Fd~}?~{#,K@5XNa=+J>V.RT2;;n!#9J1xV.Gi#:N'TrSy#,2;5CRQTr67#,9}Tr4S!#JG9J2;V*Vn:nV.D1U_#,2;D\T$=;#;2;V*I=AV!"OUWh!">ZTsV.PNU_#,2;D\PP>|#;2;SCOg5<#,2;D\5C5X@{!#KDNeU_#,R;2;V*#,7G0TMuV.1xR2!#7r0TMuV.1x#,7%4s9z#,TrFd~}?~{2;5C>[#;M~<Sl65P#,TrFd=;2;5C:O!#JG9J2;UyLlOBV.=;#,2;QxLlOBV.H(#,PE<:V.K=#,M~<Sl65P#,TrFd3G?I0N#,Fd9z?IcD!#J)N^7(V.IM#,P|N^U~V.An!#78H}>|V.~}?~{#,HtJ9R;HK!#78V.RTJB#,Np8fRTQT#;78V.RT:&#,Np8fRT@{!#M6V.Mv5XH;:s4f#,O]V.K@5XH;:sIz!#7r~}?~{O]l6:&#,H;:sD\~}?~{J$0\!#9J~}?~{1xV.JB#,TZK3Oj5PV.Rb#,2"5PR;Or#,G'@oI1=+#,JGN=GID\3IJB!#JG9JU~>YV.HU#,RD9XU[7{#,N^M(FdJ9#,@wl6@HCmV.IO#,RTVoFdJB!#5PHK?*~}?~{#,1XX=HkV.#,OHFdKy0.#,N"SkV.FZ#,<yD+Kf5P#,RT>vU=JB!#JG9JJ<Hg4&E.#,5PHK?*;'#;:sHgMQMC#,5P2;<0>\!#~}
|
||||
|
||||
~{;p9%5ZJ.6~~}
|
||||
|
||||
~{KoWST;#:72;p9%SPNe#:R;T;;pHK#,6~T;;p;}#,H}T;;p~}?~{#,KDT;;p?b#,NeT;;p6S!#PP;p1XSPRr#,Rr1XKX>_!#7";pSPJ1#,Fp;pSPHU!#J1U_#,LlV.ToR2!#HUU_#,TBTZ;~!"1Z!"Rm!"~}?~{R2!#724KKDK^U_#,7gFpV.HUR2!#72;p9%#,1XRrNe;pV.1d6xS&V.#:;p7"l6DZ#,TrTgS&V.l6Mb#;;p7"6xFd1x>2U_#,4}6xNp9%#,<+Fd;pA&#,?I4S6x4SV.#,2;?I4STrIO!#;p?I7"l6Mb#,N^4}l6DZ#,RTJ17"V.#,;p7"IO7g#,N^9%OB7g#,Vg7g>C#,R97gV9!#72>|1XV*Ne;pV.1d#,RTJ}JXV.!#9JRT;pWt9%U_Cw#,RTK.Wt9%U_G?!#K.?IRT>x#,2;?IRT6a!#7rU=J$9%H!6x2;6hFd9&U_PW#,C|T;!07QAt!1!#9JT;#:CwVwBGV.#,A<=+6hV.#,7G@{2;6/#,7G5C2;SC#,7GN#2;U=!#Vw2;?IRTE-6xPKJ&#,=+2;?IRT~}?~{6x9%U=!#:Ol6@{6x6/#,2;:Ol6@{6xIO!#E-?IRT84O2#,~}?~{?IRT84K5#,Mv9z2;?IRT844f#,K@U_2;?IRT84Iz!#9JCwVwIwV.#,A<=+>/V.!#4K029zH+>|V.5@R2!#~}
|
||||
|
||||
~{SC<d5ZJ.H}~}
|
||||
|
||||
~{KoWST;#:~} ~{72PKJ&J.Mr#,3vUwG'@o#,0YPUV.7Q#,9+<RV.7n#,HU7QG'=p#,DZMbI'6/#,5!l65@B7#,2;5C2YJBU_#,F_J.Mr<R!#O`JXJ}Dj#,RTUyR;HUV.J$#,6x0.>tB;0Y=p#,2;V*5PV.GiU_#,2;HJV.VAR2#,7GCqV.=+R2#,7GVwV.WtR2#,7GJ$V.VwR2!#9JCw>}OM=+KyRT6/6xJ$HK#,3I9&3vl6~}?~{U_#,OHV*R2!#OHV*U_#,2;?IH!l69mIq#,2;?IOsl6JB#,2;?IQil66H#,1XH!l6HK#,V*5PV.GiU_R2!#9JSC<dSPNe#:SPRr<d#,SPDZ<d#,SP74<d#,SPK@<d#,SPIz<d!#Ne<d>cFp#,D*V*Fd5@#,JGN=Iq<M#,HK>}V.1&R2!#Og<dU_#,RrFdOgHK6xSCV.#;DZ<dU_#,RrFd9YHK6xSCV.#;74<dU_#,RrFd5P<d6xSCV.#;K@<dU_#,~}??~{JBl6Mb#,AnNaNEV*V.6x4+l65P<dR2#;Iz<dU_#,741(R2!#9JH}>|V.JB#,D*GWl6<d#,IMD*:ql6<d#,JBD*C\l6<d#,7GJ%OM2;D\SC<d#,7GHJRe2;D\J9<d#,7GN"Cn2;D\5C<dV.J5!#N"TUN"TU#!N^Ky2;SC<dR2!#<dJBN47"6xOHNEU_#,<dSkKy8fU_<fK@!#72>|V.KyS{;w#,3GV.KyS{9%#,HKV.KyS{I1#,1XOHV*FdJX=+!"WsSR!"~}?~{U_!"CEU_!"IaHKV.PUC{#,AnNa<d1XKwV*V.!#5P<dV.@4<dNRU_#,Rr6x@{V.#,5<6xIaV.#,9J74<d?I5C6xSCR2#;RrJG6xV*V.#,9JOg<d!"DZ<d?I5C6xJ9R2#;RrJG6xV*V.#,9JK@<d~}??~{JB#,?IJ98f5P#;RrJG6xV*V.#,9JIz<d?IJ9HgFZ!#Ne<dV.JB#,Vw1XV*V.#,V*V.1XTZl674<d#,9J74<d2;?I2;:qR2!#NtRsV.PKR2#,RAV?TZOD#;V\V.PKR2#,B@Q@TZRs!#9JCw>}OM=+#,D\RTIOVG~}?~{<dU_#,1X3I4s9&!#4K1xV.R*#,H}>|V.KyJQ6x6/R2!#~}
|
||||
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-gb-levels-1-and-2-utf-8.txt
generated
vendored
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-gb-levels-1-and-2-utf-8.txt
generated
vendored
|
|
@ -1,107 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
after converting from Traditional Chinese to Simplified Chinese.
|
||||
--------
|
||||
始计第一
|
||||
|
||||
孙子曰:兵者,国之大事,死生之地,存亡之道,不可不察也。
|
||||
|
||||
故经之以五事,校之以计,而索其情:一曰道,二曰天,三曰地,四曰将,五曰法。
|
||||
|
||||
道者,令民与上同意,可与之死,可与之生,而不畏危也;天者,阴阳、寒暑、时制也;地者,远近、险易、广狭、死生也;将者,智、信、仁、勇、严也;法者,曲制、官道、主用也。凡此五者,将莫不闻,知之者胜,不知者不胜。
|
||||
|
||||
故校之以计,而索其情,曰:主孰有道?将孰有能?天地孰得?法令孰行?兵?孰强?士卒孰练?赏罚孰明?吾以此知胜负矣。
|
||||
|
||||
将听吾计,用之必胜,留之;将不听吾计,用之必败,去之。
|
||||
|
||||
计利以听,乃?之势,以佐其外。势者,因利而制权也。
|
||||
|
||||
兵者,诡道也。故能而示之不能,用而示之不用,近而示之远,远而示之近。利而诱之,乱而取之,实而备之,强而避之,怒而挠之,卑而骄之,佚而劳之,亲而离之,攻其无备,出其不意。此兵家之胜,不可先传也。
|
||||
|
||||
夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜,而况无算乎!吾以此观之,胜负见矣。
|
||||
|
||||
作战第二
|
||||
|
||||
孙子曰:凡用兵之法,驰车千?,革车千乘,带甲十万,千里馈粮。则内外之费,宾客之用,胶漆之材,车甲之奉,日费千金,然后十万之师举矣。
|
||||
|
||||
其用战也,贵胜,久则钝兵挫锐,攻城则力屈,久暴师则国用不足。夫钝兵挫锐,屈力?货,则诸侯乘其弊而起,虽有智者,不能善其后矣。故兵闻拙速,未睹巧之久也。夫兵久而国利者,未之有也。故不尽知用兵之害者,则不能尽知用兵之利也。
|
||||
|
||||
善用兵者,役不再籍,粮不三载,取用於国,因粮於敌,故军食可足也。国之贫於师者远输,远输则百姓贫;近於师者贵卖,贵卖则百姓竭,财竭则急於丘役。力屈财?,中原内虚於家,百姓之费,十去其七;公家之费,破军罢马,甲胄矢弩,戟?矛?,丘牛大车,十去其六。
|
||||
|
||||
故智将务食於敌,食敌一钟,当吾二十钟;萁秆一石,当吾二十石。故杀敌者,怒也;取敌之利者,货也。故车战,得车十乘以上,赏其先得者,而更其旌旗。车杂而乘之,卒善而养之,是谓胜敌而益强。
|
||||
|
||||
故兵贵胜,不贵久。故知兵之将,民之司命。国家安危之主也。
|
||||
|
||||
谋攻第三
|
||||
|
||||
孙子曰:凡用兵之法,全国?上,破国次之;全军?上,破军次之;全旅?上,破旅次之;全卒?上,破卒次之;全伍?上,破伍次之。是故百战百胜,非善之善者也;不战而屈人之兵,善之善者也。
|
||||
|
||||
故上兵伐谋,其次伐交,其次伐兵,其下攻城。攻城之法,?不得已。修???,具器械,三月而后成;距?,又三月而后已。将不胜其忿,而蚁附之,杀士三分之一,而城不拔者,此攻之灾也。
|
||||
|
||||
故善用兵者,屈人之兵,而非战也,拔人之城而非攻也,毁人之国而非久也,必以全争於天下,故兵不顿而利可全,此谋攻之法也。
|
||||
|
||||
故用兵之法,十则围之,五则攻之,倍则分之,敌则能战之,少则能逃之,不若则能避之。故小敌之坚,大敌之擒也。
|
||||
|
||||
夫将者,国之辅也。辅周则国必强,辅隙则国必弱。故君之所以患於军者三:不知军之不可以进而谓之进,不知军之不可以退而谓之退,是谓縻军;不知三军之事,而同三军之政,则军士惑矣;不知三军之权,而同三军之任,则军士疑矣。三军既惑且疑,则诸侯之难至矣。是谓乱军引胜。
|
||||
|
||||
故知胜有五:知可以战与不可以战者,胜。识?寡之用者,胜。上下同欲者,胜。以虞待不虞者,胜。将能而君不御者,胜。此五者,知胜之道也。
|
||||
|
||||
故曰:知己知彼,百战不?;不知彼而知己,一胜一负;不知彼不知己,每战必败。
|
||||
|
||||
军形第四
|
||||
|
||||
孙子曰:昔之善战者,先?不可胜,以待敌之可胜。不可胜在己,可胜在敌。故善战者,能?不可胜,不能使敌必可胜。故曰:胜可知,而不可?。
|
||||
|
||||
不可胜者,守也;可胜者,攻也。守则不足,攻则有?。善守者,藏於九地之下,善攻者,动於九天之上,故能自保而全胜也。
|
||||
|
||||
见胜不过?人之所知,非善之善者也;战胜而天下曰善,非善之善者也。故举秋毫不?多力,见日月不?明目,闻雷霆不?聪耳。古之善战者,胜於易胜者也。故善战者之胜也,无智名,无勇功,故其战胜不忒。不忒者,其所措必胜,胜已败者也。故善战者,先立於不败之地,而不失敌之败也。是故胜兵先胜,而后求战,败兵先战而后求胜。善用兵者,修道而保法,故能?胜败之政。
|
||||
|
||||
兵法:一曰度,二曰量,三曰数,四曰称,五曰胜。地生度,度生量,量生数,数生称,称生胜。故胜兵若以?称?,败兵若以?称?。胜者之战,若决积水於千仞之?者,形也。
|
||||
|
||||
兵势第五
|
||||
|
||||
孙子曰:凡治?如治寡,分数是也;斗?如斗寡,形名是也;三军之?,可使必受敌而无败者,奇正是也;兵之所加,如以?投卵者,虚实是也。
|
||||
|
||||
凡战者,以正合,以奇胜。故善出奇者,无穷如天地,不竭如江海。终而复始,日月是也。死而?生,四时是也。声不过五,五声之变,不可胜听也;色不过五,五色之变,不可胜观也;味不过五,五味之变,不可胜尝也;战势,不过奇正,奇正之变,不可胜穷也。奇正相生,如循环之无端,熟能穷之哉?
|
||||
|
||||
激水之疾,至於漂石者,势也;?鸟之疾,至於毁折者,节也。是故善战者,其势险,其节短。势如张弩,节如发机。
|
||||
|
||||
纷纷??,斗乱而不可乱也;浑浑沌沌,形圆而不可败也。乱生於治,怯生於勇,弱生於强。治乱,数也;勇怯,势也;强弱,形也。故善动敌者,形之,敌必从之;予之,敌必取之。以利动之,以卒待之。
|
||||
|
||||
故善战者,求之於势,不责於人;故能择人而任势。任势者,其战人也,如转木石。木石之性,安则静,危则动,方则止,圆则行。故善战人之势,如转圆石於千仞之山者,势也。
|
||||
|
||||
虚实第六
|
||||
|
||||
孙子曰:凡先处战地而待敌者佚,后处战地而趋战者劳。
|
||||
|
||||
故善战者,致人而不致於人。能使敌人自至者,利之也;能使敌人不得至者,害之也。故敌佚能劳之,饱能饥之,安能动之。出其所必趋,趋其所不意。行千里而不劳者,行於无人之地也;攻而必取者,攻其所不守也。守而必固者,守其所不攻也。
|
||||
|
||||
故善攻者,敌不知其所守;善守者,敌不知其所攻。微乎微乎,至於无形;神乎神乎,至於无声,故能?敌之司命。进而不可御者,冲其虚也;退而不可追者,速而不可及也。故我欲战,敌虽高垒深沟,不得不与我战者,攻其所必救也;我不欲战,虽画地而守之,敌不得与我战者,乖其所之也。故形人而我无形,则我专而敌分。我专?一,敌分?十,是以十攻其一也。则我?敌寡,能以?击寡者,则吾之所与战者约矣。吾所与战之地不可知,不可知则敌所备者多,敌所备者多,则吾所与战者寡矣。故备前则后寡,备后则前寡,备左则右寡,备右则左寡,无所不备,则无所不寡。寡者,备人者也;?者,使人备己者也。故知战之地,知战之日,则可千里而会战;不知战之地,不知战日,则左不能救右,右不能救左,前不能救后,后不能救前,而况远者数十里,近者数里乎!以吾度之,越人之兵虽多,亦奚益於胜哉!故曰:胜可?也。敌虽?,可使无斗。故策之而知得失之计,候之而知动静之理,形之而知死生之地,角之而知有?不足之处。故形兵之极,至於无形。无形则深间不能窥,智者不能谋。因形而措胜於?,?不能知。人皆知我所以胜之形,而莫知吾所以制胜之形。故其战胜不?,而应形於无穷。夫兵形象水,水之行避高而趋下,兵之形避实而击虚;水因地而制流,兵因敌而制胜。故兵无常势,水无常形。能因敌变化而取胜者,谓之神。故五行无常胜,四时无常位,日有短长,月有死生。
|
||||
|
||||
军争第七
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚?,交和而舍,莫难於军争。军争之难者,以迂?直,以患?利。故迂其途,而诱之以利,后人发,先人至,此知迂直之计者也。军争?利,军争?危。举军而争利则不及,委军而争利则?重捐。是故?甲而趋,日夜不处,倍道兼行,百?而争利,则擒三将军,劲者先,疲者后,其法十一而至;五十里而争利,则蹶上将军,其法半至;三十里而争利,则三分之二至。是故军无?重则亡,无粮食则亡,无委积则亡。故不知诸侯之谋者,不能豫交;不知山林、险阻、沮泽之形者,不能行军;不用乡导者,不能得地利。故兵以诈立,以利动,以分和?变者也。故其疾如风,其徐如林,侵掠如火,不动如山,难知如阴,动如雷震。掠乡分?,廓地分利,悬权而动。先知迂直之计者胜,此军争之法也。《军政》曰:“言不相闻,故?之金鼓;视不相见,故?之旌旗。”夫金鼓旌旗者,所以一民之耳目也。民既专一,则勇者不得独进,怯者不得独退,此用?之法也。故夜战多金鼓,昼战多旌旗,所以变人之耳目也。三军可夺气,将军可夺心。是故朝气锐,昼气惰,暮气归。善用兵者,避其锐气,击其惰归,此治气者也。以治待乱,以静待哗,此治心者也。以近待远,以佚待劳,以饱待饥,此治力者也。无邀正正之旗,无击堂堂之陈,此治变者也。故用兵之法,高陵勿向,背丘勿逆,佯北勿从,锐卒勿攻,饵兵勿食,归师勿遏,围师遗?,穷寇勿迫,此用兵之法也。
|
||||
|
||||
九变第八
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚合。泛地无舍,衢地合交,绝地无留,围地则谋,死地则战,途有所不由,军有所不击,城有所不攻,地有所不争,君命有所不受。故将通於九变之利者,知用兵矣;将不通九变之利,虽知地形,不能得地之利矣;治兵不知九变之术,虽知五利,不能得人之用矣。是故智者之虑,必杂於利害,杂於利而务可信也,杂於害而患可解也。是故屈诸侯者以害,役诸侯者以业,趋诸侯者以利。故用兵之法,无恃其不来,恃吾有以待之;无恃其不攻,恃吾有所不可攻也。故将有五危,必死可杀,必生可虏,忿速可侮,廉洁可辱,爱民可烦。凡此五者,将之过也,用兵之灾也。覆军杀将,必以五危,不可不察也。
|
||||
|
||||
行军第九
|
||||
|
||||
孙子曰:凡处军相敌,绝山依?,视生处高,战隆无登,此处山之军也。绝水必远水,客绝水而来,勿迎之於水内,令半渡而击之利,欲战者,无附於水而迎客,视生处高,无迎水流,此处水上之军也。绝斥泽,唯亟去无留,若交军於斥泽之中,必依水草而背?树,此处斥泽之军也。平陆处易,右背高,前死后生,此处平陆之军也。凡此四军之利,黄帝之所以胜四帝也。凡军好高而恶下,贵阳而贱阴,养生而处实,军无百疾,是谓必胜。丘陵堤防,必处其阳而右背之,此兵之利,地之助也。上雨水流至,欲涉者,待其定也。凡地有绝涧、天井、天牢、天罗、天陷、天隙,必亟去之,勿近也。吾远之,敌近之;吾迎之,敌背之。军旁有险阻、潢井、蒹葭、小林、??者,必谨覆索之,此伏?之所处也。敌近而静者,恃其险也;远而挑战者,欲人之进也;其所居易者,利也;?树动者,来也;?草多障者,疑也;鸟起者,伏也;兽骇者,覆也;尘高而锐者,车来也;卑而广者,徒来也;散而条达者,樵?也;少而往来者,营军也;辞卑而备者,进也;辞强而进驱者,退也;轻车先出居其侧者,陈也;无约而请和者,谋也;奔走而陈兵者,期也;半进半退者,诱也;杖而立者,饥也;汲而先饮者,渴也;见利而不进者,劳也;鸟集者,虚也;夜呼者,恐也;军扰者,将不重也;旌旗动者,乱也;吏怒者,倦也;杀马肉食者,军无粮也;悬?不返其舍者,穷寇也;谆谆翕翕,徐与人言者,失?也;数赏者,窘也;数罚者,困也;先暴而后畏其?者,不精之至也;来委谢者,欲休息也。兵怒而相迎,久而不合,又不相去,必谨察之。兵非贵益多也,惟无武进,足以并力料敌取人而已。夫惟无虑而易敌者,必擒於人。卒未亲而罚之,则不服,不服则难用。卒已亲附而罚不行,则不可用。故合之以文,齐之以武,是谓必取。令素行以教其民,则民服;令素不行以教其民,则民不服。令素行者,与?相得也。
|
||||
|
||||
地形第十
|
||||
|
||||
孙子曰:地形有通者、有?者、有支者、有隘者、有险者、有远者。我可以往,彼可以来,曰通。通形者,先居高阳,利粮道,以战则利。可以往,难以返,曰?。?形者,敌无备,出而胜之,敌若有备,出而不胜,难以返,不利。我出而不利,彼出而不利,曰支。支形者,敌虽利我,我无出也,引而去之,令敌半出而击之利。隘形者,我先居之,必盈之以待敌。若敌先居之,盈而勿从,不盈而从之。险形者,我先居之,必居高阳以待敌;若敌先居之,引而去之,勿从也。远形者,势均难以挑战,战而不利。凡此六者,地之道也,将之至任,不可不察也。凡兵有走者、有驰者、有陷者、有崩者、有乱者、有北者。凡此六者,非天地之灾,将之过也。夫势均,以一击十,曰走;卒强吏弱,曰驰;吏强卒弱,曰陷;大吏怒而不服,遇敌?而自战,将不知其能,曰崩;将弱不严,教道不明,吏卒无常,陈兵纵横,曰乱;将不能料敌,以少合?,以弱击强,兵无选锋,曰北。凡此六者,败之道也,将之至任,不可不察也。夫地形者,兵之助也。料敌制胜,计险隘远近,上将之道也。知此而用战者必胜,不知此而用战者必败。故战道必胜,主曰无战,必战可也;战道不胜,主曰必战,无战可也。故进不求名,退不避罪,唯民是保,而利於主,国之宝也。视卒如婴儿,故可以与之赴深溪;视卒如爱子,故可与之俱死。厚而不能使,爱而不能令,乱而不能治,譬若骄子,不可用也。知吾卒之可以击,而不知敌之不可击,胜之半也;知敌之可击,而不知吾卒之不可以击,胜之半也;知敌之可击,知吾卒之可以击,而不知地形之不可以战,胜之半也。故知兵者,动而不迷,举而不穷。故曰:知彼知己,胜乃不殆;知天知地,胜乃可全。
|
||||
|
||||
九地第十一
|
||||
|
||||
孙子曰:用兵之法,有散地,有轻地,有争地,有交地,有衢地,有重地,有泛地,有围地,有死地。诸侯自战其地者,?散地;入人之地不深者,?轻地;我得亦利,彼得亦利者,?争地;我可以往,彼可以来者,?交地;诸侯之地三属,先至而得天下?者,?衢地;入人之地深,背城邑多者,?重地;山林、险阻、沮泽,凡难行之道者,?泛地;所由入者隘,所从归者迂,彼寡可以击吾之?者,?围地;疾战则存,不疾战则亡者,?死地。是故散地则无战,轻地则无止,争地则无攻,交地则无绝,衢地则合交,重地则掠,泛地则行,围地则谋,死地则战。古之善用兵者,能使敌人前后不相及,?寡不相恃,贵贱不相救,上下不相收,卒离而不集,兵合而不齐。合於利而动,不合於利而止。敢问敌?而整将来,待之若何曰:先夺其所爱则听矣。兵之情主速,乘人之不及。由不虞之道,攻其所不戒也。凡?客之道,深入则专。主人不克,掠於饶野,三军足食。谨养而勿劳,并气积力,运兵计谋,?不可测。投之无所往,死且不北。死焉不得,士人尽力。兵士甚陷则不惧,无所往则固,深入则拘,不得已则斗。是故其兵不修而戒,不求而得,不约而亲,不令而信,禁祥去疑,至死无所之。吾士无?财,非恶货也;无?命,非恶寿也。令发之日,士卒坐者涕沾襟,偃卧者涕交颐,投之无所往,诸、?之勇也。故善用兵者,譬如率然。率然者,常山之蛇也。击其首则尾至,击其尾则首至,击其中则首尾俱至。敢问兵可使如率然乎?曰可。夫吴人与越人相恶也,当其同舟而济而遇风,其相救也如左右手。是故方马埋轮,未足恃也;齐勇如一,政之道也;刚柔皆得,地之理也。故善用兵者,携手若使一人,不得已也。将军之事,静以幽,正以治,能愚士卒之耳目,使之无知;易其事,革其谋,使人无识;易其居,迂其途,使民不得虑。帅与之期,如登高而去其梯;帅与之深入诸侯之地,而发其机。若驱群羊,驱而往,驱而来,莫知所之。聚三军之?,投之於险,此谓将军之事也。九地之变,屈伸之力,人情之理,不可不察也。凡?客之道,深则专,浅则散。去国越境而师者,绝地也;四彻者,衢地也;入深者,重地也;入浅者,轻地也;背固前隘者,围地也;无所往者,死地也。是故散地吾将一其志,轻地吾将使之属,争地吾将趋其后,交地吾将谨其守,交地吾将固其结,衢地吾将谨其恃,重地吾将继其食,泛地吾将进其途,围地吾将塞其?,死地吾将示之以不活。故兵之情:围则御,不得已则斗,过则从。是故不知诸侯之谋者,不能预交;不知山林、险阻、沮泽之形者,不能行军;不用乡导,不能得地利。四五者,一不知,非霸王之兵也。夫霸王之兵,伐大国,则其?不得聚;威加於敌,则其交不得合。是故不争天下之交,不养天下之权,信己之私,威加於敌,则其城可拔,其国可隳。施无法之赏,悬无政之令。犯三军之?,若使一人。犯之以事,勿告以言;犯之以害,勿告以利。投之亡地然后存,陷之死地然后生。夫?陷於害,然后能?胜败。故?兵之事,在顺详敌之意,并敌一向,千里杀将,是谓巧能成事。是故政举之日,夷关折符,无通其使,厉於廊庙之上,以诛其事。敌人开?,必亟入之,先其所爱,微与之期,践墨随敌,以决战事。是故始如处女,敌人开户;后如脱兔,敌不及拒。
|
||||
|
||||
火攻第十二
|
||||
|
||||
孙子曰:凡火攻有五:一曰火人,二曰火积,三曰火?,四曰火库,五曰火队。行火必有因,因必素具。发火有时,起火有日。时者,天之燥也。日者,月在箕、壁、翼、?也。凡此四宿者,风起之日也。凡火攻,必因五火之变而应之:火发於内,则早应之於外;火发而其兵静者,待而勿攻,极其火力,可从而从之,不可从则上。火可发於外,无待於内,以时发之,火发上风,无攻下风,昼风久,夜风止。凡军必知五火之变,以数守之。故以火佐攻者明,以水佐攻者强。水可以绝,不可以夺。夫战胜攻取而不惰其功者凶,命曰“费留”。故曰:明主虑之,良将惰之,非利不动,非得不用,非危不战。主不可以怒而兴师,将不可以?而攻战。合於利而动,不合於利而上。怒可以复喜,?可以复说,亡国不可以复存,死者不可以复生。故明主慎之,良将警之。此安国全军之道也。
|
||||
|
||||
用间第十三
|
||||
|
||||
孙子曰: 凡兴师十万,出征千里,百姓之费,公家之奉,日费千金,内外骚动,怠於道路,不得操事者,七十万家。相守数年,以争一日之胜,而爱爵禄百金,不知敌之情者,不仁之至也,非民之将也,非主之佐也,非胜之主也。故明君贤将所以动而胜人,成功出於?者,先知也。先知者,不可取於鬼神,不可象於事,不可验於度,必取於人,知敌之情者也。故用间有五:有因间,有内间,有反间,有死间,有生间。五间俱起,莫知其道,是谓神纪,人君之宝也。乡间者,因其乡人而用之;内间者,因其官人而用之;反间者,因其敌间而用之;死间者,??事於外,令吾闻知之而传於敌间也;生间者,反报也。故三军之事,莫亲於间,赏莫厚於间,事莫密於间,非圣贤不能用间,非仁义不能使间,非微妙不能得间之实。微哉微哉!无所不用间也。间事未发而先闻者,间与所告者兼死。凡军之所欲击,城之所欲攻,人之所欲杀,必先知其守将、左右、?者、门者、舍人之姓名,令吾间必索知之。敌间之来间我者,因而利之,导而舍之,故反间可得而用也;因是而知之,故乡间、内间可得而使也;因是而知之,故死间??事,可使告敌;因是而知之,故生间可使如期。五间之事,主必知之,知之必在於反间,故反间不可不厚也。昔殷之兴也,伊挚在夏;周之兴也,吕牙在殷。故明君贤将,能以上智?间者,必成大功。此兵之要,三军之所恃而动也。
|
||||
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-simplified-gbk.txt
generated
vendored
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-simplified-gbk.txt
generated
vendored
|
|
@ -1,107 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
after converting from Traditional Chinese to Simplified Chinese.
|
||||
--------
|
||||
始计第一
|
||||
|
||||
孙子曰:兵者,国之大事,死生之地,存亡之道,不可不察也。
|
||||
|
||||
故经之以五事,校之以计,而索其情:一曰道,二曰天,三曰地,四曰将,五曰法。
|
||||
|
||||
道者,令民与上同意,可与之死,可与之生,而不畏危也;天者,阴阳、寒暑、时制也;地者,远近、险易、广狭、死生也;将者,智、信、仁、勇、严也;法者,曲制、官道、主用也。凡此五者,将莫不闻,知之者胜,不知者不胜。
|
||||
|
||||
故校之以计,而索其情,曰:主孰有道?将孰有能?天地孰得?法令孰行?兵眾孰强?士卒孰练?赏罚孰明?吾以此知胜负矣。
|
||||
|
||||
将听吾计,用之必胜,留之;将不听吾计,用之必败,去之。
|
||||
|
||||
计利以听,乃為之势,以佐其外。势者,因利而制权也。
|
||||
|
||||
兵者,诡道也。故能而示之不能,用而示之不用,近而示之远,远而示之近。利而诱之,乱而取之,实而备之,强而避之,怒而挠之,卑而骄之,佚而劳之,亲而离之,攻其无备,出其不意。此兵家之胜,不可先传也。
|
||||
|
||||
夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜,而况无算乎!吾以此观之,胜负见矣。
|
||||
|
||||
作战第二
|
||||
|
||||
孙子曰:凡用兵之法,驰车千駟,革车千乘,带甲十万,千里馈粮。则内外之费,宾客之用,胶漆之材,车甲之奉,日费千金,然后十万之师举矣。
|
||||
|
||||
其用战也,贵胜,久则钝兵挫锐,攻城则力屈,久暴师则国用不足。夫钝兵挫锐,屈力殫货,则诸侯乘其弊而起,虽有智者,不能善其后矣。故兵闻拙速,未睹巧之久也。夫兵久而国利者,未之有也。故不尽知用兵之害者,则不能尽知用兵之利也。
|
||||
|
||||
善用兵者,役不再籍,粮不三载,取用於国,因粮於敌,故军食可足也。国之贫於师者远输,远输则百姓贫;近於师者贵卖,贵卖则百姓竭,财竭则急於丘役。力屈财殫,中原内虚於家,百姓之费,十去其七;公家之费,破军罢马,甲胄矢弩,戟楯矛櫓,丘牛大车,十去其六。
|
||||
|
||||
故智将务食於敌,食敌一钟,当吾二十钟;萁秆一石,当吾二十石。故杀敌者,怒也;取敌之利者,货也。故车战,得车十乘以上,赏其先得者,而更其旌旗。车杂而乘之,卒善而养之,是谓胜敌而益强。
|
||||
|
||||
故兵贵胜,不贵久。故知兵之将,民之司命。国家安危之主也。
|
||||
|
||||
谋攻第三
|
||||
|
||||
孙子曰:凡用兵之法,全国為上,破国次之;全军為上,破军次之;全旅為上,破旅次之;全卒為上,破卒次之;全伍為上,破伍次之。是故百战百胜,非善之善者也;不战而屈人之兵,善之善者也。
|
||||
|
||||
故上兵伐谋,其次伐交,其次伐兵,其下攻城。攻城之法,為不得已。修櫓轒轀,具器械,三月而后成;距闉,又三月而后已。将不胜其忿,而蚁附之,杀士三分之一,而城不拔者,此攻之灾也。
|
||||
|
||||
故善用兵者,屈人之兵,而非战也,拔人之城而非攻也,毁人之国而非久也,必以全争於天下,故兵不顿而利可全,此谋攻之法也。
|
||||
|
||||
故用兵之法,十则围之,五则攻之,倍则分之,敌则能战之,少则能逃之,不若则能避之。故小敌之坚,大敌之擒也。
|
||||
|
||||
夫将者,国之辅也。辅周则国必强,辅隙则国必弱。故君之所以患於军者三:不知军之不可以进而谓之进,不知军之不可以退而谓之退,是谓縻军;不知三军之事,而同三军之政,则军士惑矣;不知三军之权,而同三军之任,则军士疑矣。三军既惑且疑,则诸侯之难至矣。是谓乱军引胜。
|
||||
|
||||
故知胜有五:知可以战与不可以战者,胜。识眾寡之用者,胜。上下同欲者,胜。以虞待不虞者,胜。将能而君不御者,胜。此五者,知胜之道也。
|
||||
|
||||
故曰:知己知彼,百战不貽;不知彼而知己,一胜一负;不知彼不知己,每战必败。
|
||||
|
||||
军形第四
|
||||
|
||||
孙子曰:昔之善战者,先為不可胜,以待敌之可胜。不可胜在己,可胜在敌。故善战者,能為不可胜,不能使敌必可胜。故曰:胜可知,而不可為。
|
||||
|
||||
不可胜者,守也;可胜者,攻也。守则不足,攻则有餘。善守者,藏於九地之下,善攻者,动於九天之上,故能自保而全胜也。
|
||||
|
||||
见胜不过眾人之所知,非善之善者也;战胜而天下曰善,非善之善者也。故举秋毫不為多力,见日月不為明目,闻雷霆不為聪耳。古之善战者,胜於易胜者也。故善战者之胜也,无智名,无勇功,故其战胜不忒。不忒者,其所措必胜,胜已败者也。故善战者,先立於不败之地,而不失敌之败也。是故胜兵先胜,而后求战,败兵先战而后求胜。善用兵者,修道而保法,故能為胜败之政。
|
||||
|
||||
兵法:一曰度,二曰量,三曰数,四曰称,五曰胜。地生度,度生量,量生数,数生称,称生胜。故胜兵若以鎰称銖,败兵若以銖称鎰。胜者之战,若决积水於千仞之谿者,形也。
|
||||
|
||||
兵势第五
|
||||
|
||||
孙子曰:凡治眾如治寡,分数是也;斗眾如斗寡,形名是也;三军之眾,可使必受敌而无败者,奇正是也;兵之所加,如以碫投卵者,虚实是也。
|
||||
|
||||
凡战者,以正合,以奇胜。故善出奇者,无穷如天地,不竭如江海。终而复始,日月是也。死而復生,四时是也。声不过五,五声之变,不可胜听也;色不过五,五色之变,不可胜观也;味不过五,五味之变,不可胜尝也;战势,不过奇正,奇正之变,不可胜穷也。奇正相生,如循环之无端,熟能穷之哉?
|
||||
|
||||
激水之疾,至於漂石者,势也;鷙鸟之疾,至於毁折者,节也。是故善战者,其势险,其节短。势如张弩,节如发机。
|
||||
|
||||
纷纷紜紜,斗乱而不可乱也;浑浑沌沌,形圆而不可败也。乱生於治,怯生於勇,弱生於强。治乱,数也;勇怯,势也;强弱,形也。故善动敌者,形之,敌必从之;予之,敌必取之。以利动之,以卒待之。
|
||||
|
||||
故善战者,求之於势,不责於人;故能择人而任势。任势者,其战人也,如转木石。木石之性,安则静,危则动,方则止,圆则行。故善战人之势,如转圆石於千仞之山者,势也。
|
||||
|
||||
虚实第六
|
||||
|
||||
孙子曰:凡先处战地而待敌者佚,后处战地而趋战者劳。
|
||||
|
||||
故善战者,致人而不致於人。能使敌人自至者,利之也;能使敌人不得至者,害之也。故敌佚能劳之,饱能饥之,安能动之。出其所必趋,趋其所不意。行千里而不劳者,行於无人之地也;攻而必取者,攻其所不守也。守而必固者,守其所不攻也。
|
||||
|
||||
故善攻者,敌不知其所守;善守者,敌不知其所攻。微乎微乎,至於无形;神乎神乎,至於无声,故能為敌之司命。进而不可御者,冲其虚也;退而不可追者,速而不可及也。故我欲战,敌虽高垒深沟,不得不与我战者,攻其所必救也;我不欲战,虽画地而守之,敌不得与我战者,乖其所之也。故形人而我无形,则我专而敌分。我专為一,敌分為十,是以十攻其一也。则我眾敌寡,能以眾击寡者,则吾之所与战者约矣。吾所与战之地不可知,不可知则敌所备者多,敌所备者多,则吾所与战者寡矣。故备前则后寡,备后则前寡,备左则右寡,备右则左寡,无所不备,则无所不寡。寡者,备人者也;眾者,使人备己者也。故知战之地,知战之日,则可千里而会战;不知战之地,不知战日,则左不能救右,右不能救左,前不能救后,后不能救前,而况远者数十里,近者数里乎!以吾度之,越人之兵虽多,亦奚益於胜哉!故曰:胜可為也。敌虽眾,可使无斗。故策之而知得失之计,候之而知动静之理,形之而知死生之地,角之而知有餘不足之处。故形兵之极,至於无形。无形则深间不能窥,智者不能谋。因形而措胜於眾,眾不能知。人皆知我所以胜之形,而莫知吾所以制胜之形。故其战胜不復,而应形於无穷。夫兵形象水,水之行避高而趋下,兵之形避实而击虚;水因地而制流,兵因敌而制胜。故兵无常势,水无常形。能因敌变化而取胜者,谓之神。故五行无常胜,四时无常位,日有短长,月有死生。
|
||||
|
||||
军争第七
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚眾,交和而舍,莫难於军争。军争之难者,以迂為直,以患為利。故迂其途,而诱之以利,后人发,先人至,此知迂直之计者也。军争為利,军争為危。举军而争利则不及,委军而争利则輜重捐。是故捲甲而趋,日夜不处,倍道兼行,百裡而争利,则擒三将军,劲者先,疲者后,其法十一而至;五十里而争利,则蹶上将军,其法半至;三十里而争利,则三分之二至。是故军无輜重则亡,无粮食则亡,无委积则亡。故不知诸侯之谋者,不能豫交;不知山林、险阻、沮泽之形者,不能行军;不用乡导者,不能得地利。故兵以诈立,以利动,以分和為变者也。故其疾如风,其徐如林,侵掠如火,不动如山,难知如阴,动如雷震。掠乡分眾,廓地分利,悬权而动。先知迂直之计者胜,此军争之法也。《军政》曰:“言不相闻,故為之金鼓;视不相见,故為之旌旗。”夫金鼓旌旗者,所以一民之耳目也。民既专一,则勇者不得独进,怯者不得独退,此用眾之法也。故夜战多金鼓,昼战多旌旗,所以变人之耳目也。三军可夺气,将军可夺心。是故朝气锐,昼气惰,暮气归。善用兵者,避其锐气,击其惰归,此治气者也。以治待乱,以静待哗,此治心者也。以近待远,以佚待劳,以饱待饥,此治力者也。无邀正正之旗,无击堂堂之陈,此治变者也。故用兵之法,高陵勿向,背丘勿逆,佯北勿从,锐卒勿攻,饵兵勿食,归师勿遏,围师遗闕,穷寇勿迫,此用兵之法也。
|
||||
|
||||
九变第八
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚合。泛地无舍,衢地合交,绝地无留,围地则谋,死地则战,途有所不由,军有所不击,城有所不攻,地有所不争,君命有所不受。故将通於九变之利者,知用兵矣;将不通九变之利,虽知地形,不能得地之利矣;治兵不知九变之术,虽知五利,不能得人之用矣。是故智者之虑,必杂於利害,杂於利而务可信也,杂於害而患可解也。是故屈诸侯者以害,役诸侯者以业,趋诸侯者以利。故用兵之法,无恃其不来,恃吾有以待之;无恃其不攻,恃吾有所不可攻也。故将有五危,必死可杀,必生可虏,忿速可侮,廉洁可辱,爱民可烦。凡此五者,将之过也,用兵之灾也。覆军杀将,必以五危,不可不察也。
|
||||
|
||||
行军第九
|
||||
|
||||
孙子曰:凡处军相敌,绝山依穀,视生处高,战隆无登,此处山之军也。绝水必远水,客绝水而来,勿迎之於水内,令半渡而击之利,欲战者,无附於水而迎客,视生处高,无迎水流,此处水上之军也。绝斥泽,唯亟去无留,若交军於斥泽之中,必依水草而背眾树,此处斥泽之军也。平陆处易,右背高,前死后生,此处平陆之军也。凡此四军之利,黄帝之所以胜四帝也。凡军好高而恶下,贵阳而贱阴,养生而处实,军无百疾,是谓必胜。丘陵堤防,必处其阳而右背之,此兵之利,地之助也。上雨水流至,欲涉者,待其定也。凡地有绝涧、天井、天牢、天罗、天陷、天隙,必亟去之,勿近也。吾远之,敌近之;吾迎之,敌背之。军旁有险阻、潢井、蒹葭、小林、蘙薈者,必谨覆索之,此伏姦之所处也。敌近而静者,恃其险也;远而挑战者,欲人之进也;其所居易者,利也;眾树动者,来也;眾草多障者,疑也;鸟起者,伏也;兽骇者,覆也;尘高而锐者,车来也;卑而广者,徒来也;散而条达者,樵採也;少而往来者,营军也;辞卑而备者,进也;辞强而进驱者,退也;轻车先出居其侧者,陈也;无约而请和者,谋也;奔走而陈兵者,期也;半进半退者,诱也;杖而立者,饥也;汲而先饮者,渴也;见利而不进者,劳也;鸟集者,虚也;夜呼者,恐也;军扰者,将不重也;旌旗动者,乱也;吏怒者,倦也;杀马肉食者,军无粮也;悬甀不返其舍者,穷寇也;谆谆翕翕,徐与人言者,失眾也;数赏者,窘也;数罚者,困也;先暴而后畏其眾者,不精之至也;来委谢者,欲休息也。兵怒而相迎,久而不合,又不相去,必谨察之。兵非贵益多也,惟无武进,足以并力料敌取人而已。夫惟无虑而易敌者,必擒於人。卒未亲而罚之,则不服,不服则难用。卒已亲附而罚不行,则不可用。故合之以文,齐之以武,是谓必取。令素行以教其民,则民服;令素不行以教其民,则民不服。令素行者,与眾相得也。
|
||||
|
||||
地形第十
|
||||
|
||||
孙子曰:地形有通者、有掛者、有支者、有隘者、有险者、有远者。我可以往,彼可以来,曰通。通形者,先居高阳,利粮道,以战则利。可以往,难以返,曰掛。掛形者,敌无备,出而胜之,敌若有备,出而不胜,难以返,不利。我出而不利,彼出而不利,曰支。支形者,敌虽利我,我无出也,引而去之,令敌半出而击之利。隘形者,我先居之,必盈之以待敌。若敌先居之,盈而勿从,不盈而从之。险形者,我先居之,必居高阳以待敌;若敌先居之,引而去之,勿从也。远形者,势均难以挑战,战而不利。凡此六者,地之道也,将之至任,不可不察也。凡兵有走者、有驰者、有陷者、有崩者、有乱者、有北者。凡此六者,非天地之灾,将之过也。夫势均,以一击十,曰走;卒强吏弱,曰驰;吏强卒弱,曰陷;大吏怒而不服,遇敌懟而自战,将不知其能,曰崩;将弱不严,教道不明,吏卒无常,陈兵纵横,曰乱;将不能料敌,以少合眾,以弱击强,兵无选锋,曰北。凡此六者,败之道也,将之至任,不可不察也。夫地形者,兵之助也。料敌制胜,计险隘远近,上将之道也。知此而用战者必胜,不知此而用战者必败。故战道必胜,主曰无战,必战可也;战道不胜,主曰必战,无战可也。故进不求名,退不避罪,唯民是保,而利於主,国之宝也。视卒如婴儿,故可以与之赴深溪;视卒如爱子,故可与之俱死。厚而不能使,爱而不能令,乱而不能治,譬若骄子,不可用也。知吾卒之可以击,而不知敌之不可击,胜之半也;知敌之可击,而不知吾卒之不可以击,胜之半也;知敌之可击,知吾卒之可以击,而不知地形之不可以战,胜之半也。故知兵者,动而不迷,举而不穷。故曰:知彼知己,胜乃不殆;知天知地,胜乃可全。
|
||||
|
||||
九地第十一
|
||||
|
||||
孙子曰:用兵之法,有散地,有轻地,有争地,有交地,有衢地,有重地,有泛地,有围地,有死地。诸侯自战其地者,為散地;入人之地不深者,為轻地;我得亦利,彼得亦利者,為争地;我可以往,彼可以来者,為交地;诸侯之地三属,先至而得天下眾者,為衢地;入人之地深,背城邑多者,為重地;山林、险阻、沮泽,凡难行之道者,為泛地;所由入者隘,所从归者迂,彼寡可以击吾之眾者,為围地;疾战则存,不疾战则亡者,為死地。是故散地则无战,轻地则无止,争地则无攻,交地则无绝,衢地则合交,重地则掠,泛地则行,围地则谋,死地则战。古之善用兵者,能使敌人前后不相及,眾寡不相恃,贵贱不相救,上下不相收,卒离而不集,兵合而不齐。合於利而动,不合於利而止。敢问敌眾而整将来,待之若何曰:先夺其所爱则听矣。兵之情主速,乘人之不及。由不虞之道,攻其所不戒也。凡為客之道,深入则专。主人不克,掠於饶野,三军足食。谨养而勿劳,并气积力,运兵计谋,為不可测。投之无所往,死且不北。死焉不得,士人尽力。兵士甚陷则不惧,无所往则固,深入则拘,不得已则斗。是故其兵不修而戒,不求而得,不约而亲,不令而信,禁祥去疑,至死无所之。吾士无餘财,非恶货也;无餘命,非恶寿也。令发之日,士卒坐者涕沾襟,偃卧者涕交颐,投之无所往,诸、劌之勇也。故善用兵者,譬如率然。率然者,常山之蛇也。击其首则尾至,击其尾则首至,击其中则首尾俱至。敢问兵可使如率然乎?曰可。夫吴人与越人相恶也,当其同舟而济而遇风,其相救也如左右手。是故方马埋轮,未足恃也;齐勇如一,政之道也;刚柔皆得,地之理也。故善用兵者,携手若使一人,不得已也。将军之事,静以幽,正以治,能愚士卒之耳目,使之无知;易其事,革其谋,使人无识;易其居,迂其途,使民不得虑。帅与之期,如登高而去其梯;帅与之深入诸侯之地,而发其机。若驱群羊,驱而往,驱而来,莫知所之。聚三军之眾,投之於险,此谓将军之事也。九地之变,屈伸之力,人情之理,不可不察也。凡為客之道,深则专,浅则散。去国越境而师者,绝地也;四彻者,衢地也;入深者,重地也;入浅者,轻地也;背固前隘者,围地也;无所往者,死地也。是故散地吾将一其志,轻地吾将使之属,争地吾将趋其后,交地吾将谨其守,交地吾将固其结,衢地吾将谨其恃,重地吾将继其食,泛地吾将进其途,围地吾将塞其闕,死地吾将示之以不活。故兵之情:围则御,不得已则斗,过则从。是故不知诸侯之谋者,不能预交;不知山林、险阻、沮泽之形者,不能行军;不用乡导,不能得地利。四五者,一不知,非霸王之兵也。夫霸王之兵,伐大国,则其眾不得聚;威加於敌,则其交不得合。是故不争天下之交,不养天下之权,信己之私,威加於敌,则其城可拔,其国可隳。施无法之赏,悬无政之令。犯三军之眾,若使一人。犯之以事,勿告以言;犯之以害,勿告以利。投之亡地然后存,陷之死地然后生。夫眾陷於害,然后能為胜败。故為兵之事,在顺详敌之意,并敌一向,千里杀将,是谓巧能成事。是故政举之日,夷关折符,无通其使,厉於廊庙之上,以诛其事。敌人开闔,必亟入之,先其所爱,微与之期,践墨随敌,以决战事。是故始如处女,敌人开户;后如脱兔,敌不及拒。
|
||||
|
||||
火攻第十二
|
||||
|
||||
孙子曰:凡火攻有五:一曰火人,二曰火积,三曰火輜,四曰火库,五曰火队。行火必有因,因必素具。发火有时,起火有日。时者,天之燥也。日者,月在箕、壁、翼、軫也。凡此四宿者,风起之日也。凡火攻,必因五火之变而应之:火发於内,则早应之於外;火发而其兵静者,待而勿攻,极其火力,可从而从之,不可从则上。火可发於外,无待於内,以时发之,火发上风,无攻下风,昼风久,夜风止。凡军必知五火之变,以数守之。故以火佐攻者明,以水佐攻者强。水可以绝,不可以夺。夫战胜攻取而不惰其功者凶,命曰“费留”。故曰:明主虑之,良将惰之,非利不动,非得不用,非危不战。主不可以怒而兴师,将不可以慍而攻战。合於利而动,不合於利而上。怒可以复喜,慍可以复说,亡国不可以复存,死者不可以复生。故明主慎之,良将警之。此安国全军之道也。
|
||||
|
||||
用间第十三
|
||||
|
||||
孙子曰: 凡兴师十万,出征千里,百姓之费,公家之奉,日费千金,内外骚动,怠於道路,不得操事者,七十万家。相守数年,以争一日之胜,而爱爵禄百金,不知敌之情者,不仁之至也,非民之将也,非主之佐也,非胜之主也。故明君贤将所以动而胜人,成功出於眾者,先知也。先知者,不可取於鬼神,不可象於事,不可验於度,必取於人,知敌之情者也。故用间有五:有因间,有内间,有反间,有死间,有生间。五间俱起,莫知其道,是谓神纪,人君之宝也。乡间者,因其乡人而用之;内间者,因其官人而用之;反间者,因其敌间而用之;死间者,為誑事於外,令吾闻知之而传於敌间也;生间者,反报也。故三军之事,莫亲於间,赏莫厚於间,事莫密於间,非圣贤不能用间,非仁义不能使间,非微妙不能得间之实。微哉微哉!无所不用间也。间事未发而先闻者,间与所告者兼死。凡军之所欲击,城之所欲攻,人之所欲杀,必先知其守将、左右、謁者、门者、舍人之姓名,令吾间必索知之。敌间之来间我者,因而利之,导而舍之,故反间可得而用也;因是而知之,故乡间、内间可得而使也;因是而知之,故死间為誑事,可使告敌;因是而知之,故生间可使如期。五间之事,主必知之,知之必在於反间,故反间不可不厚也。昔殷之兴也,伊挚在夏;周之兴也,吕牙在殷。故明君贤将,能以上智為间者,必成大功。此兵之要,三军之所恃而动也。
|
||||
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-simplified-utf-8.txt
generated
vendored
107
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-simplified-utf-8.txt
generated
vendored
|
|
@ -1,107 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
after converting from Traditional Chinese to Simplified Chinese.
|
||||
--------
|
||||
始计第一
|
||||
|
||||
孙子曰:兵者,国之大事,死生之地,存亡之道,不可不察也。
|
||||
|
||||
故经之以五事,校之以计,而索其情:一曰道,二曰天,三曰地,四曰将,五曰法。
|
||||
|
||||
道者,令民与上同意,可与之死,可与之生,而不畏危也;天者,阴阳、寒暑、时制也;地者,远近、险易、广狭、死生也;将者,智、信、仁、勇、严也;法者,曲制、官道、主用也。凡此五者,将莫不闻,知之者胜,不知者不胜。
|
||||
|
||||
故校之以计,而索其情,曰:主孰有道?将孰有能?天地孰得?法令孰行?兵眾孰强?士卒孰练?赏罚孰明?吾以此知胜负矣。
|
||||
|
||||
将听吾计,用之必胜,留之;将不听吾计,用之必败,去之。
|
||||
|
||||
计利以听,乃為之势,以佐其外。势者,因利而制权也。
|
||||
|
||||
兵者,诡道也。故能而示之不能,用而示之不用,近而示之远,远而示之近。利而诱之,乱而取之,实而备之,强而避之,怒而挠之,卑而骄之,佚而劳之,亲而离之,攻其无备,出其不意。此兵家之胜,不可先传也。
|
||||
|
||||
夫未战而庙算胜者,得算多也;未战而庙算不胜者,得算少也。多算胜,少算不胜,而况无算乎!吾以此观之,胜负见矣。
|
||||
|
||||
作战第二
|
||||
|
||||
孙子曰:凡用兵之法,驰车千駟,革车千乘,带甲十万,千里馈粮。则内外之费,宾客之用,胶漆之材,车甲之奉,日费千金,然后十万之师举矣。
|
||||
|
||||
其用战也,贵胜,久则钝兵挫锐,攻城则力屈,久暴师则国用不足。夫钝兵挫锐,屈力殫货,则诸侯乘其弊而起,虽有智者,不能善其后矣。故兵闻拙速,未睹巧之久也。夫兵久而国利者,未之有也。故不尽知用兵之害者,则不能尽知用兵之利也。
|
||||
|
||||
善用兵者,役不再籍,粮不三载,取用於国,因粮於敌,故军食可足也。国之贫於师者远输,远输则百姓贫;近於师者贵卖,贵卖则百姓竭,财竭则急於丘役。力屈财殫,中原内虚於家,百姓之费,十去其七;公家之费,破军罢马,甲胄矢弩,戟楯矛櫓,丘牛大车,十去其六。
|
||||
|
||||
故智将务食於敌,食敌一钟,当吾二十钟;萁秆一石,当吾二十石。故杀敌者,怒也;取敌之利者,货也。故车战,得车十乘以上,赏其先得者,而更其旌旗。车杂而乘之,卒善而养之,是谓胜敌而益强。
|
||||
|
||||
故兵贵胜,不贵久。故知兵之将,民之司命。国家安危之主也。
|
||||
|
||||
谋攻第三
|
||||
|
||||
孙子曰:凡用兵之法,全国為上,破国次之;全军為上,破军次之;全旅為上,破旅次之;全卒為上,破卒次之;全伍為上,破伍次之。是故百战百胜,非善之善者也;不战而屈人之兵,善之善者也。
|
||||
|
||||
故上兵伐谋,其次伐交,其次伐兵,其下攻城。攻城之法,為不得已。修櫓轒轀,具器械,三月而后成;距闉,又三月而后已。将不胜其忿,而蚁附之,杀士三分之一,而城不拔者,此攻之灾也。
|
||||
|
||||
故善用兵者,屈人之兵,而非战也,拔人之城而非攻也,毁人之国而非久也,必以全争於天下,故兵不顿而利可全,此谋攻之法也。
|
||||
|
||||
故用兵之法,十则围之,五则攻之,倍则分之,敌则能战之,少则能逃之,不若则能避之。故小敌之坚,大敌之擒也。
|
||||
|
||||
夫将者,国之辅也。辅周则国必强,辅隙则国必弱。故君之所以患於军者三:不知军之不可以进而谓之进,不知军之不可以退而谓之退,是谓縻军;不知三军之事,而同三军之政,则军士惑矣;不知三军之权,而同三军之任,则军士疑矣。三军既惑且疑,则诸侯之难至矣。是谓乱军引胜。
|
||||
|
||||
故知胜有五:知可以战与不可以战者,胜。识眾寡之用者,胜。上下同欲者,胜。以虞待不虞者,胜。将能而君不御者,胜。此五者,知胜之道也。
|
||||
|
||||
故曰:知己知彼,百战不貽;不知彼而知己,一胜一负;不知彼不知己,每战必败。
|
||||
|
||||
军形第四
|
||||
|
||||
孙子曰:昔之善战者,先為不可胜,以待敌之可胜。不可胜在己,可胜在敌。故善战者,能為不可胜,不能使敌必可胜。故曰:胜可知,而不可為。
|
||||
|
||||
不可胜者,守也;可胜者,攻也。守则不足,攻则有餘。善守者,藏於九地之下,善攻者,动於九天之上,故能自保而全胜也。
|
||||
|
||||
见胜不过眾人之所知,非善之善者也;战胜而天下曰善,非善之善者也。故举秋毫不為多力,见日月不為明目,闻雷霆不為聪耳。古之善战者,胜於易胜者也。故善战者之胜也,无智名,无勇功,故其战胜不忒。不忒者,其所措必胜,胜已败者也。故善战者,先立於不败之地,而不失敌之败也。是故胜兵先胜,而后求战,败兵先战而后求胜。善用兵者,修道而保法,故能為胜败之政。
|
||||
|
||||
兵法:一曰度,二曰量,三曰数,四曰称,五曰胜。地生度,度生量,量生数,数生称,称生胜。故胜兵若以鎰称銖,败兵若以銖称鎰。胜者之战,若决积水於千仞之谿者,形也。
|
||||
|
||||
兵势第五
|
||||
|
||||
孙子曰:凡治眾如治寡,分数是也;斗眾如斗寡,形名是也;三军之眾,可使必受敌而无败者,奇正是也;兵之所加,如以碫投卵者,虚实是也。
|
||||
|
||||
凡战者,以正合,以奇胜。故善出奇者,无穷如天地,不竭如江海。终而复始,日月是也。死而復生,四时是也。声不过五,五声之变,不可胜听也;色不过五,五色之变,不可胜观也;味不过五,五味之变,不可胜尝也;战势,不过奇正,奇正之变,不可胜穷也。奇正相生,如循环之无端,熟能穷之哉?
|
||||
|
||||
激水之疾,至於漂石者,势也;鷙鸟之疾,至於毁折者,节也。是故善战者,其势险,其节短。势如张弩,节如发机。
|
||||
|
||||
纷纷紜紜,斗乱而不可乱也;浑浑沌沌,形圆而不可败也。乱生於治,怯生於勇,弱生於强。治乱,数也;勇怯,势也;强弱,形也。故善动敌者,形之,敌必从之;予之,敌必取之。以利动之,以卒待之。
|
||||
|
||||
故善战者,求之於势,不责於人;故能择人而任势。任势者,其战人也,如转木石。木石之性,安则静,危则动,方则止,圆则行。故善战人之势,如转圆石於千仞之山者,势也。
|
||||
|
||||
虚实第六
|
||||
|
||||
孙子曰:凡先处战地而待敌者佚,后处战地而趋战者劳。
|
||||
|
||||
故善战者,致人而不致於人。能使敌人自至者,利之也;能使敌人不得至者,害之也。故敌佚能劳之,饱能饥之,安能动之。出其所必趋,趋其所不意。行千里而不劳者,行於无人之地也;攻而必取者,攻其所不守也。守而必固者,守其所不攻也。
|
||||
|
||||
故善攻者,敌不知其所守;善守者,敌不知其所攻。微乎微乎,至於无形;神乎神乎,至於无声,故能為敌之司命。进而不可御者,冲其虚也;退而不可追者,速而不可及也。故我欲战,敌虽高垒深沟,不得不与我战者,攻其所必救也;我不欲战,虽画地而守之,敌不得与我战者,乖其所之也。故形人而我无形,则我专而敌分。我专為一,敌分為十,是以十攻其一也。则我眾敌寡,能以眾击寡者,则吾之所与战者约矣。吾所与战之地不可知,不可知则敌所备者多,敌所备者多,则吾所与战者寡矣。故备前则后寡,备后则前寡,备左则右寡,备右则左寡,无所不备,则无所不寡。寡者,备人者也;眾者,使人备己者也。故知战之地,知战之日,则可千里而会战;不知战之地,不知战日,则左不能救右,右不能救左,前不能救后,后不能救前,而况远者数十里,近者数里乎!以吾度之,越人之兵虽多,亦奚益於胜哉!故曰:胜可為也。敌虽眾,可使无斗。故策之而知得失之计,候之而知动静之理,形之而知死生之地,角之而知有餘不足之处。故形兵之极,至於无形。无形则深间不能窥,智者不能谋。因形而措胜於眾,眾不能知。人皆知我所以胜之形,而莫知吾所以制胜之形。故其战胜不復,而应形於无穷。夫兵形象水,水之行避高而趋下,兵之形避实而击虚;水因地而制流,兵因敌而制胜。故兵无常势,水无常形。能因敌变化而取胜者,谓之神。故五行无常胜,四时无常位,日有短长,月有死生。
|
||||
|
||||
军争第七
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚眾,交和而舍,莫难於军争。军争之难者,以迂為直,以患為利。故迂其途,而诱之以利,后人发,先人至,此知迂直之计者也。军争為利,军争為危。举军而争利则不及,委军而争利则輜重捐。是故捲甲而趋,日夜不处,倍道兼行,百裡而争利,则擒三将军,劲者先,疲者后,其法十一而至;五十里而争利,则蹶上将军,其法半至;三十里而争利,则三分之二至。是故军无輜重则亡,无粮食则亡,无委积则亡。故不知诸侯之谋者,不能豫交;不知山林、险阻、沮泽之形者,不能行军;不用乡导者,不能得地利。故兵以诈立,以利动,以分和為变者也。故其疾如风,其徐如林,侵掠如火,不动如山,难知如阴,动如雷震。掠乡分眾,廓地分利,悬权而动。先知迂直之计者胜,此军争之法也。《军政》曰:“言不相闻,故為之金鼓;视不相见,故為之旌旗。”夫金鼓旌旗者,所以一民之耳目也。民既专一,则勇者不得独进,怯者不得独退,此用眾之法也。故夜战多金鼓,昼战多旌旗,所以变人之耳目也。三军可夺气,将军可夺心。是故朝气锐,昼气惰,暮气归。善用兵者,避其锐气,击其惰归,此治气者也。以治待乱,以静待哗,此治心者也。以近待远,以佚待劳,以饱待饥,此治力者也。无邀正正之旗,无击堂堂之陈,此治变者也。故用兵之法,高陵勿向,背丘勿逆,佯北勿从,锐卒勿攻,饵兵勿食,归师勿遏,围师遗闕,穷寇勿迫,此用兵之法也。
|
||||
|
||||
九变第八
|
||||
|
||||
孙子曰: 凡用兵之法,将受命於君,合军聚合。泛地无舍,衢地合交,绝地无留,围地则谋,死地则战,途有所不由,军有所不击,城有所不攻,地有所不争,君命有所不受。故将通於九变之利者,知用兵矣;将不通九变之利,虽知地形,不能得地之利矣;治兵不知九变之术,虽知五利,不能得人之用矣。是故智者之虑,必杂於利害,杂於利而务可信也,杂於害而患可解也。是故屈诸侯者以害,役诸侯者以业,趋诸侯者以利。故用兵之法,无恃其不来,恃吾有以待之;无恃其不攻,恃吾有所不可攻也。故将有五危,必死可杀,必生可虏,忿速可侮,廉洁可辱,爱民可烦。凡此五者,将之过也,用兵之灾也。覆军杀将,必以五危,不可不察也。
|
||||
|
||||
行军第九
|
||||
|
||||
孙子曰:凡处军相敌,绝山依穀,视生处高,战隆无登,此处山之军也。绝水必远水,客绝水而来,勿迎之於水内,令半渡而击之利,欲战者,无附於水而迎客,视生处高,无迎水流,此处水上之军也。绝斥泽,唯亟去无留,若交军於斥泽之中,必依水草而背眾树,此处斥泽之军也。平陆处易,右背高,前死后生,此处平陆之军也。凡此四军之利,黄帝之所以胜四帝也。凡军好高而恶下,贵阳而贱阴,养生而处实,军无百疾,是谓必胜。丘陵堤防,必处其阳而右背之,此兵之利,地之助也。上雨水流至,欲涉者,待其定也。凡地有绝涧、天井、天牢、天罗、天陷、天隙,必亟去之,勿近也。吾远之,敌近之;吾迎之,敌背之。军旁有险阻、潢井、蒹葭、小林、蘙薈者,必谨覆索之,此伏姦之所处也。敌近而静者,恃其险也;远而挑战者,欲人之进也;其所居易者,利也;眾树动者,来也;眾草多障者,疑也;鸟起者,伏也;兽骇者,覆也;尘高而锐者,车来也;卑而广者,徒来也;散而条达者,樵採也;少而往来者,营军也;辞卑而备者,进也;辞强而进驱者,退也;轻车先出居其侧者,陈也;无约而请和者,谋也;奔走而陈兵者,期也;半进半退者,诱也;杖而立者,饥也;汲而先饮者,渴也;见利而不进者,劳也;鸟集者,虚也;夜呼者,恐也;军扰者,将不重也;旌旗动者,乱也;吏怒者,倦也;杀马肉食者,军无粮也;悬甀不返其舍者,穷寇也;谆谆翕翕,徐与人言者,失眾也;数赏者,窘也;数罚者,困也;先暴而后畏其眾者,不精之至也;来委谢者,欲休息也。兵怒而相迎,久而不合,又不相去,必谨察之。兵非贵益多也,惟无武进,足以并力料敌取人而已。夫惟无虑而易敌者,必擒於人。卒未亲而罚之,则不服,不服则难用。卒已亲附而罚不行,则不可用。故合之以文,齐之以武,是谓必取。令素行以教其民,则民服;令素不行以教其民,则民不服。令素行者,与眾相得也。
|
||||
|
||||
地形第十
|
||||
|
||||
孙子曰:地形有通者、有掛者、有支者、有隘者、有险者、有远者。我可以往,彼可以来,曰通。通形者,先居高阳,利粮道,以战则利。可以往,难以返,曰掛。掛形者,敌无备,出而胜之,敌若有备,出而不胜,难以返,不利。我出而不利,彼出而不利,曰支。支形者,敌虽利我,我无出也,引而去之,令敌半出而击之利。隘形者,我先居之,必盈之以待敌。若敌先居之,盈而勿从,不盈而从之。险形者,我先居之,必居高阳以待敌;若敌先居之,引而去之,勿从也。远形者,势均难以挑战,战而不利。凡此六者,地之道也,将之至任,不可不察也。凡兵有走者、有驰者、有陷者、有崩者、有乱者、有北者。凡此六者,非天地之灾,将之过也。夫势均,以一击十,曰走;卒强吏弱,曰驰;吏强卒弱,曰陷;大吏怒而不服,遇敌懟而自战,将不知其能,曰崩;将弱不严,教道不明,吏卒无常,陈兵纵横,曰乱;将不能料敌,以少合眾,以弱击强,兵无选锋,曰北。凡此六者,败之道也,将之至任,不可不察也。夫地形者,兵之助也。料敌制胜,计险隘远近,上将之道也。知此而用战者必胜,不知此而用战者必败。故战道必胜,主曰无战,必战可也;战道不胜,主曰必战,无战可也。故进不求名,退不避罪,唯民是保,而利於主,国之宝也。视卒如婴儿,故可以与之赴深溪;视卒如爱子,故可与之俱死。厚而不能使,爱而不能令,乱而不能治,譬若骄子,不可用也。知吾卒之可以击,而不知敌之不可击,胜之半也;知敌之可击,而不知吾卒之不可以击,胜之半也;知敌之可击,知吾卒之可以击,而不知地形之不可以战,胜之半也。故知兵者,动而不迷,举而不穷。故曰:知彼知己,胜乃不殆;知天知地,胜乃可全。
|
||||
|
||||
九地第十一
|
||||
|
||||
孙子曰:用兵之法,有散地,有轻地,有争地,有交地,有衢地,有重地,有泛地,有围地,有死地。诸侯自战其地者,為散地;入人之地不深者,為轻地;我得亦利,彼得亦利者,為争地;我可以往,彼可以来者,為交地;诸侯之地三属,先至而得天下眾者,為衢地;入人之地深,背城邑多者,為重地;山林、险阻、沮泽,凡难行之道者,為泛地;所由入者隘,所从归者迂,彼寡可以击吾之眾者,為围地;疾战则存,不疾战则亡者,為死地。是故散地则无战,轻地则无止,争地则无攻,交地则无绝,衢地则合交,重地则掠,泛地则行,围地则谋,死地则战。古之善用兵者,能使敌人前后不相及,眾寡不相恃,贵贱不相救,上下不相收,卒离而不集,兵合而不齐。合於利而动,不合於利而止。敢问敌眾而整将来,待之若何曰:先夺其所爱则听矣。兵之情主速,乘人之不及。由不虞之道,攻其所不戒也。凡為客之道,深入则专。主人不克,掠於饶野,三军足食。谨养而勿劳,并气积力,运兵计谋,為不可测。投之无所往,死且不北。死焉不得,士人尽力。兵士甚陷则不惧,无所往则固,深入则拘,不得已则斗。是故其兵不修而戒,不求而得,不约而亲,不令而信,禁祥去疑,至死无所之。吾士无餘财,非恶货也;无餘命,非恶寿也。令发之日,士卒坐者涕沾襟,偃卧者涕交颐,投之无所往,诸、劌之勇也。故善用兵者,譬如率然。率然者,常山之蛇也。击其首则尾至,击其尾则首至,击其中则首尾俱至。敢问兵可使如率然乎?曰可。夫吴人与越人相恶也,当其同舟而济而遇风,其相救也如左右手。是故方马埋轮,未足恃也;齐勇如一,政之道也;刚柔皆得,地之理也。故善用兵者,携手若使一人,不得已也。将军之事,静以幽,正以治,能愚士卒之耳目,使之无知;易其事,革其谋,使人无识;易其居,迂其途,使民不得虑。帅与之期,如登高而去其梯;帅与之深入诸侯之地,而发其机。若驱群羊,驱而往,驱而来,莫知所之。聚三军之眾,投之於险,此谓将军之事也。九地之变,屈伸之力,人情之理,不可不察也。凡為客之道,深则专,浅则散。去国越境而师者,绝地也;四彻者,衢地也;入深者,重地也;入浅者,轻地也;背固前隘者,围地也;无所往者,死地也。是故散地吾将一其志,轻地吾将使之属,争地吾将趋其后,交地吾将谨其守,交地吾将固其结,衢地吾将谨其恃,重地吾将继其食,泛地吾将进其途,围地吾将塞其闕,死地吾将示之以不活。故兵之情:围则御,不得已则斗,过则从。是故不知诸侯之谋者,不能预交;不知山林、险阻、沮泽之形者,不能行军;不用乡导,不能得地利。四五者,一不知,非霸王之兵也。夫霸王之兵,伐大国,则其眾不得聚;威加於敌,则其交不得合。是故不争天下之交,不养天下之权,信己之私,威加於敌,则其城可拔,其国可隳。施无法之赏,悬无政之令。犯三军之眾,若使一人。犯之以事,勿告以言;犯之以害,勿告以利。投之亡地然后存,陷之死地然后生。夫眾陷於害,然后能為胜败。故為兵之事,在顺详敌之意,并敌一向,千里杀将,是谓巧能成事。是故政举之日,夷关折符,无通其使,厉於廊庙之上,以诛其事。敌人开闔,必亟入之,先其所爱,微与之期,践墨随敌,以决战事。是故始如处女,敌人开户;后如脱兔,敌不及拒。
|
||||
|
||||
火攻第十二
|
||||
|
||||
孙子曰:凡火攻有五:一曰火人,二曰火积,三曰火輜,四曰火库,五曰火队。行火必有因,因必素具。发火有时,起火有日。时者,天之燥也。日者,月在箕、壁、翼、軫也。凡此四宿者,风起之日也。凡火攻,必因五火之变而应之:火发於内,则早应之於外;火发而其兵静者,待而勿攻,极其火力,可从而从之,不可从则上。火可发於外,无待於内,以时发之,火发上风,无攻下风,昼风久,夜风止。凡军必知五火之变,以数守之。故以火佐攻者明,以水佐攻者强。水可以绝,不可以夺。夫战胜攻取而不惰其功者凶,命曰“费留”。故曰:明主虑之,良将惰之,非利不动,非得不用,非危不战。主不可以怒而兴师,将不可以慍而攻战。合於利而动,不合於利而上。怒可以复喜,慍可以复说,亡国不可以复存,死者不可以复生。故明主慎之,良将警之。此安国全军之道也。
|
||||
|
||||
用间第十三
|
||||
|
||||
孙子曰: 凡兴师十万,出征千里,百姓之费,公家之奉,日费千金,内外骚动,怠於道路,不得操事者,七十万家。相守数年,以争一日之胜,而爱爵禄百金,不知敌之情者,不仁之至也,非民之将也,非主之佐也,非胜之主也。故明君贤将所以动而胜人,成功出於眾者,先知也。先知者,不可取於鬼神,不可象於事,不可验於度,必取於人,知敌之情者也。故用间有五:有因间,有内间,有反间,有死间,有生间。五间俱起,莫知其道,是谓神纪,人君之宝也。乡间者,因其乡人而用之;内间者,因其官人而用之;反间者,因其敌间而用之;死间者,為誑事於外,令吾闻知之而传於敌间也;生间者,反报也。故三军之事,莫亲於间,赏莫厚於间,事莫密於间,非圣贤不能用间,非仁义不能使间,非微妙不能得间之实。微哉微哉!无所不用间也。间事未发而先闻者,间与所告者兼死。凡军之所欲击,城之所欲攻,人之所欲杀,必先知其守将、左右、謁者、门者、舍人之姓名,令吾间必索知之。敌间之来间我者,因而利之,导而舍之,故反间可得而用也;因是而知之,故乡间、内间可得而使也;因是而知之,故死间為誑事,可使告敌;因是而知之,故生间可使如期。五间之事,主必知之,知之必在於反间,故反间不可不厚也。昔殷之兴也,伊挚在夏;周之兴也,吕牙在殷。故明君贤将,能以上智為间者,必成大功。此兵之要,三军之所恃而动也。
|
||||
106
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-traditional-big5.txt
generated
vendored
106
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-traditional-big5.txt
generated
vendored
|
|
@ -1,106 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
--------
|
||||
始計第一
|
||||
|
||||
孫子曰:兵者,國之大事,死生之地,存亡之道,不可不察也。
|
||||
|
||||
故經之以五事,校之以計,而索其情:一曰道,二曰天,三曰地,四曰將,五曰法。
|
||||
|
||||
道者,令民與上同意,可與之死,可與之生,而不畏危也;天者,陰陽、寒暑、時制也;地者,遠近、險易、廣狹、死生也;將者,智、信、仁、勇、嚴也;法者,曲制、官道、主用也。凡此五者,將莫不聞,知之者勝,不知者不勝。
|
||||
|
||||
故校之以計,而索其情,曰:主孰有道?將孰有能?天地孰得?法令孰行?兵眾孰強?士卒孰練?賞罰孰明?吾以此知勝負矣。
|
||||
|
||||
將聽吾計,用之必勝,留之;將不聽吾計,用之必敗,去之。
|
||||
|
||||
計利以聽,乃為之勢,以佐其外。勢者,因利而制權也。
|
||||
|
||||
兵者,詭道也。故能而示之不能,用而示之不用,近而示之遠,遠而示之近。利而誘之,亂而取之,實而備之,強而避之,怒而撓之,卑而驕之,佚而勞之,親而離之,攻其無備,出其不意。此兵家之勝,不可先傳也。
|
||||
|
||||
夫未戰而廟算勝者,得算多也;未戰而廟算不勝者,得算少也。多算勝,少算不勝,而況無算乎!吾以此觀之,勝負見矣。
|
||||
|
||||
作戰第二
|
||||
|
||||
孫子曰:凡用兵之法,馳車千駟,革車千乘,帶甲十萬,千里饋糧。則內外之費,賓客之用,膠漆之材,車甲之奉,日費千金,然後十萬之師舉矣。
|
||||
|
||||
其用戰也,貴勝,久則鈍兵挫銳,攻城則力屈,久暴師則國用不足。夫鈍兵挫銳,屈力殫貨,則諸侯乘其弊而起,雖有智者,不能善其後矣。故兵聞拙速,未睹巧之久也。夫兵久而國利者,未之有也。故不盡知用兵之害者,則不能盡知用兵之利也。
|
||||
|
||||
善用兵者,役不再籍,糧不三載,取用於國,因糧於敵,故軍食可足也。國之貧於師者遠輸,遠輸則百姓貧;近於師者貴賣,貴賣則百姓竭,財竭則急於丘役。力屈財殫,中原內虛於家,百姓之費,十去其七;公家之費,破軍罷馬,甲胄矢弩,戟楯矛櫓,丘牛大車,十去其六。
|
||||
|
||||
故智將務食於敵,食敵一鍾,當吾二十鍾;萁稈一石,當吾二十石。故殺敵者,怒也;取敵之利者,貨也。故車戰,得車十乘以上,賞其先得者,而更其旌旗。車雜而乘之,卒善而養之,是謂勝敵而益強。
|
||||
|
||||
故兵貴勝,不貴久。故知兵之將,民之司命。國家安危之主也。
|
||||
|
||||
謀攻第三
|
||||
|
||||
孫子曰:凡用兵之法,全國為上,破國次之;全軍為上,破軍次之;全旅為上,破旅次之;全卒為上,破卒次之;全伍為上,破伍次之。是故百戰百勝,非善之善者也;不戰而屈人之兵,善之善者也。
|
||||
|
||||
故上兵伐謀,其次伐交,其次伐兵,其下攻城。攻城之法,為不得已。修櫓轒轀,具器械,三月而後成;距闉,又三月而後已。將不勝其忿,而蟻附之,殺士三分之一,而城不拔者,此攻之災也。
|
||||
|
||||
故善用兵者,屈人之兵,而非戰也,拔人之城而非攻也,毀人之國而非久也,必以全爭於天下,故兵不頓而利可全,此謀攻之法也。
|
||||
|
||||
故用兵之法,十則圍之,五則攻之,倍則分之,敵則能戰之,少則能逃之,不若則能避之。故小敵之堅,大敵之擒也。
|
||||
|
||||
夫將者,國之輔也。輔周則國必強,輔隙則國必弱。故君之所以患於軍者三:不知軍之不可以進而謂之進,不知軍之不可以退而謂之退,是謂縻軍;不知三軍之事,而同三軍之政,則軍士惑矣;不知三軍之權,而同三軍之任,則軍士疑矣。三軍既惑且疑,則諸侯之難至矣。是謂亂軍引勝。
|
||||
|
||||
故知勝有五:知可以戰與不可以戰者,勝。識眾寡之用者,勝。上下同欲者,勝。以虞待不虞者,勝。將能而君不御者,勝。此五者,知勝之道也。
|
||||
|
||||
故曰:知己知彼,百戰不貽;不知彼而知己,一勝一負;不知彼不知己,每戰必敗。
|
||||
|
||||
軍形第四
|
||||
|
||||
孫子曰:昔之善戰者,先為不可勝,以待敵之可勝。不可勝在己,可勝在敵。故善戰者,能為不可勝,不能使敵必可勝。故曰:勝可知,而不可為。
|
||||
|
||||
不可勝者,守也;可勝者,攻也。守則不足,攻則有餘。善守者,藏於九地之下,善攻者,動於九天之上,故能自保而全勝也。
|
||||
|
||||
見勝不過眾人之所知,非善之善者也;戰勝而天下曰善,非善之善者也。故舉秋毫不為多力,見日月不為明目,聞雷霆不為聰耳。古之善戰者,勝於易勝者也。故善戰者之勝也,無智名,無勇功,故其戰勝不忒。不忒者,其所措必勝,勝已敗者也。故善戰者,先立於不敗之地,而不失敵之敗也。是故勝兵先勝,而後求戰,敗兵先戰而後求勝。善用兵者,修道而保法,故能為勝敗之政。
|
||||
|
||||
兵法:一曰度,二曰量,三曰數,四曰稱,五曰勝。地生度,度生量,量生數,數生稱,稱生勝。故勝兵若以鎰稱銖,敗兵若以銖稱鎰。勝者之戰,若決積水於千仞之谿者,形也。
|
||||
|
||||
兵勢第五
|
||||
|
||||
孫子曰:凡治眾如治寡,分數是也;鬥眾如鬥寡,形名是也;三軍之眾,可使必受敵而無敗者,奇正是也;兵之所加,如以碫投卵者,虛實是也。
|
||||
|
||||
凡戰者,以正合,以奇勝。故善出奇者,無窮如天地,不竭如江海。終而複始,日月是也。死而復生,四時是也。聲不過五,五聲之變,不可勝聽也;色不過五,五色之變,不可勝觀也;味不過五,五味之變,不可勝嘗也;戰勢,不過奇正,奇正之變,不可勝窮也。奇正相生,如循環之無端,熟能窮之哉?
|
||||
|
||||
激水之疾,至於漂石者,勢也;鷙鳥之疾,至於毀折者,節也。是故善戰者,其勢險,其節短。勢如張弩,節如發機。
|
||||
|
||||
紛紛紜紜,鬥亂而不可亂也;渾渾沌沌,形圓而不可敗也。亂生於治,怯生於勇,弱生於強。治亂,數也;勇怯,勢也;強弱,形也。故善動敵者,形之,敵必從之;予之,敵必取之。以利動之,以卒待之。
|
||||
|
||||
故善戰者,求之於勢,不責於人;故能擇人而任勢。任勢者,其戰人也,如轉木石。木石之性,安則靜,危則動,方則止,圓則行。故善戰人之勢,如轉圓石於千仞之山者,勢也。
|
||||
|
||||
虛實第六
|
||||
|
||||
孫子曰:凡先處戰地而待敵者佚,後處戰地而趨戰者勞。
|
||||
|
||||
故善戰者,致人而不致於人。能使敵人自至者,利之也;能使敵人不得至者,害之也。故敵佚能勞之,飽能饑之,安能動之。出其所必趨,趨其所不意。行千里而不勞者,行於無人之地也;攻而必取者,攻其所不守也。守而必固者,守其所不攻也。
|
||||
|
||||
故善攻者,敵不知其所守;善守者,敵不知其所攻。微乎微乎,至於無形;神乎神乎,至於無聲,故能為敵之司命。進而不可禦者,沖其虛也;退而不可追者,速而不可及也。故我欲戰,敵雖高壘深溝,不得不與我戰者,攻其所必救也;我不欲戰,雖畫地而守之,敵不得與我戰者,乖其所之也。故形人而我無形,則我專而敵分。我專為一,敵分為十,是以十攻其一也。則我眾敵寡,能以眾擊寡者,則吾之所與戰者約矣。吾所與戰之地不可知,不可知則敵所備者多,敵所備者多,則吾所與戰者寡矣。故備前則後寡,備後則前寡,備左則右寡,備右則左寡,無所不備,則無所不寡。寡者,備人者也;眾者,使人備己者也。故知戰之地,知戰之日,則可千里而會戰;不知戰之地,不知戰日,則左不能救右,右不能救左,前不能救後,後不能救前,而況遠者數十裏,近者數裏乎!以吾度之,越人之兵雖多,亦奚益於勝哉!故曰:勝可為也。敵雖眾,可使無鬥。故策之而知得失之計,候之而知動靜之理,形之而知死生之地,角之而知有餘不足之處。故形兵之極,至於無形。無形則深間不能窺,智者不能謀。因形而措勝於眾,眾不能知。人皆知我所以勝之形,而莫知吾所以制勝之形。故其戰勝不復,而應形於無窮。夫兵形象水,水之行避高而趨下,兵之形避實而擊虛;水因地而制流,兵因敵而制勝。故兵無常勢,水無常形。能因敵變化而取勝者,謂之神。故五行無常勝,四時無常位,日有短長,月有死生。
|
||||
|
||||
軍爭第七
|
||||
|
||||
孫子曰: 凡用兵之法,將受命於君,合軍聚眾,交和而舍,莫難於軍爭。軍爭之難者,以迂為直,以患為利。故迂其途,而誘之以利,後人發,先人至,此知迂直之計者也。軍爭為利,軍爭為危。舉軍而爭利則不及,委軍而爭利則輜重捐。是故捲甲而趨,日夜不處,倍道兼行,百裡而爭利,則擒三將軍,勁者先,疲者後,其法十一而至;五十裏而爭利,則蹶上將軍,其法半至;三十裏而爭利,則三分之二至。是故軍無輜重則亡,無糧食則亡,無委積則亡。故不知諸侯之謀者,不能豫交;不知山林、險阻、沮澤之形者,不能行軍;不用鄉導者,不能得地利。故兵以詐立,以利動,以分和為變者也。故其疾如風,其徐如林,侵掠如火,不動如山,難知如陰,動如雷震。掠鄉分眾,廓地分利,懸權而動。先知迂直之計者勝,此軍爭之法也。《軍政》曰:“言不相聞,故為之金鼓;視不相見,故為之旌旗。”夫金鼓旌旗者,所以一民之耳目也。民既專一,則勇者不得獨進,怯者不得獨退,此用眾之法也。故夜戰多金鼓,晝戰多旌旗,所以變人之耳目也。三軍可奪氣,將軍可奪心。是故朝氣銳,晝氣惰,暮氣歸。善用兵者,避其銳氣,擊其惰歸,此治氣者也。以治待亂,以靜待嘩,此治心者也。以近待遠,以佚待勞,以飽待饑,此治力者也。無邀正正之旗,無擊堂堂之陳,此治變者也。故用兵之法,高陵勿向,背丘勿逆,佯北勿從,銳卒勿攻,餌兵勿食,歸師勿遏,圍師遺闕,窮寇勿迫,此用兵之法也。
|
||||
|
||||
九變第八
|
||||
|
||||
孫子曰: 凡用兵之法,將受命於君,合軍聚合。泛地無舍,衢地合交,絕地無留,圍地則謀,死地則戰,途有所不由,軍有所不擊,城有所不攻,地有所不爭,君命有所不受。故將通於九變之利者,知用兵矣;將不通九變之利,雖知地形,不能得地之利矣;治兵不知九變之術,雖知五利,不能得人之用矣。是故智者之慮,必雜於利害,雜於利而務可信也,雜於害而患可解也。是故屈諸侯者以害,役諸侯者以業,趨諸侯者以利。故用兵之法,無恃其不來,恃吾有以待之;無恃其不攻,恃吾有所不可攻也。故將有五危,必死可殺,必生可虜,忿速可侮,廉潔可辱,愛民可煩。凡此五者,將之過也,用兵之災也。覆軍殺將,必以五危,不可不察也。
|
||||
|
||||
行軍第九
|
||||
|
||||
孫子曰:凡處軍相敵,絕山依穀,視生處高,戰隆無登,此處山之軍也。絕水必遠水,客絕水而來,勿迎之於水內,令半渡而擊之利,欲戰者,無附於水而迎客,視生處高,無迎水流,此處水上之軍也。絕斥澤,唯亟去無留,若交軍於斥澤之中,必依水草而背眾樹,此處斥澤之軍也。平陸處易,右背高,前死後生,此處平陸之軍也。凡此四軍之利,黃帝之所以勝四帝也。凡軍好高而惡下,貴陽而賤陰,養生而處實,軍無百疾,是謂必勝。丘陵堤防,必處其陽而右背之,此兵之利,地之助也。上雨水流至,欲涉者,待其定也。凡地有絕澗、天井、天牢、天羅、天陷、天隙,必亟去之,勿近也。吾遠之,敵近之;吾迎之,敵背之。軍旁有險阻、潢井、蒹葭、小林、蘙薈者,必謹覆索之,此伏姦之所處也。敵近而靜者,恃其險也;遠而挑戰者,欲人之進也;其所居易者,利也;眾樹動者,來也;眾草多障者,疑也;鳥起者,伏也;獸駭者,覆也;塵高而銳者,車來也;卑而廣者,徒來也;散而條達者,樵採也;少而往來者,營軍也;辭卑而備者,進也;辭強而進驅者,退也;輕車先出居其側者,陳也;無約而請和者,謀也;奔走而陳兵者,期也;半進半退者,誘也;杖而立者,饑也;汲而先飲者,渴也;見利而不進者,勞也;鳥集者,虛也;夜呼者,恐也;軍擾者,將不重也;旌旗動者,亂也;吏怒者,倦也;殺馬肉食者,軍無糧也;懸甀不返其舍者,窮寇也;諄諄翕翕,徐與人言者,失眾也;數賞者,窘也;數罰者,困也;先暴而後畏其眾者,不精之至也;來委謝者,欲休息也。兵怒而相迎,久而不合,又不相去,必謹察之。兵非貴益多也,惟無武進,足以並力料敵取人而已。夫惟無慮而易敵者,必擒於人。卒未親而罰之,則不服,不服則難用。卒已親附而罰不行,則不可用。故合之以文,齊之以武,是謂必取。令素行以教其民,則民服;令素不行以教其民,則民不服。令素行者,與眾相得也。
|
||||
|
||||
地形第十
|
||||
|
||||
孫子曰:地形有通者、有掛者、有支者、有隘者、有險者、有遠者。我可以往,彼可以來,曰通。通形者,先居高陽,利糧道,以戰則利。可以往,難以返,曰掛。掛形者,敵無備,出而勝之,敵若有備,出而不勝,難以返,不利。我出而不利,彼出而不利,曰支。支形者,敵雖利我,我無出也,引而去之,令敵半出而擊之利。隘形者,我先居之,必盈之以待敵。若敵先居之,盈而勿從,不盈而從之。險形者,我先居之,必居高陽以待敵;若敵先居之,引而去之,勿從也。遠形者,勢均難以挑戰,戰而不利。凡此六者,地之道也,將之至任,不可不察也。凡兵有走者、有馳者、有陷者、有崩者、有亂者、有北者。凡此六者,非天地之災,將之過也。夫勢均,以一擊十,曰走;卒強吏弱,曰馳;吏強卒弱,曰陷;大吏怒而不服,遇敵懟而自戰,將不知其能,曰崩;將弱不嚴,教道不明,吏卒無常,陳兵縱橫,曰亂;將不能料敵,以少合眾,以弱擊強,兵無選鋒,曰北。凡此六者,敗之道也,將之至任,不可不察也。夫地形者,兵之助也。料敵制勝,計險隘遠近,上將之道也。知此而用戰者必勝,不知此而用戰者必敗。故戰道必勝,主曰無戰,必戰可也;戰道不勝,主曰必戰,無戰可也。故進不求名,退不避罪,唯民是保,而利於主,國之寶也。視卒如嬰兒,故可以與之赴深溪;視卒如愛子,故可與之俱死。厚而不能使,愛而不能令,亂而不能治,譬若驕子,不可用也。知吾卒之可以擊,而不知敵之不可擊,勝之半也;知敵之可擊,而不知吾卒之不可以擊,勝之半也;知敵之可擊,知吾卒之可以擊,而不知地形之不可以戰,勝之半也。故知兵者,動而不迷,舉而不窮。故曰:知彼知己,勝乃不殆;知天知地,勝乃可全。
|
||||
|
||||
九地第十一
|
||||
|
||||
孫子曰:用兵之法,有散地,有輕地,有爭地,有交地,有衢地,有重地,有泛地,有圍地,有死地。諸侯自戰其地者,為散地;入人之地不深者,為輕地;我得亦利,彼得亦利者,為爭地;我可以往,彼可以來者,為交地;諸侯之地三屬,先至而得天下眾者,為衢地;入人之地深,背城邑多者,為重地;山林、險阻、沮澤,凡難行之道者,為泛地;所由入者隘,所從歸者迂,彼寡可以擊吾之眾者,為圍地;疾戰則存,不疾戰則亡者,為死地。是故散地則無戰,輕地則無止,爭地則無攻,交地則無絕,衢地則合交,重地則掠,泛地則行,圍地則謀,死地則戰。古之善用兵者,能使敵人前後不相及,眾寡不相恃,貴賤不相救,上下不相收,卒離而不集,兵合而不齊。合於利而動,不合於利而止。敢問敵眾而整將來,待之若何曰:先奪其所愛則聽矣。兵之情主速,乘人之不及。由不虞之道,攻其所不戒也。凡為客之道,深入則專。主人不克,掠於饒野,三軍足食。謹養而勿勞,並氣積力,運兵計謀,為不可測。投之無所往,死且不北。死焉不得,士人盡力。兵士甚陷則不懼,無所往則固,深入則拘,不得已則鬥。是故其兵不修而戒,不求而得,不約而親,不令而信,禁祥去疑,至死無所之。吾士無餘財,非惡貨也;無餘命,非惡壽也。令發之日,士卒坐者涕沾襟,偃臥者涕交頤,投之無所往,諸、劌之勇也。故善用兵者,譬如率然。率然者,常山之蛇也。擊其首則尾至,擊其尾則首至,擊其中則首尾俱至。敢問兵可使如率然乎?曰可。夫吳人與越人相惡也,當其同舟而濟而遇風,其相救也如左右手。是故方馬埋輪,未足恃也;齊勇如一,政之道也;剛柔皆得,地之理也。故善用兵者,攜手若使一人,不得已也。將軍之事,靜以幽,正以治,能愚士卒之耳目,使之無知;易其事,革其謀,使人無識;易其居,迂其途,使民不得慮。帥與之期,如登高而去其梯;帥與之深入諸侯之地,而發其機。若驅群羊,驅而往,驅而來,莫知所之。聚三軍之眾,投之於險,此謂將軍之事也。九地之變,屈伸之力,人情之理,不可不察也。凡為客之道,深則專,淺則散。去國越境而師者,絕地也;四徹者,衢地也;入深者,重地也;入淺者,輕地也;背固前隘者,圍地也;無所往者,死地也。是故散地吾將一其志,輕地吾將使之屬,爭地吾將趨其後,交地吾將謹其守,交地吾將固其結,衢地吾將謹其恃,重地吾將繼其食,泛地吾將進其途,圍地吾將塞其闕,死地吾將示之以不活。故兵之情:圍則禦,不得已則鬥,過則從。是故不知諸侯之謀者,不能預交;不知山林、險阻、沮澤之形者,不能行軍;不用鄉導,不能得地利。四五者,一不知,非霸王之兵也。夫霸王之兵,伐大國,則其眾不得聚;威加於敵,則其交不得合。是故不爭天下之交,不養天下之權,信己之私,威加於敵,則其城可拔,其國可隳。施無法之賞,懸無政之令。犯三軍之眾,若使一人。犯之以事,勿告以言;犯之以害,勿告以利。投之亡地然後存,陷之死地然後生。夫眾陷於害,然後能為勝敗。故為兵之事,在順詳敵之意,並敵一向,千里殺將,是謂巧能成事。是故政舉之日,夷關折符,無通其使,厲於廊廟之上,以誅其事。敵人開闔,必亟入之,先其所愛,微與之期,踐墨隨敵,以決戰事。是故始如處女,敵人開戶;後如脫兔,敵不及拒。
|
||||
|
||||
火攻第十二
|
||||
|
||||
孫子曰:凡火攻有五:一曰火人,二曰火積,三曰火輜,四曰火庫,五曰火隊。行火必有因,因必素具。發火有時,起火有日。時者,天之燥也。日者,月在箕、壁、翼、軫也。凡此四宿者,風起之日也。凡火攻,必因五火之變而應之:火發於內,則早應之於外;火發而其兵靜者,待而勿攻,極其火力,可從而從之,不可從則上。火可發於外,無待於內,以時發之,火發上風,無攻下風,晝風久,夜風止。凡軍必知五火之變,以數守之。故以火佐攻者明,以水佐攻者強。水可以絕,不可以奪。夫戰勝攻取而不惰其功者凶,命曰“費留”。故曰:明主慮之,良將惰之,非利不動,非得不用,非危不戰。主不可以怒而興師,將不可以慍而攻戰。合於利而動,不合於利而上。怒可以複喜,慍可以複說,亡國不可以複存,死者不可以複生。故明主慎之,良將警之。此安國全軍之道也。
|
||||
|
||||
用間第十三
|
||||
|
||||
孫子曰: 凡興師十萬,出征千里,百姓之費,公家之奉,日費千金,內外騷動,怠於道路,不得操事者,七十萬家。相守數年,以爭一日之勝,而愛爵祿百金,不知敵之情者,不仁之至也,非民之將也,非主之佐也,非勝之主也。故明君賢將所以動而勝人,成功出於眾者,先知也。先知者,不可取於鬼神,不可象於事,不可驗於度,必取於人,知敵之情者也。故用間有五:有因間,有內間,有反間,有死間,有生間。五間俱起,莫知其道,是謂神紀,人君之寶也。鄉間者,因其鄉人而用之;內間者,因其官人而用之;反間者,因其敵間而用之;死間者,為誑事於外,令吾聞知之而傳於敵間也;生間者,反報也。故三軍之事,莫親於間,賞莫厚於間,事莫密於間,非聖賢不能用間,非仁義不能使間,非微妙不能得間之實。微哉微哉!無所不用間也。間事未發而先聞者,間與所告者兼死。凡軍之所欲擊,城之所欲攻,人之所欲殺,必先知其守將、左右、謁者、門者、舍人之姓名,令吾間必索知之。敵間之來間我者,因而利之,導而舍之,故反間可得而用也;因是而知之,故鄉間、內間可得而使也;因是而知之,故死間為誑事,可使告敵;因是而知之,故生間可使如期。五間之事,主必知之,知之必在於反間,故反間不可不厚也。昔殷之興也,伊摯在夏;周之興也,呂牙在殷。故明君賢將,能以上智為間者,必成大功。此兵之要,三軍之所恃而動也。
|
||||
106
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-traditional-utf-8.txt
generated
vendored
106
vendor/golang.org/x/text/encoding/testdata/sunzi-bingfa-traditional-utf-8.txt
generated
vendored
|
|
@ -1,106 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.gutenberg.org/files/23864/23864-0.txt
|
||||
--------
|
||||
始計第一
|
||||
|
||||
孫子曰:兵者,國之大事,死生之地,存亡之道,不可不察也。
|
||||
|
||||
故經之以五事,校之以計,而索其情:一曰道,二曰天,三曰地,四曰將,五曰法。
|
||||
|
||||
道者,令民與上同意,可與之死,可與之生,而不畏危也;天者,陰陽、寒暑、時制也;地者,遠近、險易、廣狹、死生也;將者,智、信、仁、勇、嚴也;法者,曲制、官道、主用也。凡此五者,將莫不聞,知之者勝,不知者不勝。
|
||||
|
||||
故校之以計,而索其情,曰:主孰有道?將孰有能?天地孰得?法令孰行?兵眾孰強?士卒孰練?賞罰孰明?吾以此知勝負矣。
|
||||
|
||||
將聽吾計,用之必勝,留之;將不聽吾計,用之必敗,去之。
|
||||
|
||||
計利以聽,乃為之勢,以佐其外。勢者,因利而制權也。
|
||||
|
||||
兵者,詭道也。故能而示之不能,用而示之不用,近而示之遠,遠而示之近。利而誘之,亂而取之,實而備之,強而避之,怒而撓之,卑而驕之,佚而勞之,親而離之,攻其無備,出其不意。此兵家之勝,不可先傳也。
|
||||
|
||||
夫未戰而廟算勝者,得算多也;未戰而廟算不勝者,得算少也。多算勝,少算不勝,而況無算乎!吾以此觀之,勝負見矣。
|
||||
|
||||
作戰第二
|
||||
|
||||
孫子曰:凡用兵之法,馳車千駟,革車千乘,帶甲十萬,千里饋糧。則內外之費,賓客之用,膠漆之材,車甲之奉,日費千金,然後十萬之師舉矣。
|
||||
|
||||
其用戰也,貴勝,久則鈍兵挫銳,攻城則力屈,久暴師則國用不足。夫鈍兵挫銳,屈力殫貨,則諸侯乘其弊而起,雖有智者,不能善其後矣。故兵聞拙速,未睹巧之久也。夫兵久而國利者,未之有也。故不盡知用兵之害者,則不能盡知用兵之利也。
|
||||
|
||||
善用兵者,役不再籍,糧不三載,取用於國,因糧於敵,故軍食可足也。國之貧於師者遠輸,遠輸則百姓貧;近於師者貴賣,貴賣則百姓竭,財竭則急於丘役。力屈財殫,中原內虛於家,百姓之費,十去其七;公家之費,破軍罷馬,甲胄矢弩,戟楯矛櫓,丘牛大車,十去其六。
|
||||
|
||||
故智將務食於敵,食敵一鍾,當吾二十鍾;萁稈一石,當吾二十石。故殺敵者,怒也;取敵之利者,貨也。故車戰,得車十乘以上,賞其先得者,而更其旌旗。車雜而乘之,卒善而養之,是謂勝敵而益強。
|
||||
|
||||
故兵貴勝,不貴久。故知兵之將,民之司命。國家安危之主也。
|
||||
|
||||
謀攻第三
|
||||
|
||||
孫子曰:凡用兵之法,全國為上,破國次之;全軍為上,破軍次之;全旅為上,破旅次之;全卒為上,破卒次之;全伍為上,破伍次之。是故百戰百勝,非善之善者也;不戰而屈人之兵,善之善者也。
|
||||
|
||||
故上兵伐謀,其次伐交,其次伐兵,其下攻城。攻城之法,為不得已。修櫓轒轀,具器械,三月而後成;距闉,又三月而後已。將不勝其忿,而蟻附之,殺士三分之一,而城不拔者,此攻之災也。
|
||||
|
||||
故善用兵者,屈人之兵,而非戰也,拔人之城而非攻也,毀人之國而非久也,必以全爭於天下,故兵不頓而利可全,此謀攻之法也。
|
||||
|
||||
故用兵之法,十則圍之,五則攻之,倍則分之,敵則能戰之,少則能逃之,不若則能避之。故小敵之堅,大敵之擒也。
|
||||
|
||||
夫將者,國之輔也。輔周則國必強,輔隙則國必弱。故君之所以患於軍者三:不知軍之不可以進而謂之進,不知軍之不可以退而謂之退,是謂縻軍;不知三軍之事,而同三軍之政,則軍士惑矣;不知三軍之權,而同三軍之任,則軍士疑矣。三軍既惑且疑,則諸侯之難至矣。是謂亂軍引勝。
|
||||
|
||||
故知勝有五:知可以戰與不可以戰者,勝。識眾寡之用者,勝。上下同欲者,勝。以虞待不虞者,勝。將能而君不御者,勝。此五者,知勝之道也。
|
||||
|
||||
故曰:知己知彼,百戰不貽;不知彼而知己,一勝一負;不知彼不知己,每戰必敗。
|
||||
|
||||
軍形第四
|
||||
|
||||
孫子曰:昔之善戰者,先為不可勝,以待敵之可勝。不可勝在己,可勝在敵。故善戰者,能為不可勝,不能使敵必可勝。故曰:勝可知,而不可為。
|
||||
|
||||
不可勝者,守也;可勝者,攻也。守則不足,攻則有餘。善守者,藏於九地之下,善攻者,動於九天之上,故能自保而全勝也。
|
||||
|
||||
見勝不過眾人之所知,非善之善者也;戰勝而天下曰善,非善之善者也。故舉秋毫不為多力,見日月不為明目,聞雷霆不為聰耳。古之善戰者,勝於易勝者也。故善戰者之勝也,無智名,無勇功,故其戰勝不忒。不忒者,其所措必勝,勝已敗者也。故善戰者,先立於不敗之地,而不失敵之敗也。是故勝兵先勝,而後求戰,敗兵先戰而後求勝。善用兵者,修道而保法,故能為勝敗之政。
|
||||
|
||||
兵法:一曰度,二曰量,三曰數,四曰稱,五曰勝。地生度,度生量,量生數,數生稱,稱生勝。故勝兵若以鎰稱銖,敗兵若以銖稱鎰。勝者之戰,若決積水於千仞之谿者,形也。
|
||||
|
||||
兵勢第五
|
||||
|
||||
孫子曰:凡治眾如治寡,分數是也;鬥眾如鬥寡,形名是也;三軍之眾,可使必受敵而無敗者,奇正是也;兵之所加,如以碫投卵者,虛實是也。
|
||||
|
||||
凡戰者,以正合,以奇勝。故善出奇者,無窮如天地,不竭如江海。終而複始,日月是也。死而復生,四時是也。聲不過五,五聲之變,不可勝聽也;色不過五,五色之變,不可勝觀也;味不過五,五味之變,不可勝嘗也;戰勢,不過奇正,奇正之變,不可勝窮也。奇正相生,如循環之無端,熟能窮之哉?
|
||||
|
||||
激水之疾,至於漂石者,勢也;鷙鳥之疾,至於毀折者,節也。是故善戰者,其勢險,其節短。勢如張弩,節如發機。
|
||||
|
||||
紛紛紜紜,鬥亂而不可亂也;渾渾沌沌,形圓而不可敗也。亂生於治,怯生於勇,弱生於強。治亂,數也;勇怯,勢也;強弱,形也。故善動敵者,形之,敵必從之;予之,敵必取之。以利動之,以卒待之。
|
||||
|
||||
故善戰者,求之於勢,不責於人;故能擇人而任勢。任勢者,其戰人也,如轉木石。木石之性,安則靜,危則動,方則止,圓則行。故善戰人之勢,如轉圓石於千仞之山者,勢也。
|
||||
|
||||
虛實第六
|
||||
|
||||
孫子曰:凡先處戰地而待敵者佚,後處戰地而趨戰者勞。
|
||||
|
||||
故善戰者,致人而不致於人。能使敵人自至者,利之也;能使敵人不得至者,害之也。故敵佚能勞之,飽能饑之,安能動之。出其所必趨,趨其所不意。行千里而不勞者,行於無人之地也;攻而必取者,攻其所不守也。守而必固者,守其所不攻也。
|
||||
|
||||
故善攻者,敵不知其所守;善守者,敵不知其所攻。微乎微乎,至於無形;神乎神乎,至於無聲,故能為敵之司命。進而不可禦者,沖其虛也;退而不可追者,速而不可及也。故我欲戰,敵雖高壘深溝,不得不與我戰者,攻其所必救也;我不欲戰,雖畫地而守之,敵不得與我戰者,乖其所之也。故形人而我無形,則我專而敵分。我專為一,敵分為十,是以十攻其一也。則我眾敵寡,能以眾擊寡者,則吾之所與戰者約矣。吾所與戰之地不可知,不可知則敵所備者多,敵所備者多,則吾所與戰者寡矣。故備前則後寡,備後則前寡,備左則右寡,備右則左寡,無所不備,則無所不寡。寡者,備人者也;眾者,使人備己者也。故知戰之地,知戰之日,則可千里而會戰;不知戰之地,不知戰日,則左不能救右,右不能救左,前不能救後,後不能救前,而況遠者數十裏,近者數裏乎!以吾度之,越人之兵雖多,亦奚益於勝哉!故曰:勝可為也。敵雖眾,可使無鬥。故策之而知得失之計,候之而知動靜之理,形之而知死生之地,角之而知有餘不足之處。故形兵之極,至於無形。無形則深間不能窺,智者不能謀。因形而措勝於眾,眾不能知。人皆知我所以勝之形,而莫知吾所以制勝之形。故其戰勝不復,而應形於無窮。夫兵形象水,水之行避高而趨下,兵之形避實而擊虛;水因地而制流,兵因敵而制勝。故兵無常勢,水無常形。能因敵變化而取勝者,謂之神。故五行無常勝,四時無常位,日有短長,月有死生。
|
||||
|
||||
軍爭第七
|
||||
|
||||
孫子曰: 凡用兵之法,將受命於君,合軍聚眾,交和而舍,莫難於軍爭。軍爭之難者,以迂為直,以患為利。故迂其途,而誘之以利,後人發,先人至,此知迂直之計者也。軍爭為利,軍爭為危。舉軍而爭利則不及,委軍而爭利則輜重捐。是故捲甲而趨,日夜不處,倍道兼行,百裡而爭利,則擒三將軍,勁者先,疲者後,其法十一而至;五十裏而爭利,則蹶上將軍,其法半至;三十裏而爭利,則三分之二至。是故軍無輜重則亡,無糧食則亡,無委積則亡。故不知諸侯之謀者,不能豫交;不知山林、險阻、沮澤之形者,不能行軍;不用鄉導者,不能得地利。故兵以詐立,以利動,以分和為變者也。故其疾如風,其徐如林,侵掠如火,不動如山,難知如陰,動如雷震。掠鄉分眾,廓地分利,懸權而動。先知迂直之計者勝,此軍爭之法也。《軍政》曰:“言不相聞,故為之金鼓;視不相見,故為之旌旗。”夫金鼓旌旗者,所以一民之耳目也。民既專一,則勇者不得獨進,怯者不得獨退,此用眾之法也。故夜戰多金鼓,晝戰多旌旗,所以變人之耳目也。三軍可奪氣,將軍可奪心。是故朝氣銳,晝氣惰,暮氣歸。善用兵者,避其銳氣,擊其惰歸,此治氣者也。以治待亂,以靜待嘩,此治心者也。以近待遠,以佚待勞,以飽待饑,此治力者也。無邀正正之旗,無擊堂堂之陳,此治變者也。故用兵之法,高陵勿向,背丘勿逆,佯北勿從,銳卒勿攻,餌兵勿食,歸師勿遏,圍師遺闕,窮寇勿迫,此用兵之法也。
|
||||
|
||||
九變第八
|
||||
|
||||
孫子曰: 凡用兵之法,將受命於君,合軍聚合。泛地無舍,衢地合交,絕地無留,圍地則謀,死地則戰,途有所不由,軍有所不擊,城有所不攻,地有所不爭,君命有所不受。故將通於九變之利者,知用兵矣;將不通九變之利,雖知地形,不能得地之利矣;治兵不知九變之術,雖知五利,不能得人之用矣。是故智者之慮,必雜於利害,雜於利而務可信也,雜於害而患可解也。是故屈諸侯者以害,役諸侯者以業,趨諸侯者以利。故用兵之法,無恃其不來,恃吾有以待之;無恃其不攻,恃吾有所不可攻也。故將有五危,必死可殺,必生可虜,忿速可侮,廉潔可辱,愛民可煩。凡此五者,將之過也,用兵之災也。覆軍殺將,必以五危,不可不察也。
|
||||
|
||||
行軍第九
|
||||
|
||||
孫子曰:凡處軍相敵,絕山依穀,視生處高,戰隆無登,此處山之軍也。絕水必遠水,客絕水而來,勿迎之於水內,令半渡而擊之利,欲戰者,無附於水而迎客,視生處高,無迎水流,此處水上之軍也。絕斥澤,唯亟去無留,若交軍於斥澤之中,必依水草而背眾樹,此處斥澤之軍也。平陸處易,右背高,前死後生,此處平陸之軍也。凡此四軍之利,黃帝之所以勝四帝也。凡軍好高而惡下,貴陽而賤陰,養生而處實,軍無百疾,是謂必勝。丘陵堤防,必處其陽而右背之,此兵之利,地之助也。上雨水流至,欲涉者,待其定也。凡地有絕澗、天井、天牢、天羅、天陷、天隙,必亟去之,勿近也。吾遠之,敵近之;吾迎之,敵背之。軍旁有險阻、潢井、蒹葭、小林、蘙薈者,必謹覆索之,此伏姦之所處也。敵近而靜者,恃其險也;遠而挑戰者,欲人之進也;其所居易者,利也;眾樹動者,來也;眾草多障者,疑也;鳥起者,伏也;獸駭者,覆也;塵高而銳者,車來也;卑而廣者,徒來也;散而條達者,樵採也;少而往來者,營軍也;辭卑而備者,進也;辭強而進驅者,退也;輕車先出居其側者,陳也;無約而請和者,謀也;奔走而陳兵者,期也;半進半退者,誘也;杖而立者,饑也;汲而先飲者,渴也;見利而不進者,勞也;鳥集者,虛也;夜呼者,恐也;軍擾者,將不重也;旌旗動者,亂也;吏怒者,倦也;殺馬肉食者,軍無糧也;懸甀不返其舍者,窮寇也;諄諄翕翕,徐與人言者,失眾也;數賞者,窘也;數罰者,困也;先暴而後畏其眾者,不精之至也;來委謝者,欲休息也。兵怒而相迎,久而不合,又不相去,必謹察之。兵非貴益多也,惟無武進,足以並力料敵取人而已。夫惟無慮而易敵者,必擒於人。卒未親而罰之,則不服,不服則難用。卒已親附而罰不行,則不可用。故合之以文,齊之以武,是謂必取。令素行以教其民,則民服;令素不行以教其民,則民不服。令素行者,與眾相得也。
|
||||
|
||||
地形第十
|
||||
|
||||
孫子曰:地形有通者、有掛者、有支者、有隘者、有險者、有遠者。我可以往,彼可以來,曰通。通形者,先居高陽,利糧道,以戰則利。可以往,難以返,曰掛。掛形者,敵無備,出而勝之,敵若有備,出而不勝,難以返,不利。我出而不利,彼出而不利,曰支。支形者,敵雖利我,我無出也,引而去之,令敵半出而擊之利。隘形者,我先居之,必盈之以待敵。若敵先居之,盈而勿從,不盈而從之。險形者,我先居之,必居高陽以待敵;若敵先居之,引而去之,勿從也。遠形者,勢均難以挑戰,戰而不利。凡此六者,地之道也,將之至任,不可不察也。凡兵有走者、有馳者、有陷者、有崩者、有亂者、有北者。凡此六者,非天地之災,將之過也。夫勢均,以一擊十,曰走;卒強吏弱,曰馳;吏強卒弱,曰陷;大吏怒而不服,遇敵懟而自戰,將不知其能,曰崩;將弱不嚴,教道不明,吏卒無常,陳兵縱橫,曰亂;將不能料敵,以少合眾,以弱擊強,兵無選鋒,曰北。凡此六者,敗之道也,將之至任,不可不察也。夫地形者,兵之助也。料敵制勝,計險隘遠近,上將之道也。知此而用戰者必勝,不知此而用戰者必敗。故戰道必勝,主曰無戰,必戰可也;戰道不勝,主曰必戰,無戰可也。故進不求名,退不避罪,唯民是保,而利於主,國之寶也。視卒如嬰兒,故可以與之赴深溪;視卒如愛子,故可與之俱死。厚而不能使,愛而不能令,亂而不能治,譬若驕子,不可用也。知吾卒之可以擊,而不知敵之不可擊,勝之半也;知敵之可擊,而不知吾卒之不可以擊,勝之半也;知敵之可擊,知吾卒之可以擊,而不知地形之不可以戰,勝之半也。故知兵者,動而不迷,舉而不窮。故曰:知彼知己,勝乃不殆;知天知地,勝乃可全。
|
||||
|
||||
九地第十一
|
||||
|
||||
孫子曰:用兵之法,有散地,有輕地,有爭地,有交地,有衢地,有重地,有泛地,有圍地,有死地。諸侯自戰其地者,為散地;入人之地不深者,為輕地;我得亦利,彼得亦利者,為爭地;我可以往,彼可以來者,為交地;諸侯之地三屬,先至而得天下眾者,為衢地;入人之地深,背城邑多者,為重地;山林、險阻、沮澤,凡難行之道者,為泛地;所由入者隘,所從歸者迂,彼寡可以擊吾之眾者,為圍地;疾戰則存,不疾戰則亡者,為死地。是故散地則無戰,輕地則無止,爭地則無攻,交地則無絕,衢地則合交,重地則掠,泛地則行,圍地則謀,死地則戰。古之善用兵者,能使敵人前後不相及,眾寡不相恃,貴賤不相救,上下不相收,卒離而不集,兵合而不齊。合於利而動,不合於利而止。敢問敵眾而整將來,待之若何曰:先奪其所愛則聽矣。兵之情主速,乘人之不及。由不虞之道,攻其所不戒也。凡為客之道,深入則專。主人不克,掠於饒野,三軍足食。謹養而勿勞,並氣積力,運兵計謀,為不可測。投之無所往,死且不北。死焉不得,士人盡力。兵士甚陷則不懼,無所往則固,深入則拘,不得已則鬥。是故其兵不修而戒,不求而得,不約而親,不令而信,禁祥去疑,至死無所之。吾士無餘財,非惡貨也;無餘命,非惡壽也。令發之日,士卒坐者涕沾襟,偃臥者涕交頤,投之無所往,諸、劌之勇也。故善用兵者,譬如率然。率然者,常山之蛇也。擊其首則尾至,擊其尾則首至,擊其中則首尾俱至。敢問兵可使如率然乎?曰可。夫吳人與越人相惡也,當其同舟而濟而遇風,其相救也如左右手。是故方馬埋輪,未足恃也;齊勇如一,政之道也;剛柔皆得,地之理也。故善用兵者,攜手若使一人,不得已也。將軍之事,靜以幽,正以治,能愚士卒之耳目,使之無知;易其事,革其謀,使人無識;易其居,迂其途,使民不得慮。帥與之期,如登高而去其梯;帥與之深入諸侯之地,而發其機。若驅群羊,驅而往,驅而來,莫知所之。聚三軍之眾,投之於險,此謂將軍之事也。九地之變,屈伸之力,人情之理,不可不察也。凡為客之道,深則專,淺則散。去國越境而師者,絕地也;四徹者,衢地也;入深者,重地也;入淺者,輕地也;背固前隘者,圍地也;無所往者,死地也。是故散地吾將一其志,輕地吾將使之屬,爭地吾將趨其後,交地吾將謹其守,交地吾將固其結,衢地吾將謹其恃,重地吾將繼其食,泛地吾將進其途,圍地吾將塞其闕,死地吾將示之以不活。故兵之情:圍則禦,不得已則鬥,過則從。是故不知諸侯之謀者,不能預交;不知山林、險阻、沮澤之形者,不能行軍;不用鄉導,不能得地利。四五者,一不知,非霸王之兵也。夫霸王之兵,伐大國,則其眾不得聚;威加於敵,則其交不得合。是故不爭天下之交,不養天下之權,信己之私,威加於敵,則其城可拔,其國可隳。施無法之賞,懸無政之令。犯三軍之眾,若使一人。犯之以事,勿告以言;犯之以害,勿告以利。投之亡地然後存,陷之死地然後生。夫眾陷於害,然後能為勝敗。故為兵之事,在順詳敵之意,並敵一向,千里殺將,是謂巧能成事。是故政舉之日,夷關折符,無通其使,厲於廊廟之上,以誅其事。敵人開闔,必亟入之,先其所愛,微與之期,踐墨隨敵,以決戰事。是故始如處女,敵人開戶;後如脫兔,敵不及拒。
|
||||
|
||||
火攻第十二
|
||||
|
||||
孫子曰:凡火攻有五:一曰火人,二曰火積,三曰火輜,四曰火庫,五曰火隊。行火必有因,因必素具。發火有時,起火有日。時者,天之燥也。日者,月在箕、壁、翼、軫也。凡此四宿者,風起之日也。凡火攻,必因五火之變而應之:火發於內,則早應之於外;火發而其兵靜者,待而勿攻,極其火力,可從而從之,不可從則上。火可發於外,無待於內,以時發之,火發上風,無攻下風,晝風久,夜風止。凡軍必知五火之變,以數守之。故以火佐攻者明,以水佐攻者強。水可以絕,不可以奪。夫戰勝攻取而不惰其功者凶,命曰“費留”。故曰:明主慮之,良將惰之,非利不動,非得不用,非危不戰。主不可以怒而興師,將不可以慍而攻戰。合於利而動,不合於利而上。怒可以複喜,慍可以複說,亡國不可以複存,死者不可以複生。故明主慎之,良將警之。此安國全軍之道也。
|
||||
|
||||
用間第十三
|
||||
|
||||
孫子曰: 凡興師十萬,出征千里,百姓之費,公家之奉,日費千金,內外騷動,怠於道路,不得操事者,七十萬家。相守數年,以爭一日之勝,而愛爵祿百金,不知敵之情者,不仁之至也,非民之將也,非主之佐也,非勝之主也。故明君賢將所以動而勝人,成功出於眾者,先知也。先知者,不可取於鬼神,不可象於事,不可驗於度,必取於人,知敵之情者也。故用間有五:有因間,有內間,有反間,有死間,有生間。五間俱起,莫知其道,是謂神紀,人君之寶也。鄉間者,因其鄉人而用之;內間者,因其官人而用之;反間者,因其敵間而用之;死間者,為誑事於外,令吾聞知之而傳於敵間也;生間者,反報也。故三軍之事,莫親於間,賞莫厚於間,事莫密於間,非聖賢不能用間,非仁義不能使間,非微妙不能得間之實。微哉微哉!無所不用間也。間事未發而先聞者,間與所告者兼死。凡軍之所欲擊,城之所欲攻,人之所欲殺,必先知其守將、左右、謁者、門者、舍人之姓名,令吾間必索知之。敵間之來間我者,因而利之,導而舍之,故反間可得而用也;因是而知之,故鄉間、內間可得而使也;因是而知之,故死間為誑事,可使告敵;因是而知之,故生間可使如期。五間之事,主必知之,知之必在於反間,故反間不可不厚也。昔殷之興也,伊摯在夏;周之興也,呂牙在殷。故明君賢將,能以上智為間者,必成大功。此兵之要,三軍之所恃而動也。
|
||||
175
vendor/golang.org/x/text/encoding/testdata/unsu-joh-eun-nal-euc-kr.txt
generated
vendored
175
vendor/golang.org/x/text/encoding/testdata/unsu-joh-eun-nal-euc-kr.txt
generated
vendored
|
|
@ -1,175 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.ibrary.co.kr/index.php/book-list/short-stories/34-short-stories-korean/150-2008-04-20-13-22-32
|
||||
--------
|
||||
[소개]
|
||||
잔인한 운명은 이렇게 인간을 조롱하곤 한다. 우리가 평소 마음 속 저 깊은 곳에 움켜쥐고 있던 자존심 따위는 어느 한 순간 전혀 무용지물이란 것이 드러나고 만다. 하기야 이렇게 삶의 한 순간, 눈 깜짝할 새에 우리를 후려 갈기고 지나가는 그 진실이 미래의 어느날에는 또 남김없이 우리 눈 앞에 펼쳐질지도 모른다. 죽음을 앞둔 사람들에게는 자신의 삶 전체가 한 순간에 다시 보인다는 그런 얘기도 있던데...
|
||||
|
||||
다시 읽어보니 끔찍한 생각도 든다. 식민지 시대의 암울한 삶, 그 끈끈한 냄새를 피할 수 없다. 21세기를 사는 우리들에겐 그런 냄새는 아예 인연이 없는 것처럼 느껴질 수도 있을 것이다. 그러나 과연 그럴까? 이런 냄새를 모르고 평생 사는 사람도 있겠지만, 전혀 관련이 없는 것은 아닐 것이다. 그저 우연일 뿐이다. 아내를 박대하는 김 첨지의 모습... 요새 같으면 간이 배 밖으로 튀어나온 남자겠지만, 그래도 그 애정은 더 진한 것일 수도 있다.
|
||||
|
||||
[작가 소개]
|
||||
현 진 건(玄鎭健, 1900-1943) : 소설가. 한국 사실주의 단편소설의 기틀을 다진 작가이다. 본관은 연주(延州). 아호는 빙허(憑虛). 1920년대 전반기에는 자전적 요소가 강한 개인적 체험소설인 <빈처> <술 권하는 사회>, 성(性)의 문제와 애정문제를 다룬 <B사감과 러브레터> <새빨간 웃음> 등이 있으며 1920년대 중반 이후에는 <피아노> <우편국에서> <불> <고향> 등 세태에의 관심과 식민지 상황하의 현실인식이 두드러진 작품을 많이 발표했다. <운수 좋은 날>도 이러한 계열에 속하는 작품이다. 1930년대 이후에는 역사의식과 예언주의적 문학관에 근거한 역사소설 중심의 <무영탑> <흑치상지(黑齒常之)> <선화공주> 등 장편소설을 발표했다.
|
||||
|
||||
새침하게 흐린 품이 눈이 올 듯하더니 눈은 아니 오고 얼다가 만 비가 추적추적 내리었다.
|
||||
|
||||
이날이야말로 동소문 안에서 인력거꾼 노릇을 하는 김 첨지에게는 오래간만에도 닥친 운수 좋은 날이었다. 문안에(거기도 문밖은 아니지만) 들어간답시는 앞집 마나님을 전찻길까지 모셔다 드린 것을 비롯으로 행여나 손님이 있을까 하고 정류장에서 어정어정하며 내리는 사람 하나하나에게 거의 비는 듯한 눈결을 보내고 있다가 마침내 교원인 듯한 양복장이를 동광학교(東光學校)까지 태워다 주기로 되었다.
|
||||
|
||||
첫번에 삼십 전, 둘째 번에 오십 전 - 아침 댓바람에 그리 흔치 않은 일이었다. 그야말로 재수가 옴붙어서 근 열흘 동안 돈 구경도 못한 김 첨지는 십 전짜리 백통화 서 푼, 또는 다섯 푼이 찰깍하고 손바닥에 떨어질 제 거의 눈물을 흘릴 만큼 기뻤었다. 더구나 이날 이때에 이 팔십 전이라는 돈이 그에게 얼마나 유용한지 몰랐다. 컬컬한 목에 모주 한 잔도 적실 수 있거니와 그보다도 앓는 아내에게 설렁탕 한 그릇도 사다줄 수 있음이다.
|
||||
|
||||
그의 아내가 기침으로 쿨럭거리기는 벌써 달포가 넘었다. 조밥도 굶기를 먹다시피 하는 형편이니 물론 약 한 첩 써 본 일이 없다. 구태여 쓰려면 못 쓸 바도 아니로되 그는 병이란 놈에게 약을 주어 보내면 재미를 붙여서 자꾸 온다는 자기의 신조(信條)에 어디까지 충실하였다. 따라서 의사에게 보인 적이 없으니 무슨 병인지는 알 수 없으되 반듯이 누워 가지고, 일어나기는 새로 모로도 못 눕는걸 보면 중증은 중증인 듯. 병이 이대도록 심해지기는 열흘 전에 조밥을 먹고 체한 때문이다.
|
||||
|
||||
그때도 김 첨지가 오래간만에 돈을 얻어서 좁쌀 한 되와 십 전짜리 나무 한 단을 사다 주었더니 김 첨지의 말에 의지하면 그 오라질 년이 천방지축(天方地軸)으로 남비에 대고 끓였다. 마음은 급하고 불길은 달지 않아 채 익지도 않은 것을 그 오라질 년이 숟가락은 고만두고 손으로 움켜서 두 뺨에 주먹덩이 같은 혹이 불거지도록 누가 빼앗을 듯이 처박질 하더니만 그날 저녁부터 가슴이 땅긴다, 배가 켕긴다고 눈을 홉뜨고 지랄병을 하였다. 그때 김 첨지는 열화와 같이 성을 내며,
|
||||
|
||||
“에이, 오라질 년, 조롱복은 할 수가 없어, 못 먹어 병, 먹어서 병, 어쩌란 말이야! 왜 눈을 바루 뜨지 못해!”하고 김 첨지는 앓는 이의 뺨을 한 번 후려갈겼다. 홉뜬 눈은 조금 바루어졌건만 이슬이 맺히었다. 김 첨지의 눈시울도 뜨끈뜨끈하였다.
|
||||
|
||||
이 환자가 그러고도 먹는 데는 물리지 않았다. 사흘 전부터 설렁탕 국물이 마시고 싶다고 남편을 졸랐다.
|
||||
|
||||
“이런 오라질 년! 조밥도 못 먹는 년이 설렁탕은, 또 처먹고 지랄병을 하게.”라고, 야단을 쳐보았건만, 못 사주는 마음이 시원치는 않았다.
|
||||
|
||||
인제 설렁탕을 사줄 수도 있다. 앓는 어미 곁에서 배고파 보채는 개똥이(세 살먹이)에게 죽을 사줄 수도 있다. - 팔십 전을 손에 쥔 김 첨지의 마음은 푼푼하였다. 그러나 그의 행운은 그걸로 그치지 않았다. 땀과 빗물이 섞여 흐르는 목덜미를 기름주머니가 다 된 왜목 수건으로 닦으며, 그 학교 문을 돌아나올 때였다. 뒤에서 <인력거!> 하고 부르는 소리가 난다. 자기를 불러 멈춘 사람이 그 학교 학생인 줄 김 첨지는 한 번 보고 짐작할 수 있었다. 그 학생은 다짜고짜로, “남대문 정거장까지 얼마요?”라고, 물었다.
|
||||
|
||||
아마도 그 학교 기숙사에 있는 이로 동기방학을 이용하여 귀향하려 함이리라. 오늘 가기로 작정은 하였건만 비는 오고, 짐은 있고 해서 어찌할 줄 모르다가 마침 김 첨지를 보고 뛰어나왔음이리라. 그렇지 않으면 왜 구두를 채 신지 못해서 질질 끌고, 비록 <고구라> 양복일망정 노박이로 비를 맞으며 김첨지를 뒤쫓아 나왔으랴.
|
||||
|
||||
“남대문 정거장까지 말씀입니까.”하고 김 첨지는 잠깐 주저하였다. 그는 이 우중에 우장도 없이 그 먼 곳을 철벅거리고 가기가 싫었음일까? 처음 것, 둘째 것으로 그만 만족하였음일까? 아니다, 결코 아니다. 이상하게도 꼬리를 맞물고 덤비는 이 행운 앞에 조금 겁이 났음이다.그리고 집을 나올 제 아내의 부탁이 마음에 켕기었다. - 앞집 마나님한테서 부르러 왔을 제 병인은 그 뼈만 남은 얼굴에 유일의 생물 같은 유달리 크고 움폭한 눈에 애걸하는 빛을 띠우며, “오늘은 나가지 말아요. 제발 덕분에 집에 붙어있어요. 내가 이렇게 아픈데……”라고, 모기 소리같이 중얼거리고 숨을 걸그렁걸그렁 하였다.
|
||||
|
||||
그때에 김 첨지는 대수롭지 않은 듯이, “압다, 젠장맞을 년, 별 빌어먹을 소리를 다 하네. 맞붙들고 앉았으면 누가 먹여 살릴 줄 알아.”하고, 훌쩍 뛰어나오려니까 환자는 붙잡을 듯이 팔을 내저으며, “나가지 말라도 그래, 그러면 일찌기 들어와요.”하고, 목메인 소리가 뒤를 따랐다.
|
||||
|
||||
정거장까지 가잔 말을 들은 순간에 경련적으로 떠는 손, 유달리 큼직한 눈, 울 듯한 아내의 얼굴이 김 첨지의 눈앞에 어른어른하였다. “그래 남대문 정거장까지 얼마란 말이요?”하고 학생은 초조한 듯이 인력거꾼의 얼굴을 바라보며 혼잣말같이, “인천 차가 열 한 점에 있고, 그 다음에는 새로 두 점이든가.”라고, 중얼거린다.
|
||||
|
||||
“일 원 오십 전만 줍시요.” 이 말이 저도 모를 사이에 불쑥 김 첨지의 입에서 떨어졌다. 제 입으로 부르고도 스스로 그 엄청난 돈 액수에 놀래었다. 한꺼번에 이런 금액을 불러라도 본 지가 그 얼마만인가! 그러자 그 돈 벌 용기가 병자에 대한 염려를 사르고 말았다. 설마 오늘 내로 어떠랴 싶었다. 무슨 일이 있더라도 제일 제이의 행운을 곱친 것보다도 오히려 갑절이 많은 이 행운을 놓칠 수 없다 하였다.
|
||||
|
||||
“일 원 오십 전은 너무 과한데.” 이런 말을 하며 학생은 고개를 기웃하였다.
|
||||
|
||||
“아니올시다. 잇수로 치면 여기서 거기가 시오리가 넘는답니다. 또 이런 진 날에 좀더 주셔야지요.”하고 빙글빙글 웃는 차부의 얼굴에는 숨길 수 없는 기쁨이 넘쳐 흘렀다.
|
||||
|
||||
“그러면 달라는 대로 줄 터이니 빨리 가요.” 관대한 어린 손님은 그런 말을 남기고 총총히 옷도 입고 짐도 챙기러 갈 데로 갔다.
|
||||
|
||||
그 학생을 태우고 나선 김 첨지의 다리는 이상하게 거뿐하였다. 달음질을 한다느니보다 거의 나는 듯하였다. 바퀴도 어떻게 속히 도는지 군다느니보다 마치 얼음을 지쳐나가는 <스케이트> 모양으로 미끄러져 가는 듯하였다. 얼은 땅에 비가 내려 미끄럽기도 하였지만.
|
||||
|
||||
이윽고 끄는 이의 다리는 무거워졌다. 자기 집 가까이 다다른 까닭이다. 새삼스러운 염려가 그의 가슴을 눌렀다. <오늘은 나가지 말아요. 내가 이렇게 아픈데!> 이런 말이 잉잉 그의 귀에 울렸다. 그리고 병자의 움쑥 들어간 눈이 원망하는 듯이 자기를 노리는 듯하였다. 그러자 엉엉하고 우는 개똥이의 곡성을 들은 듯싶다. 딸국딸국 하고 숨 모으는 소리도 나는 듯싶다.“왜 이리우, 기차 놓치겠구먼.”하고 탄 이의 초조한 부르짖음이 간신히 그의 귀에 들어왔다. 언뜻 깨달으니 김 첨지는 인력거를 쥔 채 길 한복판에 엉거주춤 멈춰있지 않은가.
|
||||
|
||||
“예, 예.”하고, 김 첨지는 또다시 달음질하였다. 집이 차차 멀어갈수록 김 첨지의 걸음에는 다시금 신이 나기 시작하였다. 다리를 재게 놀려야만 쉴새없이 자기의 머리에 떠오르는 모든 근심과 걱정을 잊을 듯이.
|
||||
|
||||
정거장까지 끌어다주고 그 깜짝 놀란 일 원 오십 전을 정말 제 손에 쥠에, 제 말마따나 십 리나 되는 길을 비를 맞아 가며 질퍽거리고 온 생각은 아니하고, 거저나 얻은 듯이 고마왔다. 졸부나 된 듯이 기뻤다. 제자식 뻘밖에 안되는 어린 손님에게 몇 번 허리를 굽히며, “안녕히 다녀옵시요.”라고 깍듯이 재우쳤다.
|
||||
|
||||
그러나 빈 인력거를 털털거리며 이 우중에 돌아갈 일이 꿈밖이었다. 노동으로 하여 흐른 땀이 식어지자 굶주린 창자에서, 물 흐르는 옷에서 어슬어슬 한기가 솟아나기 비롯하매 일 원 오십 전이란 돈이 얼마나 괜찮고 괴로운 것인 줄 절절히 느끼었다. 정거장을 떠나는 그의 발길은 힘 하나 없었다. 온몸이 옹송그려지며 당장 그 자리에 엎어져 못 일어날 것 같았다.
|
||||
|
||||
“젠장맞을 것! 이 비를 맞으며 빈 인력거를 털털거리고 돌아를 간담. 이런 빌어먹을, 제 할미를 붙을 비가 왜 남의 상판을 딱딱 때려!”
|
||||
|
||||
그는 몹시 홧증을 내며 누구에게 반항이나 하는 듯이 게걸거렸다. 그럴 즈음에 그의 머리엔 또 새로운 광명이 비쳤나니 그것은 <이러구 갈 게 아니라 이 근처를 빙빙 돌며 차 오기를 기다리면 또 손님을 태우게 될는지도 몰라>란 생각이었다. 오늘 운수가 괴상하게도 좋으니까 그런 요행이 또한번 없으리라고 누가 보증하랴. 꼬리를 굴리는 행운이 꼭 자기를 기다리고 있다고 내기를 해도 좋을 만한 믿음을 얻게 되었다. 그렇다고 정거장 인력거꾼의 등살이 무서우니 정거장 앞에 섰을 수는 없었다.
|
||||
|
||||
그래 그는 이전에도 여러 번 해본 일이라 바로 정거장 앞 전차 정류장에서 조금 떨어지게, 사람 다니는 길과 전찻길 틈에 인력거를 세워놓고 자기는 그 근처를 빙빙 돌며 형세를 관망하기로 하였다. 얼마만에 기차는 왔고, 수십 명이나 되는 손이 정류장으로 쏟아져 나왔다. 그 중에서 손님을 물색하는 김 첨지의 눈엔 양머리에 뒤축 높은 구두를 신고 <망토>까지 두른 기생 퇴물인 듯, 난봉 여학생인 듯한 여편네의 모양이 띄었다. 그는 슬근슬근 그 여자의 곁으로 다가들었다.
|
||||
|
||||
“아씨, 인력거 아니 타시랍시요?”
|
||||
|
||||
그 여학생인지 뭔지가 한참은 매우 탯갈을 빼며 입술을 꼭 다문 채 김 첨지를 거들떠보지도 않았다. 김 첨지는 구걸하는 거지나 무엇같이 연해연방 그의 기색을 살피며, “아씨, 정거장 애들보담 아주 싸게 모셔다 드리겠읍니다. 댁이 어디신가요.”하고, 추근추근하게도 그 여자의 들고 있는 일본식 버들고리짝에 제 손을 대었다.
|
||||
|
||||
“왜 이래, 남 귀치않게.” 소리를 벽력같이 지르고는 돌아선다. 김 첨지는 어랍시요 하고 물러섰다.
|
||||
|
||||
전차는 왔다. 김 첨지는 원망스럽게 전차 타는 이를 노리고 있었다. 그러나 그의 예감(豫感)은 틀리지 않았다. 전차가 빡빡하게 사람을 싣고 움직이기 시작하였을 때 타고 남은 손 하나이 있었다. 굉장하게 큰 가방을 들고 있는걸 보면 아마 붐비는 차 안에 짐이 크다 하여 차장에게 밀려내려온 눈치였다. 김 첨지는 대어섰다.
|
||||
|
||||
“인력거를 타시랍시요.”
|
||||
|
||||
한동안 값으로 승강이를 하다가 육십 전에 인사동까지 태워다주기로 하였다. 인력거가 무거워지매 그의 몸은 이상하게도 가벼워졌고 그리고 또 인력거가 가벼워지니 몸은 다시금 무거워졌건만 이번에는 마음조차 초조해 온다. 집의 광경이 자꾸 눈앞에 어른거리어 인제 요행을 바랄 여유도 없었다. 나무 등걸이나 무엇 같고 제 것 같지도 않은 다리를 연해 꾸짖으며 갈팡질팡 뛰는 수밖에 없었다.
|
||||
|
||||
저놈의 인력거군이 저렇게 술이 취해가지고 이 진 땅에 어찌 가노, 라고 길 가는 사람이 걱정을 하리만큼 그의 걸음은 황급하였다. 흐리고 비오는 하늘은 어둠침침하게 벌써 황혼에 가까운 듯하다. 창경원 앞까지 다달아서야 그는 턱에 닿은 숨을 돌리고 걸음도 늦추잡았다. 한 걸음 두 걸음 집이 가까와올수록 그의 마음조차 괴상하게 누그러웠다. 그런데 이 누그러움은 안심에서 오는 게 아니요, 자기를 덮친 무서운 불행을 빈틈없이 알게 될 때가 박두한 것을 두려워하는 마음에서 오는 것이다.
|
||||
|
||||
그는 불행에 다닥치기 전 시간을 얼마쯤이라도 늘리려고 버르적거렸다. 기적(奇蹟)에 가까운 벌이를 하였다는 기쁨을 할 수 있으면 오래 지니고 싶었다. 그는 두리번두리번 사면을 살피었다. 그 모양은 마치 자기 집 - 곧 불행을 향하고 달려가는 제 다리를 제 힘으로는 도저히 어찌할 수 없으니 누구든지 나를 좀 잡아 다고, 구해 다고 하는 듯하였다.
|
||||
|
||||
그럴 즈음에 마침 길가 선술집에서 그의 친구 치삼이가 나온다. 그의 우글우글 살찐 얼굴에 주홍이 돋는 듯, 온 턱과 뺨을 시커멓게 구레나룻이 덮였거늘, 노르탱탱한 얼굴이 바짝 말라서 여기저기 고랑이 패고, 수염도 있대야 턱밑에만 마치 솔잎 송이를 거꾸로 붙여놓은 듯한 김 첨지의 풍채하고는 기이한 대상을 짓고 있었다.
|
||||
|
||||
“여보게 김 첨지, 자네 문안 들어갔다 오는 모양일세그려. 돈 많이 벌었을 테니 한 잔 빨리게.”
|
||||
|
||||
뚱뚱보는 말라깽이를 보든 맡에 부르짖었다. 그 목소리는 몸짓과 딴판으로 연하고 싹싹하였다. 김 첨지는 이 친구를 만난 게 어떻게 반가운지 몰랐다. 자기를 살려준 은인이나 무엇같이 고맙기도 하였다.
|
||||
|
||||
“자네는 벌써 한잔 한 모양일세그려. 자네도 오늘 재미가 좋아보이.”하고, 김 첨지는 얼굴을 펴서 웃었다.
|
||||
|
||||
“압다, 재미 안 좋다고 술 못 먹을 낸가. 그런데 여보게, 자네 왼몸이 어째 물독에 빠진 새앙쥐 같은가? 어서 이리 들어와 말리게.”
|
||||
|
||||
선술집은 훈훈하고 뜨뜻하였다. 추어탕을 끓이는 솥뚜껑을 열 적마다 뭉게뭉게 떠오르는 흰 김, 석쇠에서 뻐지짓뻐지짓 구워지는 너비아니 구이며 제육이며 간이며 콩팥이며 북어며 빈대떡……이 너저분하게 늘어놓인 안주 탁자에 김 첨지는 갑자기 속이 쓰려서 견딜 수 없었다. 마음대로 할 양이면 거기 있는 모든 먹음 먹이를 모조리 깡그리 집어삼켜도 시원치 않았다. 하되 배고픈 이는 위선 분량 많은 빈대떡 두 개를 쪼이기도 하고 추어탕을 한 그릇 청하였다.
|
||||
|
||||
주린 창자는 음식맛을 보더니 더욱더욱 비어지며 자꾸자꾸 들이라들이라 하였다. 순식간에 두부와 미꾸리 든 국 한 그릇을 그냥 물같이 들이키고 말았다. 세째 그릇을 받아들었을 제 데우던 막걸이 곱배기 두 잔이 더웠다. 치삼이와 같이 마시자 원원히 비었던 속이라 찌르르하고 창자에 퍼지며 얼굴이 화끈하였다. 눌러 곱배기 한 잔을 또 마셨다.
|
||||
|
||||
김 첨지의 눈은 벌써 개개 풀리기 시작하였다. 석쇠에 얹힌 떡 두 개를 숭덩숭덩 썰어서 볼을 불룩거리며 또 곱배기 두 잔을 부어라 하였다.
|
||||
|
||||
치삼은 의아한 듯이 김 첨지를 보며, “여보게 또 붓다니, 벌써 우리가 넉 잔씩 먹었네, 돈이 사십 전일세.”라고 주의시켰다.
|
||||
|
||||
“아따 이놈아, 사십 전이 그리 끔찍하냐. 오늘 내가 돈을 막 벌었어. 참 오늘 운수가 좋았느니.”
|
||||
|
||||
“그래 얼마를 벌었단 말인가?”
|
||||
|
||||
“삼십 원을 벌었어, 삼십 원을! 이런 젠장맞을 술을 왜 안부어……괜찮다 괜찮다, 막 먹어도 상관이 없어. 오늘 돈 산더미같이 벌었는데.”
|
||||
|
||||
“어, 이 사람 취했군, 그만두세.”
|
||||
|
||||
“이놈아, 이걸 먹고 취할 내냐, 어서 더 먹어.”하고는 치삼의 귀를 잡아채며 취한 이는 부르짖었다. 그리고 술을 붓는 열 다섯 살 됨직한 중대가리에게로 달려들며, “이놈, 오라질 놈, 왜 술을 붓지 않어.”라고 야단을 쳤다. 중대가리는 히히 웃고 치삼을 보며 문의하는 듯이 눈짓을 하였다. 주정꾼이 눈치를 알아보고 화를 버럭내며, “에미를 붙을 이 오라질 놈들 같으니, 이놈 내가 돈이 없을 줄 알고.”하자마자 허리춤을 훔칫훔칫 하더니 일 원짜리 한 장을 꺼내어 중대가리 앞에 펄쩍 집어던졌다. 그 사품에 몇 푼 은전이 잘그랑 하며 떨어진다.
|
||||
|
||||
“여보게 돈 떨어졌네, 왜 돈을 막 끼얹나.” 이런 말을 하며 일변 돈을 줍는다. 김 첨지는 취한 중에도 돈의 거처를 살피는 듯이 눈을 크게 떠서 땅을 내려다보다가 불시에 제 하는 짓이 너무 더럽다는 듯이 고개를 소스라치자 더욱 성을 내며, “봐라 봐! 이 더러운 놈들아, 내가 돈이 없나, 다리뼉다구를 꺾어놓을 놈들 같으니.”하고 치삼의 주워주는 돈을 받아, “이 원수엣 돈! 이 육시를 할 돈!”하면서, 풀매질을 친다. 벽에 맞아 떨어진 돈은 다시 술 끓이는 양푼에 떨어지며 정당한 매를 맞는다는 듯이 쨍하고 울었다.
|
||||
|
||||
곱배기 두 잔은 또 부어질 겨를도 없이 말려가고 말았다. 김 첨지는 입술과 수염에 붙은 술을 빨아들이고 나서 매우 만족한 듯이 그 솔잎 송이 수염을 쓰다듬으며, “또 부어, 또 부어.”라고, 외쳤다.
|
||||
|
||||
또 한 잔 먹고 나서 김 첨지는 치삼의 어깨를 치며 문득 껄껄 웃는다. 그 웃음 소리가 어떻게 컸는지 술집에 있는 이의 눈은 모두 김 첨지에게로 몰리었다. 웃는 이는 더욱 웃으며, “여보게 치삼이, 내 우스운 이야기 하나 할까. 오늘 손을 태고 정거장에까지 가지 않았겠나.”
|
||||
|
||||
“그래서.”
|
||||
|
||||
“갔다가 그저 오기가 안 됐데그려. 그래 전차 정류장에서 어름어름하며 손님 하나를 태울 궁리를 하지 않았나. 거기 마침 마나님이신지 여학생님이신지 - 요새야 어디 논다니와 아가씨를 구별할 수가 있던가 - <망토>를 두르고 비를 맞고 서 있겠지. 슬근슬근 가까이 가서 인력거 타시랍시요 하고 손가방을 받으랴니까 내 손을 탁 뿌리치고 홱 돌아서더니만 <왜 남을 이렇게 귀찮게 굴어!> 그 소리야말로 꾀꼬리 소리지, 허허!”
|
||||
|
||||
김 첨지는 교묘하게도 정말 꾀꼬리 같은 소리를 내었다. 모든 사람은 일시에 웃었다.
|
||||
|
||||
“빌어먹을 깍쟁이 같은 년, 누가 저를 어쩌나, <왜 남을 귀찮게 굴어!> 어이구 소리가 처신도 없지, 허허.”
|
||||
|
||||
웃음 소리들은 높아졌다. 그러나 그 웃음 소리들이 사라지기 전에 김 첨지는 훌쩍훌쩍 울기 시작하였다.
|
||||
|
||||
치삼은 어이없이 주정뱅이를 바라보며, “금방 웃고 지랄을 하더니 우는 건 또 무슨 일인가.”
|
||||
|
||||
김 첨지는 연해 코를 들여마시며, “우리 마누라가 죽었다네.”
|
||||
|
||||
“뭐, 마누라가 죽다니, 언제?”
|
||||
|
||||
“이놈아 언제는. 오늘이지.”
|
||||
|
||||
“엑기 미친 놈, 거짓말 말아.”
|
||||
|
||||
“거짓말은 왜, 참말로 죽었어, 참말로... 마누라 시체를 집어 뻐들쳐놓고 내가 술을 먹다니, 내가 죽일 놈이야, 죽일 놈이야.”하고 김 첨지는 엉엉 소리를 내어 운다.
|
||||
|
||||
치삼은 흥이 조금 깨어지는 얼굴로, “원 이 사람이, 참말을 하나 거짓말을 하나. 그러면 집으로 가세, 가.”하고 우는 이의 팔을 잡아당기었다.
|
||||
|
||||
치삼의 끄는 손을 뿌리치더니 김 첨지는 눈물이 글썽글썽한 눈으로 싱그레 웃는다.
|
||||
|
||||
“죽기는 누가 죽어.”하고 득의가 양양.
|
||||
|
||||
“죽기는 왜 죽어, 생때같이 살아만 있단다. 그 오라질 년이 밥을 죽이지. 인제 나한테 속았다.”하고 어린애 모양으로 손뼉을 치며 웃는다.
|
||||
|
||||
“이 사람이 정말 미쳤단 말인가. 나도 아주먼네가 앓는단 말은 들었는데.”하고, 치삼이도 어느 불안을 느끼는 듯이 김 첨지에게 또 돌아가라고 권하였다.
|
||||
|
||||
“안 죽었어, 안 죽었대도그래.”
|
||||
|
||||
김 첨지는 홧증을 내며 확신있게 소리를 질렀으되 그 소리엔 안 죽은 것을 믿으려고 애쓰는 가락이 있었다. 기어이 일 원어치를 채워서 곱배기 한 잔씩 더 먹고 나왔다. 궂은 비는 의연히 추적추적 내린다.
|
||||
|
||||
김 첨지는 취중에도 설렁탕을 사가지고 집에 다달았다. 집이라 해도 물론 셋집이요, 또 집 전체를 세든 게 아니라 안과 뚝떨어진 행랑방 한 간을 빌려 든 것인데 물을 길어대고 한 달에 일 원씩 내는 터이다. 만일 김 첨지가 주기를 띠지 않았던들 한 발을 대문에 들여놓았을 제 그곳을 지배하는 무시무시한 정적(靜寂) - 폭풍우가 지나간 뒤의 바다 같은 정적에 다리가 떨렸으리라.
|
||||
|
||||
쿨룩거리는 기침 소리도 들을 수 없다. 그르렁거리는 숨소리조차 들을 수 없다. 다만 이 무덤같은 침묵을 깨뜨리는 - 깨뜨린다느니보다 한층 더 침묵을 깊게 하고 불길하게 하는 빡빡하는 그윽한 소리, 어린애의 젖 빠는 소리가 날 뿐이다. 만일 청각(聽覺)이 예민한 이 같으면 그 빡빡 소리는 빨 따름이요, 꿀떡꿀떡 하고 젖 넘어가는 소리가 없으니 빈 젖을 빤다는 것도 짐작할는지 모르리라.
|
||||
|
||||
혹은 김 첨지도 이 불길한 침묵을 짐작했는지도 모른다. 그렇지 않으면 대문에 들어서자마자 전에 없이, “이 난장 맞을 년, 남편이 들어오는데 나와보지도 않아, 이 오라질 년.”이라고 고함을 친 게 수상하다. 이 고함이야말로 제 몸을 엄습해오는 무시무시한 증을 쫓아버리려는 허장성세(虛張聲勢)인 까닭이다.
|
||||
|
||||
하여간 김 첨지는 방문을 왈칵 열었다. 구역을 나게 하는 추기 - 떨어진 삿자리 밑에서 나온 먼지내, 빨지 않은 기저귀에서 나는 똥내와 오줌내, 가지각색 때가 케케히 앉은 옷내, 병인의 땀 썩은 내가 섞인 추기가 무딘 김 첨지의 코를 찔렀다.
|
||||
|
||||
방안에 들어서며 설렁탕을 한구석에 놓을 사이도 없이 주정군은 목청을 있는 대로 다 내어 호통을 쳤다.
|
||||
|
||||
“이런 오라질 년, 주야장천(晝夜長川) 누워만 있으면 제일이야! 남편이 와도 일어나지를 못해.”라는 소리와 함께 발길로 누운 이의 다리를 몹시 찼다. 그러나 발길에 채이는 건 사람의 살이 아니고 나무등걸과 같은 느낌이 있었다. 이때에 빽빽 소리가 응아 소리로 변하였다. 개똥이가 물었던 젖을 빼어놓고 운다. 운대도 온 얼굴을 찡그려 붙여서, 운다는 표정을 할 뿐이다. 응아 소리도 입에서 나는 게 아니고 마치 뱃속에서 나는 듯하였다. 울다가 울다가 목도 잠겼고 또 울 기운조차 시진한 것 같다.
|
||||
|
||||
발로 차도 그 보람이 없는 걸 보자 남편은 아내의 머리맡으로 달려들어 그야말로 까치집 같은 환자의 머리를 꺼들어 흔들며, “이 년아, 말을 해, 말을! 입이 붙었어, 이 오라질 년!”
|
||||
|
||||
“…”
|
||||
|
||||
“으응, 이것 봐, 아무 말이 없네.”
|
||||
“…”
|
||||
|
||||
“이년아, 죽었단 말이냐, 왜 말이 없어.”
|
||||
|
||||
“…”
|
||||
|
||||
“으응. 또 대답이 없네, 정말 죽었나버이.”
|
||||
|
||||
이러다가 누운 이의 흰 창을 덮은, 위로 치뜬 눈을 알아보자마자, “이 눈깔! 이 눈깔! 왜 나를 바라보지 못하고 천정만 보느냐, 응.”하는 말 끝엔 목이 메었다. 그러자 산 사람의 눈에서 떨어진 닭의 똥 같은 눈물이 죽은 이의 뻣뻣한 얼굴을 어룽어룽 적시었다. 문득 김 첨지는 미칠 듯이 제 얼굴을 죽은 이의 얼굴에 한테 비비대며 중얼거렸다.
|
||||
|
||||
“설렁탕을 사다놓았는데 왜 먹지를 못하니, 왜 먹지를 못하니... 괴상하게도 오늘은! 운수가 좋더니만... ”
|
||||
175
vendor/golang.org/x/text/encoding/testdata/unsu-joh-eun-nal-utf-8.txt
generated
vendored
175
vendor/golang.org/x/text/encoding/testdata/unsu-joh-eun-nal-utf-8.txt
generated
vendored
|
|
@ -1,175 +0,0 @@
|
|||
This file was derived from
|
||||
http://www.ibrary.co.kr/index.php/book-list/short-stories/34-short-stories-korean/150-2008-04-20-13-22-32
|
||||
--------
|
||||
[소개]
|
||||
잔인한 운명은 이렇게 인간을 조롱하곤 한다. 우리가 평소 마음 속 저 깊은 곳에 움켜쥐고 있던 자존심 따위는 어느 한 순간 전혀 무용지물이란 것이 드러나고 만다. 하기야 이렇게 삶의 한 순간, 눈 깜짝할 새에 우리를 후려 갈기고 지나가는 그 진실이 미래의 어느날에는 또 남김없이 우리 눈 앞에 펼쳐질지도 모른다. 죽음을 앞둔 사람들에게는 자신의 삶 전체가 한 순간에 다시 보인다는 그런 얘기도 있던데...
|
||||
|
||||
다시 읽어보니 끔찍한 생각도 든다. 식민지 시대의 암울한 삶, 그 끈끈한 냄새를 피할 수 없다. 21세기를 사는 우리들에겐 그런 냄새는 아예 인연이 없는 것처럼 느껴질 수도 있을 것이다. 그러나 과연 그럴까? 이런 냄새를 모르고 평생 사는 사람도 있겠지만, 전혀 관련이 없는 것은 아닐 것이다. 그저 우연일 뿐이다. 아내를 박대하는 김 첨지의 모습... 요새 같으면 간이 배 밖으로 튀어나온 남자겠지만, 그래도 그 애정은 더 진한 것일 수도 있다.
|
||||
|
||||
[작가 소개]
|
||||
현 진 건(玄鎭健, 1900-1943) : 소설가. 한국 사실주의 단편소설의 기틀을 다진 작가이다. 본관은 연주(延州). 아호는 빙허(憑虛). 1920년대 전반기에는 자전적 요소가 강한 개인적 체험소설인 <빈처> <술 권하는 사회>, 성(性)의 문제와 애정문제를 다룬 <B사감과 러브레터> <새빨간 웃음> 등이 있으며 1920년대 중반 이후에는 <피아노> <우편국에서> <불> <고향> 등 세태에의 관심과 식민지 상황하의 현실인식이 두드러진 작품을 많이 발표했다. <운수 좋은 날>도 이러한 계열에 속하는 작품이다. 1930년대 이후에는 역사의식과 예언주의적 문학관에 근거한 역사소설 중심의 <무영탑> <흑치상지(黑齒常之)> <선화공주> 등 장편소설을 발표했다.
|
||||
|
||||
새침하게 흐린 품이 눈이 올 듯하더니 눈은 아니 오고 얼다가 만 비가 추적추적 내리었다.
|
||||
|
||||
이날이야말로 동소문 안에서 인력거꾼 노릇을 하는 김 첨지에게는 오래간만에도 닥친 운수 좋은 날이었다. 문안에(거기도 문밖은 아니지만) 들어간답시는 앞집 마나님을 전찻길까지 모셔다 드린 것을 비롯으로 행여나 손님이 있을까 하고 정류장에서 어정어정하며 내리는 사람 하나하나에게 거의 비는 듯한 눈결을 보내고 있다가 마침내 교원인 듯한 양복장이를 동광학교(東光學校)까지 태워다 주기로 되었다.
|
||||
|
||||
첫번에 삼십 전, 둘째 번에 오십 전 - 아침 댓바람에 그리 흔치 않은 일이었다. 그야말로 재수가 옴붙어서 근 열흘 동안 돈 구경도 못한 김 첨지는 십 전짜리 백통화 서 푼, 또는 다섯 푼이 찰깍하고 손바닥에 떨어질 제 거의 눈물을 흘릴 만큼 기뻤었다. 더구나 이날 이때에 이 팔십 전이라는 돈이 그에게 얼마나 유용한지 몰랐다. 컬컬한 목에 모주 한 잔도 적실 수 있거니와 그보다도 앓는 아내에게 설렁탕 한 그릇도 사다줄 수 있음이다.
|
||||
|
||||
그의 아내가 기침으로 쿨럭거리기는 벌써 달포가 넘었다. 조밥도 굶기를 먹다시피 하는 형편이니 물론 약 한 첩 써 본 일이 없다. 구태여 쓰려면 못 쓸 바도 아니로되 그는 병이란 놈에게 약을 주어 보내면 재미를 붙여서 자꾸 온다는 자기의 신조(信條)에 어디까지 충실하였다. 따라서 의사에게 보인 적이 없으니 무슨 병인지는 알 수 없으되 반듯이 누워 가지고, 일어나기는 새로 모로도 못 눕는걸 보면 중증은 중증인 듯. 병이 이대도록 심해지기는 열흘 전에 조밥을 먹고 체한 때문이다.
|
||||
|
||||
그때도 김 첨지가 오래간만에 돈을 얻어서 좁쌀 한 되와 십 전짜리 나무 한 단을 사다 주었더니 김 첨지의 말에 의지하면 그 오라질 년이 천방지축(天方地軸)으로 남비에 대고 끓였다. 마음은 급하고 불길은 달지 않아 채 익지도 않은 것을 그 오라질 년이 숟가락은 고만두고 손으로 움켜서 두 뺨에 주먹덩이 같은 혹이 불거지도록 누가 빼앗을 듯이 처박질 하더니만 그날 저녁부터 가슴이 땅긴다, 배가 켕긴다고 눈을 홉뜨고 지랄병을 하였다. 그때 김 첨지는 열화와 같이 성을 내며,
|
||||
|
||||
“에이, 오라질 년, 조롱복은 할 수가 없어, 못 먹어 병, 먹어서 병, 어쩌란 말이야! 왜 눈을 바루 뜨지 못해!”하고 김 첨지는 앓는 이의 뺨을 한 번 후려갈겼다. 홉뜬 눈은 조금 바루어졌건만 이슬이 맺히었다. 김 첨지의 눈시울도 뜨끈뜨끈하였다.
|
||||
|
||||
이 환자가 그러고도 먹는 데는 물리지 않았다. 사흘 전부터 설렁탕 국물이 마시고 싶다고 남편을 졸랐다.
|
||||
|
||||
“이런 오라질 년! 조밥도 못 먹는 년이 설렁탕은, 또 처먹고 지랄병을 하게.”라고, 야단을 쳐보았건만, 못 사주는 마음이 시원치는 않았다.
|
||||
|
||||
인제 설렁탕을 사줄 수도 있다. 앓는 어미 곁에서 배고파 보채는 개똥이(세 살먹이)에게 죽을 사줄 수도 있다. - 팔십 전을 손에 쥔 김 첨지의 마음은 푼푼하였다. 그러나 그의 행운은 그걸로 그치지 않았다. 땀과 빗물이 섞여 흐르는 목덜미를 기름주머니가 다 된 왜목 수건으로 닦으며, 그 학교 문을 돌아나올 때였다. 뒤에서 <인력거!> 하고 부르는 소리가 난다. 자기를 불러 멈춘 사람이 그 학교 학생인 줄 김 첨지는 한 번 보고 짐작할 수 있었다. 그 학생은 다짜고짜로, “남대문 정거장까지 얼마요?”라고, 물었다.
|
||||
|
||||
아마도 그 학교 기숙사에 있는 이로 동기방학을 이용하여 귀향하려 함이리라. 오늘 가기로 작정은 하였건만 비는 오고, 짐은 있고 해서 어찌할 줄 모르다가 마침 김 첨지를 보고 뛰어나왔음이리라. 그렇지 않으면 왜 구두를 채 신지 못해서 질질 끌고, 비록 <고구라> 양복일망정 노박이로 비를 맞으며 김첨지를 뒤쫓아 나왔으랴.
|
||||
|
||||
“남대문 정거장까지 말씀입니까.”하고 김 첨지는 잠깐 주저하였다. 그는 이 우중에 우장도 없이 그 먼 곳을 철벅거리고 가기가 싫었음일까? 처음 것, 둘째 것으로 그만 만족하였음일까? 아니다, 결코 아니다. 이상하게도 꼬리를 맞물고 덤비는 이 행운 앞에 조금 겁이 났음이다.그리고 집을 나올 제 아내의 부탁이 마음에 켕기었다. - 앞집 마나님한테서 부르러 왔을 제 병인은 그 뼈만 남은 얼굴에 유일의 생물 같은 유달리 크고 움폭한 눈에 애걸하는 빛을 띠우며, “오늘은 나가지 말아요. 제발 덕분에 집에 붙어있어요. 내가 이렇게 아픈데……”라고, 모기 소리같이 중얼거리고 숨을 걸그렁걸그렁 하였다.
|
||||
|
||||
그때에 김 첨지는 대수롭지 않은 듯이, “압다, 젠장맞을 년, 별 빌어먹을 소리를 다 하네. 맞붙들고 앉았으면 누가 먹여 살릴 줄 알아.”하고, 훌쩍 뛰어나오려니까 환자는 붙잡을 듯이 팔을 내저으며, “나가지 말라도 그래, 그러면 일찌기 들어와요.”하고, 목메인 소리가 뒤를 따랐다.
|
||||
|
||||
정거장까지 가잔 말을 들은 순간에 경련적으로 떠는 손, 유달리 큼직한 눈, 울 듯한 아내의 얼굴이 김 첨지의 눈앞에 어른어른하였다. “그래 남대문 정거장까지 얼마란 말이요?”하고 학생은 초조한 듯이 인력거꾼의 얼굴을 바라보며 혼잣말같이, “인천 차가 열 한 점에 있고, 그 다음에는 새로 두 점이든가.”라고, 중얼거린다.
|
||||
|
||||
“일 원 오십 전만 줍시요.” 이 말이 저도 모를 사이에 불쑥 김 첨지의 입에서 떨어졌다. 제 입으로 부르고도 스스로 그 엄청난 돈 액수에 놀래었다. 한꺼번에 이런 금액을 불러라도 본 지가 그 얼마만인가! 그러자 그 돈 벌 용기가 병자에 대한 염려를 사르고 말았다. 설마 오늘 내로 어떠랴 싶었다. 무슨 일이 있더라도 제일 제이의 행운을 곱친 것보다도 오히려 갑절이 많은 이 행운을 놓칠 수 없다 하였다.
|
||||
|
||||
“일 원 오십 전은 너무 과한데.” 이런 말을 하며 학생은 고개를 기웃하였다.
|
||||
|
||||
“아니올시다. 잇수로 치면 여기서 거기가 시오리가 넘는답니다. 또 이런 진 날에 좀더 주셔야지요.”하고 빙글빙글 웃는 차부의 얼굴에는 숨길 수 없는 기쁨이 넘쳐 흘렀다.
|
||||
|
||||
“그러면 달라는 대로 줄 터이니 빨리 가요.” 관대한 어린 손님은 그런 말을 남기고 총총히 옷도 입고 짐도 챙기러 갈 데로 갔다.
|
||||
|
||||
그 학생을 태우고 나선 김 첨지의 다리는 이상하게 거뿐하였다. 달음질을 한다느니보다 거의 나는 듯하였다. 바퀴도 어떻게 속히 도는지 군다느니보다 마치 얼음을 지쳐나가는 <스케이트> 모양으로 미끄러져 가는 듯하였다. 얼은 땅에 비가 내려 미끄럽기도 하였지만.
|
||||
|
||||
이윽고 끄는 이의 다리는 무거워졌다. 자기 집 가까이 다다른 까닭이다. 새삼스러운 염려가 그의 가슴을 눌렀다. <오늘은 나가지 말아요. 내가 이렇게 아픈데!> 이런 말이 잉잉 그의 귀에 울렸다. 그리고 병자의 움쑥 들어간 눈이 원망하는 듯이 자기를 노리는 듯하였다. 그러자 엉엉하고 우는 개똥이의 곡성을 들은 듯싶다. 딸국딸국 하고 숨 모으는 소리도 나는 듯싶다.“왜 이리우, 기차 놓치겠구먼.”하고 탄 이의 초조한 부르짖음이 간신히 그의 귀에 들어왔다. 언뜻 깨달으니 김 첨지는 인력거를 쥔 채 길 한복판에 엉거주춤 멈춰있지 않은가.
|
||||
|
||||
“예, 예.”하고, 김 첨지는 또다시 달음질하였다. 집이 차차 멀어갈수록 김 첨지의 걸음에는 다시금 신이 나기 시작하였다. 다리를 재게 놀려야만 쉴새없이 자기의 머리에 떠오르는 모든 근심과 걱정을 잊을 듯이.
|
||||
|
||||
정거장까지 끌어다주고 그 깜짝 놀란 일 원 오십 전을 정말 제 손에 쥠에, 제 말마따나 십 리나 되는 길을 비를 맞아 가며 질퍽거리고 온 생각은 아니하고, 거저나 얻은 듯이 고마왔다. 졸부나 된 듯이 기뻤다. 제자식 뻘밖에 안되는 어린 손님에게 몇 번 허리를 굽히며, “안녕히 다녀옵시요.”라고 깍듯이 재우쳤다.
|
||||
|
||||
그러나 빈 인력거를 털털거리며 이 우중에 돌아갈 일이 꿈밖이었다. 노동으로 하여 흐른 땀이 식어지자 굶주린 창자에서, 물 흐르는 옷에서 어슬어슬 한기가 솟아나기 비롯하매 일 원 오십 전이란 돈이 얼마나 괜찮고 괴로운 것인 줄 절절히 느끼었다. 정거장을 떠나는 그의 발길은 힘 하나 없었다. 온몸이 옹송그려지며 당장 그 자리에 엎어져 못 일어날 것 같았다.
|
||||
|
||||
“젠장맞을 것! 이 비를 맞으며 빈 인력거를 털털거리고 돌아를 간담. 이런 빌어먹을, 제 할미를 붙을 비가 왜 남의 상판을 딱딱 때려!”
|
||||
|
||||
그는 몹시 홧증을 내며 누구에게 반항이나 하는 듯이 게걸거렸다. 그럴 즈음에 그의 머리엔 또 새로운 광명이 비쳤나니 그것은 <이러구 갈 게 아니라 이 근처를 빙빙 돌며 차 오기를 기다리면 또 손님을 태우게 될는지도 몰라>란 생각이었다. 오늘 운수가 괴상하게도 좋으니까 그런 요행이 또한번 없으리라고 누가 보증하랴. 꼬리를 굴리는 행운이 꼭 자기를 기다리고 있다고 내기를 해도 좋을 만한 믿음을 얻게 되었다. 그렇다고 정거장 인력거꾼의 등살이 무서우니 정거장 앞에 섰을 수는 없었다.
|
||||
|
||||
그래 그는 이전에도 여러 번 해본 일이라 바로 정거장 앞 전차 정류장에서 조금 떨어지게, 사람 다니는 길과 전찻길 틈에 인력거를 세워놓고 자기는 그 근처를 빙빙 돌며 형세를 관망하기로 하였다. 얼마만에 기차는 왔고, 수십 명이나 되는 손이 정류장으로 쏟아져 나왔다. 그 중에서 손님을 물색하는 김 첨지의 눈엔 양머리에 뒤축 높은 구두를 신고 <망토>까지 두른 기생 퇴물인 듯, 난봉 여학생인 듯한 여편네의 모양이 띄었다. 그는 슬근슬근 그 여자의 곁으로 다가들었다.
|
||||
|
||||
“아씨, 인력거 아니 타시랍시요?”
|
||||
|
||||
그 여학생인지 뭔지가 한참은 매우 탯갈을 빼며 입술을 꼭 다문 채 김 첨지를 거들떠보지도 않았다. 김 첨지는 구걸하는 거지나 무엇같이 연해연방 그의 기색을 살피며, “아씨, 정거장 애들보담 아주 싸게 모셔다 드리겠읍니다. 댁이 어디신가요.”하고, 추근추근하게도 그 여자의 들고 있는 일본식 버들고리짝에 제 손을 대었다.
|
||||
|
||||
“왜 이래, 남 귀치않게.” 소리를 벽력같이 지르고는 돌아선다. 김 첨지는 어랍시요 하고 물러섰다.
|
||||
|
||||
전차는 왔다. 김 첨지는 원망스럽게 전차 타는 이를 노리고 있었다. 그러나 그의 예감(豫感)은 틀리지 않았다. 전차가 빡빡하게 사람을 싣고 움직이기 시작하였을 때 타고 남은 손 하나이 있었다. 굉장하게 큰 가방을 들고 있는걸 보면 아마 붐비는 차 안에 짐이 크다 하여 차장에게 밀려내려온 눈치였다. 김 첨지는 대어섰다.
|
||||
|
||||
“인력거를 타시랍시요.”
|
||||
|
||||
한동안 값으로 승강이를 하다가 육십 전에 인사동까지 태워다주기로 하였다. 인력거가 무거워지매 그의 몸은 이상하게도 가벼워졌고 그리고 또 인력거가 가벼워지니 몸은 다시금 무거워졌건만 이번에는 마음조차 초조해 온다. 집의 광경이 자꾸 눈앞에 어른거리어 인제 요행을 바랄 여유도 없었다. 나무 등걸이나 무엇 같고 제 것 같지도 않은 다리를 연해 꾸짖으며 갈팡질팡 뛰는 수밖에 없었다.
|
||||
|
||||
저놈의 인력거군이 저렇게 술이 취해가지고 이 진 땅에 어찌 가노, 라고 길 가는 사람이 걱정을 하리만큼 그의 걸음은 황급하였다. 흐리고 비오는 하늘은 어둠침침하게 벌써 황혼에 가까운 듯하다. 창경원 앞까지 다달아서야 그는 턱에 닿은 숨을 돌리고 걸음도 늦추잡았다. 한 걸음 두 걸음 집이 가까와올수록 그의 마음조차 괴상하게 누그러웠다. 그런데 이 누그러움은 안심에서 오는 게 아니요, 자기를 덮친 무서운 불행을 빈틈없이 알게 될 때가 박두한 것을 두려워하는 마음에서 오는 것이다.
|
||||
|
||||
그는 불행에 다닥치기 전 시간을 얼마쯤이라도 늘리려고 버르적거렸다. 기적(奇蹟)에 가까운 벌이를 하였다는 기쁨을 할 수 있으면 오래 지니고 싶었다. 그는 두리번두리번 사면을 살피었다. 그 모양은 마치 자기 집 - 곧 불행을 향하고 달려가는 제 다리를 제 힘으로는 도저히 어찌할 수 없으니 누구든지 나를 좀 잡아 다고, 구해 다고 하는 듯하였다.
|
||||
|
||||
그럴 즈음에 마침 길가 선술집에서 그의 친구 치삼이가 나온다. 그의 우글우글 살찐 얼굴에 주홍이 돋는 듯, 온 턱과 뺨을 시커멓게 구레나룻이 덮였거늘, 노르탱탱한 얼굴이 바짝 말라서 여기저기 고랑이 패고, 수염도 있대야 턱밑에만 마치 솔잎 송이를 거꾸로 붙여놓은 듯한 김 첨지의 풍채하고는 기이한 대상을 짓고 있었다.
|
||||
|
||||
“여보게 김 첨지, 자네 문안 들어갔다 오는 모양일세그려. 돈 많이 벌었을 테니 한 잔 빨리게.”
|
||||
|
||||
뚱뚱보는 말라깽이를 보든 맡에 부르짖었다. 그 목소리는 몸짓과 딴판으로 연하고 싹싹하였다. 김 첨지는 이 친구를 만난 게 어떻게 반가운지 몰랐다. 자기를 살려준 은인이나 무엇같이 고맙기도 하였다.
|
||||
|
||||
“자네는 벌써 한잔 한 모양일세그려. 자네도 오늘 재미가 좋아보이.”하고, 김 첨지는 얼굴을 펴서 웃었다.
|
||||
|
||||
“압다, 재미 안 좋다고 술 못 먹을 낸가. 그런데 여보게, 자네 왼몸이 어째 물독에 빠진 새앙쥐 같은가? 어서 이리 들어와 말리게.”
|
||||
|
||||
선술집은 훈훈하고 뜨뜻하였다. 추어탕을 끓이는 솥뚜껑을 열 적마다 뭉게뭉게 떠오르는 흰 김, 석쇠에서 뻐지짓뻐지짓 구워지는 너비아니 구이며 제육이며 간이며 콩팥이며 북어며 빈대떡……이 너저분하게 늘어놓인 안주 탁자에 김 첨지는 갑자기 속이 쓰려서 견딜 수 없었다. 마음대로 할 양이면 거기 있는 모든 먹음 먹이를 모조리 깡그리 집어삼켜도 시원치 않았다. 하되 배고픈 이는 위선 분량 많은 빈대떡 두 개를 쪼이기도 하고 추어탕을 한 그릇 청하였다.
|
||||
|
||||
주린 창자는 음식맛을 보더니 더욱더욱 비어지며 자꾸자꾸 들이라들이라 하였다. 순식간에 두부와 미꾸리 든 국 한 그릇을 그냥 물같이 들이키고 말았다. 세째 그릇을 받아들었을 제 데우던 막걸이 곱배기 두 잔이 더웠다. 치삼이와 같이 마시자 원원히 비었던 속이라 찌르르하고 창자에 퍼지며 얼굴이 화끈하였다. 눌러 곱배기 한 잔을 또 마셨다.
|
||||
|
||||
김 첨지의 눈은 벌써 개개 풀리기 시작하였다. 석쇠에 얹힌 떡 두 개를 숭덩숭덩 썰어서 볼을 불룩거리며 또 곱배기 두 잔을 부어라 하였다.
|
||||
|
||||
치삼은 의아한 듯이 김 첨지를 보며, “여보게 또 붓다니, 벌써 우리가 넉 잔씩 먹었네, 돈이 사십 전일세.”라고 주의시켰다.
|
||||
|
||||
“아따 이놈아, 사십 전이 그리 끔찍하냐. 오늘 내가 돈을 막 벌었어. 참 오늘 운수가 좋았느니.”
|
||||
|
||||
“그래 얼마를 벌었단 말인가?”
|
||||
|
||||
“삼십 원을 벌었어, 삼십 원을! 이런 젠장맞을 술을 왜 안부어……괜찮다 괜찮다, 막 먹어도 상관이 없어. 오늘 돈 산더미같이 벌었는데.”
|
||||
|
||||
“어, 이 사람 취했군, 그만두세.”
|
||||
|
||||
“이놈아, 이걸 먹고 취할 내냐, 어서 더 먹어.”하고는 치삼의 귀를 잡아채며 취한 이는 부르짖었다. 그리고 술을 붓는 열 다섯 살 됨직한 중대가리에게로 달려들며, “이놈, 오라질 놈, 왜 술을 붓지 않어.”라고 야단을 쳤다. 중대가리는 히히 웃고 치삼을 보며 문의하는 듯이 눈짓을 하였다. 주정꾼이 눈치를 알아보고 화를 버럭내며, “에미를 붙을 이 오라질 놈들 같으니, 이놈 내가 돈이 없을 줄 알고.”하자마자 허리춤을 훔칫훔칫 하더니 일 원짜리 한 장을 꺼내어 중대가리 앞에 펄쩍 집어던졌다. 그 사품에 몇 푼 은전이 잘그랑 하며 떨어진다.
|
||||
|
||||
“여보게 돈 떨어졌네, 왜 돈을 막 끼얹나.” 이런 말을 하며 일변 돈을 줍는다. 김 첨지는 취한 중에도 돈의 거처를 살피는 듯이 눈을 크게 떠서 땅을 내려다보다가 불시에 제 하는 짓이 너무 더럽다는 듯이 고개를 소스라치자 더욱 성을 내며, “봐라 봐! 이 더러운 놈들아, 내가 돈이 없나, 다리뼉다구를 꺾어놓을 놈들 같으니.”하고 치삼의 주워주는 돈을 받아, “이 원수엣 돈! 이 육시를 할 돈!”하면서, 풀매질을 친다. 벽에 맞아 떨어진 돈은 다시 술 끓이는 양푼에 떨어지며 정당한 매를 맞는다는 듯이 쨍하고 울었다.
|
||||
|
||||
곱배기 두 잔은 또 부어질 겨를도 없이 말려가고 말았다. 김 첨지는 입술과 수염에 붙은 술을 빨아들이고 나서 매우 만족한 듯이 그 솔잎 송이 수염을 쓰다듬으며, “또 부어, 또 부어.”라고, 외쳤다.
|
||||
|
||||
또 한 잔 먹고 나서 김 첨지는 치삼의 어깨를 치며 문득 껄껄 웃는다. 그 웃음 소리가 어떻게 컸는지 술집에 있는 이의 눈은 모두 김 첨지에게로 몰리었다. 웃는 이는 더욱 웃으며, “여보게 치삼이, 내 우스운 이야기 하나 할까. 오늘 손을 태고 정거장에까지 가지 않았겠나.”
|
||||
|
||||
“그래서.”
|
||||
|
||||
“갔다가 그저 오기가 안 됐데그려. 그래 전차 정류장에서 어름어름하며 손님 하나를 태울 궁리를 하지 않았나. 거기 마침 마나님이신지 여학생님이신지 - 요새야 어디 논다니와 아가씨를 구별할 수가 있던가 - <망토>를 두르고 비를 맞고 서 있겠지. 슬근슬근 가까이 가서 인력거 타시랍시요 하고 손가방을 받으랴니까 내 손을 탁 뿌리치고 홱 돌아서더니만 <왜 남을 이렇게 귀찮게 굴어!> 그 소리야말로 꾀꼬리 소리지, 허허!”
|
||||
|
||||
김 첨지는 교묘하게도 정말 꾀꼬리 같은 소리를 내었다. 모든 사람은 일시에 웃었다.
|
||||
|
||||
“빌어먹을 깍쟁이 같은 년, 누가 저를 어쩌나, <왜 남을 귀찮게 굴어!> 어이구 소리가 처신도 없지, 허허.”
|
||||
|
||||
웃음 소리들은 높아졌다. 그러나 그 웃음 소리들이 사라지기 전에 김 첨지는 훌쩍훌쩍 울기 시작하였다.
|
||||
|
||||
치삼은 어이없이 주정뱅이를 바라보며, “금방 웃고 지랄을 하더니 우는 건 또 무슨 일인가.”
|
||||
|
||||
김 첨지는 연해 코를 들여마시며, “우리 마누라가 죽었다네.”
|
||||
|
||||
“뭐, 마누라가 죽다니, 언제?”
|
||||
|
||||
“이놈아 언제는. 오늘이지.”
|
||||
|
||||
“엑기 미친 놈, 거짓말 말아.”
|
||||
|
||||
“거짓말은 왜, 참말로 죽었어, 참말로... 마누라 시체를 집어 뻐들쳐놓고 내가 술을 먹다니, 내가 죽일 놈이야, 죽일 놈이야.”하고 김 첨지는 엉엉 소리를 내어 운다.
|
||||
|
||||
치삼은 흥이 조금 깨어지는 얼굴로, “원 이 사람이, 참말을 하나 거짓말을 하나. 그러면 집으로 가세, 가.”하고 우는 이의 팔을 잡아당기었다.
|
||||
|
||||
치삼의 끄는 손을 뿌리치더니 김 첨지는 눈물이 글썽글썽한 눈으로 싱그레 웃는다.
|
||||
|
||||
“죽기는 누가 죽어.”하고 득의가 양양.
|
||||
|
||||
“죽기는 왜 죽어, 생때같이 살아만 있단다. 그 오라질 년이 밥을 죽이지. 인제 나한테 속았다.”하고 어린애 모양으로 손뼉을 치며 웃는다.
|
||||
|
||||
“이 사람이 정말 미쳤단 말인가. 나도 아주먼네가 앓는단 말은 들었는데.”하고, 치삼이도 어느 불안을 느끼는 듯이 김 첨지에게 또 돌아가라고 권하였다.
|
||||
|
||||
“안 죽었어, 안 죽었대도그래.”
|
||||
|
||||
김 첨지는 홧증을 내며 확신있게 소리를 질렀으되 그 소리엔 안 죽은 것을 믿으려고 애쓰는 가락이 있었다. 기어이 일 원어치를 채워서 곱배기 한 잔씩 더 먹고 나왔다. 궂은 비는 의연히 추적추적 내린다.
|
||||
|
||||
김 첨지는 취중에도 설렁탕을 사가지고 집에 다달았다. 집이라 해도 물론 셋집이요, 또 집 전체를 세든 게 아니라 안과 뚝떨어진 행랑방 한 간을 빌려 든 것인데 물을 길어대고 한 달에 일 원씩 내는 터이다. 만일 김 첨지가 주기를 띠지 않았던들 한 발을 대문에 들여놓았을 제 그곳을 지배하는 무시무시한 정적(靜寂) - 폭풍우가 지나간 뒤의 바다 같은 정적에 다리가 떨렸으리라.
|
||||
|
||||
쿨룩거리는 기침 소리도 들을 수 없다. 그르렁거리는 숨소리조차 들을 수 없다. 다만 이 무덤같은 침묵을 깨뜨리는 - 깨뜨린다느니보다 한층 더 침묵을 깊게 하고 불길하게 하는 빡빡하는 그윽한 소리, 어린애의 젖 빠는 소리가 날 뿐이다. 만일 청각(聽覺)이 예민한 이 같으면 그 빡빡 소리는 빨 따름이요, 꿀떡꿀떡 하고 젖 넘어가는 소리가 없으니 빈 젖을 빤다는 것도 짐작할는지 모르리라.
|
||||
|
||||
혹은 김 첨지도 이 불길한 침묵을 짐작했는지도 모른다. 그렇지 않으면 대문에 들어서자마자 전에 없이, “이 난장 맞을 년, 남편이 들어오는데 나와보지도 않아, 이 오라질 년.”이라고 고함을 친 게 수상하다. 이 고함이야말로 제 몸을 엄습해오는 무시무시한 증을 쫓아버리려는 허장성세(虛張聲勢)인 까닭이다.
|
||||
|
||||
하여간 김 첨지는 방문을 왈칵 열었다. 구역을 나게 하는 추기 - 떨어진 삿자리 밑에서 나온 먼지내, 빨지 않은 기저귀에서 나는 똥내와 오줌내, 가지각색 때가 케케히 앉은 옷내, 병인의 땀 썩은 내가 섞인 추기가 무딘 김 첨지의 코를 찔렀다.
|
||||
|
||||
방안에 들어서며 설렁탕을 한구석에 놓을 사이도 없이 주정군은 목청을 있는 대로 다 내어 호통을 쳤다.
|
||||
|
||||
“이런 오라질 년, 주야장천(晝夜長川) 누워만 있으면 제일이야! 남편이 와도 일어나지를 못해.”라는 소리와 함께 발길로 누운 이의 다리를 몹시 찼다. 그러나 발길에 채이는 건 사람의 살이 아니고 나무등걸과 같은 느낌이 있었다. 이때에 빽빽 소리가 응아 소리로 변하였다. 개똥이가 물었던 젖을 빼어놓고 운다. 운대도 온 얼굴을 찡그려 붙여서, 운다는 표정을 할 뿐이다. 응아 소리도 입에서 나는 게 아니고 마치 뱃속에서 나는 듯하였다. 울다가 울다가 목도 잠겼고 또 울 기운조차 시진한 것 같다.
|
||||
|
||||
발로 차도 그 보람이 없는 걸 보자 남편은 아내의 머리맡으로 달려들어 그야말로 까치집 같은 환자의 머리를 꺼들어 흔들며, “이 년아, 말을 해, 말을! 입이 붙었어, 이 오라질 년!”
|
||||
|
||||
“…”
|
||||
|
||||
“으응, 이것 봐, 아무 말이 없네.”
|
||||
“…”
|
||||
|
||||
“이년아, 죽었단 말이냐, 왜 말이 없어.”
|
||||
|
||||
“…”
|
||||
|
||||
“으응. 또 대답이 없네, 정말 죽었나버이.”
|
||||
|
||||
이러다가 누운 이의 흰 창을 덮은, 위로 치뜬 눈을 알아보자마자, “이 눈깔! 이 눈깔! 왜 나를 바라보지 못하고 천정만 보느냐, 응.”하는 말 끝엔 목이 메었다. 그러자 산 사람의 눈에서 떨어진 닭의 똥 같은 눈물이 죽은 이의 뻣뻣한 얼굴을 어룽어룽 적시었다. 문득 김 첨지는 미칠 듯이 제 얼굴을 죽은 이의 얼굴에 한테 비비대며 중얼거렸다.
|
||||
|
||||
“설렁탕을 사다놓았는데 왜 먹지를 못하니, 왜 먹지를 못하니... 괴상하게도 오늘은! 운수가 좋더니만... ”
|
||||
114
vendor/golang.org/x/text/encoding/traditionalchinese/all_test.go
generated
vendored
114
vendor/golang.org/x/text/encoding/traditionalchinese/all_test.go
generated
vendored
|
|
@ -1,114 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package traditionalchinese
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/enctest"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
func dec(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Decode", e.NewDecoder(), nil
|
||||
}
|
||||
func enc(e encoding.Encoding) (dir string, t transform.Transformer, err error) {
|
||||
return "Encode", e.NewEncoder(), internal.ErrASCIIReplacement
|
||||
}
|
||||
|
||||
func TestNonRepertoire(t *testing.T) {
|
||||
testCases := []struct {
|
||||
init func(e encoding.Encoding) (string, transform.Transformer, error)
|
||||
e encoding.Encoding
|
||||
src, want string
|
||||
}{
|
||||
{dec, Big5, "\x80", "\ufffd"},
|
||||
{dec, Big5, "\x81", "\ufffd"},
|
||||
{dec, Big5, "\x81\x30", "\ufffd\x30"},
|
||||
{dec, Big5, "\x81\x40", "\ufffd"},
|
||||
{dec, Big5, "\x81\xa0", "\ufffd"},
|
||||
{dec, Big5, "\xff", "\ufffd"},
|
||||
|
||||
{enc, Big5, "갂", ""},
|
||||
{enc, Big5, "a갂", "a"},
|
||||
{enc, Big5, "\u43f0갂", "\x87@"},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
dir, tr, wantErr := tc.init(tc.e)
|
||||
t.Run(fmt.Sprintf("%s/%v/%q", dir, tc.e, tc.src), func(t *testing.T) {
|
||||
dst := make([]byte, 100)
|
||||
src := []byte(tc.src)
|
||||
for i := 0; i <= len(tc.src); i++ {
|
||||
nDst, nSrc, err := tr.Transform(dst, src[:i], false)
|
||||
if err != nil && err != transform.ErrShortSrc && err != wantErr {
|
||||
t.Fatalf("error on first call to Transform: %v", err)
|
||||
}
|
||||
n, _, err := tr.Transform(dst[nDst:], src[nSrc:], true)
|
||||
nDst += n
|
||||
if err != wantErr {
|
||||
t.Fatalf("(%q|%q): got %v; want %v", tc.src[:i], tc.src[i:], err, wantErr)
|
||||
}
|
||||
if got := string(dst[:nDst]); got != tc.want {
|
||||
t.Errorf("(%q|%q):\ngot %q\nwant %q", tc.src[:i], tc.src[i:], got, tc.want)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasics(t *testing.T) {
|
||||
// The encoded forms can be verified by the iconv program:
|
||||
// $ echo 月日は百代 | iconv -f UTF-8 -t SHIFT-JIS | xxd
|
||||
testCases := []struct {
|
||||
e encoding.Encoding
|
||||
encPrefix string
|
||||
encSuffix string
|
||||
encoded string
|
||||
utf8 string
|
||||
}{{
|
||||
e: Big5,
|
||||
encoded: "A\x87\x40\x87\x41\x87\x45\xa1\x40\xfe\xfd\xfe\xfeZ\xa3\xe1",
|
||||
utf8: "A\u43f0\u4c32\U00027267\u3000\U0002910d\u79d4Z€",
|
||||
}, {
|
||||
e: Big5,
|
||||
encoded: "\xaa\xe1\xb6\xa1\xa4\x40\xb3\xfd\xb0\x73\xa1\x41\xbf\x57\xb0\x75" +
|
||||
"\xb5\x4c\xac\xdb\xbf\xcb\xa1\x43",
|
||||
utf8: "花間一壺酒,獨酌無相親。",
|
||||
}}
|
||||
|
||||
for _, tc := range testCases {
|
||||
enctest.TestEncoding(t, tc.e, tc.encoded, tc.utf8, "", "")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFiles(t *testing.T) { enctest.TestFile(t, Big5) }
|
||||
|
||||
func BenchmarkEncoding(b *testing.B) { enctest.Benchmark(b, Big5) }
|
||||
|
||||
// TestBig5CircumflexAndMacron tests the special cases listed in
|
||||
// http://encoding.spec.whatwg.org/#big5
|
||||
// Note that these special cases aren't preserved by round-tripping through
|
||||
// decoding and encoding (since
|
||||
// http://encoding.spec.whatwg.org/index-big5.txt does not have an entry for
|
||||
// U+0304 or U+030C), so we can't test this in TestBasics.
|
||||
func TestBig5CircumflexAndMacron(t *testing.T) {
|
||||
src := "\x88\x5f\x88\x60\x88\x61\x88\x62\x88\x63\x88\x64\x88\x65\x88\x66 " +
|
||||
"\x88\xa2\x88\xa3\x88\xa4\x88\xa5\x88\xa6"
|
||||
want := "ÓǑÒ\u00ca\u0304Ế\u00ca\u030cỀÊ " +
|
||||
"ü\u00ea\u0304ế\u00ea\u030cề"
|
||||
dst, err := ioutil.ReadAll(transform.NewReader(
|
||||
strings.NewReader(src), Big5.NewDecoder()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := string(dst); got != want {
|
||||
t.Fatalf("\ngot %q\nwant %q", got, want)
|
||||
}
|
||||
}
|
||||
199
vendor/golang.org/x/text/encoding/traditionalchinese/big5.go
generated
vendored
199
vendor/golang.org/x/text/encoding/traditionalchinese/big5.go
generated
vendored
|
|
@ -1,199 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package traditionalchinese
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/internal"
|
||||
"golang.org/x/text/encoding/internal/identifier"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// All is a list of all defined encodings in this package.
|
||||
var All = []encoding.Encoding{Big5}
|
||||
|
||||
// Big5 is the Big5 encoding, also known as Code Page 950.
|
||||
var Big5 encoding.Encoding = &big5
|
||||
|
||||
var big5 = internal.Encoding{
|
||||
&internal.SimpleEncoding{big5Decoder{}, big5Encoder{}},
|
||||
"Big5",
|
||||
identifier.Big5,
|
||||
}
|
||||
|
||||
type big5Decoder struct{ transform.NopResetter }
|
||||
|
||||
func (big5Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size, s := rune(0), 0, ""
|
||||
loop:
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
switch c0 := src[nSrc]; {
|
||||
case c0 < utf8.RuneSelf:
|
||||
r, size = rune(c0), 1
|
||||
|
||||
case 0x81 <= c0 && c0 < 0xff:
|
||||
if nSrc+1 >= len(src) {
|
||||
if !atEOF {
|
||||
err = transform.ErrShortSrc
|
||||
break loop
|
||||
}
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
}
|
||||
c1 := src[nSrc+1]
|
||||
switch {
|
||||
case 0x40 <= c1 && c1 < 0x7f:
|
||||
c1 -= 0x40
|
||||
case 0xa1 <= c1 && c1 < 0xff:
|
||||
c1 -= 0x62
|
||||
case c1 < 0x40:
|
||||
r, size = utf8.RuneError, 1
|
||||
goto write
|
||||
default:
|
||||
r, size = utf8.RuneError, 2
|
||||
goto write
|
||||
}
|
||||
r, size = '\ufffd', 2
|
||||
if i := int(c0-0x81)*157 + int(c1); i < len(decode) {
|
||||
if 1133 <= i && i < 1167 {
|
||||
// The two-rune special cases for LATIN CAPITAL / SMALL E WITH CIRCUMFLEX
|
||||
// AND MACRON / CARON are from http://encoding.spec.whatwg.org/#big5
|
||||
switch i {
|
||||
case 1133:
|
||||
s = "\u00CA\u0304"
|
||||
goto writeStr
|
||||
case 1135:
|
||||
s = "\u00CA\u030C"
|
||||
goto writeStr
|
||||
case 1164:
|
||||
s = "\u00EA\u0304"
|
||||
goto writeStr
|
||||
case 1166:
|
||||
s = "\u00EA\u030C"
|
||||
goto writeStr
|
||||
}
|
||||
}
|
||||
r = rune(decode[i])
|
||||
if r == 0 {
|
||||
r = '\ufffd'
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
r, size = utf8.RuneError, 1
|
||||
}
|
||||
|
||||
write:
|
||||
if nDst+utf8.RuneLen(r) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += utf8.EncodeRune(dst[nDst:], r)
|
||||
continue loop
|
||||
|
||||
writeStr:
|
||||
if nDst+len(s) > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break loop
|
||||
}
|
||||
nDst += copy(dst[nDst:], s)
|
||||
continue loop
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
type big5Encoder struct{ transform.NopResetter }
|
||||
|
||||
func (big5Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
r, size := rune(0), 0
|
||||
for ; nSrc < len(src); nSrc += size {
|
||||
r = rune(src[nSrc])
|
||||
|
||||
// Decode a 1-byte rune.
|
||||
if r < utf8.RuneSelf {
|
||||
size = 1
|
||||
if nDst >= len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst] = uint8(r)
|
||||
nDst++
|
||||
continue
|
||||
|
||||
} else {
|
||||
// Decode a multi-byte rune.
|
||||
r, size = utf8.DecodeRune(src[nSrc:])
|
||||
if size == 1 {
|
||||
// All valid runes of size 1 (those below utf8.RuneSelf) were
|
||||
// handled above. We have invalid UTF-8 or we haven't seen the
|
||||
// full character yet.
|
||||
if !atEOF && !utf8.FullRune(src[nSrc:]) {
|
||||
err = transform.ErrShortSrc
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if r >= utf8.RuneSelf {
|
||||
// func init checks that the switch covers all tables.
|
||||
switch {
|
||||
case encode0Low <= r && r < encode0High:
|
||||
if r = rune(encode0[r-encode0Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode1Low <= r && r < encode1High:
|
||||
if r = rune(encode1[r-encode1Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode2Low <= r && r < encode2High:
|
||||
if r = rune(encode2[r-encode2Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode3Low <= r && r < encode3High:
|
||||
if r = rune(encode3[r-encode3Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode4Low <= r && r < encode4High:
|
||||
if r = rune(encode4[r-encode4Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode5Low <= r && r < encode5High:
|
||||
if r = rune(encode5[r-encode5Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode6Low <= r && r < encode6High:
|
||||
if r = rune(encode6[r-encode6Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
case encode7Low <= r && r < encode7High:
|
||||
if r = rune(encode7[r-encode7Low]); r != 0 {
|
||||
goto write2
|
||||
}
|
||||
}
|
||||
err = internal.ErrASCIIReplacement
|
||||
break
|
||||
}
|
||||
|
||||
write2:
|
||||
if nDst+2 > len(dst) {
|
||||
err = transform.ErrShortDst
|
||||
break
|
||||
}
|
||||
dst[nDst+0] = uint8(r >> 8)
|
||||
dst[nDst+1] = uint8(r)
|
||||
nDst += 2
|
||||
continue
|
||||
}
|
||||
return nDst, nSrc, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that the hard-coded encode switch covers all tables.
|
||||
if numEncodeTables != 8 {
|
||||
panic("bad numEncodeTables")
|
||||
}
|
||||
}
|
||||
140
vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go
generated
vendored
140
vendor/golang.org/x/text/encoding/traditionalchinese/maketables.go
generated
vendored
|
|
@ -1,140 +0,0 @@
|
|||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This program generates tables.go:
|
||||
// go run maketables.go | gofmt > tables.go
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("// generated by go run maketables.go; DO NOT EDIT\n\n")
|
||||
fmt.Printf("// Package traditionalchinese provides Traditional Chinese encodings such as Big5.\n")
|
||||
fmt.Printf(`package traditionalchinese // import "golang.org/x/text/encoding/traditionalchinese"` + "\n\n")
|
||||
|
||||
res, err := http.Get("http://encoding.spec.whatwg.org/index-big5.txt")
|
||||
if err != nil {
|
||||
log.Fatalf("Get: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
mapping := [65536]uint32{}
|
||||
reverse := [65536 * 4]uint16{}
|
||||
|
||||
scanner := bufio.NewScanner(res.Body)
|
||||
for scanner.Scan() {
|
||||
s := strings.TrimSpace(scanner.Text())
|
||||
if s == "" || s[0] == '#' {
|
||||
continue
|
||||
}
|
||||
x, y := uint16(0), uint32(0)
|
||||
if _, err := fmt.Sscanf(s, "%d 0x%x", &x, &y); err != nil {
|
||||
log.Fatalf("could not parse %q", s)
|
||||
}
|
||||
if x < 0 || 126*157 <= x {
|
||||
log.Fatalf("Big5 code %d is out of range", x)
|
||||
}
|
||||
mapping[x] = y
|
||||
|
||||
// The WHATWG spec http://encoding.spec.whatwg.org/#indexes says that
|
||||
// "The index pointer for code point in index is the first pointer
|
||||
// corresponding to code point in index", which would normally mean
|
||||
// that the code below should be guarded by "if reverse[y] == 0", but
|
||||
// last instead of first seems to match the behavior of
|
||||
// "iconv -f UTF-8 -t BIG5". For example, U+8005 者 occurs twice in
|
||||
// http://encoding.spec.whatwg.org/index-big5.txt, as index 2148
|
||||
// (encoded as "\x8e\xcd") and index 6543 (encoded as "\xaa\xcc")
|
||||
// and "echo 者 | iconv -f UTF-8 -t BIG5 | xxd" gives "\xaa\xcc".
|
||||
c0, c1 := x/157, x%157
|
||||
if c1 < 0x3f {
|
||||
c1 += 0x40
|
||||
} else {
|
||||
c1 += 0x62
|
||||
}
|
||||
reverse[y] = (0x81+c0)<<8 | c1
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Fatalf("scanner error: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("// decode is the decoding table from Big5 code to Unicode.\n")
|
||||
fmt.Printf("// It is defined at http://encoding.spec.whatwg.org/index-big5.txt\n")
|
||||
fmt.Printf("var decode = [...]uint32{\n")
|
||||
for i, v := range mapping {
|
||||
if v != 0 {
|
||||
fmt.Printf("\t%d: 0x%08X,\n", i, v)
|
||||
}
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
|
||||
// Any run of at least separation continuous zero entries in the reverse map will
|
||||
// be a separate encode table.
|
||||
const separation = 1024
|
||||
|
||||
intervals := []interval(nil)
|
||||
low, high := -1, -1
|
||||
for i, v := range reverse {
|
||||
if v == 0 {
|
||||
continue
|
||||
}
|
||||
if low < 0 {
|
||||
low = i
|
||||
} else if i-high >= separation {
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
low = i
|
||||
}
|
||||
high = i + 1
|
||||
}
|
||||
if high >= 0 {
|
||||
intervals = append(intervals, interval{low, high})
|
||||
}
|
||||
sort.Sort(byDecreasingLength(intervals))
|
||||
|
||||
fmt.Printf("const numEncodeTables = %d\n\n", len(intervals))
|
||||
fmt.Printf("// encodeX are the encoding tables from Unicode to Big5 code,\n")
|
||||
fmt.Printf("// sorted by decreasing length.\n")
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("// encode%d: %5d entries for runes in [%6d, %6d).\n", i, v.len(), v.low, v.high)
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
||||
for i, v := range intervals {
|
||||
fmt.Printf("const encode%dLow, encode%dHigh = %d, %d\n\n", i, i, v.low, v.high)
|
||||
fmt.Printf("var encode%d = [...]uint16{\n", i)
|
||||
for j := v.low; j < v.high; j++ {
|
||||
x := reverse[j]
|
||||
if x == 0 {
|
||||
continue
|
||||
}
|
||||
fmt.Printf("\t%d-%d: 0x%04X,\n", j, v.low, x)
|
||||
}
|
||||
fmt.Printf("}\n\n")
|
||||
}
|
||||
}
|
||||
|
||||
// interval is a half-open interval [low, high).
|
||||
type interval struct {
|
||||
low, high int
|
||||
}
|
||||
|
||||
func (i interval) len() int { return i.high - i.low }
|
||||
|
||||
// byDecreasingLength sorts intervals by decreasing length.
|
||||
type byDecreasingLength []interval
|
||||
|
||||
func (b byDecreasingLength) Len() int { return len(b) }
|
||||
func (b byDecreasingLength) Less(i, j int) bool { return b[i].len() > b[j].len() }
|
||||
func (b byDecreasingLength) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
37142
vendor/golang.org/x/text/encoding/traditionalchinese/tables.go
generated
vendored
37142
vendor/golang.org/x/text/encoding/traditionalchinese/tables.go
generated
vendored
File diff suppressed because it is too large
Load diff
82
vendor/golang.org/x/text/encoding/unicode/override.go
generated
vendored
82
vendor/golang.org/x/text/encoding/unicode/override.go
generated
vendored
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package unicode
|
||||
|
||||
import (
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// BOMOverride returns a new decoder transformer that is identical to fallback,
|
||||
// except that the presence of a Byte Order Mark at the start of the input
|
||||
// causes it to switch to the corresponding Unicode decoding. It will only
|
||||
// consider BOMs for UTF-8, UTF-16BE, and UTF-16LE.
|
||||
//
|
||||
// This differs from using ExpectBOM by allowing a BOM to switch to UTF-8, not
|
||||
// just UTF-16 variants, and allowing falling back to any encoding scheme.
|
||||
//
|
||||
// This technique is recommended by the W3C for use in HTML 5: "For
|
||||
// compatibility with deployed content, the byte order mark (also known as BOM)
|
||||
// is considered more authoritative than anything else."
|
||||
// http://www.w3.org/TR/encoding/#specification-hooks
|
||||
//
|
||||
// Using BOMOverride is mostly intended for use cases where the first characters
|
||||
// of a fallback encoding are known to not be a BOM, for example, for valid HTML
|
||||
// and most encodings.
|
||||
func BOMOverride(fallback transform.Transformer) transform.Transformer {
|
||||
// TODO: possibly allow a variadic argument of unicode encodings to allow
|
||||
// specifying details of which fallbacks are supported as well as
|
||||
// specifying the details of the implementations. This would also allow for
|
||||
// support for UTF-32, which should not be supported by default.
|
||||
return &bomOverride{fallback: fallback}
|
||||
}
|
||||
|
||||
type bomOverride struct {
|
||||
fallback transform.Transformer
|
||||
current transform.Transformer
|
||||
}
|
||||
|
||||
func (d *bomOverride) Reset() {
|
||||
d.current = nil
|
||||
d.fallback.Reset()
|
||||
}
|
||||
|
||||
var (
|
||||
// TODO: we could use decode functions here, instead of allocating a new
|
||||
// decoder on every NewDecoder as IgnoreBOM decoders can be stateless.
|
||||
utf16le = UTF16(LittleEndian, IgnoreBOM)
|
||||
utf16be = UTF16(BigEndian, IgnoreBOM)
|
||||
)
|
||||
|
||||
const utf8BOM = "\ufeff"
|
||||
|
||||
func (d *bomOverride) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
|
||||
if d.current != nil {
|
||||
return d.current.Transform(dst, src, atEOF)
|
||||
}
|
||||
if len(src) < 3 && !atEOF {
|
||||
return 0, 0, transform.ErrShortSrc
|
||||
}
|
||||
d.current = d.fallback
|
||||
bomSize := 0
|
||||
if len(src) >= 2 {
|
||||
if src[0] == 0xFF && src[1] == 0xFE {
|
||||
d.current = utf16le.NewDecoder()
|
||||
bomSize = 2
|
||||
} else if src[0] == 0xFE && src[1] == 0xFF {
|
||||
d.current = utf16be.NewDecoder()
|
||||
bomSize = 2
|
||||
} else if len(src) >= 3 &&
|
||||
src[0] == utf8BOM[0] &&
|
||||
src[1] == utf8BOM[1] &&
|
||||
src[2] == utf8BOM[2] {
|
||||
d.current = transform.Nop
|
||||
bomSize = 3
|
||||
}
|
||||
}
|
||||
if bomSize < len(src) {
|
||||
nDst, nSrc, err = d.current.Transform(dst, src[bomSize:], atEOF)
|
||||
}
|
||||
return nDst, nSrc + bomSize, err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue