string-builder.ts 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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) write(builder, __paddingSpaces[len]);
  57. }
  58. export function write(builder: StringBuilder, val: string) {
  59. if (!val) return;
  60. if (builder.offset === builder.capacity) {
  61. builder.chunks[builder.chunks.length] = builder.current.join('');
  62. builder.offset = 0;
  63. }
  64. builder.current[builder.offset++] = val;
  65. }
  66. /** Write without check. */
  67. export function writeSafe(builder: StringBuilder, val: string) {
  68. if (builder.offset === builder.capacity) {
  69. builder.chunks[builder.chunks.length] = builder.current.join('');
  70. builder.offset = 0;
  71. }
  72. builder.current[builder.offset++] = val;
  73. }
  74. export function writePadLeft(builder: StringBuilder, val: string, totalWidth: number) {
  75. if (!val) { whitespace(builder, totalWidth); return; }
  76. let padding = totalWidth - val.length;
  77. whitespace(builder, padding);
  78. writeSafe(builder, val);
  79. }
  80. export function writePadRight(builder: StringBuilder, val: string, totalWidth: number) {
  81. if (!val) { whitespace(builder, totalWidth); return; }
  82. let padding = totalWidth - val.length;
  83. writeSafe(builder, val);
  84. whitespace(builder, padding);
  85. }
  86. export function writeInteger(builder: StringBuilder, val: number) {
  87. writeSafe(builder, '' + val);
  88. }
  89. export function writeIntegerPadLeft(builder: StringBuilder, val: number, totalWidth: number) {
  90. let s = '' + val;
  91. let padding = totalWidth - s.length;
  92. whitespace(builder, padding);
  93. writeSafe(builder, s);
  94. }
  95. export function writeIntegerPadRight(builder: StringBuilder, val: number, totalWidth: number) {
  96. let s = '' + val;
  97. let padding = totalWidth - s.length;
  98. writeSafe(builder, s);
  99. whitespace(builder, padding);
  100. }
  101. /**
  102. * @example writeFloat(123.2123, 100) -- 2 decim
  103. */
  104. export function writeFloat(builder: StringBuilder, val: number, precisionMultiplier: number) {
  105. writeSafe(builder, '' + Math.round(precisionMultiplier * val) / precisionMultiplier)
  106. }
  107. export function writeFloatPadLeft(builder: StringBuilder, val: number, precisionMultiplier: number, totalWidth: number) {
  108. let s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;
  109. let padding = totalWidth - s.length;
  110. whitespace(builder, padding);
  111. writeSafe(builder, s);
  112. }
  113. export function writeFloatPadRight(builder: StringBuilder, val: number, precisionMultiplier: number, totalWidth: number) {
  114. let s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;
  115. let padding = totalWidth - s.length;
  116. writeSafe(builder, s);
  117. whitespace(builder, padding);
  118. }
  119. }
  120. export default StringBuilder