vlq.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import type { StringReader, StringWriter } from './strings';
  2. export const comma = ','.charCodeAt(0);
  3. export const semicolon = ';'.charCodeAt(0);
  4. const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  5. const intToChar = new Uint8Array(64); // 64 possible chars.
  6. const charToInt = new Uint8Array(128); // z is 122 in ASCII
  7. for (let i = 0; i < chars.length; i++) {
  8. const c = chars.charCodeAt(i);
  9. intToChar[i] = c;
  10. charToInt[c] = i;
  11. }
  12. export function decodeInteger(reader: StringReader): number {
  13. let value = 0;
  14. let shift = 0;
  15. let integer = 0;
  16. do {
  17. const c = reader.next();
  18. integer = charToInt[c];
  19. value |= (integer & 31) << shift;
  20. shift += 5;
  21. } while (integer & 32);
  22. return value;
  23. }
  24. export function decodeSign(num: number): number {
  25. return num & 1 ? -0x80000000 | -(num >>> 1) : num >>> 1;
  26. }
  27. export function encodeInteger(builder: StringWriter, num: number) {
  28. do {
  29. let clamped = num & 0b011111;
  30. num >>>= 5;
  31. if (num > 0) clamped |= 0b100000;
  32. builder.write(intToChar[clamped]);
  33. } while (num > 0);
  34. }
  35. export function encodeSign(num: number): number {
  36. return num < 0 ? (-num << 1) | 1 : num << 1;
  37. }
  38. export function hasMoreVlq(reader: StringReader, max: number) {
  39. if (reader.pos >= max) return false;
  40. return reader.peek() !== comma;
  41. }