├── package.json ├── bower.json ├── rb └── jsonh.rb ├── py2 └── jsonh.py ├── README.md ├── php5 └── JSONH.class.php └── js ├── jsonh.js └── test └── jsonh.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsonh", 3 | "version": "0.0.6", 4 | "main": "./js/jsonh.js", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/WebReflection/JSONH.git" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JSONH", 3 | "version": "0.0.4", 4 | "homepage": "https://github.com/WebReflection/JSONH", 5 | "authors": [ 6 | "Andrea Giammarchi", 7 | "@WebReflection" 8 | ], 9 | "description": "JSON Homogeneous Collections Compressor", 10 | "main": "./js/jsonh.js", 11 | "keywords": [ 12 | "json", 13 | "jsonh", 14 | "compressing" 15 | ], 16 | "license": "MIT", 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /rb/jsonh.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | Copyright (C) 2011 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | =end 22 | 23 | require 'json' 24 | 25 | module JSONH 26 | module_function 27 | 28 | def dump(obj) 29 | pack(obj).to_json 30 | end 31 | 32 | def load(str) 33 | unpack(JSON.load(str)) 34 | end 35 | 36 | def pack(hlist) 37 | return [] if hlist.empty? 38 | keys = hlist.first.keys 39 | [keys.size, *keys, *hlist.map(&:values).flatten(1)] 40 | end 41 | 42 | def unpack(hlist) 43 | ksize = Integer(hlist[0]) 44 | keys = hlist[1, ksize] 45 | values = hlist[ksize+1..-1] 46 | values.each_slice(ksize).map do |values| 47 | Hash[keys.zip(values)] 48 | end 49 | end 50 | end 51 | 52 | if $0 == __FILE__ 53 | require 'bacon' 54 | Bacon.summary_on_exit 55 | 56 | describe JSONH do 57 | collection = [ 58 | {'a' => 'A', 'b' => 'B'}, 59 | {'a' => 'C', 'b' => 'D'}, 60 | {'a' => 'E', 'b' => 'F'} 61 | ] 62 | 63 | json = %([2,"a","b","A","B","C","D","E","F"]) 64 | 65 | it 'dumps homogenous collections' do 66 | JSONH.dump(collection).should == json 67 | end 68 | 69 | it 'loads homogenous collections' do 70 | JSONH.load(json).should == collection 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /py2/jsonh.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | """ 4 | Copyright (C) 2011 by Andrea Giammarchi, @WebReflection 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | def dump(obj, fp, *args, **kwargs): 26 | return json.dump(pack(obj), fp, *args, **kwargs) 27 | 28 | def dumps(obj, *args, **kwargs): 29 | return json.dumps(pack(obj), *args, **kwargs) 30 | 31 | def load(fp, *args, **kwargs): 32 | return unpack(json.load(fp, *args, **kwargs)) 33 | 34 | def loads(str, *args, **kwargs): 35 | return unpack(json.loads(str, *args, **kwargs)) 36 | 37 | def pack(dict_list): 38 | length = len(dict_list) 39 | keys = length and dict_list[0].keys() or [] 40 | klength = len(keys) 41 | result = [] 42 | i = 0 43 | while i < length: 44 | o = dict_list[i] 45 | ki = 0 46 | while ki < klength: 47 | result.append(o[keys[ki]]) 48 | ki = ki + 1 49 | i = i + 1 50 | return [klength] + keys + result 51 | 52 | def unpack(hlist): 53 | length = len(hlist) 54 | klength = hlist[0] 55 | result = [] 56 | i = 1 + klength 57 | while i < length: 58 | o = dict() 59 | ki = 0 60 | while ki < klength: 61 | ki = ki + 1 62 | o[hlist[ki]] = hlist[i] 63 | i = i + 1 64 | result.append(o) 65 | return result 66 | 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [JSONH](http://webreflection.blogspot.com/2011/08/last-version-of-json-hpack.html) - JSON Homogeneous Collections Compressor 2 | ============================================================================================================================ 3 | 4 | 📢 **Check [packatoon](https://github.com/WebReflection/packatoon) out** to have just the packing/unpacking ability 🥳 5 | 6 | What is JSONH 7 | ------------- 8 | 9 | JSONH is one of the most performant, yet safe, cross programming language, way to pack and unpack generic homogenous collections. 10 | Based on native or shimmed JSON implementation, JSONH is nothing different than a procedure performed right before `JSON.stringify(data)` or right after `JSON.parse(data)` 11 | 12 | [It is demonstrated](http://jsperf.com/jsonh/2) that overall performances of JSONH are up to 3 times faster in compression and 2 times in parsing thanks to smaller and simplified nature of the collection/string. 13 | 14 | It is also demonstrated that resulting bandwidth size will be incrementally smaller than equivalent JSON operation reaching, in certain cases, down to 30% of original size and without gzip/deflate compression in place. 15 | 16 | JSONH is the latest version of [json.hpack](https://github.com/WebReflection/json.hpack) project and based on [JSONDB concept](http://michaux.ca/articles/json-db-a-compressed-json-format). 17 | 18 | New in version 0.0.2 ( JS only ) 19 | -------------------------------- 20 | * added experimental and optional `schema` argument at the end of all methods in order to parse automatically one or more nested homogenous collections 21 | * covered via unit tests pack/unpack with or without the usage of a schema 22 | 23 | 24 | What is an Homogenous Collection 25 | -------------------------------- 26 | 27 | Usually a database result set, stored as list of objects where all of them contains the same amount of keys with identical name. 28 | This is a basic homogeneous collection example: 29 | ```js 30 | [ 31 | {"a":"A","b":"B"}, 32 | {"a":"C","b":"D"}, 33 | {"a":"E","b":"F"} 34 | ] 35 | ``` 36 | We all have exchange over the network one or more homogenous collections at least once. 37 | JSONH is able to pack the example into `[2,"a","b","A","B","C","D","E","F"]` and unpack it into original collection at light speed. 38 | 39 | 40 | JSONH is suitable for 41 | --------------------- 42 | 43 | * runtime data compression with or without gzip/deflate on both client and server side 44 | * creation of static JavaScript files to serve in order to save space on Hard Drive and eventually make runtime gzip/deflate compression easier (smaller input) 45 | * send huge collection of data from the client to the server and improving performances over `JSON.stringify(data)` and required network bandwidth 46 | 47 | If the generic object/data contains one or more homogenous collections, JSONH is suitable for these cases too via `pack` and `unpack` operations. 48 | Please read the [related post](http://webreflection.blogspot.com/2011/08/jsonh-and-hybrid-js-objects.html) to know more. 49 | 50 | 51 | JSONH API 52 | --------- 53 | Every implementation is suitable for the programming language code style and every method supports original JSON signature. 54 | As example the JavaScript version is a global `JSONH` object with `stringify`, `parse`, `pack`, and `unpack` methods. 55 | 56 | The python version is a module similar to `json` one with current methods: `dump`, `dumps`, `load`, `loads`, `pack`, and `unpack`. 57 | 58 | import jsonh 59 | 60 | print(jsonh.dumps( 61 | [{"a": "A", "b": "B"}, {"a": "C", "b": "D"}, {"a": "E", "b": "F"}], 62 | separator = (',',':') 63 | )) 64 | 65 | 66 | The php 5 version is a static class plus some function in order to let developers decide for their favorite stile. 67 | Extra arguments accepted by `json_encode` and `json_decode` are supported as well. 68 | 69 | require_once('JSONH.class.php'); 70 | 71 | // classic style 72 | jsonh_encode($object); // jsonh_decode($str) 73 | 74 | // static public style 75 | JSONH::stringify($object); // JSONH::parse($str); 76 | 77 | // singleton style 78 | JSONH()->stringify($object); // JSONH()->parse($str) 79 | 80 | 81 | 82 | TODO 83 | ---- 84 | 85 | * clean up locally tests and use a standard one able to cover all aspects per each implementation 86 | * C# version, and hopefully with other developers help other languages too 87 | * simplified yet cross platform way to *map* hybrid objects, specifying via white list one or more nested properties to `pack` on stringify, and `unpack` on parse (automated and addressed compression for complex objects) 88 | 89 | JavaScript And Native JSON Escape Problems 90 | ------------------------------------------ 91 | As [@garethheyes](https://twitter.com/garethheyes) pointed out by in [this post](http://www.thespanner.co.uk/2011/07/25/the-json-specification-is-now-wrong/), native `JSON.stringify(data)` may produce invalid JavaScript. 92 | Since JSONH aim is *not* to change native JSON behavior, neither is JSONH a replacement for JSON, all I can suggest is to perform this replacement when and if data could be corrupted: 93 | 94 | JSONH.stringify(data).replace( 95 | /\u2028|\u2029/g, 96 | function (m) { 97 | return "\\u202" + (m === "\u2028" ? "8" : "9"); 98 | }) 99 | 100 | This will ensure proper escape for those characters plus performances will be still better thanks to reduced string output size (compared with the equivalent operation performed by `JSON.stringify(data)`). 101 | -------------------------------------------------------------------------------- /php5/JSONH.class.php: -------------------------------------------------------------------------------- 1 | $keys[$ki++] 114 | ); 115 | } 116 | return array_merge(array($klength), $keys, $result); 117 | } 118 | 119 | private static function _unpack_array( 120 | /*array /*use type hint if you can removing initial comment*/ 121 | $hlist 122 | ) { 123 | for ( 124 | $length = count($hlist), 125 | $klength = $hlist[0], 126 | $result = array(), 127 | $i = 1 + $klength, 128 | $j = 0, 129 | $ki, $o; 130 | $i < $length; 131 | ) { 132 | for ( 133 | $o = array(), $ki = 0; 134 | $ki < $klength; 135 | $o[$hlist[++$ki]] = $hlist[$i++] 136 | ); 137 | $result[$j++] = $o; 138 | } 139 | return $result; 140 | } 141 | 142 | private static function _unpack_object( 143 | /*array /*use type hint if you can removing initial comment*/ 144 | $hlist 145 | ) { 146 | for ( 147 | $length = count($hlist), 148 | $klength = $hlist[0], 149 | $result = array(), 150 | $i = 1 + $klength, 151 | $j = 0, 152 | $ki, $o; 153 | $i < $length; 154 | ) { 155 | for ( 156 | $o = new StdClass, $ki = 0; 157 | $ki < $klength; 158 | $o->$hlist[++$ki] = $hlist[$i++] 159 | ); 160 | $result[$j++] = $o; 161 | } 162 | return $result; 163 | } 164 | 165 | // simple helper 166 | private static function _getKeys($object) { 167 | $keys = array(); 168 | foreach ($object as $key => $value) $keys[] = $key; 169 | return $keys; 170 | } 171 | 172 | } 173 | 174 | function JSONH() { 175 | static $JSONH; 176 | return isset($JSONH) ? $JSONH : $JSONH = new JSONH; 177 | } 178 | 179 | function jsonh_encode($object, $options = 0) { 180 | return JSONH::stringify($object, $options); 181 | } 182 | 183 | function jsonh_decode($str, $assoc = false, $depth = 512, $options = 0) { 184 | return JSONH::parse($str, $assoc, $depth, $options); 185 | } 186 | 187 | ?> 188 | -------------------------------------------------------------------------------- /js/jsonh.js: -------------------------------------------------------------------------------- 1 | // both UPPER and lower, you choose 2 | var JSONH, jsonh = JSONH = function (Array, JSON) {"use strict"; // if you want 3 | 4 | /** 5 | * Copyright (C) 2011 by Andrea Giammarchi, @WebReflection 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | // transforms [{a:"A"},{a:"B"}] to [1,"a","A","B"] 27 | function hpack(list) { 28 | for (var 29 | length = list.length, 30 | // defined properties (out of one object is enough) 31 | keys = Object_keys(length ? list[0] : {}), 32 | klength = keys.length, 33 | // static length stack of JS values 34 | result = Array(length * klength), 35 | i = 0, 36 | j = 0, 37 | ki, o; 38 | i < length; ++i 39 | ) { 40 | for ( 41 | o = list[i], ki = 0; 42 | ki < klength; 43 | result[j++] = o[keys[ki++]] 44 | ); 45 | } 46 | // keys.length, keys, result 47 | return concat.call([klength], keys, result); 48 | } 49 | 50 | // transforms [1,"a","A","B"] to [{a:"A"},{a:"B"}] 51 | function hunpack(hlist) { 52 | for (var 53 | length = hlist.length, 54 | klength = hlist[0], 55 | result = Array(((length - klength - 1) / klength) || 0), 56 | i = 1 + klength, 57 | j = 0, 58 | ki, o; 59 | i < length; 60 | ) { 61 | for ( 62 | result[j++] = (o = {}), ki = 0; 63 | ki < klength; 64 | o[hlist[++ki]] = hlist[i++] 65 | ); 66 | } 67 | return result; 68 | } 69 | 70 | // recursive: called via map per each item h(pack|unpack)ing each entry through the schema 71 | function iteratingWith(method) { 72 | return function iterate(item) { 73 | for (var 74 | path = this, 75 | current = item, 76 | i = 0, length = path.length, 77 | j, k, tmp; 78 | i < length; ++i 79 | ) { 80 | if (isArray(tmp = current[k = path[i]])) { 81 | j = i + 1; 82 | current[k] = j < length ? 83 | map.call(tmp, method, path.slice(j)) : 84 | method(tmp) 85 | ; 86 | } 87 | current = current[k]; 88 | } 89 | return item; 90 | }; 91 | } 92 | 93 | // called per each schema (pack|unpack)ing each schema 94 | function packOrUnpack(method) { 95 | return function parse(o, schema) { 96 | for (var 97 | wasArray = isArray(o), 98 | result = concat.call(arr, o), 99 | path = concat.call(arr, schema), 100 | i = 0, length = path.length; 101 | i < length; ++i 102 | ) { 103 | result = map.call(result, method, path[i].split(".")); 104 | } 105 | return wasArray ? result : result[0]; 106 | }; 107 | } 108 | 109 | // JSONH.pack 110 | function pack(list, schema) { 111 | return schema ? packSchema(list, schema) : hpack(list); 112 | } 113 | 114 | // JSONH unpack 115 | function unpack(hlist, schema) { 116 | return schema ? unpackSchema(hlist, schema) : hunpack(hlist); 117 | } 118 | 119 | // JSON.stringify after JSONH.pack 120 | function stringify(list, replacer, space, schema) { 121 | return JSON_stringify(pack(list, schema), replacer, space); 122 | } 123 | 124 | // JSONH.unpack after JSON.parse 125 | function parse(hlist, reviver, schema) { 126 | return unpack(JSON_parse(hlist, reviver), schema); 127 | } 128 | 129 | var 130 | // recycled for different operations 131 | arr = [], 132 | // trapped once reused forever 133 | concat = arr.concat, 134 | // addressed cross platform Object.keys shim 135 | Object_keys = Object.keys || function (o) { 136 | var keys = [], key; 137 | for (key in o) o.hasOwnProperty(key) && keys.push(key); 138 | return keys; 139 | }, 140 | // addressed cross platform Array.isArray shim 141 | isArray = Array.isArray || (function (toString, arrayToString) { 142 | arrayToString = toString.call(arr); 143 | return function isArray(o) { 144 | return toString.call(o) == arrayToString; 145 | }; 146 | }({}.toString)), 147 | // fast and partial Array#map shim 148 | map = arr.map || function (callback, context) { 149 | for (var 150 | self = this, i = self.length, result = Array(i); 151 | i--; 152 | result[i] = callback.call(context, self[i], i, self) 153 | ); 154 | return result; 155 | }, 156 | // schema related (pack|unpack)ing operations 157 | packSchema = packOrUnpack(iteratingWith(hpack)), 158 | unpackSchema = packOrUnpack(iteratingWith(hunpack)), 159 | // JSON object shortcuts 160 | JSON_stringify = JSON.stringify, 161 | JSON_parse = JSON.parse 162 | ; 163 | 164 | return { 165 | pack: pack, 166 | parse: parse, 167 | stringify: stringify, 168 | unpack: unpack 169 | }; 170 | 171 | }(Array, JSON); 172 | 173 | // export for node.js 174 | if(typeof module != 'undefined' && module.exports) { 175 | module.exports = jsonh; 176 | } -------------------------------------------------------------------------------- /js/test/jsonh.js: -------------------------------------------------------------------------------- 1 | // https://github.com/WebReflection/wru 2 | function wru(wru){var assert=wru.assert,async=wru.async; 3 | 4 | var jsonh = require("../jsonh"); 5 | 6 | // enojy your tests! 7 | wru.test([ 8 | { 9 | name: "nested array and schema", 10 | test: function () { 11 | var 12 | object = [{a:[[{b:12}]]}], 13 | initial = JSON.stringify(object), 14 | schema = ['a.c'] 15 | ; 16 | assert("back to normal", initial === JSON.stringify(jsonh.parse(jsonh.stringify(object, null, null, schema), null, schema))); 17 | } 18 | }, { 19 | name: "require did not fail", 20 | test: function () { 21 | assert("jsonh is an object", typeof jsonh == "object"); 22 | assert("jsonh.parse is a function", typeof jsonh.parse == "function"); 23 | assert("jsonh.stringify is a function", typeof jsonh.stringify == "function"); 24 | assert("jsonh.pack is a function", typeof jsonh.pack == "function"); 25 | assert("jsonh.unpack is a function", typeof jsonh.unpack == "function"); 26 | } 27 | }, { 28 | name: "un/packing without schema", 29 | test: function () { 30 | var 31 | original = [{a:"A"},{a:"B"}], 32 | soriginal = JSON.stringify(original), 33 | packed = jsonh.pack(original), 34 | spacked = JSON.stringify(packed) 35 | ; 36 | assert("successfully packed", spacked == '[1,"a","A","B"]'); 37 | assert("successfully unpacked", JSON.stringify(jsonh.unpack(packed)) == soriginal); 38 | assert("successfully stringified", jsonh.stringify(JSON.parse(soriginal)) === spacked); 39 | assert("successfully parsed", JSON.stringify(jsonh.parse(spacked)) == soriginal); 40 | } 41 | }, { 42 | name: "un/packing with schema", 43 | test: function () { 44 | var 45 | schema = ["b.c", "b.d"], 46 | test = [ 47 | { 48 | b: { 49 | c: [ 50 | {a: 1}, 51 | {a: 2} 52 | ], 53 | d: [ 54 | {a: 3}, 55 | {a: 4} 56 | ] 57 | } 58 | }, { 59 | a: 1, 60 | b: { 61 | c: [ 62 | {a: 5}, 63 | {a: 6} 64 | ], 65 | d: [ 66 | {a: 7}, 67 | {a: 8} 68 | ] 69 | } 70 | } 71 | ], 72 | original = JSON.stringify(test), 73 | packed 74 | ; 75 | assert("successfully stringified", 76 | (packed = jsonh.stringify(test, null, null, schema)) === 77 | '[{"b":{"c":[1,"a",1,2],"d":[1,"a",3,4]}},{"a":1,"b":{"c":[1,"a",5,6],"d":[1,"a",7,8]}}]' 78 | ); 79 | assert("successfully parsed", 80 | JSON.stringify(jsonh.parse(packed, null, schema)) === 81 | original 82 | ); 83 | } 84 | }, { 85 | name: "un/packing with Arrays of Array", 86 | test: function () { 87 | var 88 | test = [ 89 | [ 90 | {x: 1, y: 2}, 91 | {x: 3, y: 4} 92 | ], 93 | [ 94 | {a: 1, b: 2}, 95 | {a: 3, b: 4} 96 | ] 97 | ], 98 | original = JSON.stringify(test), 99 | packed 100 | ; 101 | assert("successfully stringified", 102 | (packed = JSON.stringify(test, function (key, value) { 103 | if (key !== '' && value instanceof Array) { 104 | value = jsonh.pack(value); 105 | } 106 | return value; 107 | }, null)) === 108 | '[[2,"x","y",1,2,3,4],[2,"a","b",1,2,3,4]]' 109 | ); 110 | assert("successfully parsed", 111 | JSON.stringify(JSON.parse(packed, function (key, value) { 112 | if (key !== '' && value instanceof Array) { 113 | value = jsonh.unpack(value); 114 | } 115 | return value; 116 | })) === 117 | original 118 | ); 119 | } 120 | } 121 | ]); 122 | 123 | 124 | 125 | } 126 | 127 | 128 | 129 | 130 | 131 | // wru related code 132 | /*! 133 | (C) Andrea Giammarchi, @WebReflection - Mit Style License 134 | */ 135 | var setTimeout=global.setTimeout,setInterval=global.setInterval,clearInterval=global.clearInterval,clearTimeout=global.clearTimeout;setTimeout||(function(h,c,g,a){setInterval=global.setInterval=function b(j,i){return e(j,i,g.call(arguments,2),1)};setTimeout=global.setTimeout=function d(j,i){return e(j,i,g.call(arguments,2))};clearInterval=global.clearInterval=clearTimeout=global.clearTimeout=function f(i){c[i].cancel();h.purge();delete c[i]};function e(l,k,j,i){var m=++a;c[m]=new JavaAdapter(java.util.TimerTask,{run:function(){l.apply(null,j)}});i?h.schedule(c[m],k,k):h.schedule(c[m],k);return m}})(new java.util.Timer(),{},[].slice,0);wru(function(U){function h(){w=F.call(j);if(w){l(Z);l((ad(w,O)&&w[O])||(ad(w,e)&&w[e])||L);a=[];q=[];P=[];X={};b("setup");P[ae]||b("test");I||n()}else{p()}}function l(ah,ag){ah=ah+(ag?"":"\n");try{require("util").print(ah)}catch(af){try{require("sys").print(ah)}catch(af){java.lang.System.out.print(ah)}}}function p(){l(g);l(Z);switch(true){case !!aa:l(N+" "+aa+" Errors");case !!z:l(J+g+z+" Failures");default:l(y+" "+o+" Passes")}l(Z);l(g);try{process.exit()}catch(af){quit()}}function c(af){for(var ag=0,ah=af[ae];ag