formatConversion.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright 2021-2024 Avaiga Private Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  5. * the License. You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  10. * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. * specific language governing permissions and limitations under the License.
  12. */
  13. /*
  14. * Regular expressions used for parsing sprintf format strings.
  15. */
  16. const re = {
  17. text: /^[^\x25]+/, // Matches non-placeholder text
  18. modulo: /^\x25{2}/, // Matches the '%%' escape sequence
  19. placeholder: /^\x25?(?:\.(\d+))?([b-giostuvxX])/, // Matches placeholders
  20. };
  21. /*
  22. * This function formats a precision specifier for a number. It takes an optional precision and specifier string.
  23. * If no precision is provided, it defaults to 2. The function returns a string that represents the formatted precision.
  24. */
  25. const precisionFormat = (precision?: string, specifier?: string): string => {
  26. // Default to precision of 2 if not specified
  27. return "." + (precision?.slice(1) ?? "2") + specifier;
  28. }
  29. /*
  30. * This function parses a sprintf format string and returns an array of strings and objects. Each object has a single
  31. * key, 'placeholder', that contains the placeholder string.
  32. */
  33. const sprintfParse = (fmt?: string): (string | { placeholder: string; })[] => {
  34. let _fmt = fmt;
  35. let match;
  36. const parse_tree = [];
  37. while (_fmt) {
  38. if ((match = re.text.exec(_fmt)) !== null) {
  39. // Non-placeholder text
  40. parse_tree.push(match[0]);
  41. } else if ((match = re.modulo.exec(_fmt)) !== null) {
  42. // '%%' escape sequence
  43. parse_tree.push('%');
  44. } else if ((match = re.placeholder.exec(_fmt)) !== null) {
  45. // Placeholder
  46. if (match && match[0]) {
  47. parse_tree.push({
  48. placeholder: match[0],
  49. });
  50. }
  51. }
  52. if (match) {
  53. _fmt = _fmt.substring(match[0].length);
  54. }
  55. }
  56. return parse_tree;
  57. }
  58. /*
  59. * This function converts a sprintf format string to a D3 format string. It takes an optional sprintf format string and
  60. * returns a D3 format string. If no format string is provided, it returns an empty string.
  61. */
  62. export const sprintfToD3Converter = (fmt?: string): string => {
  63. const sprintf_fmt_arr = sprintfParse(fmt);
  64. const objectIndex = sprintf_fmt_arr.findIndex((element) => typeof element === 'object');
  65. let placeholderValue;
  66. if (typeof sprintf_fmt_arr[objectIndex] === 'object' && sprintf_fmt_arr[objectIndex] !== null) {
  67. placeholderValue = (sprintf_fmt_arr[objectIndex] as { placeholder: string }).placeholder;
  68. }
  69. if (!placeholderValue) {
  70. return "";
  71. }
  72. return placeholderValue.replace(/%([0-9]*)([.][0-9]+)?([bdieufgoxX])/g, (match, width, precision, type) => {
  73. switch (type) {
  74. case "b":
  75. case "d":
  76. case "e":
  77. case "o":
  78. case "x":
  79. case "X":
  80. return type;
  81. case "i":
  82. return "d";
  83. case "f":
  84. case "g":
  85. return precisionFormat(precision, type);
  86. case "u":
  87. return "("
  88. default:
  89. return "";
  90. }
  91. });
  92. }
  93. /*
  94. * This function extracts the prefix from a sprintf format string. It takes an optional sprintf format string and returns
  95. * a string that represents the prefix of the format string. If no format string is provided, it returns an empty string.
  96. */
  97. export const extractPrefix = (fmt?: string): string => {
  98. if (!fmt) return "";
  99. const sprintf_fmt_arr = sprintfParse(fmt);
  100. const objectIndex = sprintf_fmt_arr.findIndex((element) => typeof element === 'object');
  101. return sprintf_fmt_arr.slice(0, objectIndex).join('');
  102. }
  103. /*
  104. * This function extracts the suffix from a sprintf format string. It takes an optional sprintf format string and returns
  105. * a string that represents the suffix of the format string. If no format string is provided, it returns an empty string.
  106. */
  107. export const extractSuffix = (fmt?: string): string => {
  108. if (!fmt) return "";
  109. const sprintf_fmt_arr = sprintfParse(fmt);
  110. const objectIndex = sprintf_fmt_arr.findIndex((element) => typeof element === 'object');
  111. return sprintf_fmt_arr.slice(objectIndex + 1).join('');
  112. }