stdlib/source_map/vlq.rb in opal-0.6.3 vs stdlib/source_map/vlq.rb in opal-0.7.0.beta1
- old
+ new
@@ -1,122 +1,98 @@
-class SourceMap
- # Support for encoding/decoding the variable length quantity format
- # described in the spec at:
+module SourceMap
+ # Public: Base64 VLQ encoding
#
- # https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
+ # Adopted from ConradIrwin/ruby-source_map
+ # https://github.com/ConradIrwin/ruby-source_map/blob/master/lib/source_map/vlq.rb
#
- # This implementation is heavily based on https://github.com/mozilla/source-map
- # Copyright 2009-2011, Mozilla Foundation and contributors, BSD
+ # Resources
#
+ # http://en.wikipedia.org/wiki/Variable-length_quantity
+ # https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
+ # https://github.com/mozilla/source-map/blob/master/lib/source-map/base64-vlq.js
+ #
module VLQ
+ VLQ_BASE_SHIFT = 5
+ VLQ_BASE = 1 << VLQ_BASE_SHIFT
+ VLQ_BASE_MASK = VLQ_BASE - 1
+ VLQ_CONTINUATION_BIT = VLQ_BASE
- # A single base 64 digit can contain 6 bits of data. For the base 64 variable
- # length quantities we use in the source map spec, the first bit is the sign,
- # the next four bits are the actual value, and the 6th bit is the
- # continuation bit. The continuation bit tells us whether there are more
- # digits in this value following this digit.
- #
- # Continuation
- # | Sign
- # | |
- # V V
- # 101011
-
- VLQ_BASE_SHIFT = 5;
-
- # binary: 100000
- VLQ_BASE = 1 << VLQ_BASE_SHIFT;
-
- # binary: 011111
- VLQ_BASE_MASK = VLQ_BASE - 1;
-
- # binary: 100000
- VLQ_CONTINUATION_BIT = VLQ_BASE;
-
BASE64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('')
- BASE64_VALUES = (0..64).inject({}){ |h, i| h.update BASE64_DIGITS[i] => i }
+ BASE64_VALUES = (0...64).inject({}) { |h, i| h[BASE64_DIGITS[i]] = i; h }
- # Returns the base 64 VLQ encoded value.
- def self.encode(int)
-
- vlq = to_vlq_signed(int)
- encoded = []
-
- begin
- digit = vlq & VLQ_BASE_MASK
- vlq >>= VLQ_BASE_SHIFT
- digit |= VLQ_CONTINUATION_BIT if vlq > 0
- encoded << base64_encode(digit)
- end while vlq > 0
-
- encoded.join
+ # Public: Encode a list of numbers into a compact VLQ string.
+ #
+ # ary - An Array of Integers
+ #
+ # Returns a VLQ String.
+ def self.encode(ary)
+ result = []
+ ary.each do |n|
+ vlq = n < 0 ? ((-n) << 1) + 1 : n << 1
+ begin
+ digit = vlq & VLQ_BASE_MASK
+ vlq >>= VLQ_BASE_SHIFT
+ digit |= VLQ_CONTINUATION_BIT if vlq > 0
+ result << BASE64_DIGITS[digit]
+ end while vlq > 0
+ end
+ result.join
end
- # Decodes the next base 64 VLQ value from the given string and returns the
- # value and the rest of the string.
+ # Public: Decode a VLQ string.
+ #
+ # str - VLQ encoded String
+ #
+ # Returns an Array of Integers.
def self.decode(str)
-
- vlq = 0
- shift = 0
- continue = true
+ result = []
chars = str.split('')
-
- while continue
- char = chars.shift or raise "Expected more digits in base 64 VLQ value."
- digit = base64_decode(char)
- continue = false if (digit & VLQ_CONTINUATION_BIT) == 0
- digit &= VLQ_BASE_MASK
- vlq += digit << shift
- shift += VLQ_BASE_SHIFT
+ while chars.any?
+ vlq = 0
+ shift = 0
+ continuation = true
+ while continuation
+ char = chars.shift
+ raise ArgumentError unless char
+ digit = BASE64_VALUES[char]
+ continuation = false if (digit & VLQ_CONTINUATION_BIT) == 0
+ digit &= VLQ_BASE_MASK
+ vlq += digit << shift
+ shift += VLQ_BASE_SHIFT
+ end
+ result << (vlq & 1 == 1 ? -(vlq >> 1) : vlq >> 1)
end
-
- [from_vlq_signed(vlq), chars.join('')]
+ result
end
- # Decode an array of variable length quantities from the given string and
- # return them.
- def self.decode_array(str)
- output = []
- while str != ''
- int, str = decode(str)
- output << int
- end
- output
+ # Public: Encode a mapping array into a compact VLQ string.
+ #
+ # ary - Two dimensional Array of Integers.
+ #
+ # Returns a VLQ encoded String seperated by , and ;.
+ def self.encode_mappings(ary)
+ ary.map { |group|
+ group.map { |segment|
+ encode(segment)
+ }.join(',')
+ }.join(';')
end
- protected
+ # Public: Decode a VLQ string into mapping numbers.
+ #
+ # str - VLQ encoded String
+ #
+ # Returns an two dimensional Array of Integers.
+ def self.decode_mappings(str)
+ mappings = []
- def self.base64_encode(int)
- BASE64_DIGITS[int] or raise ArgumentError, "#{int} is not a valid base64 digit"
- end
-
- def self.base64_decode(char)
- BASE64_VALUES[char] or raise ArgumentError, "#{char} is not a valid base64 digit"
- end
-
- # Converts from a two's-complement integer to an integer where the
- # sign bit is placed in the least significant bit. For example, as decimals:
- # 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
- # 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
- def self.to_vlq_signed(int)
- if int < 0
- ((-int) << 1) + 1
- else
- int << 1
+ str.split(';').each_with_index do |group, index|
+ mappings[index] = []
+ group.split(',').each do |segment|
+ mappings[index] << decode(segment)
+ end
end
- end
- # Converts to a two's-complement value from a value where the sign bit is
- # placed in the least significant bit. For example, as decimals:
- #
- # 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
- # 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
- def self.from_vlq_signed(vlq)
- if vlq & 1 == 1
- -(vlq >> 1)
- else
- vlq >> 1
- end
+ mappings
end
-
end
end