string-builder.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /**
  2. * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * Adapted from CIFTools.js (https://github.com/dsehnal/CIFTools.js)
  5. *
  6. * @author David Sehnal <david.sehnal@gmail.com>
  7. */
  8. interface StringBuilder {
  9. current: string[],
  10. offset: number,
  11. capacity: number,
  12. chunks: string[]
  13. }
  14. namespace StringBuilder {
  15. export function create(chunkCapacity = 512): StringBuilder {
  16. return {
  17. current: [],
  18. offset: 0,
  19. capacity: chunkCapacity,
  20. chunks: []
  21. };
  22. }
  23. export function getString(builder: StringBuilder) {
  24. if (!builder.chunks.length) {
  25. if (builder.current.length === builder.offset) return builder.current.join('');
  26. return builder.current.splice(0, builder.offset).join('');
  27. }
  28. if (builder.offset > 0) {
  29. builder.chunks[builder.chunks.length] = builder.current.length === builder.offset
  30. ? builder.current.join('')
  31. : builder.current.slice(0, builder.offset).join('');
  32. }
  33. return builder.chunks.join('');
  34. }
  35. export function getChunks(builder: StringBuilder): string[] {
  36. if (builder.offset > 0) {
  37. if (builder.current.length === builder.offset) builder.chunks[builder.chunks.length] = builder.current.join('');
  38. else builder.chunks[builder.chunks.length] = builder.current.slice(0, builder.offset).join('');
  39. builder.offset = 0;
  40. }
  41. return builder.chunks;
  42. }
  43. const enum PaddingSpaces { Count = 512 }
  44. const __paddingSpaces: string[] = [];
  45. (function () {
  46. let s = '';
  47. for (let i = 0; i < PaddingSpaces.Count; i++) {
  48. __paddingSpaces[i] = s;
  49. s = s + ' ';
  50. }
  51. })();
  52. export function newline(builder: StringBuilder) {
  53. writeSafe(builder, '\n');
  54. }
  55. export function whitespace(builder: StringBuilder, len: number) {
  56. if (len > 0) writeSafe(builder, __paddingSpaces[len]);
  57. }
  58. export function whitespace1(builder: StringBuilder) {
  59. writeSafe(builder, ' ');
  60. }
  61. export function write(builder: StringBuilder, val: string) {
  62. if (!val) return;
  63. if (builder.offset === builder.capacity) {
  64. builder.chunks[builder.chunks.length] = builder.current.join('');
  65. builder.offset = 0;
  66. }
  67. builder.current[builder.offset++] = val;
  68. }
  69. /** Write without check. */
  70. export function writeSafe(builder: StringBuilder, val: string) {
  71. if (builder.offset === builder.capacity) {
  72. builder.chunks[builder.chunks.length] = builder.current.join('');
  73. builder.offset = 0;
  74. }
  75. builder.current[builder.offset++] = val;
  76. }
  77. export function writePadLeft(builder: StringBuilder, val: string, totalWidth: number) {
  78. if (!val) { whitespace(builder, totalWidth); return; }
  79. let padding = totalWidth - val.length;
  80. whitespace(builder, padding);
  81. writeSafe(builder, val);
  82. }
  83. export function writePadRight(builder: StringBuilder, val: string, totalWidth: number) {
  84. if (!val) { whitespace(builder, totalWidth); return; }
  85. let padding = totalWidth - val.length;
  86. writeSafe(builder, val);
  87. whitespace(builder, padding);
  88. }
  89. export function writeInteger(builder: StringBuilder, val: number) {
  90. writeSafe(builder, '' + val);
  91. }
  92. export function writeIntegerAndSpace(builder: StringBuilder, val: number) {
  93. writeSafe(builder, '' + val + ' ');
  94. }
  95. export function writeIntegerPadLeft(builder: StringBuilder, val: number, totalWidth: number) {
  96. let s = '' + val;
  97. let padding = totalWidth - s.length;
  98. whitespace(builder, padding);
  99. writeSafe(builder, s);
  100. }
  101. export function writeIntegerPadRight(builder: StringBuilder, val: number, totalWidth: number) {
  102. let s = '' + val;
  103. let padding = totalWidth - s.length;
  104. writeSafe(builder, s);
  105. whitespace(builder, padding);
  106. }
  107. /**
  108. * @example writeFloat(123.2123, 100) -- 2 decim
  109. */
  110. export function writeFloat(builder: StringBuilder, val: number, precisionMultiplier: number) {
  111. writeSafe(builder, '' + Math.round(precisionMultiplier * val) / precisionMultiplier)
  112. }
  113. export function writeFloatPadLeft(builder: StringBuilder, val: number, precisionMultiplier: number, totalWidth: number) {
  114. let s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;
  115. let padding = totalWidth - s.length;
  116. whitespace(builder, padding);
  117. writeSafe(builder, s);
  118. }
  119. export function writeFloatPadRight(builder: StringBuilder, val: number, precisionMultiplier: number, totalWidth: number) {
  120. let s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;
  121. let padding = totalWidth - s.length;
  122. writeSafe(builder, s);
  123. whitespace(builder, padding);
  124. }
  125. }
  126. export default StringBuilder