ByteRepr.js 11 KB

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