binary-extract
Advanced tools
Comparing version 0.0.1 to 0.1.0
155
bench.js
@@ -5,33 +5,134 @@ | ||
var buf = Buffer(JSON.stringify({ | ||
foo: 'bar', | ||
bar: 'baz', | ||
beep: [ | ||
{ boop: true }, | ||
{ nice: 3 } | ||
], | ||
boop: { | ||
some: { | ||
more: ['chunk'] | ||
} | ||
}, | ||
check: 'sweet' | ||
})); | ||
var near = Buffer(JSON.stringify( | ||
{ properties: | ||
{ selected: '2', | ||
lastName: '', | ||
username: 'someone', | ||
category: 'Wedding Venues', | ||
firstName: '', | ||
product: 'planner', | ||
location: '', | ||
platform: 'ios', | ||
email: 'someone@yahoo.com', | ||
member_id: '12312313123123', | ||
filtered: 'false', | ||
viewed: 3 }, | ||
projectId: 'foobarbaz', | ||
userId: '123123123123123', | ||
sessionId: 'FF8D19D8-123123-449E-A0B9-2181C4886020', | ||
requestId: 'F3C49DEB-123123-4A54-BB72-D4BE591E4B29', | ||
action: 'Track', | ||
event: 'Vendor Category Viewed', | ||
timestamp: '2014-04-23T20:55:19.000Z', | ||
context: | ||
{ providers: | ||
{ Crittercism: false, | ||
Amplitude: false, | ||
Mixpanel: false, | ||
Countly: false, | ||
Localytics: false, | ||
'Google Analytics': false, | ||
Flurry: false, | ||
Tapstream: false, | ||
Bugsnag: false }, | ||
appReleaseVersion: '2.3.1', | ||
osVersion: '7.1', | ||
os: 'iPhone OS', | ||
appVersion: '690', | ||
screenHeight: 480, | ||
'library-version': '0.10.3', | ||
traits: | ||
{ lastName: '', | ||
product: 'planner', | ||
member_id: '123123123123123', | ||
firstName: '', | ||
email: 'someone@yahoo.com', | ||
platform: 'ios', | ||
username: 'someone' }, | ||
screenWidth: 320, | ||
deviceManufacturer: 'Apple', | ||
library: 'analytics-ios', | ||
idForAdvertiser: '1323232-A0ED-47AB-BE4F-274F2252E4B4', | ||
deviceModel: 'iPad3,4' }, | ||
requestTime: '2014-04-23T20:55:44.211Z', | ||
version: 1, | ||
channel: 'server' } | ||
)); | ||
var cycles = 100000; | ||
var far = Buffer(JSON.stringify( | ||
{ properties: | ||
{ selected: '2', | ||
lastName: '', | ||
username: 'someone', | ||
category: 'Wedding Venues', | ||
firstName: '', | ||
product: 'planner', | ||
location: '', | ||
platform: 'ios', | ||
email: 'someone@yahoo.com', | ||
member_id: '12312313123123', | ||
filtered: 'false', | ||
viewed: 3 }, | ||
userId: '123123123123123', | ||
sessionId: 'FF8D19D8-123123-449E-A0B9-2181C4886020', | ||
requestId: 'F3C49DEB-123123-4A54-BB72-D4BE591E4B29', | ||
action: 'Track', | ||
event: 'Vendor Category Viewed', | ||
timestamp: '2014-04-23T20:55:19.000Z', | ||
context: | ||
{ providers: | ||
{ Crittercism: false, | ||
Amplitude: false, | ||
Mixpanel: false, | ||
Countly: false, | ||
Localytics: false, | ||
'Google Analytics': false, | ||
Flurry: false, | ||
Tapstream: false, | ||
Bugsnag: false }, | ||
appReleaseVersion: '2.3.1', | ||
osVersion: '7.1', | ||
os: 'iPhone OS', | ||
appVersion: '690', | ||
screenHeight: 480, | ||
'library-version': '0.10.3', | ||
traits: | ||
{ lastName: '', | ||
product: 'planner', | ||
member_id: '123123123123123', | ||
firstName: '', | ||
email: 'someone@yahoo.com', | ||
platform: 'ios', | ||
username: 'someone' }, | ||
screenWidth: 320, | ||
deviceManufacturer: 'Apple', | ||
library: 'analytics-ios', | ||
idForAdvertiser: '1323232-A0ED-47AB-BE4F-274F2252E4B4', | ||
deviceModel: 'iPad3,4' }, | ||
projectId: 'foobarbaz', | ||
requestTime: '2014-04-23T20:55:44.211Z', | ||
version: 1, | ||
channel: 'server' } | ||
)); | ||
var start = Date.now(); | ||
for (var i = 0; i < cycles; i++) { | ||
var obj = JSON.parse(buf.toString('utf8')); | ||
equal(obj.check, 'sweet'); | ||
} | ||
suite('near', function(){ | ||
bench('native', function(){ | ||
var obj = JSON.parse(near.toString()); | ||
var val = obj.projectId; | ||
}) | ||
console.log('naive(): %s ms', Date.now() - start); | ||
bench('extract', function(){ | ||
var val = extract(near, 'projectId'); | ||
}) | ||
}) | ||
start = Date.now(); | ||
for (var i = 0; i < cycles; i++) { | ||
equal(extract(buf, 'check'), 'sweet'); | ||
} | ||
suite('far', function(){ | ||
bench('native', function(){ | ||
var obj = JSON.parse(far.toString()); | ||
var val = obj.projectId; | ||
}) | ||
console.log('extract(): %s ms', Date.now() - start); | ||
bench('extract', function(){ | ||
var val = extract(far, 'projectId'); | ||
}) | ||
}) |
0.1.0 / 2014-05-19 | ||
================== | ||
* add passing test for false positive sub key matches | ||
* docs | ||
* add multi match support | ||
* add near/far benchmarks | ||
* use matcha for benchmarks | ||
0.0.1 / 2014-03-18 | ||
@@ -3,0 +12,0 @@ ================== |
49
index.js
@@ -22,6 +22,9 @@ | ||
/** | ||
* Extract the value of `key` in the json `buf`. | ||
* Extract the value of `keys` in the json `buf`. | ||
* | ||
* If `keys` is a single key, returns the value. | ||
* If `keys` is an array of keys, returns an array of values. | ||
* | ||
* @param {Buffer} buf | ||
* @param {String} key | ||
* @param {Array|String} keys | ||
* @return {Mixed} | ||
@@ -31,8 +34,15 @@ * @api public | ||
function extract(buf, key){ | ||
function extract(buf, keys){ | ||
if (!Array.isArray(keys)) keys = [keys]; | ||
var values = []; | ||
var matched = {}; | ||
var isKey = true; | ||
var inString = false; | ||
var level = 0; | ||
var chars = strToCharCodes(key); | ||
var chars = keys.map(strToCharCodes); | ||
var c; | ||
var match; | ||
var start; | ||
var end; | ||
@@ -58,9 +68,28 @@ for (var i = 0; i < buf.length; i++) { | ||
} | ||
if (!isKey || level > 1 || !isMatch(buf, i, chars)) continue; | ||
if (!isKey || level > 1) continue; | ||
var start = i + key.length + 2; | ||
var end = findEnd(buf, start); | ||
for (var j = 0; j < keys.length; j++) { | ||
if (!matched[keys[j]] && isMatch(buf, i, chars[j])) { | ||
match = { | ||
key: keys[j], | ||
chars: chars[j], | ||
idx: j | ||
}; | ||
matched[keys[i]] = true; | ||
break; | ||
}; | ||
} | ||
if (!match) continue; | ||
return parse(buf, start, end); | ||
start = i + match.key.length + 2; | ||
end = findEnd(buf, start); | ||
values[match.idx] = parse(buf, start, end); | ||
match = null; | ||
if (values.length == keys.length) break; | ||
} | ||
return keys.length != 1 | ||
? values | ||
: values[0]; | ||
} | ||
@@ -97,3 +126,3 @@ | ||
/** | ||
* Check if `buf[i+n]` equals `chars`. | ||
* Check if `buf[i-1] - buf[i+n]` equals `"chars"`. | ||
* | ||
@@ -108,5 +137,7 @@ * @param {Array[Number]} chars | ||
function isMatch(buf, i, chars){ | ||
if (buf[i - 1] != mark) return false; | ||
for (var j = 0; j < chars.length; j++) { | ||
if (buf[i + j] != chars[j]) return false; | ||
} | ||
if (buf[i + chars.length] != mark) return false; | ||
return true; | ||
@@ -113,0 +144,0 @@ } |
{ | ||
"name": "binary-extract", | ||
"description": "Extract a value from a binary json blob", | ||
"version": "0.0.1", | ||
"description": "Extract values from a binary json blob", | ||
"version": "0.1.0", | ||
"repository": "segmentio/binary-extract", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"mocha": "~1.18.0" | ||
"mocha": "~1.18.0", | ||
"matcha": "~0.5.0" | ||
}, | ||
@@ -10,0 +11,0 @@ "scripts": { |
# binary-extract | ||
Extract a value from a buffer of json without parsing the whole thing. | ||
Extract one or more values from a buffer of json without parsing the whole thing. | ||
@@ -23,2 +23,5 @@ [![build status](https://secure.travis-ci.org/segmentio/binary-extract.png)](http://travis-ci.org/segmentio/binary-extract) | ||
// => 'baz' | ||
var values = extract(buf, ['foo', 'nested']) | ||
// => ["bar", {"bar":"nope"}] | ||
``` | ||
@@ -43,8 +46,11 @@ | ||
### extract(buf, key) | ||
### extract(buf, keys) | ||
Extract the value of `key` in the json `buf`. | ||
Extract the value of `keys` in the json `buf`. | ||
The value can be any valid JSON structure. | ||
If `keys` is a __String__, returns a value. If `keys` is an __Array__ of | ||
keys, returns an array of values. | ||
## License | ||
@@ -51,0 +57,0 @@ |
@@ -11,2 +11,6 @@ | ||
}) | ||
it('should extract multiple values', function(){ | ||
var buf = toBuf({ a: '0', b: '1', c: '2' }); | ||
equal(extract(buf, ['a', 'c']), ['0', '2']); | ||
}) | ||
it('should end on ,', function(){ | ||
@@ -44,2 +48,6 @@ var buf = toBuf({ foo: 'bar', bar: 'baz' }); | ||
}); | ||
it('should ignore sub key matches', function(){ | ||
var buf = toBuf({ _a: '0', a_: '1', _a_: '2', a: '3' }); | ||
equal(extract(buf, 'a'), '3'); | ||
}); | ||
}) | ||
@@ -46,0 +54,0 @@ |
Sorry, the diff of this file is not supported yet
11084
344
58
2