JavaScript RunLength Compress/Decompress

JavaScript RunLength Compress/Decompress

by polygonplanet

HTML

<div>input:</div>
<div>
  <textarea id="input">にゃーーーーーーーーーーーーーーーーーーーーーーーーん!!!!!!!!!!!!!!!!!!!!</textarea>
</div>
<div id="input-status"></div>
<div>
  <button type="button" id="compress">↓Compress↓</button>
  <button type="button" id="decompress">↑Decompress↑</button>
  <button type="button" id="clear">Clear</button>
</div>
<div>output:</div>
<div>
  <textarea id="output"></textarea>
</div>
<div id="output-status"></div>

CSS

textarea {
  width: 99%;
  height: 200px;
}

JavaScript

// ランレングス圧縮/解凍
var RunLength = {
  compress : function(s) {
    return s.replace(/([\s\S])\1{0,8}/g, function(a, c) {
      return c + a.length;
    });
  },
  decompress : function(s) {
    return s.replace(/([\s\S])(\d)/g, function(a, c, n) {
      return new Array(++n).join(c);
    });
  }
};


$('#compress').click(function() {
  doCompress();
});

$('#decompress').click(function() {
  doDecompress();
});

$('#clear').click(function() {
  $('#input').val('');
  updateStatus();
});

$('#input,#output').bind('input', function() {
  updateStatus();
});


var getByteSize = function() {
  var s, i, len,
      toCharCode = function() {
        var c1 = s.charCodeAt(i), c2, j;
        if (0xD800 <= c1 && c1 <= 0xD8FF) {
          j = i + 1;
          if (j < len) {
            c2 = s.charCodeAt(j);
            if (0xDC00 <= c2 && c2 <= 0xDFFF) {
              c1 = ((c1 & 0x3FF) << 10) + (c2 & 0x3FF) + 0x10000;
              i = j;
            } else {
              return false;
            }
          } else {
            return false;
          }
        }
        return c1;
      };
  return function(string) {
    var size = 0, c;
    s = String(string);
    if (s) {
      len = s.length;
      for (i = 0; i < len; i++) {
        c = toCharCode();
        if (c !== false) {
          if (c < 0x80) {
            size += 1;
          } else if (c < 0x800) {
            size += 2;
          } else if (c < 0x10000) {
            size += 3;
          } else if (c < 0x200000) {
            size += 4;
          } else if (c < 0x4000000) {
            size += 5;
          } else {
            size += 6;
          }
        }
      }
    }
    s = i = len = null;
    return size;
  };
}();


function updateStatus() {
  var inputStatus = $('#input-status'),
      outputStatus = $('#output-status'),
      input = $('#input'),
      output = $('#output');

  var ratio = (
    getByteSize(output.val()) / getByteSize(input.val()) * 100
  ).toFixed(2);

  inputStatus.text(
   ...