github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/third_party/pypy/binascii.py (about)

     1  """A pure Python implementation of binascii.
     2  
     3  Rather slow and buggy in corner cases.
     4  PyPy provides an RPython version too.
     5  """
     6  
     7  class Error(Exception):
     8      pass
     9  
    10  class Done(Exception):
    11      pass
    12  
    13  class Incomplete(Exception):
    14      pass
    15  
    16  def a2b_uu(s):
    17      if not s:
    18          return ''
    19  
    20      length = (ord(s[0]) - 0x20) % 64
    21  
    22      def quadruplets_gen(s):
    23          while s:
    24              try:
    25                  yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3])
    26              except IndexError:
    27                  s += '   '
    28                  yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3])
    29                  return
    30              s = s[4:]
    31  
    32      try:
    33          result = [''.join(
    34              [chr((A - 0x20) << 2 | (((B - 0x20) >> 4) & 0x3)),
    35              chr(((B - 0x20) & 0xf) << 4 | (((C - 0x20) >> 2) & 0xf)),
    36              chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3f))
    37              ]) for A, B, C, D in quadruplets_gen(s[1:].rstrip())]
    38      except ValueError:
    39          raise Error('Illegal char')
    40      result = ''.join(result)
    41      trailingdata = result[length:]
    42      # if trailingdata.strip('\x00'):
    43      #     raise Error('Trailing garbage')
    44      result = result[:length]
    45      if len(result) < length:
    46          result += ((length - len(result)) * '\x00')
    47      return result
    48  
    49  
    50  def b2a_uu(s):
    51      length = len(s)
    52      if length > 45:
    53          raise Error('At most 45 bytes at once')
    54  
    55      def triples_gen(s):
    56          while s:
    57              try:
    58                  yield ord(s[0]), ord(s[1]), ord(s[2])
    59              except IndexError:
    60                  s += '\0\0'
    61                  yield ord(s[0]), ord(s[1]), ord(s[2])
    62                  return
    63              s = s[3:]
    64  
    65      result = [''.join(
    66          [chr(0x20 + (( A >> 2                    ) & 0x3F)),
    67           chr(0x20 + (((A << 4) | ((B >> 4) & 0xF)) & 0x3F)),
    68           chr(0x20 + (((B << 2) | ((C >> 6) & 0x3)) & 0x3F)),
    69           chr(0x20 + (( C                         ) & 0x3F))])
    70                for A, B, C in triples_gen(s)]
    71      return chr(ord(' ') + (length & 077)) + ''.join(result) + '\n'
    72  
    73  
    74  table_a2b_base64 = {
    75      'A': 0,
    76      'B': 1,
    77      'C': 2,
    78      'D': 3,
    79      'E': 4,
    80      'F': 5,
    81      'G': 6,
    82      'H': 7,
    83      'I': 8,
    84      'J': 9,
    85      'K': 10,
    86      'L': 11,
    87      'M': 12,
    88      'N': 13,
    89      'O': 14,
    90      'P': 15,
    91      'Q': 16,
    92      'R': 17,
    93      'S': 18,
    94      'T': 19,
    95      'U': 20,
    96      'V': 21,
    97      'W': 22,
    98      'X': 23,
    99      'Y': 24,
   100      'Z': 25,
   101      'a': 26,
   102      'b': 27,
   103      'c': 28,
   104      'd': 29,
   105      'e': 30,
   106      'f': 31,
   107      'g': 32,
   108      'h': 33,
   109      'i': 34,
   110      'j': 35,
   111      'k': 36,
   112      'l': 37,
   113      'm': 38,
   114      'n': 39,
   115      'o': 40,
   116      'p': 41,
   117      'q': 42,
   118      'r': 43,
   119      's': 44,
   120      't': 45,
   121      'u': 46,
   122      'v': 47,
   123      'w': 48,
   124      'x': 49,
   125      'y': 50,
   126      'z': 51,
   127      '0': 52,
   128      '1': 53,
   129      '2': 54,
   130      '3': 55,
   131      '4': 56,
   132      '5': 57,
   133      '6': 58,
   134      '7': 59,
   135      '8': 60,
   136      '9': 61,
   137      '+': 62,
   138      '/': 63,
   139      '=': 0,
   140  }
   141  
   142  
   143  def a2b_base64(s):
   144      if not isinstance(s, (str, unicode)):
   145          raise TypeError("expected string or unicode, got %r" % (s,))
   146      s = s.rstrip()
   147      # clean out all invalid characters, this also strips the final '=' padding
   148      # check for correct padding
   149  
   150      def next_valid_char(s, pos):
   151          for i in range(pos + 1, len(s)):
   152              c = s[i]
   153              if c < '\x7f':
   154                  try:
   155                      table_a2b_base64[c]
   156                      return c
   157                  except KeyError:
   158                      pass
   159          return None
   160  
   161      quad_pos = 0
   162      leftbits = 0
   163      leftchar = 0
   164      res = []
   165      for i, c in enumerate(s):
   166          if c > '\x7f' or c == '\n' or c == '\r' or c == ' ':
   167              continue
   168          if c == '=':
   169              if quad_pos < 2 or (quad_pos == 2 and next_valid_char(s, i) != '='):
   170                  continue
   171              else:
   172                  leftbits = 0
   173                  break
   174          try:
   175              next_c = table_a2b_base64[c]
   176          except KeyError:
   177              continue
   178          quad_pos = (quad_pos + 1) & 0x03
   179          leftchar = (leftchar << 6) | next_c
   180          leftbits += 6
   181          if leftbits >= 8:
   182              leftbits -= 8
   183              res.append((leftchar >> leftbits & 0xff))
   184              leftchar &= ((1 << leftbits) - 1)
   185      if leftbits != 0:
   186          raise Error('Incorrect padding')
   187  
   188      return ''.join([chr(i) for i in res])
   189  
   190  table_b2a_base64 = \
   191  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
   192  
   193  def b2a_base64(s):
   194      length = len(s)
   195      final_length = length % 3
   196  
   197      def triples_gen(s):
   198          while s:
   199              try:
   200                  yield ord(s[0]), ord(s[1]), ord(s[2])
   201              except IndexError:
   202                  s += '\0\0'
   203                  yield ord(s[0]), ord(s[1]), ord(s[2])
   204                  return
   205              s = s[3:]
   206  
   207  
   208      a = triples_gen(s[ :length - final_length])
   209  
   210      result = [''.join(
   211          [table_b2a_base64[( A >> 2                    ) & 0x3F],
   212           table_b2a_base64[((A << 4) | ((B >> 4) & 0xF)) & 0x3F],
   213           table_b2a_base64[((B << 2) | ((C >> 6) & 0x3)) & 0x3F],
   214           table_b2a_base64[( C                         ) & 0x3F]])
   215                for A, B, C in a]
   216  
   217      final = s[length - final_length:]
   218      if final_length == 0:
   219          snippet = ''
   220      elif final_length == 1:
   221          a = ord(final[0])
   222          snippet = table_b2a_base64[(a >> 2 ) & 0x3F] + \
   223                    table_b2a_base64[(a << 4 ) & 0x3F] + '=='
   224      else:
   225          a = ord(final[0])
   226          b = ord(final[1])
   227          snippet = table_b2a_base64[(a >> 2) & 0x3F] + \
   228                    table_b2a_base64[((a << 4) | (b >> 4) & 0xF) & 0x3F] + \
   229                    table_b2a_base64[(b << 2) & 0x3F] + '='
   230      return ''.join(result) + snippet + '\n'
   231  
   232  def a2b_qp(s, header=False):
   233      inp = 0
   234      odata = []
   235      while inp < len(s):
   236          if s[inp] == '=':
   237              inp += 1
   238              if inp >= len(s):
   239                  break
   240              # Soft line breaks
   241              if (s[inp] == '\n') or (s[inp] == '\r'):
   242                  if s[inp] != '\n':
   243                      while inp < len(s) and s[inp] != '\n':
   244                          inp += 1
   245                  if inp < len(s):
   246                      inp += 1
   247              elif s[inp] == '=':
   248                  # broken case from broken python qp
   249                  odata.append('=')
   250                  inp += 1
   251              elif s[inp] in hex_numbers and s[inp + 1] in hex_numbers:
   252                  ch = chr(int(s[inp:inp+2], 16))
   253                  inp += 2
   254                  odata.append(ch)
   255              else:
   256                  odata.append('=')
   257          elif header and s[inp] == '_':
   258              odata.append(' ')
   259              inp += 1
   260          else:
   261              odata.append(s[inp])
   262              inp += 1
   263      return ''.join(odata)
   264  
   265  def b2a_qp(data, quotetabs=False, istext=True, header=False):
   266      """quotetabs=True means that tab and space characters are always
   267         quoted.
   268         istext=False means that \r and \n are treated as regular characters
   269         header=True encodes space characters with '_' and requires
   270         real '_' characters to be quoted.
   271      """
   272      MAXLINESIZE = 76
   273  
   274      # See if this string is using CRLF line ends
   275      lf = data.find('\n')
   276      crlf = lf > 0 and data[lf-1] == '\r'
   277  
   278      inp = 0
   279      linelen = 0
   280      odata = []
   281      while inp < len(data):
   282          c = data[inp]
   283          if (c > '~' or
   284              c == '=' or
   285              (header and c == '_') or
   286              (c == '.' and linelen == 0 and (inp+1 == len(data) or
   287                                              data[inp+1] == '\n' or
   288                                              data[inp+1] == '\r')) or
   289              (not istext and (c == '\r' or c == '\n')) or
   290              ((c == '\t' or c == ' ') and (inp + 1 == len(data))) or
   291              (c <= ' ' and c != '\r' and c != '\n' and
   292               (quotetabs or (not quotetabs and (c != '\t' and c != ' '))))):
   293              linelen += 3
   294              if linelen >= MAXLINESIZE:
   295                  odata.append('=')
   296                  if crlf: odata.append('\r')
   297                  odata.append('\n')
   298                  linelen = 3
   299              odata.append('=' + two_hex_digits(ord(c)))
   300              inp += 1
   301          else:
   302              if (istext and
   303                  (c == '\n' or (inp+1 < len(data) and c == '\r' and
   304                                 data[inp+1] == '\n'))):
   305                  linelen = 0
   306                  # Protect against whitespace on end of line
   307                  if (len(odata) > 0 and
   308                      (odata[-1] == ' ' or odata[-1] == '\t')):
   309                      ch = ord(odata[-1])
   310                      odata[-1] = '='
   311                      odata.append(two_hex_digits(ch))
   312  
   313                  if crlf: odata.append('\r')
   314                  odata.append('\n')
   315                  if c == '\r':
   316                      inp += 2
   317                  else:
   318                      inp += 1
   319              else:
   320                  if (inp + 1 < len(data) and
   321                      data[inp+1] != '\n' and
   322                      (linelen + 1) >= MAXLINESIZE):
   323                      odata.append('=')
   324                      if crlf: odata.append('\r')
   325                      odata.append('\n')
   326                      linelen = 0
   327  
   328                  linelen += 1
   329                  if header and c == ' ':
   330                      c = '_'
   331                  odata.append(c)
   332                  inp += 1
   333      return ''.join(odata)
   334  
   335  hex_numbers = '0123456789ABCDEF'
   336  def hex(n):
   337      if n == 0:
   338          return '0'
   339  
   340      if n < 0:
   341          n = -n
   342          sign = '-'
   343      else:
   344          sign = ''
   345      arr = []
   346  
   347      def hex_gen(n):
   348          """ Yield a nibble at a time. """
   349          while n:
   350              yield n % 0x10
   351              n = n / 0x10
   352  
   353      for nibble in hex_gen(n):
   354          arr = [hex_numbers[nibble]] + arr
   355      return sign + ''.join(arr)
   356  
   357  def two_hex_digits(n):
   358      return hex_numbers[n / 0x10] + hex_numbers[n % 0x10]
   359  
   360  
   361  def strhex_to_int(s):
   362      i = 0
   363      for c in s:
   364          i = i * 0x10 + hex_numbers.index(c)
   365      return i
   366  
   367  hqx_encoding = '!"#$%&\'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr'
   368  
   369  DONE = 0x7f
   370  SKIP = 0x7e
   371  FAIL = 0x7d
   372  
   373  table_a2b_hqx = [
   374      #^@    ^A    ^B    ^C    ^D    ^E    ^F    ^G
   375      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   376      #\b    \t    \n    ^K    ^L    \r    ^N    ^O
   377      FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
   378      #^P    ^Q    ^R    ^S    ^T    ^U    ^V    ^W
   379      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   380      #^X    ^Y    ^Z    ^[    ^\    ^]    ^^    ^_
   381      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   382      #      !     "     #     $     %     &     '
   383      FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
   384      #(     )     *     +     ,     -     .     /
   385      0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
   386      #0     1     2     3     4     5     6     7
   387      0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
   388      #8     9     :     ;     <     =     >     ?
   389      0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
   390      #@     A     B     C     D     E     F     G
   391      0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
   392      #H     I     J     K     L     M     N     O
   393      0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
   394      #P     Q     R     S     T     U     V     W
   395      0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
   396      #X     Y     Z     [     \     ]     ^     _
   397      0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
   398      #`     a     b     c     d     e     f     g
   399      0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
   400      #h     i     j     k     l     m     n     o
   401      0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
   402      #p     q     r     s     t     u     v     w
   403      0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
   404      #x     y     z     {     |     }     ~    ^?
   405      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   406      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   407      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   408      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   409      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   410      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   411      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   412      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   413      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   414      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   415      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   416      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   417      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   418      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   419      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   420      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   421      FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
   422  ]
   423  
   424  def a2b_hqx(s):
   425      result = []
   426  
   427      def quadruples_gen(s):
   428          t = []
   429          for c in s:
   430              res = table_a2b_hqx[ord(c)]
   431              if res == SKIP:
   432                  continue
   433              elif res == FAIL:
   434                  raise Error('Illegal character')
   435              elif res == DONE:
   436                  yield t
   437                  raise Done
   438              else:
   439                  t.append(res)
   440              if len(t) == 4:
   441                  yield t
   442                  t = []
   443          yield t
   444  
   445      done = 0
   446      try:
   447          for snippet in quadruples_gen(s):
   448              length = len(snippet)
   449              if length == 4:
   450                  result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4)))
   451                  result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2)))
   452                  result.append(chr(((snippet[2] & 0x03) << 6) | (snippet[3])))
   453              elif length == 3:
   454                  result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4)))
   455                  result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2)))
   456              elif length == 2:
   457                  result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4)))
   458      except Done:
   459          done = 1
   460      except Error:
   461          raise
   462      return (''.join(result), done)
   463  
   464  def b2a_hqx(s):
   465      result =[]
   466  
   467      def triples_gen(s):
   468          while s:
   469              try:
   470                  yield ord(s[0]), ord(s[1]), ord(s[2])
   471              except IndexError:
   472                  yield tuple([ord(c) for c in s])
   473              s = s[3:]
   474  
   475      for snippet in triples_gen(s):
   476          length = len(snippet)
   477          if length == 3:
   478              result.append(
   479                  hqx_encoding[(snippet[0] & 0xfc) >> 2])
   480              result.append(hqx_encoding[
   481                  ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)])
   482              result.append(hqx_encoding[
   483                  (snippet[1] & 0x0f) << 2 | ((snippet[2] & 0xc0) >> 6)])
   484              result.append(hqx_encoding[snippet[2] & 0x3f])
   485          elif length == 2:
   486              result.append(
   487                  hqx_encoding[(snippet[0] & 0xfc) >> 2])
   488              result.append(hqx_encoding[
   489                  ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)])
   490              result.append(hqx_encoding[
   491                  (snippet[1] & 0x0f) << 2])
   492          elif length == 1:
   493              result.append(
   494                  hqx_encoding[(snippet[0] & 0xfc) >> 2])
   495              result.append(hqx_encoding[
   496                  ((snippet[0] & 0x03) << 4)])
   497      return ''.join(result)
   498  
   499  crctab_hqx = [
   500          0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
   501          0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
   502          0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
   503          0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
   504          0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
   505          0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
   506          0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
   507          0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
   508          0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
   509          0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
   510          0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
   511          0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
   512          0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
   513          0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
   514          0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
   515          0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
   516          0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
   517          0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
   518          0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
   519          0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
   520          0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
   521          0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
   522          0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
   523          0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
   524          0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
   525          0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
   526          0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
   527          0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
   528          0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
   529          0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
   530          0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
   531          0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
   532  ]
   533  
   534  def crc_hqx(s, crc):
   535      for c in s:
   536          crc = ((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ ord(c)]
   537  
   538      return crc
   539  
   540  def rlecode_hqx(s):
   541      """
   542      Run length encoding for binhex4.
   543      The CPython implementation does not do run length encoding
   544      of \x90 characters. This implementation does.
   545      """
   546      if not s:
   547          return ''
   548      result = []
   549      prev = s[0]
   550      count = 1
   551      # Add a dummy character to get the loop to go one extra round.
   552      # The dummy must be different from the last character of s.
   553      # In the same step we remove the first character, which has
   554      # already been stored in prev.
   555      if s[-1] == '!':
   556          s = s[1:] + '?'
   557      else:
   558          s = s[1:] + '!'
   559  
   560      for c in s:
   561          if c == prev and count < 255:
   562              count += 1
   563          else:
   564              if count == 1:
   565                  if prev != '\x90':
   566                      result.append(prev)
   567                  else:
   568                      result += ['\x90', '\x00']
   569              elif count < 4:
   570                  if prev != '\x90':
   571                      result += [prev] * count
   572                  else:
   573                      result += ['\x90', '\x00'] * count
   574              else:
   575                  if prev != '\x90':
   576                      result += [prev, '\x90', chr(count)]
   577                  else:
   578                      result += ['\x90', '\x00', '\x90', chr(count)]
   579              count = 1
   580              prev = c
   581  
   582      return ''.join(result)
   583  
   584  def rledecode_hqx(s):
   585      s = s.split('\x90')
   586      result = [s[0]]
   587      prev = s[0]
   588      for snippet in s[1:]:
   589          count = ord(snippet[0])
   590          if count > 0:
   591              result.append(prev[-1] * (count-1))
   592              prev = snippet
   593          else:
   594              result. append('\x90')
   595              prev = '\x90'
   596          result.append(snippet[1:])
   597  
   598      return ''.join(result)
   599  
   600  crc_32_tab = [
   601      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
   602      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
   603      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
   604      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
   605      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
   606      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
   607      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
   608      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
   609      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
   610      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
   611      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
   612      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
   613      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
   614      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
   615      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
   616      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
   617      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
   618      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
   619      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
   620      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
   621      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
   622      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
   623      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
   624      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
   625      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
   626      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
   627      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
   628      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
   629      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
   630      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
   631      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
   632      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
   633      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
   634      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
   635      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
   636      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
   637      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
   638      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
   639      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
   640      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
   641      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
   642      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
   643      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
   644      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
   645      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
   646      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
   647      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
   648      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
   649      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
   650      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
   651      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
   652      0x2d02ef8dL
   653  ]
   654  
   655  def crc32(s, crc=0):
   656      result = 0
   657      crc = ~long(crc) & 0xffffffffL
   658      for c in s:
   659          crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8)
   660          #/* Note:  (crc >> 8) MUST zero fill on left
   661  
   662      result = crc ^ 0xffffffffL
   663  
   664      if result > (1 << 31):
   665          result = ((result + (1<<31)) % (1<<32)) - (1<<31)
   666  
   667      return result
   668  
   669  def b2a_hex(s):
   670      result = []
   671      for char in s:
   672          c = (ord(char) >> 4) & 0xf
   673          if c > 9:
   674              c = c + ord('a') - 10
   675          else:
   676              c = c + ord('0')
   677          result.append(chr(c))
   678          c = ord(char) & 0xf
   679          if c > 9:
   680              c = c + ord('a') - 10
   681          else:
   682              c = c + ord('0')
   683          result.append(chr(c))
   684      return ''.join(result)
   685  
   686  hexlify = b2a_hex
   687  
   688  table_hex = [
   689      -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   690      -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   691      -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   692      0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
   693      -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   694      -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   695      -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
   696      -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
   697  ]
   698  
   699  
   700  def a2b_hex(t):
   701      result = []
   702  
   703      def pairs_gen(s):
   704          while s:
   705              try:
   706                  yield table_hex[ord(s[0])], table_hex[ord(s[1])]
   707              except IndexError:
   708                  if len(s):
   709                      raise TypeError('Odd-length string')
   710                  return
   711              s = s[2:]
   712  
   713      for a, b in pairs_gen(t):
   714          if a < 0 or b < 0:
   715              raise TypeError('Non-hexadecimal digit found')
   716          result.append(chr((a << 4) + b))
   717      return ''.join(result)
   718  
   719  
   720  unhexlify = a2b_hex