JSFiddle - React, Tailwind, and code Playground

by Jon-Carlos Rivera

HTML

<script>
/**
 * Parser for exponential Golomb codes, a variable-bitwidth number encoding
 * scheme used by h264.
 */
function ExpGolomb (workingData) {
  var
    // the number of bytes left to examine in workingData
    workingBytesAvailable = workingData.byteLength,

    // the current word being examined
    workingWord = 0, // :uint

    // the number of bits left to examine in the current word
    workingBitsAvailable = 0; // :uint;

  // ():uint
  this.length = function() {
    return (8 * workingBytesAvailable);
  };

  // ():uint
  this.bitsAvailable = function() {
    return (8 * workingBytesAvailable) + workingBitsAvailable;
  };

  // ():void
  this.loadWord = function() {
    var
      position = workingData.byteLength - workingBytesAvailable,
      workingBytes = new Uint8Array(4),
      availableBytes = Math.min(4, workingBytesAvailable);

    if (availableBytes === 0) {
      throw new Error('no bytes available');
    }

    workingBytes.set(workingData.subarray(position,
                                          position + availableBytes));
    workingWord = new DataView(workingBytes.buffer).getUint32(0);

    // track the amount of workingData that has been processed
    workingBitsAvailable = availableBytes * 8;
    workingBytesAvailable -= availableBytes;
  };

  // (count:int):void
  this.skipBits = function(count) {
    var skipBytes; // :int
    if (workingBitsAvailable > count) {
      workingWord          <<= count;
      workingBitsAvailable -= count;
    } else {
      count -= workingBitsAvailable;
      skipBytes = Math.floor(count / 8);

      count -= (skipBytes * 8);
      workingBytesAvailable -= skipBytes;

      this.loadWord();

      workingWord <<= count;
      workingBitsAvailable -= count;
    }
  };

  // (size:int):uint
  this.readBits = function(size) {
    var
      bits = Math.min(workingBitsAvailable, size), // :uint
      valu = workingWord >>> (32 - bits); // :uint
    // if size > 31, handle error
   ...

JavaScript

'use strict';
/**
 * General ExpGolomb Encoded Structure Parse Functions 
 */

let parse = function(parseFns) {
  return function (expGolombDecoder, output, index) {
    parseFns.forEach((fn) => {
      let response = fn(expGolombDecoder, output, index);
      expGolombDecoder = response[0];
      output = response[1];
    });

    return [expGolombDecoder, output];
  };
};

let read = function (name, format) {
  let nameMatch = (/([^\[]*)(\[.*\])?/).exec(name);
  let formatMatch = (/(.*)\((.*)\)/i).exec(format);
  let property;
  let nameArray;
  let type;
  let size;

  if (nameMatch && nameMatch.length > 1) {
    property = nameMatch[1];
    nameArray = nameMatch[2] !== undefined;
  } else {
    throw new Error('ExpGolomb Error: Invalid name "' + format + '".');
  }

  if (formatMatch && formatMatch.length > 2) {
    type = formatMatch[1];
    size = parseFloat(formatMatch[2]);
    if (isNaN(size)) {
      size = formatMatch[2];
    }
  } else {
    throw new Error('ExpGolomb Error: Unrecognized format "' + format + '".');
  }

  return function (expGolombDecoder, output, index) {
    let typeTable = {
      b: () => expGolombDecoder.readUnsignedByte(),
      f: (n) => expGolombDecoder.readBits(n),
      i: (n) => expGolombDecoder.readBits(n), // TODO: Fix
      se: () => expGolombDecoder.readExpGolomb(),
      u: (n) => expGolombDecoder.readBits(n),
      ue: () => expGolombDecoder.readUnsignedExpGolomb()
    };

    let value;

    if (typeof size === 'number') {
      value = typeTable[type](size);
    } else if (size === 'v') {
      value = typeTable[type]();
    }

    if (!nameArray) {
      output[property] = value;
    } else {
      if (!Array.isArray(output[property])) {
        output[property] = [];
      }

      if (index !== undefined) {
        output[property][index] = value;
      } else {
        output[property].push(value);
      }
    }

    return [expGolombDecoder, output];
  };
};

let on = function (conditionFn, parseFn) {
  return...