Permalink
Browse files

javascript version

  • Loading branch information...
1 parent 5228126 commit 7cc2927ba20ae972b141f71503fac938b2d645ba @WebReflection committed May 18, 2009
Showing with 279 additions and 0 deletions.
  1. +41 −0 build.php
  2. +7 −0 build/json.hpack.js
  3. +5 −0 build/json.hpack.min.js
  4. +9 −0 gzip.php
  5. +1 −0 src/javascript/json.hpack.js
  6. +1 −0 test/5000.txt
  7. +215 −0 test/index.html
  8. BIN yuicompressor-2.4.2.jar
View
41 build.php
@@ -0,0 +1,41 @@
+<?php
+$time = microtime(true);
+$cl = '
+/** version 1.0 2009-05-14
+ * @author Andrea Giammarchi
+ * @license Mit Style License
+ * @project http://code.google.com/p/hpack/
+ */
+';
+$name = 'json.hpack';
+$output = array(
+ 'json.hpack'
+);
+// -- simple build
+$file = 'build/'.$name.'.js';
+$filemin = str_replace('.js', '.min.js', $file);
+if(!function_exists('file_put_contents')){
+ function file_put_contents($file, $content){
+ $fp = fopen($file, 'wb');
+ fwrite($fp, $content);
+ fclose($fp);
+ }
+}
+$nl = "\n";
+foreach($output as $key => $value)
+ $output[$key] = file_get_contents('src/javascript/'.$value.'.js');
+$output = implode($nl, $output);
+$output = ($cl=trim($cl)).$nl.$nl.$output;
+if(file_exists($file))
+ unlink($file);
+if(file_exists($filemin))
+ unlink($filemin);
+file_put_contents($file, $output);
+exec('java -jar yuicompressor-2.4.2.jar --nomunge '.$file.' -o '.$filemin);
+$min = $cl.file_get_contents($filemin);
+file_put_contents($filemin, $min);
+ob_start('ob_gzhandler');
+header('Content-Type: text/javascript');
+header('X-Served-In: '.(microtime(true) - $time));
+exit($min);
+?>
View
7 build/json.hpack.js
@@ -0,0 +1,7 @@
+/** version 1.0 2009-05-14
+ * @author Andrea Giammarchi
+ * @license Mit Style License
+ * @project http://code.google.com/p/hpack/
+ */
+
+/** JSON homogeneous collection packer
View
5 build/json.hpack.min.js
@@ -0,0 +1,5 @@
+/** version 1.0 2009-05-14
+ * @author Andrea Giammarchi
+ * @license Mit Style License
+ * @project http://code.google.com/p/hpack/
+ */(function(cache){(this.JSON||(JSON={})).hpack=function(collection,compression){if(3<compression){var i=JSON.hbest(collection),result=cache[i];cache=[]}else{var indexOf=Array.prototype.indexOf||function(v){for(var l=this.length,i=0;i<l;++i){if(this[i]===v){return i}}return -1},header=[],result=[header],first=collection[0],index=0,k=0,len;for(var key in first){header[index++]=key}len=index;index=0;for(var length=collection.length,i=0;i<length;++i){for(var item=collection[i],row=[],j=0;j<len;++j){row[j]=item[header[j]]}result[++index]=row}++index;if(0<compression){for(row=result[1],j=0;j<len;++j){if(typeof row[j]!="number"){header.splice(j,1,first=[header[j],[]]);first=first[1];first.indexOf=indexOf;for(i=1;i<index;++i){var value=result[i][j],l=first.indexOf(value);result[i][j]=l<0?first.push(value)-1:l}}}}if(1<compression){length-=Math.floor(length/2);for(j=0;j<len;++j){if(header[j] instanceof Array){if(length<(first=header[j][1]).length){for(i=1;i<index;++i){var value=result[i][j];result[i][j]=first[value]}header[j]=header[j][0]}}}}if(2<compression){length=result.length;for(j=0;j<len;++j){if(header[j] instanceof Array){for(row=header[j][1],value=[],first=[],k=0,i=1;i<length;++i){value[k]=row[first[k]=result[i][j]];++k}if(JSON.stringify(value).length<JSON.stringify(first.concat(row)).length){for(k=0,i=1;i<length;++i){result[i][j]=value[k];++k}header[j]=header[j][0]}}}}if(0<compression){for(j=0;j<len;++j){if(header[j] instanceof Array){header.splice(j,1,header[j][0],header[j][1]);++len;++j}}}}return result};JSON.hunpack=function(collection){for(var result=[],keys=[],header=collection[0],len=header.length,length=collection.length,index=-1,k=-1,i=0,l=0,j,row;i<len;++i){keys[++k]=header[i];if(typeof header[i+1]=="object"){++i;for(j=1;j<length;++j){row=collection[j];row[l]=header[i][row[l]]}}++l}row="\\x"+'"'.charCodeAt(0).toString(16);for(i=0,len=keys.length;i<len;++i){keys[i]='o["'.concat(keys[i].replace('"',row),'"]=a[',i,"];")}var anonymous=Function("o,a",keys.join("")+"return o;");for(j=1;j<length;++j){result[++index]=anonymous({},collection[j])}return result};JSON.hclone=function(collection){for(var clone=[],i=0,length=collection.length;i<length;++i){clone[i]=collection[i].slice(0)}return clone};JSON.hbest=function(collection){for(var i=0,j=0,len=0,length=0;i<4;++i){cache[i]=JSON.hpack(collection,i);len=JSON.stringify(cache[i]).length;if(length===0){length=len}else{if(len<length){length=len;j=i}}}return j}})([]);
View
9 gzip.php
@@ -0,0 +1,9 @@
+<?php
+if(isset($_POST['data'])){
+ $time = microtime(true);
+ $length = gzencode($_POST['data'], 9, FORCE_GZIP);
+ $time = microtime(true) - $time;
+ header('X-Served-In: '.$time);
+ exit(''.strlen($length));
+}
+?>
View
1 src/javascript/json.hpack.js
@@ -0,0 +1 @@
+/** JSON homogeneous collection packer
View
1 test/5000.txt
1 addition, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
215 test/index.html
@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<!--
+/** JSON.hpack simple test suite
+ * @author Andrea Giammarchi
+ * @license Mit Style License
+ * @blog http://webreflection.blogspot.com/
+ * @project http://code.google.com/p/vice-versa/
+ * @version 0.20090421193521
+ */
+-->
+<html>
+ <head>
+ <title>JSON.hpack :: Homogeneous Collection Packer</title>
+ <style type="text/css">
+ html, body {
+ padding: 0;
+ margin: 0;
+ width: 100%;
+ height: 100%;
+ }
+ div {
+ font-family: "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Verdana, Tahoma, sans-serif;
+ font-weight: normal;
+ width: 49%;
+ height: 100%;
+ float: left;
+ padding: 0;
+ overflow: auto;
+ }
+ * {
+ font-size: 9pt;
+ }
+ textarea {
+ height: 90%;
+ }
+ button {
+ height: 10%;
+ }
+ textarea, button {
+ width: 100%;
+ float: left;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ }
+ pre {
+ border-top: 1px dotted silver;
+ padding-left: 2px;
+ overflow: auto;
+ }
+ </style>
+ <script type="text/javascript">if(!this.JSON)document.write('<'.concat('script type="text/javascript" src="http://www.json.org/json2.js"><', '/script', '>'));</script>
+ <script type="text/javascript">(function(p){document.write('<'.concat('script type="text/javascript" src="', -1 < location.href.indexOf("?build") ? "../build.php" : "../build/" + p + ".min.js", '"><', '/script', '>'))})
+ ("json.hpack");
+ </script>
+ <script type="text/javascript" src="http://vice-versa.googlecode.com/svn/trunk/build/vice-versa.min.js"></script>
+ <script type="text/javascript">
+ attachEvent("onload", function(){
+ function bench(callback, time){
+ for(var
+ result = {all:[]},
+ i = 0,
+ length = time || 12;
+ i < length; ++i
+ ){
+ time = new Date;
+ callback();
+ time = new Date - time;
+ result.all.push(time);
+ };
+ result.max = Math.max.apply(null, result.all);
+ result.min = Math.min.apply(null, result.all);
+ if(length < 3)
+ result.avg = ((result.max + result.min) / 2).toFixed(2);
+ else {
+ i = 0;
+ while(length)
+ i += result.all[--length];
+ i -= result.max + result.min;
+ i /= result.all.length - 2;
+ result.avg = i.toFixed(2);
+ };
+ return result;
+ };
+ function cursor(cursor) {
+ var i = 0,
+ length = cursor.length - 1;
+ return {
+ curr: function() { return cursor[i] },
+ next: function() { return cursor[i < length ? ++i : i = 0] },
+ prev: function() { return cursor[0 < i ? --i : i = length] }
+ }
+ };
+ function size(bytes){
+ var i = 0;
+ while(1024 < bytes){
+ bytes /= 1024;
+ ++i;
+ };
+ return bytes.toFixed(2) + " " + ["bytes", "Kb", "Mb", "Gb"][i];
+ };
+ function gzip(s){
+ var xhr = new XMLHttpRequest;
+ xhr.open("POST", "../gzip.php?" + Math.random(), false);
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ xhr.send("data=" + encodeURIComponent(s));
+ return /^[0-9]+$/.test(xhr.responseText) ? size(xhr.responseText >> 0) : "unknown: greater than max allowed post data";
+ };
+ function test(which){
+ switch(which++) {
+ case 0:
+ var b = bench(function(){original = JSON.stringify(a)}, 5);
+ panel.innerHTML += '<pre>' + original + '</pre>';
+ panel.innerHTML += '<pre>Array to JSON String : ' + b.avg + ' milliseconds</pre>';
+ setTimeout(function(){
+ b =
+ convertionTime = new Date - convertionTime;
+ panel.innerHTML += '<pre>JSON String to Array : ' + bench(function(){var o=Function("return " + original)()}, 5).avg + ' milliseconds</pre>';
+ setTimeout(function(){
+ panel.innerHTML += '<pre>JSON String length : ' + original.length + '</pre>';
+ panel.innerHTML += '<pre>JSON String gzip : ' + gzip(original) + '</pre>';
+ setTimeout(test, delay, which);
+ }, delay);
+ }, delay);
+ break;
+ default:
+ if(which === 2){
+ var convertionTime = new Date;
+ var comp = JSON.hbest(a);
+ convertionTime = new Date - convertionTime;
+ panel.innerHTML += '<h1>JSON.hpack best compression level is ' + comp + '</h1>';
+ panel.innerHTML += '<pre>' + convertionTime + ' ms to retrieve the best option (one time operation)</pre>';
+ } else if(which === 7)
+ return button.disabled = false;
+ var comp = which - 2;
+ panel.innerHTML += "<h1>JSON.hpack compression level " + (comp === 4 ? " 4 as \"best option\"" : comp) + " test</h1>";
+ var convertionTime = new Date;
+ var json = JSON.stringify(JSON.hpack(a, comp));
+ convertionTime = new Date - convertionTime;
+ panel.innerHTML += '<pre>' + json + '</pre>';
+ panel.innerHTML += '<pre>Array to JSON String via hpack: ' + convertionTime + ' milliseconds</pre>';
+ setTimeout(function(){
+ convertionTime = new Date;
+ var o = JSON.hunpack(JSON.hclone(Function("return " + json)()));
+ convertionTime = new Date - convertionTime;
+ panel.innerHTML += '<pre>JSON String via hpack to Array : ' + convertionTime + ' milliseconds</pre>';
+ setTimeout(function(){
+ panel.innerHTML += '<pre>JSON String via hpack length : ' + json.length + '</pre>';
+ panel.innerHTML += '<pre>JSON String via hpack gzip : ' + gzip(json) + '</pre>';
+ setTimeout(function(){
+ panel.innerHTML += '<pre>were hpack/hunpack reliable : ' + (JSON.stringify(o) === original) + '</pre>';
+ setTimeout(test, delay, which);
+ }, delay);
+ }, delay);
+ }, delay);
+ break;
+ };
+ };
+ var textarea= document.query("textarea")[0],
+ panel = document.query("div")[1],
+ button = document.query("button")[0],
+ delay = 250,
+ a, original
+ ;
+ panel.style.borderLeft = "1px solid silver";
+ button.disabled = false;
+ button.attachEvent("onclick", function(){
+ event.srcElement.disabled = true;
+ try {
+ a = event._value || Function("return " + textarea.value)();
+ if(a instanceof Array && a.every(function(v){return v instanceof Object})){
+ panel.innerHTML = "<h1>JSON test [homogeneous collection length: " + a.length + "]</h1>";
+ setTimeout(test, 100, 0);
+ } else
+ throw new Error("It does not seem an homogeneous collection");
+ } catch(e) {
+ panel.innerHTML = e.message;
+ button.disabled = false;
+ };
+ });
+ detachEvent("onload", arguments.callee);
+ big = function(){
+ var xhr = new XMLHttpRequest,
+ value = textarea.value,
+ anim = cursor(["-", "\\", "|", "/"]),
+ interval= setInterval(function(){
+ textarea.value = "[" + anim.next() + "] Retrieving 5000 homogeneous collection";
+ }, 100);
+ xhr.open("GET", "5000.txt", true);
+ xhr.onreadystatechange = function(){
+ if(xhr.readyState === 4){
+ clearInterval(interval);
+ textarea.style.display = "none";
+ textarea.value = xhr.responseText;
+ button.fireEvent("onclick");
+ textarea.value = value;
+ textarea.style.display = "";
+ }
+ };
+ xhr.send(null);
+ return false;
+ };
+ setInterval(function(){
+ document.body.style.height = document.documentElement.clientHeight + "px";
+ }, 5000);
+ });
+ </script>
+ </head>
+ <body>
+ <div><textarea></textarea><button>go</button></div>
+ <div>Write an homogeneous collection to start the test (as example)
+ <pre style="cursor:pointer;" onclick="document.query('textarea')[0].value=this.innerText;return false">[{name:"Andrea", age:31, gender:"Male", skilled:true}, {name:"Eva", age:27, gender:"Female", skilled:true}, {name:"Daniele", age:26, gender:"Male", skilled:false}]</pre>
+ or run <a href="#big" onclick="return window[this.href.split('#')[1]]();">5000 rows array</a> test</div>
+ </body>
+</html>
View
BIN yuicompressor-2.4.2.jar
Binary file not shown.

0 comments on commit 7cc2927

Please sign in to comment.