1 /* Base64 library for ActionScript 3.0. |
|
2 * Based on: Ma Bingyao code. |
|
3 * Optimized by: Jean-Philippe Auclair / jpauclair.wordpress.com |
|
4 * Copyright (C) 2007 Ma Bingyao <andot@ujn.edu.cn> |
|
5 * LastModified: Oct 26, 2009 |
|
6 * This library is free. You can redistribute it and/or modify it. |
|
7 */ |
|
8 package com.hurlant.util{ |
|
9 import flash.utils.ByteArray; |
|
10 |
|
11 public class Base64 |
|
12 { |
|
13 private static const _encodeChars : Vector.<int> = InitEncoreChar(); |
|
14 private static const _decodeChars : Vector.<int> = InitDecodeChar(); |
|
15 |
|
16 public static function encodeByteArray(data : ByteArray) : String |
|
17 { |
|
18 var out : ByteArray = new ByteArray(); |
|
19 //Presetting the length keep the memory smaller and optimize speed since there is no "grow" needed |
|
20 out.length = (2 + data.length - ((data.length + 2) % 3)) * 4 / 3; //Preset length //1.6 to 1.5 ms |
|
21 var i : int = 0; |
|
22 var r : int = data.length % 3; |
|
23 var len : int = data.length - r; |
|
24 var c : int; //read (3) character AND write (4) characters |
|
25 |
|
26 while (i < len) |
|
27 { |
|
28 //Read 3 Characters (8bit * 3 = 24 bits) |
|
29 c = data[i++] << 16 | data[i++] << 8 | data[i++]; |
|
30 |
|
31 //Cannot optimize this to read int because of the positioning overhead. (as3 bytearray seek is slow) |
|
32 //Convert to 4 Characters (6 bit * 4 = 24 bits) |
|
33 c = (_encodeChars[c >>> 18] << 24) | (_encodeChars[c >>> 12 & 0x3f] << 16) | (_encodeChars[c >>> 6 & 0x3f] << 8) | _encodeChars[c & 0x3f]; |
|
34 |
|
35 //Optimization: On older and slower computer, do one write Int instead of 4 write byte: 1.5 to 0.71 ms |
|
36 out.writeInt(c); |
|
37 /* |
|
38 out.writeByte(_encodeChars[c >> 18] ); |
|
39 out.writeByte(_encodeChars[c >> 12 & 0x3f]); |
|
40 out.writeByte(_encodeChars[c >> 6 & 0x3f]); |
|
41 out.writeByte(_encodeChars[c & 0x3f]); |
|
42 */ |
|
43 } |
|
44 |
|
45 if (r == 1) //Need two "=" padding |
|
46 { |
|
47 //Read one char, write two chars, write padding |
|
48 c = data[i]; |
|
49 c = (_encodeChars[c >>> 2] << 24) | (_encodeChars[(c & 0x03) << 4] << 16) | 61 << 8 | 61; |
|
50 out.writeInt(c); |
|
51 } |
|
52 else if (r == 2) //Need one "=" padding |
|
53 { |
|
54 c = data[i++] << 8 | data[i]; |
|
55 c = (_encodeChars[c >>> 10] << 24) | (_encodeChars[c >>> 4 & 0x3f] << 16) | (_encodeChars[(c & 0x0f) << 2] << 8) | 61; |
|
56 out.writeInt(c); |
|
57 } |
|
58 |
|
59 out.position = 0; |
|
60 return out.readUTFBytes(out.length); |
|
61 } |
|
62 |
|
63 |
|
64 public static function decodeToByteArray(str : String) : ByteArray |
|
65 { |
|
66 var c1 : int; |
|
67 var c2 : int; |
|
68 var c3 : int; |
|
69 var c4 : int; |
|
70 var i : int; |
|
71 var len : int; |
|
72 var out : ByteArray; |
|
73 len = str.length; |
|
74 i = 0; |
|
75 out = new ByteArray(); |
|
76 var byteString : ByteArray = new ByteArray(); |
|
77 byteString.writeUTFBytes(str); |
|
78 while (i < len) |
|
79 { |
|
80 //c1 |
|
81 do |
|
82 { |
|
83 c1 = _decodeChars[byteString[i++]]; |
|
84 } while (i < len && c1 == -1); |
|
85 if (c1 == -1) break; |
|
86 |
|
87 //c2 |
|
88 do |
|
89 { |
|
90 c2 = _decodeChars[byteString[i++]]; |
|
91 } while (i < len && c2 == -1); |
|
92 if (c2 == -1) break; |
|
93 |
|
94 out.writeByte((c1 << 2) | ((c2 & 0x30) >> 4)); |
|
95 |
|
96 //c3 |
|
97 do |
|
98 { |
|
99 c3 = byteString[i++]; |
|
100 if (c3 == 61) return out; |
|
101 |
|
102 c3 = _decodeChars[c3]; |
|
103 } while (i < len && c3 == -1); |
|
104 if (c3 == -1) break; |
|
105 |
|
106 out.writeByte(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2)); |
|
107 |
|
108 //c4 |
|
109 do { |
|
110 c4 = byteString[i++]; |
|
111 if (c4 == 61) return out; |
|
112 |
|
113 c4 = _decodeChars[c4]; |
|
114 } while (i < len && c4 == -1); |
|
115 if (c4 == -1) break; |
|
116 |
|
117 out.writeByte(((c3 & 0x03) << 6) | c4); |
|
118 |
|
119 } |
|
120 |
|
121 out.position = 0; |
|
122 |
|
123 return out; |
|
124 } |
|
125 |
|
126 public static function encode(data : String) : String { |
|
127 // Convert string to ByteArray |
|
128 var bytes : ByteArray = new ByteArray(); |
|
129 bytes.writeUTFBytes(data); |
|
130 |
|
131 // Return encoded ByteArray |
|
132 return encodeByteArray(bytes); |
|
133 } |
|
134 |
|
135 public static function decode(data : String) : String { |
|
136 // Decode data to ByteArray |
|
137 var bytes : ByteArray = decodeToByteArray(data); |
|
138 |
|
139 // Convert to string and return |
|
140 return bytes.readUTFBytes(bytes.length); |
|
141 } |
|
142 |
|
143 public static function InitEncoreChar() : Vector.<int> |
|
144 { |
|
145 var encodeChars : Vector.<int> = new Vector.<int>(); |
|
146 // We could push the number directly, but i think it's nice to see the characters (with no overhead on encode/decode) |
|
147 var chars : String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
|
148 for (var i : int = 0; i < 64; i++) |
|
149 { |
|
150 encodeChars.push(chars.charCodeAt(i)); |
|
151 } |
|
152 /* |
|
153 encodeChars.push( |
|
154 65, 66, 67, 68, 69, 70, 71, 72, |
|
155 73, 74, 75, 76, 77, 78, 79, 80, |
|
156 81, 82, 83, 84, 85, 86, 87, 88, |
|
157 89, 90, 97, 98, 99, 100, 101, 102, |
|
158 103, 104, 105, 106, 107, 108, 109, 110, |
|
159 111, 112, 113, 114, 115, 116, 117, 118, |
|
160 119, 120, 121, 122, 48, 49, 50, 51, |
|
161 52, 53, 54, 55, 56, 57, 43, 47); |
|
162 */ |
|
163 return encodeChars; |
|
164 } |
|
165 |
|
166 public static function InitDecodeChar() : Vector.<int> |
|
167 { |
|
168 var decodeChars : Vector.<int> = new Vector.<int>(); |
|
169 |
|
170 decodeChars.push(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
171 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
172 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, |
|
173 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, |
|
174 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
|
175 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, |
|
176 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, |
|
177 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 |
|
178 - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
179 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
180 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
181 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
182 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
183 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
184 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
|
185 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); |
|
186 return decodeChars; |
|
187 } |
|
188 } |
|
189 } |
|