ByteRepr.js 9.3 KB

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