Skip to content

Commit ccda93c

Browse files
committed
Merge pull request #1 from jhermsmeier/next
bencode.js update/rewrite
2 parents 0c3ff65 + f780452 commit ccda93c

File tree

7 files changed

+506
-156
lines changed

7 files changed

+506
-156
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Mark Schmale <[email protected]>
2+
Jonas Hermsmeier <[email protected]>

README.md

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,120 @@
1-
### Usage
21

3-
var bencode = require("bencode");
4-
var data = bencode.decode(benstring);
2+
# node-bencode
3+
4+
A node library for encoding and decoding bencoded data,
5+
according to the [BitTorrent specification](http://www.bittorrent.org/beps/bep_0003.html).
6+
7+
## Index
8+
9+
- [About BEncoding](#about-bencoding)
10+
- [Installation](#install-with-npm)
11+
- [Usage](#usage)
12+
- [API](#api)
13+
14+
## About BEncoding
15+
16+
from [Wikipedia](https://en.wikipedia.org/wiki/Bencoding):
17+
18+
Bencode (pronounced like B encode) is the encoding used by the peer-to-peer
19+
file sharing system BitTorrent for storing and transmitting loosely structured data.
20+
21+
It supports four different types of values:
22+
- byte strings
23+
- integers
24+
- lists
25+
- dictionaries
26+
27+
Bencoding is most commonly used in torrent files.
28+
These metadata files are simply bencoded dictionaries.
29+
30+
## Install with [npm](http://npmjs.org)
31+
32+
```
33+
npm install bencode
34+
```
35+
36+
## Usage
37+
38+
```javascript
39+
var bencode = require( 'bencode' )
40+
```
41+
42+
### Encoding
43+
44+
```javascript
45+
46+
var data = {
47+
string: 'Hello World',
48+
integer: 12345,
49+
dict: {
50+
key: 'This is a string within a dictionary'
51+
},
52+
list: [ 1, 2, 3, 4, 'string', 5, {} ]
53+
}
54+
55+
var result = bencode.encode( data )
56+
57+
```
58+
59+
#### Output
60+
61+
```
62+
d6:string11:Hello World7:integeri12345e4:dictd3:key36:This is a string within a dictionarye4:litli1ei2ei3ei4e6:stringi5edeee
63+
```
64+
65+
### Decoding
66+
67+
```javascript
68+
var data = new Buffer( 'd6:string11:Hello World7:integeri12345e4:dictd3:key36:This is a string within a dictionarye4:litli1ei2ei3ei4e6:stringi5edeee' )
69+
var result = bencode.decode( data )
70+
```
71+
72+
#### Output
73+
74+
```javascript
75+
{
76+
string: <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>,
77+
integer: 12345,
78+
dict: {
79+
key: <Buffer 54 68 69 73 20 69 73 20 61 20 73 74 72 69 6e 67 20 77 69 74 68 69 6e 20 61 20 64 69 63 74 69 6f 6e 61 72 79>
80+
},
81+
list: [ 1, 2, 3, 4, <Buffer 73 74 72 69 6e 67>, 5, {} ]
82+
}
83+
```
84+
85+
Automagically convert bytestrings to strings:
86+
87+
```javascript
88+
var result = bencode.decode( data, true )
89+
```
90+
91+
#### Output
92+
93+
```javascript
94+
{
95+
string: 'Hello World',
96+
integer: 12345,
97+
dict: {
98+
key: 'This is a string within a dictionary'
99+
},
100+
list: [ 1, 2, 3, 4, 'string', 5, {} ]
101+
}
102+
```
103+
104+
## API
105+
106+
### bencode.encode( *data* )
107+
108+
> `Buffer` | `Array` | `String` | `Object` | `Number` __data__
109+
110+
Returns `String`
111+
112+
### bencode.decode( *data*, *toString* )
113+
114+
> `Buffer` __data__
115+
> `Boolean` __toString__
116+
117+
If `toString` is set to something truthy,
118+
bytestrings are automatically converted to strings.
119+
120+
Returns `Object` | `Array` | `Buffer` | `String` | `Number`

benchmark/bencode.old.js

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/*
2+
* ----------------------------------------------------------------------------
3+
* node-bencode v0.1.0
4+
* <[email protected]> wrote this file. As long as you retain this notice
5+
* you can do whatever you want with this stuff. If we meet some day, and you
6+
* think this stuff is worth it, you can buy me a beer in return. Mark Schmale
7+
* ----------------------------------------------------------------------------
8+
*/
9+
var sys = require('sys');
10+
11+
/**
12+
* decodes a bencoded string
13+
*/
14+
exports.decode = function decode(str) {
15+
var arr = str.split('');
16+
17+
function integer(start) {
18+
var c = '', n = '', i = 0, mul = 1;
19+
var len = arr.length;
20+
if(arr[start] === '-') {
21+
mul = -1;
22+
start = start+1;
23+
}
24+
for(i=start;i<len;i++) {
25+
c = arr[i];
26+
if(c == parseInt(c)) {
27+
n = n + c;
28+
} else {
29+
break;
30+
}
31+
}
32+
return {next: i+1, ret: mul*parseInt(n)};
33+
}
34+
35+
function text(start) {
36+
var nfo = integer(start),
37+
start = nfo.next,
38+
len = nfo.ret
39+
i = 0
40+
full = '';
41+
42+
for(i=start;i<len+start;i++) {
43+
full = full + arr[i]
44+
}
45+
return {next: i, ret: full};
46+
}
47+
48+
function list(start) {
49+
var len = arr.length,
50+
i = start+1,
51+
list = [],
52+
tmp = {},
53+
lcnt = 0;
54+
while(i<len && arr[i] !== 'e') {
55+
tmp = next(i);
56+
i = tmp.next;
57+
list[lcnt] = tmp.ret;
58+
lcnt++;
59+
}
60+
return {next: i+1, ret: list};
61+
}
62+
63+
function dictionary(start) {
64+
var len = arr.length,
65+
i = start+1,
66+
list = {},
67+
tmp = {},
68+
isKey = true,
69+
key = '';
70+
while(i<len && arr[i] !== 'e') {
71+
tmp = next(i);
72+
i = tmp.next;
73+
if(isKey === true) {
74+
key = tmp.ret;
75+
} else {
76+
list[key] = tmp.ret;
77+
}
78+
isKey = !isKey;
79+
}
80+
return {next: i+1, ret: list};
81+
}
82+
83+
84+
function next(start) {
85+
var data = 0;
86+
start = start || 0;
87+
switch(arr[start]) {
88+
case 'i': // integer
89+
data = integer(start+1);
90+
break;
91+
case 'l': // liste
92+
data = list(start);
93+
break;
94+
case 'd': // dict
95+
data = dictionary(start);
96+
break;
97+
default: // string
98+
data = text(start);
99+
}
100+
return data;
101+
}
102+
103+
return next(0).ret;
104+
}
105+
106+
exports.encode = function encode(data) {
107+
/* sys.puts(sys.inspect(typeof(data)));
108+
sys.puts(sys.inspect(is_array(data)));*/
109+
110+
function encode_string(data) {
111+
return data.length + ":" + data;
112+
}
113+
114+
function encode_integer(data) {
115+
return "i" + data + "e";
116+
}
117+
118+
function encode_list(data) {
119+
var max = data.length;
120+
var i = 0;
121+
var str = "l";
122+
for(i=0;i<max;i++) {
123+
str = str + encode(data[i]);
124+
}
125+
str = str + "e";
126+
return str;
127+
}
128+
129+
function encode_dict(data) {
130+
var str = "d";
131+
for(var key in data) {
132+
str = str + encode_string(key) + encode(data[key]);
133+
}
134+
str = str + "e";
135+
return str;
136+
}
137+
138+
/** helper **/
139+
function is_array(obj) {
140+
return obj.constructor == Array;
141+
}
142+
143+
var str = "";
144+
145+
switch(typeof(data)) {
146+
case 'object':
147+
if(is_array(data) === true) {
148+
str = encode_list(data);
149+
} else {
150+
str = encode_dict(data);
151+
}
152+
break;
153+
154+
case 'number':
155+
str = encode_integer(data);
156+
break;
157+
158+
case 'string':
159+
str = encode_string(data);
160+
break;
161+
}
162+
return str;
163+
}

benchmark/index.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
var bencode = require( '../' )
3+
var old = require( './bencode.old' )
4+
var Benchmark = require( 'benchmark' )
5+
var fs = require( 'fs' )
6+
7+
var suite = new Benchmark.Suite
8+
9+
var buffer = fs.readFileSync( __dirname + '/test.torrent' )
10+
var data = bencode.decode( buffer, true )
11+
var string = bencode.encode( data )
12+
13+
suite
14+
.add( 'new#encode( Object )', function () {
15+
bencode.encode( data )
16+
})
17+
.add( 'old#encode( Object )', function () {
18+
old.encode( data )
19+
})
20+
.add( 'new#decode( Buffer )', function () {
21+
bencode.decode( buffer )
22+
})
23+
.add( 'new#decode( Buffer, true )', function () {
24+
bencode.decode( buffer, true )
25+
})
26+
.add( 'old#decode( String )', function () {
27+
old.decode( string )
28+
})
29+
.on( 'cycle', function ( event, bench ) {
30+
console.log( bench.toString(), bench.error || '' )
31+
})
32+
.run()

benchmark/test.torrent

27.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)