NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

punycode.py (5626B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\encodings\punycode.py
      2 import codecs
      3 
      4 def segregate(str):
      5     base = []
      6     extended = {}
      7     for c in str:
      8         if ord(c) < 128:
      9             base.append(c)
     10         else:
     11             extended[c] = 1
     12 
     13     extended = extended.keys()
     14     extended.sort()
     15     return (''.join(base).encode('ascii'), extended)
     16 
     17 
     18 def selective_len(str, max):
     19     res = 0
     20     for c in str:
     21         if ord(c) < max:
     22             res += 1
     23 
     24     return res
     25 
     26 
     27 def selective_find(str, char, index, pos):
     28     l = len(str)
     29     while 1:
     30         pos += 1
     31         if pos == l:
     32             return (-1, -1)
     33         c = str[pos]
     34         if c == char:
     35             return (index + 1, pos)
     36         if c < char:
     37             index += 1
     38 
     39 
     40 def insertion_unsort(str, extended):
     41     oldchar = 128
     42     result = []
     43     oldindex = -1
     44     for c in extended:
     45         index = pos = -1
     46         char = ord(c)
     47         curlen = selective_len(str, char)
     48         delta = (curlen + 1) * (char - oldchar)
     49         while 1:
     50             index, pos = selective_find(str, c, index, pos)
     51             if index == -1:
     52                 break
     53             delta += index - oldindex
     54             result.append(delta - 1)
     55             oldindex = index
     56             delta = 0
     57 
     58         oldchar = char
     59 
     60     return result
     61 
     62 
     63 def T(j, bias):
     64     res = 36 * (j + 1) - bias
     65     if res < 1:
     66         return 1
     67     if res > 26:
     68         return 26
     69     return res
     70 
     71 
     72 digits = 'abcdefghijklmnopqrstuvwxyz0123456789'
     73 
     74 def generate_generalized_integer(N, bias):
     75     result = []
     76     j = 0
     77     while 1:
     78         t = T(j, bias)
     79         if N < t:
     80             result.append(digits[N])
     81             return result
     82         result.append(digits[t + (N - t) % (36 - t)])
     83         N = (N - t) // (36 - t)
     84         j += 1
     85 
     86 
     87 def adapt(delta, first, numchars):
     88     if first:
     89         delta //= 700
     90     else:
     91         delta //= 2
     92     delta += delta // numchars
     93     divisions = 0
     94     while delta > 455:
     95         delta = delta // 35
     96         divisions += 36
     97 
     98     bias = divisions + 36 * delta // (delta + 38)
     99     return bias
    100 
    101 
    102 def generate_integers(baselen, deltas):
    103     result = []
    104     bias = 72
    105     for points, delta in enumerate(deltas):
    106         s = generate_generalized_integer(delta, bias)
    107         result.extend(s)
    108         bias = adapt(delta, points == 0, baselen + points + 1)
    109 
    110     return ''.join(result)
    111 
    112 
    113 def punycode_encode(text):
    114     base, extended = segregate(text)
    115     base = base.encode('ascii')
    116     deltas = insertion_unsort(text, extended)
    117     extended = generate_integers(len(base), deltas)
    118     if base:
    119         return base + '-' + extended
    120     return extended
    121 
    122 
    123 def decode_generalized_number(extended, extpos, bias, errors):
    124     result = 0
    125     w = 1
    126     j = 0
    127     while 1:
    128         try:
    129             char = ord(extended[extpos])
    130         except IndexError:
    131             if errors == 'strict':
    132                 raise UnicodeError, 'incomplete punicode string'
    133             return (extpos + 1, None)
    134 
    135         extpos += 1
    136         if 65 <= char <= 90:
    137             digit = char - 65
    138         elif 48 <= char <= 57:
    139             digit = char - 22
    140         elif errors == 'strict':
    141             raise UnicodeError("Invalid extended code point '%s'" % extended[extpos])
    142         else:
    143             return (extpos, None)
    144         t = T(j, bias)
    145         result += digit * w
    146         if digit < t:
    147             return (extpos, result)
    148         w = w * (36 - t)
    149         j += 1
    150 
    151 
    152 def insertion_sort(base, extended, errors):
    153     char = 128
    154     pos = -1
    155     bias = 72
    156     extpos = 0
    157     while extpos < len(extended):
    158         newpos, delta = decode_generalized_number(extended, extpos, bias, errors)
    159         if delta is None:
    160             return base
    161         pos += delta + 1
    162         char += pos // (len(base) + 1)
    163         if char > 1114111:
    164             if errors == 'strict':
    165                 raise UnicodeError, 'Invalid character U+%x' % char
    166             char = ord('?')
    167         pos = pos % (len(base) + 1)
    168         base = base[:pos] + unichr(char) + base[pos:]
    169         bias = adapt(delta, extpos == 0, len(base))
    170         extpos = newpos
    171 
    172     return base
    173 
    174 
    175 def punycode_decode(text, errors):
    176     pos = text.rfind('-')
    177     if pos == -1:
    178         base = ''
    179         extended = text
    180     else:
    181         base = text[:pos]
    182         extended = text[pos + 1:]
    183     base = unicode(base, 'ascii', errors)
    184     extended = extended.upper()
    185     return insertion_sort(base, extended, errors)
    186 
    187 
    188 class Codec(codecs.Codec):
    189 
    190     def encode(self, input, errors = 'strict'):
    191         res = punycode_encode(input)
    192         return (res, len(input))
    193 
    194     def decode(self, input, errors = 'strict'):
    195         if errors not in ('strict', 'replace', 'ignore'):
    196             raise UnicodeError, 'Unsupported error handling ' + errors
    197         res = punycode_decode(input, errors)
    198         return (res, len(input))
    199 
    200 
    201 class IncrementalEncoder(codecs.IncrementalEncoder):
    202 
    203     def encode(self, input, final = False):
    204         return punycode_encode(input)
    205 
    206 
    207 class IncrementalDecoder(codecs.IncrementalDecoder):
    208 
    209     def decode(self, input, final = False):
    210         if self.errors not in ('strict', 'replace', 'ignore'):
    211             raise UnicodeError, 'Unsupported error handling ' + self.errors
    212         return punycode_decode(input, self.errors)
    213 
    214 
    215 class StreamWriter(Codec, codecs.StreamWriter):
    216     pass
    217 
    218 
    219 class StreamReader(Codec, codecs.StreamReader):
    220     pass
    221 
    222 
    223 def getregentry():
    224     return codecs.CodecInfo(name='punycode', encode=Codec().encode, decode=Codec().decode, incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader)