ByteRepr.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. import Utils from "../Utils.js";
  2. /**
  3. * Byte representation operations.
  4. *
  5. * @author n1474335 [n1474335@gmail.com]
  6. * @copyright Crown Copyright 2016
  7. * @license Apache-2.0
  8. *
  9. * @namespace
  10. */
  11. const ByteRepr = {
  12. /**
  13. * @constant
  14. * @default
  15. */
  16. DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF"],
  17. /**
  18. * @constant
  19. * @default
  20. */
  21. TO_HEX_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
  22. /**
  23. * @constant
  24. * @default
  25. */
  26. FROM_HEX_DELIM_OPTIONS: ["Auto", "Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "0x", "\\x", "None"],
  27. /**
  28. * @constant
  29. * @default
  30. */
  31. BIN_DELIM_OPTIONS: ["Space", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"],
  32. /**
  33. * To Hex operation.
  34. *
  35. * @param {ArrayBuffer} input
  36. * @param {Object[]} args
  37. * @returns {string}
  38. */
  39. runToHex: function(input, args) {
  40. const delim = Utils.charRep[args[0] || "Space"];
  41. return Utils.toHex(new Uint8Array(input), delim, 2);
  42. },
  43. /**
  44. * From Hex operation.
  45. *
  46. * @param {string} input
  47. * @param {Object[]} args
  48. * @returns {byteArray}
  49. */
  50. runFromHex: function(input, args) {
  51. const delim = args[0] || "Space";
  52. return Utils.fromHex(input, delim, 2);
  53. },
  54. /**
  55. * To Octal operation.
  56. *
  57. * @author Matt C [matt@artemisbot.uk]
  58. * @param {byteArray} input
  59. * @param {Object[]} args
  60. * @returns {string}
  61. */
  62. runToOct: function(input, args) {
  63. const delim = Utils.charRep[args[0] || "Space"];
  64. return input.map(val => val.toString(8)).join(delim);
  65. },
  66. /**
  67. * From Octal operation.
  68. *
  69. * @author Matt C [matt@artemisbot.uk]
  70. * @param {string} input
  71. * @param {Object[]} args
  72. * @returns {byteArray}
  73. */
  74. runFromOct: function(input, args) {
  75. const delim = Utils.charRep[args[0] || "Space"];
  76. if (input.length === 0) return [];
  77. return input.split(delim).map(val => parseInt(val, 8));
  78. },
  79. /**
  80. * @constant
  81. * @default
  82. */
  83. CHARCODE_BASE: 16,
  84. /**
  85. * To Charcode operation.
  86. *
  87. * @param {string} input
  88. * @param {Object[]} args
  89. * @returns {string}
  90. */
  91. runToCharcode: function(input, args) {
  92. let delim = Utils.charRep[args[0] || "Space"],
  93. base = args[1],
  94. output = "",
  95. padding = 2,
  96. ordinal;
  97. if (base < 2 || base > 36) {
  98. throw "Error: Base argument must be between 2 and 36";
  99. }
  100. const charcode = Utils.strToCharcode(input);
  101. for (let i = 0; i < charcode.length; i++) {
  102. ordinal = charcode[i];
  103. if (base === 16) {
  104. if (ordinal < 256) padding = 2;
  105. else if (ordinal < 65536) padding = 4;
  106. else if (ordinal < 16777216) padding = 6;
  107. else if (ordinal < 4294967296) padding = 8;
  108. else padding = 2;
  109. if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
  110. output += Utils.hex(ordinal, padding) + delim;
  111. } else {
  112. if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
  113. output += ordinal.toString(base) + delim;
  114. }
  115. }
  116. return output.slice(0, -delim.length);
  117. },
  118. /**
  119. * From Charcode operation.
  120. *
  121. * @param {string} input
  122. * @param {Object[]} args
  123. * @returns {byteArray}
  124. */
  125. runFromCharcode: function(input, args) {
  126. let delim = Utils.charRep[args[0] || "Space"],
  127. base = args[1],
  128. bites = input.split(delim),
  129. i = 0;
  130. if (base < 2 || base > 36) {
  131. throw "Error: Base argument must be between 2 and 36";
  132. }
  133. if (input.length === 0) {
  134. return [];
  135. }
  136. if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
  137. // Split into groups of 2 if the whole string is concatenated and
  138. // too long to be a single character
  139. if (bites.length === 1 && input.length > 17) {
  140. bites = [];
  141. for (i = 0; i < input.length; i += 2) {
  142. bites.push(input.slice(i, i+2));
  143. }
  144. }
  145. let latin1 = "";
  146. for (i = 0; i < bites.length; i++) {
  147. latin1 += Utils.chr(parseInt(bites[i], base));
  148. }
  149. return Utils.strToByteArray(latin1);
  150. },
  151. /**
  152. * Highlight to hex
  153. *
  154. * @param {Object[]} pos
  155. * @param {number} pos[].start
  156. * @param {number} pos[].end
  157. * @param {Object[]} args
  158. * @returns {Object[]} pos
  159. */
  160. highlightTo: function(pos, args) {
  161. let delim = Utils.charRep[args[0] || "Space"],
  162. len = delim === "\r\n" ? 1 : delim.length;
  163. pos[0].start = pos[0].start * (2 + len);
  164. pos[0].end = pos[0].end * (2 + len) - len;
  165. // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
  166. if (delim === "0x" || delim === "\\x") {
  167. pos[0].start += 2;
  168. pos[0].end += 2;
  169. }
  170. return pos;
  171. },
  172. /**
  173. * Highlight from hex
  174. *
  175. * @param {Object[]} pos
  176. * @param {number} pos[].start
  177. * @param {number} pos[].end
  178. * @param {Object[]} args
  179. * @returns {Object[]} pos
  180. */
  181. highlightFrom: function(pos, args) {
  182. let delim = Utils.charRep[args[0] || "Space"],
  183. len = delim === "\r\n" ? 1 : delim.length,
  184. width = len + 2;
  185. // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly
  186. if (delim === "0x" || delim === "\\x") {
  187. if (pos[0].start > 1) pos[0].start -= 2;
  188. else pos[0].start = 0;
  189. if (pos[0].end > 1) pos[0].end -= 2;
  190. else pos[0].end = 0;
  191. }
  192. pos[0].start = pos[0].start === 0 ? 0 : Math.round(pos[0].start / width);
  193. pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / width);
  194. return pos;
  195. },
  196. /**
  197. * To Decimal operation.
  198. *
  199. * @param {byteArray} input
  200. * @param {Object[]} args
  201. * @returns {string}
  202. */
  203. runToDecimal: function(input, args) {
  204. const delim = Utils.charRep[args[0]];
  205. return input.join(delim);
  206. },
  207. /**
  208. * From Decimal operation.
  209. *
  210. * @param {string} input
  211. * @param {Object[]} args
  212. * @returns {byteArray}
  213. */
  214. runFromDecimal: function(input, args) {
  215. const delim = Utils.charRep[args[0]];
  216. let byteStr = input.split(delim), output = [];
  217. if (byteStr[byteStr.length-1] === "")
  218. byteStr = byteStr.slice(0, byteStr.length-1);
  219. for (let i = 0; i < byteStr.length; i++) {
  220. output[i] = parseInt(byteStr[i], 10);
  221. }
  222. return output;
  223. },
  224. /**
  225. * To Binary operation.
  226. *
  227. * @param {byteArray} input
  228. * @param {Object[]} args
  229. * @returns {string}
  230. */
  231. runToBinary: function(input, args) {
  232. let delim = Utils.charRep[args[0] || "Space"],
  233. output = "",
  234. padding = 8;
  235. for (let i = 0; i < input.length; i++) {
  236. output += input[i].toString(2).padStart(padding, "0") + delim;
  237. }
  238. if (delim.length) {
  239. return output.slice(0, -delim.length);
  240. } else {
  241. return output;
  242. }
  243. },
  244. /**
  245. * From Binary operation.
  246. *
  247. * @param {string} input
  248. * @param {Object[]} args
  249. * @returns {byteArray}
  250. */
  251. runFromBinary: function(input, args) {
  252. const delimRegex = Utils.regexRep[args[0] || "Space"];
  253. input = input.replace(delimRegex, "");
  254. const output = [];
  255. const byteLen = 8;
  256. for (let i = 0; i < input.length; i += byteLen) {
  257. output.push(parseInt(input.substr(i, byteLen), 2));
  258. }
  259. return output;
  260. },
  261. /**
  262. * Highlight to binary
  263. *
  264. * @param {Object[]} pos
  265. * @param {number} pos[].start
  266. * @param {number} pos[].end
  267. * @param {Object[]} args
  268. * @returns {Object[]} pos
  269. */
  270. highlightToBinary: function(pos, args) {
  271. const delim = Utils.charRep[args[0] || "Space"];
  272. pos[0].start = pos[0].start * (8 + delim.length);
  273. pos[0].end = pos[0].end * (8 + delim.length) - delim.length;
  274. return pos;
  275. },
  276. /**
  277. * Highlight from binary
  278. *
  279. * @param {Object[]} pos
  280. * @param {number} pos[].start
  281. * @param {number} pos[].end
  282. * @param {Object[]} args
  283. * @returns {Object[]} pos
  284. */
  285. highlightFromBinary: function(pos, args) {
  286. const delim = Utils.charRep[args[0] || "Space"];
  287. pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length));
  288. pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length));
  289. return pos;
  290. },
  291. /**
  292. * @constant
  293. * @default
  294. */
  295. HEX_CONTENT_CONVERT_WHICH: ["Only special chars", "Only special chars including spaces", "All chars"],
  296. /**
  297. * @constant
  298. * @default
  299. */
  300. HEX_CONTENT_SPACES_BETWEEN_BYTES: false,
  301. /**
  302. * To Hex Content operation.
  303. *
  304. * @param {byteArray} input
  305. * @param {Object[]} args
  306. * @returns {string}
  307. */
  308. runToHexContent: function(input, args) {
  309. const convert = args[0];
  310. const spaces = args[1];
  311. if (convert === "All chars") {
  312. let result = "|" + Utils.toHex(input) + "|";
  313. if (!spaces) result = result.replace(/ /g, "");
  314. return result;
  315. }
  316. let output = "",
  317. inHex = false,
  318. convertSpaces = convert === "Only special chars including spaces",
  319. b;
  320. for (let i = 0; i < input.length; i++) {
  321. b = input[i];
  322. if ((b === 32 && convertSpaces) || (b < 48 && b !== 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) {
  323. if (!inHex) {
  324. output += "|";
  325. inHex = true;
  326. } else if (spaces) output += " ";
  327. output += Utils.toHex([b]);
  328. } else {
  329. if (inHex) {
  330. output += "|";
  331. inHex = false;
  332. }
  333. output += Utils.chr(input[i]);
  334. }
  335. }
  336. if (inHex) output += "|";
  337. return output;
  338. },
  339. /**
  340. * From Hex Content operation.
  341. *
  342. * @param {string} input
  343. * @param {Object[]} args
  344. * @returns {byteArray}
  345. */
  346. runFromHexContent: function(input, args) {
  347. const regex = /\|([a-f\d ]{2,})\|/gi;
  348. let output = [], m, i = 0;
  349. while ((m = regex.exec(input))) {
  350. // Add up to match
  351. for (; i < m.index;)
  352. output.push(Utils.ord(input[i++]));
  353. // Add match
  354. const bytes = Utils.fromHex(m[1]);
  355. if (bytes) {
  356. for (let a = 0; a < bytes.length;)
  357. output.push(bytes[a++]);
  358. } else {
  359. // Not valid hex, print as normal
  360. for (; i < regex.lastIndex;)
  361. output.push(Utils.ord(input[i++]));
  362. }
  363. i = regex.lastIndex;
  364. }
  365. // Add all after final match
  366. for (; i < input.length;)
  367. output.push(Utils.ord(input[i++]));
  368. return output;
  369. },
  370. };
  371. export default ByteRepr;