Skip to content

Commit 8dd202f

Browse files
authored
feat: support get raw string by string length (#30)
1 parent 7dd0a0c commit 8dd202f

File tree

4 files changed

+98
-21
lines changed

4 files changed

+98
-21
lines changed

benchmark/get.js

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ suite
143143
.add('getRawString(0, 100)', function () {
144144
putRawStringBytes.getRawString(0, 100);
145145
})
146+
.add('getRawStringByStringLength(0, 100)', function () {
147+
putRawStringBytes.getRawStringByStringLength(0, 100);
148+
})
146149

147150
.on('cycle', function(event) {
148151
benchmarks.add(event.target);
@@ -155,22 +158,31 @@ suite
155158
})
156159
.run({ 'async': false });
157160

158-
// node version: v0.11.12, date: Mon May 12 2014 19:14:26 GMT+0800 (CST)
161+
// node version: v8.9.0, date: Thu Nov 16 2017 12:27:51 GMT+0800 (CST)
159162
// Starting...
160-
// 15 tests completed.
161-
162-
// get(0, 1) => copy Buffer x 2,059,464 ops/sec ±9.18% (69 runs sampled)
163-
// get(0, 100) => copy Buffer x 2,124,455 ops/sec ±4.98% (75 runs sampled)
164-
// get(0, 4096) => copy Buffer x 356,927 ops/sec ±9.43% (56 runs sampled)
165-
// get() => byte x 15,477,897 ops/sec ±3.05% (89 runs sampled)
166-
// getChar(0) x 52,541,591 ops/sec ±1.04% (95 runs sampled)
167-
// getShort(0) x 26,297,086 ops/sec ±2.46% (89 runs sampled)
168-
// getInt(0) x 18,772,003 ops/sec ±6.27% (71 runs sampled)
169-
// getFloat(0) x 13,132,298 ops/sec ±1.68% (97 runs sampled)
170-
// getDouble(0) x 10,968,594 ops/sec ±1.27% (94 runs sampled)
171-
// getLong(0) x 11,849,374 ops/sec ±2.63% (96 runs sampled)
172-
// getString(0) x 2,358,382 ops/sec ±5.78% (76 runs sampled)
173-
// getCString(0) x 1,618,356 ops/sec ±8.41% (72 runs sampled)
174-
// readRawString(4, 100) x 4,790,991 ops/sec ±9.25% (79 runs sampled)
175-
// readRawString(100) x 5,434,663 ops/sec ±1.32% (95 runs sampled)
176-
// getRawString(0, 100) x 5,497,325 ops/sec ±1.02% (98 runs sampled)
163+
// 24 tests completed.
164+
//
165+
// _offset = 0 x 1,313,398,169 ops/sec ±1.69% (92 runs sampled)
166+
// position(0) x 154,052,896 ops/sec ±1.90% (91 runs sampled)
167+
// position() x 234,018,744 ops/sec ±12.30% (91 runs sampled)
168+
// _bytes.copy(0, 1) x 1,359,434 ops/sec ±1.75% (89 runs sampled)
169+
// get(0, 1) => copy Buffer x 1,318,288 ops/sec ±2.01% (86 runs sampled)
170+
// get(0, 100) => copy Buffer x 1,122,101 ops/sec ±1.07% (77 runs sampled)
171+
// get(0, 4096) => copy Buffer x 360,451 ops/sec ±3.04% (84 runs sampled)
172+
// _bytes[i] x 668,005,958 ops/sec ±1.15% (94 runs sampled)
173+
// get() => byte x 139,503,339 ops/sec ±0.94% (92 runs sampled)
174+
// get(0) => byte x 145,565,421 ops/sec ±0.88% (94 runs sampled)
175+
// getChar(0) x 146,359,082 ops/sec ±0.90% (94 runs sampled)
176+
// _bytes.readUInt16BE x 135,816,353 ops/sec ±0.97% (93 runs sampled)
177+
// getShort(0) x 122,965,917 ops/sec ±1.09% (93 runs sampled)
178+
// getShort() x 118,434,346 ops/sec ±0.93% (90 runs sampled)
179+
// getInt(0) x 23,725,763 ops/sec ±1.15% (91 runs sampled)
180+
// getFloat(0) x 10,082,681 ops/sec ±0.95% (93 runs sampled)
181+
// getDouble(0) x 9,406,714 ops/sec ±2.16% (92 runs sampled)
182+
// getLong(0) x 62,055,693 ops/sec ±1.69% (92 runs sampled)
183+
// getString(0) x 5,086,919 ops/sec ±1.53% (93 runs sampled)
184+
// getCString(0) x 5,088,544 ops/sec ±1.07% (91 runs sampled)
185+
// readRawString(4, 100) x 6,293,722 ops/sec ±1.12% (90 runs sampled)
186+
// readRawString(100) x 6,189,186 ops/sec ±1.02% (90 runs sampled)
187+
// getRawString(0, 100) x 1,232,435 ops/sec ±1.23% (89 runs sampled)
188+
// getRawStringByStringLength(0, 100) x 1,203,666 ops/sec ±1.34% (94 runs sampled)

lib/byte.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,41 @@ ByteBuffer.prototype._copy = function (start, end) {
405405
return buf;
406406
};
407407

408+
ByteBuffer.prototype.getRawStringByStringLength = function (index, length) {
409+
var needUpdateOffset = false;
410+
if (arguments.length === 1) {
411+
length = index;
412+
index = this._offset;
413+
needUpdateOffset = true;
414+
}
415+
416+
var data = [];
417+
var bufLength = 0;
418+
while (length--) {
419+
var pos = index + bufLength;
420+
var ch = this._bytes[pos];
421+
if (ch < 0x80) {
422+
data.push(ch);
423+
bufLength += 1;
424+
} else if ((ch & 0xe0) === 0xc0) {
425+
var ch1 = this._bytes[++pos];
426+
var v = ((ch & 0x1f) << 6) + (ch1 & 0x3f);
427+
data.push(v);
428+
bufLength += 2;
429+
} else if ((ch & 0xf0) === 0xe0) {
430+
var ch1 = this._bytes[++pos];
431+
var ch2 = this._bytes[++pos];
432+
var v = ((ch & 0x0f) << 12) + ((ch1 & 0x3f) << 6) + (ch2 & 0x3f);
433+
data.push(v);
434+
bufLength += 3;
435+
} else {
436+
throw new Error('string is not valid UTF-8 encode');
437+
}
438+
}
439+
if (needUpdateOffset) this._offset += bufLength;
440+
return String.fromCharCode.apply(String, data);
441+
};
442+
408443
ByteBuffer.prototype.getRawString = function (index, length) {
409444
if (typeof index !== 'number') {
410445
// getRawString() => current offset char string

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"intelli-espower-loader": "^1.0.1",
3131
"istanbul": "*",
3232
"jshint": "*",
33-
"mocha": "*",
33+
"mocha": "3",
3434
"optimized": "^1.2.0",
3535
"power-assert": "^1.4.4"
3636
},
@@ -56,4 +56,4 @@
5656
},
5757
"author": "fengmk2 <[email protected]> (http://fengmk2.com)",
5858
"license": "MIT"
59-
}
59+
}

