1
- /*!{id:msgpack.js,ver:1.02 ,license:"MIT",author:"uupaa.js@gmail .com"}*/
1
+ /*!{id:msgpack.js,ver:1.03 ,license:"MIT",author:"uupaa.js@gmail .com"}*/
2
2
3
3
// === msgpack ===
4
4
// MessagePack -> http://msgpack.sourceforge.net/
@@ -18,15 +18,15 @@ globalScope.msgpack = {
18
18
} ;
19
19
20
20
var _ie = / M S I E / . test ( navigator . userAgent ) ,
21
- _bit2num = { } , // BitStringToNumber { "00000000": 0, ... "11111111": 255 }
22
21
_bin2num = { } , // BinaryStringToNumber { "\00": 0, ... "\ff": 255 }
23
22
_num2bin = { } , // NumberToBinaryString { 0: "\00", ... 255: "\ff" }
24
23
_num2b64 = ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
25
24
"abcdefghijklmnopqrstuvwxyz0123456789+/" ) . split ( "" ) ,
26
25
_sign = { 8 : 0x80 , 16 : 0x8000 , 32 : 0x80000000 } ,
27
- _pooledArray = [ ] ,
28
- _IEEE754positive = / ^ .( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) $ / ,
29
- _IEEE754negative = / ^ ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) ( .{ 8 } ) $ / ;
26
+ _buf = [ ] , // decode buffer
27
+ _idx = 0 , // decode buffer[index]
28
+ _ary = [ ] , // pooled array
29
+ _toString = Object . prototype . toString ;
30
30
31
31
// for WebWorkers Code Block
32
32
self . importScripts && ( onmessage = function ( event ) {
@@ -52,19 +52,19 @@ function msgpackpack(data, // @param Mix:
52
52
53
53
// msgpack.unpack
54
54
function msgpackunpack ( data ) { // @param BinaryString/ByteArray:
55
- // @return Mix:
55
+ // @return Mix/undefined: undefined is error return
56
56
// [1][String to mix] msgpack.unpack("...") -> {}
57
57
// [2][ByteArray to mix] msgpack.unpack([...]) -> {}
58
58
59
- return { data : typeof data === "string" ? toByteArray ( data )
60
- : data ,
61
- index : - 1 , decode : decode } . decode ( ) ;
59
+ _buf = typeof data === "string" ? toByteArray ( data ) : data ;
60
+ _idx = - 1 ;
61
+ return decode ( ) ;
62
62
}
63
63
64
64
// inner - encoder
65
65
function encode ( rv , // @param ByteArray: result
66
66
mix ) { // @param Mix: source data
67
- var size = 0 , i = 0 , iz , c , ary , hash , pos ,
67
+ var size = 0 , i = 0 , iz , c , pos ,
68
68
high , low , i64 = 0 , sign , exp , frac ;
69
69
70
70
if ( mix == null ) { // null or undefined
@@ -111,38 +111,49 @@ function encode(rv, // @param ByteArray: result
111
111
}
112
112
if ( i64 ) {
113
113
high = Math . floor ( mix / 0x100000000 ) ;
114
- low = mix & ( 0x100000000 - 1 ) ;
114
+ low = mix & 0xffffffff ;
115
115
rv . push ( mix < 0 ? 0xd3 : 0xcf ,
116
- ( high >> 24 ) & 0xff , ( high >> 16 ) & 0xff ,
117
- ( high >> 8 ) & 0xff , high & 0xff ,
118
- ( low >> 24 ) & 0xff , ( low >> 16 ) & 0xff ,
119
- ( low >> 8 ) & 0xff , low & 0xff ) ;
116
+ ( high >> 24 ) & 0xff , ( high >> 16 ) & 0xff ,
117
+ ( high >> 8 ) & 0xff , high & 0xff ,
118
+ ( low >> 24 ) & 0xff , ( low >> 16 ) & 0xff ,
119
+ ( low >> 8 ) & 0xff , low & 0xff ) ;
120
120
}
121
121
} else { // double
122
- // THX! edvakf
123
- // http://javascript.g.hatena.ne.jp/edvakf/20100614/1276503044
124
- hash = _bit2num ;
122
+ // THX!! @edvakf
123
+ // http://javascript.g.hatena.ne.jp/edvakf/20101128/1291000731
125
124
sign = mix < 0 ;
126
125
sign && ( mix *= - 1 ) ;
127
126
127
+ // exp => 11 bits
128
128
// add offset 1023 to ensure positive
129
129
// 0.6931471805599453 = Math.LN2;
130
130
exp = ( ( Math . log ( mix ) / 0.6931471805599453 ) + 1023 ) | 0 ;
131
131
132
+ // frac => 53 bits
132
133
// shift 52 - (exp - 1023) bits to make integer part exactly 53 bits,
133
134
// then throw away trash less than decimal point
134
- frac = ( Math . floor ( mix * Math . pow ( 2 , 52 + 1023 - exp ) ) ) .
135
- toString ( 2 ) . slice ( 1 ) ;
136
-
137
- // exp is between 1 and 2047. make it 11 bits
138
- // http://d.hatena.ne.jp/uupaa/20101128
139
- _pooledArray = ! sign ? _IEEE754positive . exec ( ( exp + 4096 ) . toString ( 2 ) + frac )
140
- : _IEEE754negative . exec ( ( exp + 2048 ) . toString ( 2 ) + frac ) ;
141
- ary = _pooledArray ; // alias
142
- rv . push ( 0xcb , hash [ ary [ 1 ] ] , hash [ ary [ 2 ] ] ,
143
- hash [ ary [ 3 ] ] , hash [ ary [ 4 ] ] ,
144
- hash [ ary [ 5 ] ] , hash [ ary [ 6 ] ] ,
145
- hash [ ary [ 7 ] ] , hash [ ary [ 8 ] ] ) ;
135
+ frac = Math . floor ( mix * Math . pow ( 2 , 52 + 1023 - exp ) ) ;
136
+
137
+ // S+-Exp(11)--++-----------------Fraction(52bits)-----------------------+
138
+ // || || |
139
+ // v+----------++--------------------------------------------------------+
140
+ // 00000000|00000000|00000000|00000000|00000000|00000000|00000000|00000000
141
+ // 6 5 55 4 4 3 2 1 8 0
142
+ // 3 6 21 8 0 2 4 6
143
+ //
144
+ // +----------high(32bits)-----------+ +----------low(32bits)------------+
145
+ // | | | |
146
+ // +---------------------------------+ +---------------------------------+
147
+ // 3 2 21 1 8 0
148
+ // 1 4 09 6
149
+ low = frac & 0xffffffff ;
150
+ high = ( ( frac / 0x100000000 ) & 0xfffff ) | ( exp << 20 ) ;
151
+ sign && ( high += 0x80000000 ) ;
152
+
153
+ rv . push ( 0xcb , ( high >> 24 ) & 0xff , ( high >> 16 ) & 0xff ,
154
+ ( high >> 8 ) & 0xff , high & 0xff ,
155
+ ( low >> 24 ) & 0xff , ( low >> 16 ) & 0xff ,
156
+ ( low >> 8 ) & 0xff , low & 0xff ) ;
146
157
}
147
158
break ;
148
159
case "string" :
@@ -181,25 +192,35 @@ function encode(rv, // @param ByteArray: result
181
192
}
182
193
break ;
183
194
default : // array or hash
184
- if ( Object . prototype . toString . call ( mix ) === "[object Array]" ) { // array
195
+ if ( _toString . call ( mix ) === "[object Array]" ) { // array
185
196
size = mix . length ;
186
197
setType ( rv , 16 , size , [ 0x90 , 0xdc , 0xdd ] ) ;
187
198
for ( ; i < size ; ++ i ) {
188
199
encode ( rv , mix [ i ] ) ;
189
200
}
190
201
} else { // hash
191
- if ( Object . keys ) {
192
- size = Object . keys ( mix ) . length ;
193
- } else {
194
- for ( i in mix ) {
195
- mix . hasOwnProperty ( i ) && ++ size ;
196
- }
197
- }
198
- setType ( rv , 16 , size , [ 0x80 , 0xde , 0xdf ] ) ;
202
+ // http://d.hatena.ne.jp/uupaa/20101129
203
+ pos = rv . length ; // keep rewrite position
204
+
205
+ // set default type [0x80 + 0]
206
+ rv . push ( 0x80 ) ;
207
+ size = 0 ;
208
+
199
209
for ( i in mix ) {
210
+ ++ size ;
200
211
encode ( rv , i ) ;
201
212
encode ( rv , mix [ i ] ) ;
202
213
}
214
+
215
+ // rewrite hash type.
216
+ if ( size && size < 16 ) {
217
+ rv [ pos ] = 0x80 + size ;
218
+ } else if ( size < 0x10000 ) { // 16
219
+ rv . splice ( pos , 1 , 0xde , size >> 8 , size & 0xff ) ;
220
+ } else if ( size < 0x100000000 ) { // 32
221
+ rv . splice ( pos , 1 , 0xdf , size >>> 24 , ( size >> 16 ) & 0xff ,
222
+ ( size >> 8 ) & 0xff , size & 0xff ) ;
223
+ }
203
224
}
204
225
}
205
226
}
@@ -208,10 +229,8 @@ function encode(rv, // @param ByteArray: result
208
229
209
230
// inner - decoder
210
231
function decode ( ) { // @return Mix:
211
- var rv , undef , size , i = 0 , iz , msb = 0 , c , sign , exp , frac , key , ary ,
212
- that = this ,
213
- data = that . data ,
214
- type = data [ ++ that . index ] ;
232
+ var ary , hash , num = 0 , i = 0 , iz , msb = 0 , c , sign , exp , frac , key ,
233
+ buf = _buf , type = buf [ ++ _idx ] ;
215
234
216
235
if ( type >= 0xe0 ) { // Negative FixNum (111x xxxx) (-32 ~ -1)
217
236
return type - 0x100 ;
@@ -220,113 +239,108 @@ function decode() { // @return Mix:
220
239
return type ;
221
240
}
222
241
if ( type < 0x90 ) { // FixMap (1000 xxxx)
223
- size = type - 0x80 ;
224
- type = 0x80 ;
242
+ num = type - ( type = 0x80 ) ;
225
243
} else if ( type < 0xa0 ) { // FixArray (1001 xxxx)
226
- size = type - 0x90 ;
227
- type = 0x90 ;
244
+ num = type - ( type = 0x90 ) ;
228
245
} else if ( type < 0xc0 ) { // FixRaw (101x xxxx)
229
- size = type - 0xa0 ;
230
- type = 0xa0 ;
246
+ num = type - ( type = 0xa0 ) ;
231
247
}
232
248
switch ( type ) {
233
249
case 0xc0 : return null ;
234
250
case 0xc2 : return false ;
235
251
case 0xc3 : return true ;
236
- case 0xca : rv = readByte ( that , 4 ) ; // float
237
- sign = rv & _sign [ 32 ] ; // 1bit
238
- exp = ( rv >> 23 ) & 0xff ; // 8bits
239
- frac = rv & 0x7fffff ; // 23bits
240
- if ( ! rv || rv === 0x80000000 ) { // 0.0 or -0.0
252
+ case 0xca : // float
253
+ num = buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
254
+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
255
+ sign = num & _sign [ 32 ] ; // 1bit
256
+ exp = ( num >> 23 ) & 0xff ; // 8bits
257
+ frac = num & 0x7fffff ; // 23bits
258
+ if ( ! num || num === 0x80000000 ) { // 0.0 or -0.0
241
259
return 0 ;
242
260
}
243
261
if ( exp === 0xff ) { // NaN or Infinity
244
262
return frac ? NaN : Infinity ;
245
263
}
246
264
return ( sign ? - 1 : 1 ) *
247
265
( frac | 0x800000 ) * Math . pow ( 2 , exp - 127 - 23 ) ; // 127: bias
248
- case 0xcb : rv = readByte ( that , 4 ) ; // double
249
- sign = rv & _sign [ 32 ] ; // 1bit
250
- exp = ( rv >> 20 ) & 0x7ff ; // 11bits
251
- frac = rv & 0xfffff ; // 52bits - 32bits (high word)
252
- if ( ! rv || rv === 0x80000000 ) { // 0.0 or -0.0
266
+ case 0xcb : // double
267
+ num = buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
268
+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
269
+ sign = num & _sign [ 32 ] ; // 1bit
270
+ exp = ( num >> 20 ) & 0x7ff ; // 11bits
271
+ frac = num & 0xfffff ; // 52bits - 32bits (high word)
272
+ if ( ! num || num === 0x80000000 ) { // 0.0 or -0.0
273
+ _idx += 4 ;
253
274
return 0 ;
254
275
}
255
276
if ( exp === 0x7ff ) { // NaN or Infinity
277
+ _idx += 4 ;
256
278
return frac ? NaN : Infinity ;
257
279
}
280
+ num = buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
281
+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
258
282
return ( sign ? - 1 : 1 ) *
259
- ( ( frac | 0x100000 ) * Math . pow ( 2 , exp - 1023 - 20 ) // 1023: bias
260
- + readByte ( that , 4 ) * Math . pow ( 2 , exp - 1023 - 52 ) ) ;
261
- case 0xcf : return readByte ( that , 4 ) * Math . pow ( 2 , 32 ) +
262
- readByte ( that , 4 ) ; // uint 64
263
- case 0xce : return readByte ( that , 4 ) ; // uint 32
264
- case 0xcd : return readByte ( that , 2 ) ; // uint 16
265
- case 0xcc : return readByte ( that , 1 ) ; // uint 8
266
- case 0xd3 : return decodeInt64 ( that ) ; // int 64
267
- case 0xd2 : rv = readByte ( that , 4 ) ; // int 32
268
- case 0xd1 : rv === undef && ( rv = readByte ( that , 2 ) ) ; // int 16
269
- case 0xd0 : rv === undef && ( rv = readByte ( that , 1 ) ) ; // int 8
283
+ ( ( frac | 0x100000 ) * Math . pow ( 2 , exp - 1023 - 20 ) // 1023: bias
284
+ + num * Math . pow ( 2 , exp - 1023 - 52 ) ) ;
285
+ // 0xcf: uint64, 0xce: uint32, 0xcd: uint16
286
+ case 0xcf : num = buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
287
+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
288
+ return num * 0x100000000 +
289
+ buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
290
+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
291
+ case 0xce : num += buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) ;
292
+ case 0xcd : num += buf [ ++ _idx ] << 8 ;
293
+ case 0xcc : return num + buf [ ++ _idx ] ;
294
+ case 0xd3 : return decodeInt64 ( ) ;
295
+ // 0xd2: int32, 0xd1: int16, 0xd0: int8
296
+ case 0xd2 : num += buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) ;
297
+ case 0xd1 : num += buf [ ++ _idx ] << 8 ;
298
+ case 0xd0 : num += buf [ ++ _idx ] ;
270
299
msb = 4 << ( ( type & 0x3 ) + 1 ) ; // 8, 16, 32
271
- return rv < _sign [ msb ] ? rv : rv - _sign [ msb ] * 2 ;
272
- case 0xdb : size = readByte ( that , 4 ) ; // raw 32
273
- case 0xda : size === undef && ( size = readByte ( that , 2 ) ) ; // raw 16
274
- case 0xa0 : i = that . index + 1 ; // raw
275
- that . index += size ;
300
+ return num < _sign [ msb ] ? num : num - _sign [ msb ] * 2 ;
301
+ // 0xdb: raw32, 0xda: raw16, 0xa0: raw
302
+ case 0xdb : num += buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) ;
303
+ case 0xda : num += ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
304
+ case 0xa0 : i = _idx + 1 ;
276
305
// utf8.decode
277
- _pooledArray = [ ] ;
278
- ary = _pooledArray ; // alias
279
- for ( iz = i + size ; i < iz ; ++ i ) {
280
- c = data [ i ] ; // first byte
281
- if ( c < 0x80 ) { // ASCII(0x00 ~ 0x7f)
282
- ary . push ( c ) ;
283
- } else if ( c < 0xe0 ) {
284
- ary . push ( ( c & 0x1f ) << 6 | ( data [ ++ i ] & 0x3f ) ) ;
285
- } else if ( c < 0xf0 ) {
286
- ary . push ( ( c & 0x0f ) << 12 | ( data [ ++ i ] & 0x3f ) << 6
287
- | ( data [ ++ i ] & 0x3f ) ) ;
288
- }
306
+ _ary = [ ] ;
307
+ ary = _ary ; // alias
308
+ for ( iz = i + num ; i < iz ; ++ i ) {
309
+ c = buf [ i ] ; // first byte
310
+ ary . push ( c < 0x80 ? c : // ASCII(0x00 ~ 0x7f)
311
+ c < 0xe0 ? ( ( c & 0x1f ) << 6 | ( buf [ ++ i ] & 0x3f ) ) :
312
+ c < 0xf0 ? ( ( c & 0x0f ) << 12 | ( buf [ ++ i ] & 0x3f ) << 6
313
+ | ( buf [ ++ i ] & 0x3f ) ) : 0 ) ;
289
314
}
315
+ _idx += num ;
290
316
return ary . length < 1024000 ? String . fromCharCode . apply ( null , ary )
291
317
: byteArrayToByteString ( ary ) ;
292
- case 0xdf : size = readByte ( that , 4 ) ; // map 32
293
- case 0xde : size === undef && ( size = readByte ( that , 2 ) ) ; // map 16
294
- case 0x80 : for ( rv = { } ; i < size ; ++ i ) { // map
295
- key = that . decode ( ) ;
296
- rv [ key ] = that . decode ( ) ; // key/value pair
318
+ // 0xdf: map32, 0xde: map16, 0x80: map
319
+ case 0xdf : num += buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) ;
320
+ case 0xde : num += ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
321
+ case 0x80 : for ( hash = { } ; i < num ; ++ i ) {
322
+ key = decode ( ) ;
323
+ hash [ key ] = decode ( ) ; // key/value pair
297
324
}
298
- return rv ;
299
- case 0xdd : size = readByte ( that , 4 ) ; // array 32
300
- case 0xdc : size === undef && ( size = readByte ( that , 2 ) ) ; // array 16
301
- case 0x90 : for ( rv = [ ] ; i < size ; ++ i ) { // array
302
- rv . push ( that . decode ( ) ) ;
325
+ return hash ;
326
+ // 0xdd: array32, 0xdc: array16, 0x90: array
327
+ case 0xdd : num += buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) ;
328
+ case 0xdc : num += ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
329
+ case 0x90 : for ( ary = [ ] ; i < num ; ++ i ) {
330
+ ary . push ( decode ( ) ) ;
303
331
}
332
+ return ary ;
304
333
}
305
- return rv ;
306
- }
307
-
308
- // inner - read byte
309
- function readByte ( that , // @param Object:
310
- size ) { // @param Number:
311
- // @return Number:
312
- var rv = 0 , data = that . data , i = that . index ;
313
-
314
- switch ( size ) {
315
- case 4 : rv += data [ ++ i ] * 0x1000000 + ( data [ ++ i ] << 16 ) ;
316
- case 2 : rv += data [ ++ i ] << 8 ;
317
- case 1 : rv += data [ ++ i ] ;
318
- }
319
- that . index = i ;
320
- return rv ;
334
+ return ;
321
335
}
322
336
323
337
// inner - decode int64
324
- function decodeInt64 ( that ) { // @param Object:
338
+ function decodeInt64 ( ) {
325
339
// @return Number:
326
340
var rv , overflow = 0 ,
327
- bytes = that . data . slice ( that . index + 1 , that . index + 9 ) ;
341
+ bytes = _buf . slice ( _idx + 1 , _idx + 9 ) ;
328
342
329
- that . index += 8 ;
343
+ _idx += 8 ;
330
344
331
345
// avoid overflow
332
346
if ( bytes [ 0 ] & 0x80 ) {
@@ -637,7 +651,6 @@ function base64encode(data) { // @param ByteArray:
637
651
638
652
for ( ; i < 0x100 ; ++ i ) {
639
653
v = String . fromCharCode ( i ) ;
640
- _bit2num [ ( "0000000" + i . toString ( 2 ) ) . slice ( - 8 ) ] = i ;
641
654
_bin2num [ v ] = i ; // "\00" -> 0x00
642
655
_num2bin [ i ] = v ; // 0 -> "\00"
643
656
}
0 commit comments