binary-extract
Advanced tools
Comparing version
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 @@ [](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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
11084
71.23%344
66.99%58
11.54%2
100%2
100%