test/byte.test.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,17 +465,20 @@ describe('byte.test.js', function () {
465465
bytes.putRawString(' world');
466466
assert(bytes.toString() === '<ByteBuffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>');
467467
assert(bytes.getRawString(0, 11) === 'hello world');
468+
assert(bytes.getRawStringByStringLength(0, 11) === 'hello world');
468469
bytes.position(0);
469470
assert(bytes.getRawString() === 'h');
470471

471472
bytes = ByteBuffer.allocate(1);
472473
bytes.putRawString('你好');
473474
assert(bytes.toString() === '<ByteBuffer e4 bd a0 e5 a5 bd>');
474475
assert(bytes.position(0).readRawString(6) === '你好');
476+
assert(bytes.position(0).getRawString(0, 6) === '你好');
477+
assert(bytes.position(0).getRawStringByStringLength(2) === '你好');
475478
bytes.putRawString(0, '我们');
476479
assert(bytes.toString() === '<ByteBuffer e6 88 91 e4 bb ac>');
477480
assert(bytes.getRawString(0, 6) === '我们');
478-
481+
assert(bytes.getRawStringByStringLength(0, 2) === '我们');
479482
assert(bytes.readRawString(0, 6) === '我们');
480483

481484
bytes = ByteBuffer.allocate(1);
@@ -633,19 +636,22 @@ describe('byte.test.js', function () {
633636
bytes.putRawString(str);
634637
assert(bytes.toString() === '<ByteBuffer 68 65 6c 6c 6f e9 a6 83 e5 b0 b2>');
635638
assert.deepEqual(bytes.getRawString(0, 11), str);
639+
assert.deepEqual(bytes.getRawStringByStringLength(0, 7), str);
636640
// gbk
637641
var bytes = ByteBuffer.allocate(1);
638642
var str = 'hello\ud83c\udf3c';
639643
bytes.putRawString(str);
640644
assert(bytes.toString() === '<ByteBuffer 68 65 6c 6c 6f ed a0 bc ed bc bc>');
641645
assert.deepEqual(bytes.getRawString(0, 11), str);
646+
assert.deepEqual(bytes.getRawStringByStringLength(0, 7), str);
642647

643648
var bytes = ByteBuffer.allocate(1);
644649
// java encode bytes: [-19, -96, -67, -19, -72, -128, 87, 119, 119, -23, -126, -93]
645650
var str = '\ud83d\ude00Www那';
646651
bytes.putRawString(str);
647652
assert(bytes.toString() === '<ByteBuffer ed a0 bd ed b8 80 57 77 77 e9 82 a3>');
648653
assert.deepEqual(bytes.getRawString(0, 12), str);
654+
assert.deepEqual(bytes.getRawStringByStringLength(0, 6), str);
649655

650656
// Construction of a special test case which triggers the bug
651657
// of allocating insufficient space via _checkSize
@@ -766,4 +772,28 @@ describe('byte.test.js', function () {
766772
assert.deepEqual(buf, new Buffer([0, 0, 0, 5]));
767773
});
768774
});
775+
776+
describe('getRawStringByStringLength()', function () {
777+
it('should get with mixed sting success', function () {
778+
var bytes = ByteBuffer.allocate(1000);
779+
var str = '你好啊,1234,abcde,\ud83d\ude00Www那';
780+
bytes.putRawString(str);
781+
var pos = bytes.position();
782+
bytes.position(0);
783+
assert(str === bytes.getRawStringByStringLength(0, str.length));
784+
assert(bytes.position() === 0);
785+
assert(str === bytes.getRawStringByStringLength(str.length));
786+
assert(bytes.position() === pos);
787+
});
788+
789+
it('should throw if encode error', function () {
790+
var bytes = ByteBuffer.allocate(1000);
791+
var str = '你好啊,1234,abcde,\ud83d\ude00Www那';
792+
bytes.putRawString(str);
793+
bytes.put(0xfd);
794+
assert.throws(function () {
795+
bytes.getRawStringByStringLength(0, str.length + 1);
796+
}, 'string is not valid UTF-8 encode');
797+
});
798+
});
769799
});

0 commit comments

Comments
 (0)