Class: Amp::Encoding::Base85

Inherits:
Object
  • Object
show all
Defined in:
lib/amp/encoding/base85.rb

Overview

This class provides methods for encoding and decoding to base85, a storage format used by Mercurial. Base85 is like base64, only with some extra characters to improve compression. This is a direct port of the python file base85.py in the Mercurial distribution.

Constant Summary collapse

B85chars =

The allowable Base 85 characters (encoding)

'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~'
B85dec =

The lookup table to go from character -> decimal (decoding)

{}

Class Method Summary collapse

Class Method Details

.decode(text) ⇒ String

Decodes a base85 encoded string and returns it. This code sort of mystifies me. Slash looking at it I’m not sure why we don’t just code it in C. Maybe we will eventually. Fucking python coders.

Parameters:

  • text (String)

    the base85 encoded string to decode

Returns:

  • (String)

    the decoded text



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/amp/encoding/base85.rb', line 65

def self.decode text
  l = text.size
  out = []
  i = 0
  while i < text.size
    chunk = text[i .. i+4]
    acc = 0
    chunk.size.times do |j|
      acc = acc * 85 + B85dec[chunk[j].chr]
    end
    out << acc
    i += 5
  end
  
  cl = l % 5
  if cl > 0
    acc *= 85 ** (5 - cl)
    if cl > 1
      acc += 0xffffff >> (cl - 2) * 8
    end
    out[-1] = acc
  end
  
  out = out.pack("N#{out.size}")
  if cl > 0
    out = out[0 .. (-1 * (5-cl) - 1)]
  end
  out
end

.encode(str, pad = false) ⇒ String

Encodes the given string in Base85, and possibly pad it. This code makes sense to me. Fuck I hate python.

Parameters:

  • str (String)

    the string to be encoded

  • pad (Boolean) (defaults to: false)

    whether or not to pad the resulting output

Returns:

  • (String)

    Base85 encoded string



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/amp/encoding/base85.rb', line 25

def self.encode str, pad=false
  l = str.size
  r = l % 4
  str += "\0" * (4-r)
  longs = str.size >> 2
  out = []
  words = str.unpack("N#{longs}")
  
  words.each do |word|
    word, r = word.divmod 85
    e = B85chars[r].chr
    word, r = word.divmod 85
    d = B85chars[r].chr
    word, r = word.divmod 85
    c = B85chars[r].chr
    word, r = word.divmod 85
    b = B85chars[r].chr
    word, r = word.divmod 85
    a = B85chars[r].chr
    
    out += [a,b,c,d,e]
  end
  
  out = out.join("")
  return out if pad
  
  olen = l % 4
  olen += 1 if olen > 0
  olen += l / 4 * 5
  
  out[0 .. olen-1]
end