1
- /*!{id:msgpack.js,ver:1.01 ,license:"MIT",author:"uupaa.js@gmail .com"}*/
1
+ /*!{id:msgpack.js,ver:1.02 ,license:"MIT",author:"uupaa.js@gmail .com"}*/
2
2
3
3
// === msgpack ===
4
4
// MessagePack -> http://msgpack.sourceforge.net/
@@ -24,7 +24,7 @@ var _ie = /MSIE/.test(navigator.userAgent),
24
24
_num2b64 = ( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
25
25
"abcdefghijklmnopqrstuvwxyz0123456789+/" ) . split ( "" ) ,
26
26
_sign = { 8 : 0x80 , 16 : 0x8000 , 32 : 0x80000000 } ,
27
- _split8char = / . { 8 } / g;
27
+ _8bits = / [ 0 1 ] { 8 } / g;
28
28
29
29
// for WebWorkers Code Block
30
30
self . importScripts && ( onmessage = function ( event ) {
@@ -42,10 +42,21 @@ function msgpackpack(data, // @param Mix:
42
42
// [1][mix to String] msgpack.pack({}, true) -> "..."
43
43
// [2][mix to ByteArray] msgpack.pack({}) -> [...]
44
44
45
- var byteArray = encode ( [ ] , data ) ;
45
+ var byteArray = encode ( [ ] , data ) , rv , i , iz , num2bin = _num2bin ;
46
46
47
- return toString ? String . fromCharCode . apply ( null , byteArray ) // toString
48
- : byteArray ;
47
+ if ( toString ) {
48
+ // http://d.hatena.ne.jp/uupaa/20101128
49
+ try {
50
+ return String . fromCharCode . apply ( this , byteArray ) ; // toString
51
+ } catch ( err ) {
52
+ ; // avoid "Maximum call stack size exceeded"
53
+ }
54
+ for ( rv = [ ] , i = 0 , iz = byteArray . length ; i < iz ; ++ i ) {
55
+ rv [ i ] = num2bin [ byteArray [ i ] ] ;
56
+ }
57
+ return rv . join ( "" ) ;
58
+ }
59
+ return byteArray ;
49
60
}
50
61
51
62
// msgpack.unpack
@@ -62,7 +73,7 @@ function msgpackunpack(data) { // @param BinaryString/ByteArray:
62
73
// inner - encoder
63
74
function encode ( rv , // @param ByteArray: result
64
75
mix ) { // @param Mix: source data
65
- var size = 0 , i = 0 , iz , c , ary , hash ,
76
+ var size = 0 , i = 0 , iz , c , hash , pos ,
66
77
high , low , i64 = 0 , sign , exp , frac ;
67
78
68
79
if ( mix == null ) { // null or undefined
@@ -77,7 +88,7 @@ function encode(rv, // @param ByteArray: result
77
88
rv . push ( 0xcb , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff ) ; // quiet NaN
78
89
} else if ( mix === Infinity ) {
79
90
rv . push ( 0xcb , 0x7f , 0xf0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ) ; // positive infinity
80
- } else if ( Math . floor ( mix ) === mix ) {
91
+ } else if ( Math . floor ( mix ) === mix ) { // int or uint
81
92
if ( mix < 0 ) { // int
82
93
if ( mix >= - 32 ) { // negative fixnum
83
94
rv . push ( 0xe0 + mix + 32 ) ;
@@ -132,30 +143,52 @@ function encode(rv, // @param ByteArray: result
132
143
toString ( 2 ) . slice ( 1 ) ;
133
144
134
145
// exp is between 1 and 2047. make it 11 bits
135
- exp = ( "000000000" + exp . toString ( 2 ) ) . slice ( - 11 ) ;
136
-
137
- ary = ( + sign + exp + frac ) . match ( _split8char ) ;
146
+ // http://d.hatena.ne.jp/uupaa/20101128
147
+ if ( ! sign ) {
148
+ ary = ( ( exp + 4096 ) . toString ( 2 ) . slice ( 1 ) + frac ) . match ( _8bits ) ;
149
+ } else {
150
+ ary = ( ( exp + 2048 ) . toString ( 2 ) + frac ) . match ( _8bits ) ;
151
+ }
138
152
rv . push ( 0xcb , hash [ ary [ 0 ] ] , hash [ ary [ 1 ] ] ,
139
153
hash [ ary [ 2 ] ] , hash [ ary [ 3 ] ] ,
140
154
hash [ ary [ 4 ] ] , hash [ ary [ 5 ] ] ,
141
155
hash [ ary [ 6 ] ] , hash [ ary [ 7 ] ] ) ;
142
156
}
143
157
break ;
144
158
case "string" :
159
+ // http://d.hatena.ne.jp/uupaa/20101128
160
+ iz = mix . length ;
161
+ pos = rv . length ; // keep rewrite position
162
+
163
+ // set default type [0xa0 + ASCIIString.length]
164
+ rv . push ( 0xa0 + iz ) ;
165
+
145
166
// utf8.encode
146
- for ( ary = [ ] , iz = mix . length , i = 0 ; i < iz ; ++ i ) {
167
+ for ( i = 0 ; i < iz ; ++ i ) {
147
168
c = mix . charCodeAt ( i ) ;
148
169
if ( c < 0x80 ) { // ASCII(0x00 ~ 0x7f)
149
- ary . push ( c & 0x7f ) ;
170
+ rv . push ( c & 0x7f ) ;
150
171
} else if ( c < 0x0800 ) {
151
- ary . push ( ( ( c >>> 6 ) & 0x1f ) | 0xc0 , ( c & 0x3f ) | 0x80 ) ;
172
+ rv . push ( ( ( c >>> 6 ) & 0x1f ) | 0xc0 , ( c & 0x3f ) | 0x80 ) ;
152
173
} else if ( c < 0x10000 ) {
153
- ary . push ( ( ( c >>> 12 ) & 0x0f ) | 0xe0 ,
174
+ rv . push ( ( ( c >>> 12 ) & 0x0f ) | 0xe0 ,
154
175
( ( c >>> 6 ) & 0x3f ) | 0x80 , ( c & 0x3f ) | 0x80 ) ;
155
176
}
156
177
}
157
- setType ( rv , 32 , ary . length , [ 0xa0 , 0xda , 0xdb ] ) ;
158
- Array . prototype . push . apply ( rv , ary ) ;
178
+ size = rv . length - pos - 1 ; // -1 = default type(0xa0 + length)
179
+
180
+ // rewrite string type.
181
+ if ( iz !== size ) {
182
+ // has none ascii string or length >= 32
183
+ if ( size < 32 ) {
184
+ rv [ pos ] = 0xa0 + size ;
185
+ } else if ( size < 0x10000 ) { // 16
186
+ rv . splice ( pos , 1 , 0xda , size >> 8 , size & 0xff ) ;
187
+ } else if ( size < 0x100000000 ) { // 32
188
+ rv . splice ( pos , 1 , 0xdb , size >>> 24 , ( size >> 16 ) & 0xff ,
189
+ ( size >> 8 ) & 0xff , size & 0xff ) ;
190
+ }
191
+ }
159
192
break ;
160
193
default : // array or hash
161
194
if ( Object . prototype . toString . call ( mix ) === "[object Array]" ) { // array
0 commit comments