blob: 9324e387f4bf8b8ce6635508fb6f156e028a9038 [file] [log] [blame]
Wentao Shangbd63e462012-12-03 16:19:33 -08001/**
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07002 * This class contains utilities to help parse the data
Jeff Thompson146d7de2012-11-17 16:15:28 -08003 * author: Meki Cheraoui, Jeff Thompson
Jeff Thompson745026e2012-10-13 12:49:20 -07004 * See COPYING for copyright and distribution information.
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07005 */
6
Jeff Thompson3ed09eb2013-07-29 14:54:23 -07007/**
8 * A DataUtils has static methods for converting data.
9 * @constructor
10 */
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070011var DataUtils = function DataUtils(){
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070012};
13
14
15/*
Jeff Thompson3ed09eb2013-07-29 14:54:23 -070016 * NOTE THIS IS CURRENTLY NOT BEING USED
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070017 *
18 */
19
Meki Cherkaoui8f173612012-06-06 01:05:40 -070020DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070021 "QRSTUVWXYZabcdef" +
22 "ghijklmnopqrstuv" +
23 "wxyz0123456789+/" +
24 "=";
25
Meki Cherkaoui8f173612012-06-06 01:05:40 -070026
27/**
28 * Raw String to Base 64
29 */
Meki Cherkaouib21911b2012-05-18 16:54:37 -070030DataUtils.stringtoBase64=function stringtoBase64(input) {
Jeff Thompson3a09fc82013-07-26 19:59:05 -070031 //input = escape(input);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070032 var output = "";
33 var chr1, chr2, chr3 = "";
34 var enc1, enc2, enc3, enc4 = "";
35 var i = 0;
36
37 do {
38 chr1 = input.charCodeAt(i++);
39 chr2 = input.charCodeAt(i++);
40 chr3 = input.charCodeAt(i++);
41
42 enc1 = chr1 >> 2;
43 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
44 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
45 enc4 = chr3 & 63;
46
47 if (isNaN(chr2)) {
48 enc3 = enc4 = 64;
49 } else if (isNaN(chr3)) {
50 enc4 = 64;
51 }
52
53 output = output +
Meki Cherkaoui8f173612012-06-06 01:05:40 -070054 DataUtils.keyStr.charAt(enc1) +
55 DataUtils.keyStr.charAt(enc2) +
56 DataUtils.keyStr.charAt(enc3) +
57 DataUtils.keyStr.charAt(enc4);
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070058 chr1 = chr2 = chr3 = "";
59 enc1 = enc2 = enc3 = enc4 = "";
60 } while (i < input.length);
61
62 return output;
63 }
64
Meki Cherkaoui8f173612012-06-06 01:05:40 -070065/**
66 * Base 64 to Raw String
67 */
Meki Cherkaouib21911b2012-05-18 16:54:37 -070068DataUtils.base64toString = function base64toString(input) {
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070069 var output = "";
70 var chr1, chr2, chr3 = "";
71 var enc1, enc2, enc3, enc4 = "";
72 var i = 0;
73
74 // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
75 var base64test = /[^A-Za-z0-9\+\/\=]/g;
Jeff Thompson74957972012-10-07 21:14:32 -070076 /* Test for invalid characters. */
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070077 if (base64test.exec(input)) {
78 alert("There were invalid base64 characters in the input text.\n" +
79 "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
80 "Expect errors in decoding.");
81 }
Meki Cherkaoui8f173612012-06-06 01:05:40 -070082
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070083 input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
84
85 do {
Meki Cherkaoui8f173612012-06-06 01:05:40 -070086 enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
87 enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
88 enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
89 enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));
Meki Cherkaouif441d3a2012-04-22 15:17:52 -070090
91 chr1 = (enc1 << 2) | (enc2 >> 4);
92 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
93 chr3 = ((enc3 & 3) << 6) | enc4;
94
95 output = output + String.fromCharCode(chr1);
96
97 if (enc3 != 64) {
98 output = output + String.fromCharCode(chr2);
99 }
100 if (enc4 != 64) {
101 output = output + String.fromCharCode(chr3);
102 }
103
104 chr1 = chr2 = chr3 = "";
105 enc1 = enc2 = enc3 = enc4 = "";
106
107 } while (i < input.length);
108
Jeff Thompson2d9c5aa2013-08-09 11:27:32 -0700109 return output;
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700110 };
Meki Cherkaouif441d3a2012-04-22 15:17:52 -0700111
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700112/**
Jeff Thompson34a585f2012-11-11 19:16:02 -0800113 * Uint8Array to Hex String
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700114 */
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700115//http://ejohn.org/blog/numbers-hex-and-colors/
Wentao Shang0e291c82012-12-02 23:36:29 -0800116DataUtils.toHex = function(args){
117 if (LOG>4) console.log('ABOUT TO CONVERT '+ args);
118 //console.log(args);
Jeff Thompson8b44aa12012-11-11 18:39:47 -0800119 var ret = "";
Wentao Shang0e291c82012-12-02 23:36:29 -0800120 for ( var i = 0; i < args.length; i++ )
121 ret += (args[i] < 16 ? "0" : "") + args[i].toString(16);
Jeff Thompson8b44aa12012-11-11 18:39:47 -0800122 if (LOG>4) console.log('Converted to: ' + ret);
123 return ret; //.toUpperCase();
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700124}
125
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700126/**
Jeff Thompsona566e792012-10-06 21:46:34 -0700127 * Raw string to hex string.
128 */
Wentao Shang0e291c82012-12-02 23:36:29 -0800129DataUtils.stringToHex = function(args){
Jeff Thompsona566e792012-10-06 21:46:34 -0700130 var ret = "";
Wentao Shang0e291c82012-12-02 23:36:29 -0800131 for (var i = 0; i < args.length; ++i) {
132 var value = args.charCodeAt(i);
Jeff Thompsona566e792012-10-06 21:46:34 -0700133 ret += (value < 16 ? "0" : "") + value.toString(16);
134 }
135 return ret;
136}
137
138/**
Jeff Thompson34a585f2012-11-11 19:16:02 -0800139 * Uint8Array to raw string.
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700140 */
Wentao Shang0e291c82012-12-02 23:36:29 -0800141DataUtils.toString = function(args){
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700142 //console.log(arguments);
143 var ret = "";
Wentao Shang0e291c82012-12-02 23:36:29 -0800144 for ( var i = 0; i < args.length; i++ )
145 ret += String.fromCharCode(args[i]);
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700146 return ret;
147}
148
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700149/**
Jeff Thompson34a585f2012-11-11 19:16:02 -0800150 * Hex String to Uint8Array.
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700151 */
Jeff Thompson34a585f2012-11-11 19:16:02 -0800152DataUtils.toNumbers = function(str) {
153 if (typeof str == 'string') {
154 var ret = new Uint8Array(Math.floor(str.length / 2));
155 var i = 0;
156 str.replace(/(..)/g, function(str) {
157 ret[i++] = parseInt(str, 16);
158 });
159 return ret;
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700160 }
161}
162
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700163/**
Jeff Thompson74957972012-10-07 21:14:32 -0700164 * Hex String to raw string.
165 */
166DataUtils.hexToRawString = function(str) {
167 if(typeof str =='string') {
168 var ret = "";
169 str.replace(/(..)/g, function(s) {
170 ret += String.fromCharCode(parseInt(s, 16));
171 });
172 return ret;
173 }
174}
175
176/**
Jeff Thompson34a585f2012-11-11 19:16:02 -0800177 * Raw String to Uint8Array.
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700178 */
Wentao Shangab9018d2012-12-18 11:35:45 -0800179DataUtils.toNumbersFromString = function(str) {
Jeff Thompson34a585f2012-11-11 19:16:02 -0800180 var bytes = new Uint8Array(str.length);
Meki Cherkaouib21911b2012-05-18 16:54:37 -0700181 for(var i=0;i<str.length;i++)
182 bytes[i] = str.charCodeAt(i);
183 return bytes;
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700184}
185
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700186/**
Jeff Thompsonadba4912012-11-15 22:29:13 -0800187 * Encode str as utf8 and return as Uint8Array.
Jeff Thompson3a782592012-11-18 17:34:33 -0800188 * TODO: Use TextEncoder when available.
Jeff Thompsonadba4912012-11-15 22:29:13 -0800189 */
190DataUtils.stringToUtf8Array = function(str) {
191 return DataUtils.toNumbersFromString(str2rstr_utf8(str));
192}
193
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700194/**
Jeff Thompson5e6ab9a2012-11-28 21:19:59 -0800195 * arrays is an array of Uint8Array. Return a new Uint8Array which is the concatenation of all.
Jeff Thompson95f935b2012-11-11 20:29:01 -0800196 */
Jeff Thompson5e6ab9a2012-11-28 21:19:59 -0800197DataUtils.concatArrays = function(arrays) {
198 var totalLength = 0;
199 for (var i = 0; i < arrays.length; ++i)
200 totalLength += arrays[i].length;
201
202 var result = new Uint8Array(totalLength);
203 var offset = 0;
204 for (var i = 0; i < arrays.length; ++i) {
205 result.set(arrays[i], offset);
206 offset += arrays[i].length;
207 }
208 return result;
209
Jeff Thompson95f935b2012-11-11 20:29:01 -0800210}
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700211
Jeff Thompson3a782592012-11-18 17:34:33 -0800212// TODO: Take Uint8Array and use TextDecoder when available.
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700213DataUtils.decodeUtf8 = function (utftext) {
214 var string = "";
215 var i = 0;
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700216 var c = 0;
217 var c1 = 0;
218 var c2 = 0;
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700219
220 while ( i < utftext.length ) {
221
222 c = utftext.charCodeAt(i);
223
224 if (c < 128) {
225 string += String.fromCharCode(c);
226 i++;
227 }
228 else if((c > 191) && (c < 224)) {
229 c2 = utftext.charCodeAt(i+1);
230 string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
231 i += 2;
232 }
233 else {
234 c2 = utftext.charCodeAt(i+1);
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700235 var c3 = utftext.charCodeAt(i+2);
Meki Cherkaoui8f173612012-06-06 01:05:40 -0700236 string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
237 i += 3;
238 }
239
240 }
241
242 return string;
243 };
244
Jeff Thompsonbb976092012-09-29 17:01:38 -0700245/**
246 * Return true if a1 and a2 are the same length with equal elements.
247 */
248DataUtils.arraysEqual = function(a1, a2){
249 if (a1.length != a2.length)
250 return false;
251
252 for (var i = 0; i < a1.length; ++i) {
253 if (a1[i] != a2[i])
254 return false;
255 }
256
257 return true;
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700258};
259
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700260/**
Jeff Thompson95f935b2012-11-11 20:29:01 -0800261 * Convert the big endian Uint8Array to an unsigned int.
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700262 * Don't check for overflow.
263 */
264DataUtils.bigEndianToUnsignedInt = function(bytes) {
265 var result = 0;
266 for (var i = 0; i < bytes.length; ++i) {
267 result <<= 8;
268 result += bytes[i];
269 }
270 return result;
271};
272
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700273/**
Jeff Thompson95f935b2012-11-11 20:29:01 -0800274 * Convert the int value to a new big endian Uint8Array and return.
275 * If value is 0 or negative, return Uint8Array(0).
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700276 */
277DataUtils.nonNegativeIntToBigEndian = function(value) {
Jeff Thompson40df2fa2012-11-24 09:59:12 -0800278 value = Math.round(value);
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700279 if (value <= 0)
Jeff Thompson95f935b2012-11-11 20:29:01 -0800280 return new Uint8Array(0);
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700281
Jeff Thompson95f935b2012-11-11 20:29:01 -0800282 // Assume value is not over 64 bits.
Jeff Thompson40df2fa2012-11-24 09:59:12 -0800283 var size = 8;
284 var result = new Uint8Array(size);
Jeff Thompson95f935b2012-11-11 20:29:01 -0800285 var i = 0;
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700286 while (value != 0) {
Jeff Thompson40df2fa2012-11-24 09:59:12 -0800287 ++i;
288 result[size - i] = value & 0xff;
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700289 value >>= 8;
290 }
Jeff Thompson40df2fa2012-11-24 09:59:12 -0800291 return result.subarray(size - i, size);
Jeff Thompsondeda95e2012-10-21 19:17:56 -0700292};
Jeff Thompson36a1a252012-12-13 22:50:43 -0800293
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700294/**
Jeff Thompson36a1a252012-12-13 22:50:43 -0800295 * Modify array to randomly shuffle the elements.
296 */
297DataUtils.shuffle = function(array) {
298 for (var i = array.length - 1; i >= 1; --i) {
299 // j is from 0 to i.
300 var j = Math.floor(Math.random() * (i + 1));
301 var temp = array[i];
302 array[i] = array[j];
303 array[j] = temp;
304 }
Jeff Thompson3ed09eb2013-07-29 14:54:23 -0700305};