...

Source file src/pkg/vendor/golang.org/x/net/idna/punycode.go

     1	// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
     2	
     3	// Copyright 2016 The Go Authors. All rights reserved.
     4	// Use of this source code is governed by a BSD-style
     5	// license that can be found in the LICENSE file.
     6	
     7	package idna
     8	
     9	// This file implements the Punycode algorithm from RFC 3492.
    10	
    11	import (
    12		"math"
    13		"strings"
    14		"unicode/utf8"
    15	)
    16	
    17	// These parameter values are specified in section 5.
    18	//
    19	// All computation is done with int32s, so that overflow behavior is identical
    20	// regardless of whether int is 32-bit or 64-bit.
    21	const (
    22		base        int32 = 36
    23		damp        int32 = 700
    24		initialBias int32 = 72
    25		initialN    int32 = 128
    26		skew        int32 = 38
    27		tmax        int32 = 26
    28		tmin        int32 = 1
    29	)
    30	
    31	func punyError(s string) error { return &labelError{s, "A3"} }
    32	
    33	// decode decodes a string as specified in section 6.2.
    34	func decode(encoded string) (string, error) {
    35		if encoded == "" {
    36			return "", nil
    37		}
    38		pos := 1 + strings.LastIndex(encoded, "-")
    39		if pos == 1 {
    40			return "", punyError(encoded)
    41		}
    42		if pos == len(encoded) {
    43			return encoded[:len(encoded)-1], nil
    44		}
    45		output := make([]rune, 0, len(encoded))
    46		if pos != 0 {
    47			for _, r := range encoded[:pos-1] {
    48				output = append(output, r)
    49			}
    50		}
    51		i, n, bias := int32(0), initialN, initialBias
    52		for pos < len(encoded) {
    53			oldI, w := i, int32(1)
    54			for k := base; ; k += base {
    55				if pos == len(encoded) {
    56					return "", punyError(encoded)
    57				}
    58				digit, ok := decodeDigit(encoded[pos])
    59				if !ok {
    60					return "", punyError(encoded)
    61				}
    62				pos++
    63				i += digit * w
    64				if i < 0 {
    65					return "", punyError(encoded)
    66				}
    67				t := k - bias
    68				if t < tmin {
    69					t = tmin
    70				} else if t > tmax {
    71					t = tmax
    72				}
    73				if digit < t {
    74					break
    75				}
    76				w *= base - t
    77				if w >= math.MaxInt32/base {
    78					return "", punyError(encoded)
    79				}
    80			}
    81			x := int32(len(output) + 1)
    82			bias = adapt(i-oldI, x, oldI == 0)
    83			n += i / x
    84			i %= x
    85			if n > utf8.MaxRune || len(output) >= 1024 {
    86				return "", punyError(encoded)
    87			}
    88			output = append(output, 0)
    89			copy(output[i+1:], output[i:])
    90			output[i] = n
    91			i++
    92		}
    93		return string(output), nil
    94	}
    95	
    96	// encode encodes a string as specified in section 6.3 and prepends prefix to
    97	// the result.
    98	//
    99	// The "while h < length(input)" line in the specification becomes "for
   100	// remaining != 0" in the Go code, because len(s) in Go is in bytes, not runes.
   101	func encode(prefix, s string) (string, error) {
   102		output := make([]byte, len(prefix), len(prefix)+1+2*len(s))
   103		copy(output, prefix)
   104		delta, n, bias := int32(0), initialN, initialBias
   105		b, remaining := int32(0), int32(0)
   106		for _, r := range s {
   107			if r < 0x80 {
   108				b++
   109				output = append(output, byte(r))
   110			} else {
   111				remaining++
   112			}
   113		}
   114		h := b
   115		if b > 0 {
   116			output = append(output, '-')
   117		}
   118		for remaining != 0 {
   119			m := int32(0x7fffffff)
   120			for _, r := range s {
   121				if m > r && r >= n {
   122					m = r
   123				}
   124			}
   125			delta += (m - n) * (h + 1)
   126			if delta < 0 {
   127				return "", punyError(s)
   128			}
   129			n = m
   130			for _, r := range s {
   131				if r < n {
   132					delta++
   133					if delta < 0 {
   134						return "", punyError(s)
   135					}
   136					continue
   137				}
   138				if r > n {
   139					continue
   140				}
   141				q := delta
   142				for k := base; ; k += base {
   143					t := k - bias
   144					if t < tmin {
   145						t = tmin
   146					} else if t > tmax {
   147						t = tmax
   148					}
   149					if q < t {
   150						break
   151					}
   152					output = append(output, encodeDigit(t+(q-t)%(base-t)))
   153					q = (q - t) / (base - t)
   154				}
   155				output = append(output, encodeDigit(q))
   156				bias = adapt(delta, h+1, h == b)
   157				delta = 0
   158				h++
   159				remaining--
   160			}
   161			delta++
   162			n++
   163		}
   164		return string(output), nil
   165	}
   166	
   167	func decodeDigit(x byte) (digit int32, ok bool) {
   168		switch {
   169		case '0' <= x && x <= '9':
   170			return int32(x - ('0' - 26)), true
   171		case 'A' <= x && x <= 'Z':
   172			return int32(x - 'A'), true
   173		case 'a' <= x && x <= 'z':
   174			return int32(x - 'a'), true
   175		}
   176		return 0, false
   177	}
   178	
   179	func encodeDigit(digit int32) byte {
   180		switch {
   181		case 0 <= digit && digit < 26:
   182			return byte(digit + 'a')
   183		case 26 <= digit && digit < 36:
   184			return byte(digit + ('0' - 26))
   185		}
   186		panic("idna: internal error in punycode encoding")
   187	}
   188	
   189	// adapt is the bias adaptation function specified in section 6.1.
   190	func adapt(delta, numPoints int32, firstTime bool) int32 {
   191		if firstTime {
   192			delta /= damp
   193		} else {
   194			delta /= 2
   195		}
   196		delta += delta / numPoints
   197		k := int32(0)
   198		for delta > ((base-tmin)*tmax)/2 {
   199			delta /= base - tmin
   200			k += base
   201		}
   202		return k + (base-tmin+1)*delta/(delta+skew)
   203	}
   204	

View as plain text