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"}*/
22
33// === msgpack ===
44// MessagePack -> http://msgpack.sourceforge.net/
@@ -18,15 +18,15 @@ globalScope.msgpack = {
1818} ;
1919
2020var _ie = / M S I E / . test ( navigator . userAgent ) ,
21- _bit2num = { } , // BitStringToNumber { "00000000": 0, ... "11111111": 255 }
2221 _bin2num = { } , // BinaryStringToNumber { "\00": 0, ... "\ff": 255 }
2322 _num2bin = { } , // NumberToBinaryString { 0: "\00", ... 255: "\ff" }
2423 _num2b64 = ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
2524 "abcdefghijklmnopqrstuvwxyz0123456789+/" ) . split ( "" ) ,
2625 _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 ;
3030
3131// for WebWorkers Code Block
3232self . importScripts && ( onmessage = function ( event ) {
@@ -52,19 +52,19 @@ function msgpackpack(data, // @param Mix:
5252
5353// msgpack.unpack
5454function msgpackunpack ( data ) { // @param BinaryString/ByteArray:
55- // @return Mix:
55+ // @return Mix/undefined: undefined is error return
5656 // [1][String to mix] msgpack.unpack("...") -> {}
5757 // [2][ByteArray to mix] msgpack.unpack([...]) -> {}
5858
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 ( ) ;
6262}
6363
6464// inner - encoder
6565function encode ( rv , // @param ByteArray: result
6666 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 ,
6868 high , low , i64 = 0 , sign , exp , frac ;
6969
7070 if ( mix == null ) { // null or undefined
@@ -111,38 +111,49 @@ function encode(rv, // @param ByteArray: result
111111 }
112112 if ( i64 ) {
113113 high = Math . floor ( mix / 0x100000000 ) ;
114- low = mix & ( 0x100000000 - 1 ) ;
114+ low = mix & 0xffffffff ;
115115 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 ) ;
120120 }
121121 } 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
125124 sign = mix < 0 ;
126125 sign && ( mix *= - 1 ) ;
127126
127+ // exp => 11 bits
128128 // add offset 1023 to ensure positive
129129 // 0.6931471805599453 = Math.LN2;
130130 exp = ( ( Math . log ( mix ) / 0.6931471805599453 ) + 1023 ) | 0 ;
131131
132+ // frac => 53 bits
132133 // shift 52 - (exp - 1023) bits to make integer part exactly 53 bits,
133134 // 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 ) ;
146157 }
147158 break ;
148159 case "string" :
@@ -181,25 +192,35 @@ function encode(rv, // @param ByteArray: result
181192 }
182193 break ;
183194 default : // array or hash
184- if ( Object . prototype . toString . call ( mix ) === "[object Array]" ) { // array
195+ if ( _toString . call ( mix ) === "[object Array]" ) { // array
185196 size = mix . length ;
186197 setType ( rv , 16 , size , [ 0x90 , 0xdc , 0xdd ] ) ;
187198 for ( ; i < size ; ++ i ) {
188199 encode ( rv , mix [ i ] ) ;
189200 }
190201 } 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+
199209 for ( i in mix ) {
210+ ++ size ;
200211 encode ( rv , i ) ;
201212 encode ( rv , mix [ i ] ) ;
202213 }
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+ }
203224 }
204225 }
205226 }
@@ -208,10 +229,8 @@ function encode(rv, // @param ByteArray: result
208229
209230// inner - decoder
210231function 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 ] ;
215234
216235 if ( type >= 0xe0 ) { // Negative FixNum (111x xxxx) (-32 ~ -1)
217236 return type - 0x100 ;
@@ -220,113 +239,108 @@ function decode() { // @return Mix:
220239 return type ;
221240 }
222241 if ( type < 0x90 ) { // FixMap (1000 xxxx)
223- size = type - 0x80 ;
224- type = 0x80 ;
242+ num = type - ( type = 0x80 ) ;
225243 } else if ( type < 0xa0 ) { // FixArray (1001 xxxx)
226- size = type - 0x90 ;
227- type = 0x90 ;
244+ num = type - ( type = 0x90 ) ;
228245 } else if ( type < 0xc0 ) { // FixRaw (101x xxxx)
229- size = type - 0xa0 ;
230- type = 0xa0 ;
246+ num = type - ( type = 0xa0 ) ;
231247 }
232248 switch ( type ) {
233249 case 0xc0 : return null ;
234250 case 0xc2 : return false ;
235251 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
241259 return 0 ;
242260 }
243261 if ( exp === 0xff ) { // NaN or Infinity
244262 return frac ? NaN : Infinity ;
245263 }
246264 return ( sign ? - 1 : 1 ) *
247265 ( 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 ;
253274 return 0 ;
254275 }
255276 if ( exp === 0x7ff ) { // NaN or Infinity
277+ _idx += 4 ;
256278 return frac ? NaN : Infinity ;
257279 }
280+ num = buf [ ++ _idx ] * 0x1000000 + ( buf [ ++ _idx ] << 16 ) +
281+ ( buf [ ++ _idx ] << 8 ) + buf [ ++ _idx ] ;
258282 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 ] ;
270299 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 ;
276305 // 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 ) ;
289314 }
315+ _idx += num ;
290316 return ary . length < 1024000 ? String . fromCharCode . apply ( null , ary )
291317 : 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
297324 }
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 ( ) ) ;
303331 }
332+ return ary ;
304333 }
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 ;
321335}
322336
323337// inner - decode int64
324- function decodeInt64 ( that ) { // @param Object:
338+ function decodeInt64 ( ) {
325339 // @return Number:
326340 var rv , overflow = 0 ,
327- bytes = that . data . slice ( that . index + 1 , that . index + 9 ) ;
341+ bytes = _buf . slice ( _idx + 1 , _idx + 9 ) ;
328342
329- that . index += 8 ;
343+ _idx += 8 ;
330344
331345 // avoid overflow
332346 if ( bytes [ 0 ] & 0x80 ) {
@@ -637,7 +651,6 @@ function base64encode(data) { // @param ByteArray:
637651
638652 for ( ; i < 0x100 ; ++ i ) {
639653 v = String . fromCharCode ( i ) ;
640- _bit2num [ ( "0000000" + i . toString ( 2 ) ) . slice ( - 8 ) ] = i ;
641654 _bin2num [ v ] = i ; // "\00" -> 0x00
642655 _num2bin [ i ] = v ; // 0 -> "\00"
643656 }
0 commit comments