SeqUtils.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import Utils from "../Utils.js";
  2. /**
  3. * Sequence utility operations.
  4. *
  5. * @author n1474335 [n1474335@gmail.com]
  6. * @copyright Crown Copyright 2016
  7. * @license Apache-2.0
  8. *
  9. * @namespace
  10. */
  11. const SeqUtils = {
  12. /**
  13. * @constant
  14. * @default
  15. */
  16. DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
  17. /**
  18. * @constant
  19. * @default
  20. */
  21. SORT_REVERSE: false,
  22. /**
  23. * @constant
  24. * @default
  25. */
  26. SORT_ORDER: ["Alphabetical (case sensitive)", "Alphabetical (case insensitive)", "IP address", "Numeric"],
  27. /**
  28. * Sort operation.
  29. *
  30. * @param {string} input
  31. * @param {Object[]} args
  32. * @returns {string}
  33. */
  34. runSort: function (input, args) {
  35. let delim = Utils.charRep[args[0]],
  36. sortReverse = args[1],
  37. order = args[2],
  38. sorted = input.split(delim);
  39. if (order === "Alphabetical (case sensitive)") {
  40. sorted = sorted.sort();
  41. } else if (order === "Alphabetical (case insensitive)") {
  42. sorted = sorted.sort(SeqUtils._caseInsensitiveSort);
  43. } else if (order === "IP address") {
  44. sorted = sorted.sort(SeqUtils._ipSort);
  45. } else if (order === "Numeric") {
  46. sorted = sorted.sort(SeqUtils._numericSort);
  47. }
  48. if (sortReverse) sorted.reverse();
  49. return sorted.join(delim);
  50. },
  51. /**
  52. * Unique operation.
  53. *
  54. * @param {string} input
  55. * @param {Object[]} args
  56. * @returns {string}
  57. */
  58. runUnique: function (input, args) {
  59. const delim = Utils.charRep[args[0]];
  60. return input.split(delim).unique().join(delim);
  61. },
  62. /**
  63. * @constant
  64. * @default
  65. */
  66. SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
  67. /**
  68. * Count occurrences operation.
  69. *
  70. * @param {string} input
  71. * @param {Object[]} args
  72. * @returns {number}
  73. */
  74. runCount: function(input, args) {
  75. let search = args[0].string,
  76. type = args[0].option;
  77. if (type === "Regex" && search) {
  78. try {
  79. let regex = new RegExp(search, "gi"),
  80. matches = input.match(regex);
  81. return matches.length;
  82. } catch (err) {
  83. return 0;
  84. }
  85. } else if (search) {
  86. if (type.indexOf("Extended") === 0) {
  87. search = Utils.parseEscapedChars(search);
  88. }
  89. return input.count(search);
  90. } else {
  91. return 0;
  92. }
  93. },
  94. /**
  95. * @constant
  96. * @default
  97. */
  98. REVERSE_BY: ["Character", "Line"],
  99. /**
  100. * Reverse operation.
  101. *
  102. * @param {byteArray} input
  103. * @param {Object[]} args
  104. * @returns {byteArray}
  105. */
  106. runReverse: function (input, args) {
  107. let i;
  108. if (args[0] === "Line") {
  109. let lines = [],
  110. line = [],
  111. result = [];
  112. for (i = 0; i < input.length; i++) {
  113. if (input[i] === 0x0a) {
  114. lines.push(line);
  115. line = [];
  116. } else {
  117. line.push(input[i]);
  118. }
  119. }
  120. lines.push(line);
  121. lines.reverse();
  122. for (i = 0; i < lines.length; i++) {
  123. result = result.concat(lines[i]);
  124. result.push(0x0a);
  125. }
  126. return result.slice(0, input.length);
  127. } else {
  128. return input.reverse();
  129. }
  130. },
  131. /**
  132. * Add line numbers operation.
  133. *
  134. * @param {string} input
  135. * @param {Object[]} args
  136. * @returns {string}
  137. */
  138. runAddLineNumbers: function(input, args) {
  139. let lines = input.split("\n"),
  140. output = "",
  141. width = lines.length.toString().length;
  142. for (let n = 0; n < lines.length; n++) {
  143. output += (n+1).toString().padStart(width, " ") + " " + lines[n] + "\n";
  144. }
  145. return output.slice(0, output.length-1);
  146. },
  147. /**
  148. * Remove line numbers operation.
  149. *
  150. * @param {string} input
  151. * @param {Object[]} args
  152. * @returns {string}
  153. */
  154. runRemoveLineNumbers: function(input, args) {
  155. return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, "");
  156. },
  157. /**
  158. * Expand alphabet range operation.
  159. *
  160. * @param {string} input
  161. * @param {Object[]} args
  162. * @returns {string}
  163. */
  164. runExpandAlphRange: function(input, args) {
  165. return Utils.expandAlphRange(input).join(args[0]);
  166. },
  167. /**
  168. * Comparison operation for sorting of strings ignoring case.
  169. *
  170. * @private
  171. * @param {string} a
  172. * @param {string} b
  173. * @returns {number}
  174. */
  175. _caseInsensitiveSort: function(a, b) {
  176. return a.toLowerCase().localeCompare(b.toLowerCase());
  177. },
  178. /**
  179. * Comparison operation for sorting of IPv4 addresses.
  180. *
  181. * @private
  182. * @param {string} a
  183. * @param {string} b
  184. * @returns {number}
  185. */
  186. _ipSort: function(a, b) {
  187. let a_ = a.split("."),
  188. b_ = b.split(".");
  189. a_ = a_[0] * 0x1000000 + a_[1] * 0x10000 + a_[2] * 0x100 + a_[3] * 1;
  190. b_ = b_[0] * 0x1000000 + b_[1] * 0x10000 + b_[2] * 0x100 + b_[3] * 1;
  191. if (isNaN(a_) && !isNaN(b_)) return 1;
  192. if (!isNaN(a_) && isNaN(b_)) return -1;
  193. if (isNaN(a_) && isNaN(b_)) return a.localeCompare(b);
  194. return a_ - b_;
  195. },
  196. /**
  197. * Comparison operation for sorting of numeric values.
  198. *
  199. * @author Chris van Marle
  200. * @private
  201. * @param {string} a
  202. * @param {string} b
  203. * @returns {number}
  204. */
  205. _numericSort: function _numericSort(a, b) {
  206. let a_ = a.split(/([^\d]+)/),
  207. b_ = b.split(/([^\d]+)/);
  208. for (let i = 0; i < a_.length && i < b.length; ++i) {
  209. if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
  210. if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
  211. if (isNaN(a_[i]) && isNaN(b_[i])) {
  212. let ret = a_[i].localeCompare(b_[i]); // Compare strings
  213. if (ret !== 0) return ret;
  214. }
  215. if (!isNaN(a_[i]) && !isNaN(a_[i])) { // Compare numbers
  216. if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
  217. }
  218. }
  219. return a.localeCompare(b);
  220. },
  221. };
  222. export default SeqUtils;