Wentao Shang | bd63e46 | 2012-12-03 16:19:33 -0800 | [diff] [blame] | 1 | /** |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 2 | * This class contains utilities to help parse the data |
Jeff Thompson | 146d7de | 2012-11-17 16:15:28 -0800 | [diff] [blame] | 3 | * author: Meki Cheraoui, Jeff Thompson |
Jeff Thompson | 745026e | 2012-10-13 12:49:20 -0700 | [diff] [blame] | 4 | * See COPYING for copyright and distribution information. |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 5 | */ |
| 6 | |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 7 | /** |
| 8 | * A DataUtils has static methods for converting data. |
| 9 | * @constructor |
| 10 | */ |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 11 | var DataUtils = function DataUtils(){ |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 12 | }; |
| 13 | |
| 14 | |
| 15 | /* |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 16 | * NOTE THIS IS CURRENTLY NOT BEING USED |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 17 | * |
| 18 | */ |
| 19 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 20 | DataUtils.keyStr = "ABCDEFGHIJKLMNOP" + |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 21 | "QRSTUVWXYZabcdef" + |
| 22 | "ghijklmnopqrstuv" + |
| 23 | "wxyz0123456789+/" + |
| 24 | "="; |
| 25 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 26 | |
| 27 | /** |
| 28 | * Raw String to Base 64 |
| 29 | */ |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 30 | DataUtils.stringtoBase64=function stringtoBase64(input) { |
Jeff Thompson | 3a09fc8 | 2013-07-26 19:59:05 -0700 | [diff] [blame] | 31 | //input = escape(input); |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 32 | 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 Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 54 | DataUtils.keyStr.charAt(enc1) + |
| 55 | DataUtils.keyStr.charAt(enc2) + |
| 56 | DataUtils.keyStr.charAt(enc3) + |
| 57 | DataUtils.keyStr.charAt(enc4); |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 58 | chr1 = chr2 = chr3 = ""; |
| 59 | enc1 = enc2 = enc3 = enc4 = ""; |
| 60 | } while (i < input.length); |
| 61 | |
| 62 | return output; |
| 63 | } |
| 64 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 65 | /** |
| 66 | * Base 64 to Raw String |
| 67 | */ |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 68 | DataUtils.base64toString = function base64toString(input) { |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 69 | 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 Thompson | 7495797 | 2012-10-07 21:14:32 -0700 | [diff] [blame] | 76 | /* Test for invalid characters. */ |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 77 | 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 Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 82 | |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 83 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); |
| 84 | |
| 85 | do { |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 86 | 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 Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 90 | |
| 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 Thompson | 2d9c5aa | 2013-08-09 11:27:32 -0700 | [diff] [blame^] | 109 | return output; |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 110 | }; |
Meki Cherkaoui | f441d3a | 2012-04-22 15:17:52 -0700 | [diff] [blame] | 111 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 112 | /** |
Jeff Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 113 | * Uint8Array to Hex String |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 114 | */ |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 115 | //http://ejohn.org/blog/numbers-hex-and-colors/ |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 116 | DataUtils.toHex = function(args){ |
| 117 | if (LOG>4) console.log('ABOUT TO CONVERT '+ args); |
| 118 | //console.log(args); |
Jeff Thompson | 8b44aa1 | 2012-11-11 18:39:47 -0800 | [diff] [blame] | 119 | var ret = ""; |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 120 | for ( var i = 0; i < args.length; i++ ) |
| 121 | ret += (args[i] < 16 ? "0" : "") + args[i].toString(16); |
Jeff Thompson | 8b44aa1 | 2012-11-11 18:39:47 -0800 | [diff] [blame] | 122 | if (LOG>4) console.log('Converted to: ' + ret); |
| 123 | return ret; //.toUpperCase(); |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 126 | /** |
Jeff Thompson | a566e79 | 2012-10-06 21:46:34 -0700 | [diff] [blame] | 127 | * Raw string to hex string. |
| 128 | */ |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 129 | DataUtils.stringToHex = function(args){ |
Jeff Thompson | a566e79 | 2012-10-06 21:46:34 -0700 | [diff] [blame] | 130 | var ret = ""; |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 131 | for (var i = 0; i < args.length; ++i) { |
| 132 | var value = args.charCodeAt(i); |
Jeff Thompson | a566e79 | 2012-10-06 21:46:34 -0700 | [diff] [blame] | 133 | ret += (value < 16 ? "0" : "") + value.toString(16); |
| 134 | } |
| 135 | return ret; |
| 136 | } |
| 137 | |
| 138 | /** |
Jeff Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 139 | * Uint8Array to raw string. |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 140 | */ |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 141 | DataUtils.toString = function(args){ |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 142 | //console.log(arguments); |
| 143 | var ret = ""; |
Wentao Shang | 0e291c8 | 2012-12-02 23:36:29 -0800 | [diff] [blame] | 144 | for ( var i = 0; i < args.length; i++ ) |
| 145 | ret += String.fromCharCode(args[i]); |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 146 | return ret; |
| 147 | } |
| 148 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 149 | /** |
Jeff Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 150 | * Hex String to Uint8Array. |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 151 | */ |
Jeff Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 152 | DataUtils.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 Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 160 | } |
| 161 | } |
| 162 | |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 163 | /** |
Jeff Thompson | 7495797 | 2012-10-07 21:14:32 -0700 | [diff] [blame] | 164 | * Hex String to raw string. |
| 165 | */ |
| 166 | DataUtils.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 Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 177 | * Raw String to Uint8Array. |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 178 | */ |
Wentao Shang | ab9018d | 2012-12-18 11:35:45 -0800 | [diff] [blame] | 179 | DataUtils.toNumbersFromString = function(str) { |
Jeff Thompson | 34a585f | 2012-11-11 19:16:02 -0800 | [diff] [blame] | 180 | var bytes = new Uint8Array(str.length); |
Meki Cherkaoui | b21911b | 2012-05-18 16:54:37 -0700 | [diff] [blame] | 181 | for(var i=0;i<str.length;i++) |
| 182 | bytes[i] = str.charCodeAt(i); |
| 183 | return bytes; |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 184 | } |
| 185 | |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 186 | /** |
Jeff Thompson | adba491 | 2012-11-15 22:29:13 -0800 | [diff] [blame] | 187 | * Encode str as utf8 and return as Uint8Array. |
Jeff Thompson | 3a78259 | 2012-11-18 17:34:33 -0800 | [diff] [blame] | 188 | * TODO: Use TextEncoder when available. |
Jeff Thompson | adba491 | 2012-11-15 22:29:13 -0800 | [diff] [blame] | 189 | */ |
| 190 | DataUtils.stringToUtf8Array = function(str) { |
| 191 | return DataUtils.toNumbersFromString(str2rstr_utf8(str)); |
| 192 | } |
| 193 | |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 194 | /** |
Jeff Thompson | 5e6ab9a | 2012-11-28 21:19:59 -0800 | [diff] [blame] | 195 | * arrays is an array of Uint8Array. Return a new Uint8Array which is the concatenation of all. |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 196 | */ |
Jeff Thompson | 5e6ab9a | 2012-11-28 21:19:59 -0800 | [diff] [blame] | 197 | DataUtils.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 Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 210 | } |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 211 | |
Jeff Thompson | 3a78259 | 2012-11-18 17:34:33 -0800 | [diff] [blame] | 212 | // TODO: Take Uint8Array and use TextDecoder when available. |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 213 | DataUtils.decodeUtf8 = function (utftext) { |
| 214 | var string = ""; |
| 215 | var i = 0; |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 216 | var c = 0; |
| 217 | var c1 = 0; |
| 218 | var c2 = 0; |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 219 | |
| 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 Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 235 | var c3 = utftext.charCodeAt(i+2); |
Meki Cherkaoui | 8f17361 | 2012-06-06 01:05:40 -0700 | [diff] [blame] | 236 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); |
| 237 | i += 3; |
| 238 | } |
| 239 | |
| 240 | } |
| 241 | |
| 242 | return string; |
| 243 | }; |
| 244 | |
Jeff Thompson | bb97609 | 2012-09-29 17:01:38 -0700 | [diff] [blame] | 245 | /** |
| 246 | * Return true if a1 and a2 are the same length with equal elements. |
| 247 | */ |
| 248 | DataUtils.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 Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 258 | }; |
| 259 | |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 260 | /** |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 261 | * Convert the big endian Uint8Array to an unsigned int. |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 262 | * Don't check for overflow. |
| 263 | */ |
| 264 | DataUtils.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 Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 273 | /** |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 274 | * Convert the int value to a new big endian Uint8Array and return. |
| 275 | * If value is 0 or negative, return Uint8Array(0). |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 276 | */ |
| 277 | DataUtils.nonNegativeIntToBigEndian = function(value) { |
Jeff Thompson | 40df2fa | 2012-11-24 09:59:12 -0800 | [diff] [blame] | 278 | value = Math.round(value); |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 279 | if (value <= 0) |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 280 | return new Uint8Array(0); |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 281 | |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 282 | // Assume value is not over 64 bits. |
Jeff Thompson | 40df2fa | 2012-11-24 09:59:12 -0800 | [diff] [blame] | 283 | var size = 8; |
| 284 | var result = new Uint8Array(size); |
Jeff Thompson | 95f935b | 2012-11-11 20:29:01 -0800 | [diff] [blame] | 285 | var i = 0; |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 286 | while (value != 0) { |
Jeff Thompson | 40df2fa | 2012-11-24 09:59:12 -0800 | [diff] [blame] | 287 | ++i; |
| 288 | result[size - i] = value & 0xff; |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 289 | value >>= 8; |
| 290 | } |
Jeff Thompson | 40df2fa | 2012-11-24 09:59:12 -0800 | [diff] [blame] | 291 | return result.subarray(size - i, size); |
Jeff Thompson | deda95e | 2012-10-21 19:17:56 -0700 | [diff] [blame] | 292 | }; |
Jeff Thompson | 36a1a25 | 2012-12-13 22:50:43 -0800 | [diff] [blame] | 293 | |
Jeff Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 294 | /** |
Jeff Thompson | 36a1a25 | 2012-12-13 22:50:43 -0800 | [diff] [blame] | 295 | * Modify array to randomly shuffle the elements. |
| 296 | */ |
| 297 | DataUtils.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 Thompson | 3ed09eb | 2013-07-29 14:54:23 -0700 | [diff] [blame] | 305 | }; |