vlq.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. var toArr = require('./toArr');
  2. exports = {
  3. encode: function(arr) {
  4. arr = toArr(arr);
  5. var ret = '';
  6. for (var i = 0, len = arr.length; i < len; i++) {
  7. ret += encode(arr[i]);
  8. }
  9. return ret;
  10. },
  11. decode: function(str) {
  12. var ret = [];
  13. var i = 0;
  14. var len = str.length;
  15. while (i < len) {
  16. var value = 0;
  17. var continuation = false;
  18. var shift = 0;
  19. do {
  20. var digit = charToInt[str[i++]];
  21. continuation = (digit & VLQ_CONTINUATION_BIT) !== 0;
  22. digit &= VLQ_BASE_MASK;
  23. value = value + (digit << shift);
  24. shift = shift + VLQ_BASE_SHIFT;
  25. } while (continuation);
  26. ret.push(fromVLQSigned(value));
  27. }
  28. return ret;
  29. }
  30. };
  31. var charToInt = {};
  32. var intToChar = {};
  33. var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  34. for (var i = 0, len = chars.length; i < len; i++) {
  35. charToInt[chars[i]] = i;
  36. intToChar[i] = chars[i];
  37. }
  38. var VLQ_BASE_SHIFT = 5;
  39. var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
  40. var VLQ_BASE_MASK = VLQ_BASE - 1;
  41. var VLQ_CONTINUATION_BIT = VLQ_BASE;
  42. function encode(value) {
  43. var ret = '';
  44. value = toVLQSigned(value);
  45. do {
  46. var digit = value & VLQ_BASE_MASK;
  47. value >>>= VLQ_BASE_SHIFT;
  48. if (value > 0) {
  49. digit |= VLQ_CONTINUATION_BIT;
  50. }
  51. ret += intToChar[digit];
  52. } while (value > 0);
  53. return ret;
  54. }
  55. function toVLQSigned(value) {
  56. if (value < 0) {
  57. return (-value << 1) + 1;
  58. } else {
  59. return (value << 1) + 0;
  60. }
  61. }
  62. function fromVLQSigned(value) {
  63. var negate = (value & 1) === 1;
  64. value = value >> 1;
  65. return negate ? -value : value;
  66. }
  67. module.exports = exports;