number-parser.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /*
  2. * Copyright (c) 2017 molio contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * from https://github.com/dsehnal/CIFTools.js
  5. * @author David Sehnal <david.sehnal@gmail.com>
  6. */
  7. /**
  8. * Efficient integer and float parsers.
  9. *
  10. * For the purposes of parsing numbers from the mmCIF data representations,
  11. * up to 4 times faster than JS parseInt/parseFloat.
  12. */
  13. export function parseIntSkipLeadingWhitespace(str: string, start: number, end: number) {
  14. while (start < end && str.charCodeAt(start) === 32) start++;
  15. return parseInt(str, start, end);
  16. }
  17. export function parseInt(str: string, start: number, end: number) {
  18. let ret = 0, neg = 1;
  19. if (str.charCodeAt(start) === 45 /* - */) { neg = -1; start++; }
  20. for (; start < end; start++) {
  21. let c = str.charCodeAt(start) - 48;
  22. if (c > 9 || c < 0) return (neg * ret) | 0;
  23. else ret = (10 * ret + c) | 0;
  24. }
  25. return neg * ret;
  26. }
  27. function parseScientific(main: number, str: string, start: number, end: number) {
  28. // handle + in '1e+1' separately.
  29. if (str.charCodeAt(start) === 43 /* + */) start++;
  30. return main * Math.pow(10.0, parseInt(str, start, end));
  31. }
  32. export function parseFloatSkipLeadingWhitespace(str: string, start: number, end: number) {
  33. while (start < end && str.charCodeAt(start) === 32) start++;
  34. return parseFloat(str, start, end);
  35. }
  36. export function parseFloat(str: string, start: number, end: number) {
  37. let neg = 1.0, ret = 0.0, point = 0.0, div = 1.0;
  38. if (str.charCodeAt(start) === 45) {
  39. neg = -1.0;
  40. ++start;
  41. }
  42. while (start < end) {
  43. let c = str.charCodeAt(start) - 48;
  44. if (c >= 0 && c < 10) {
  45. ret = ret * 10 + c;
  46. ++start;
  47. } else if (c === -2) { // .
  48. ++start;
  49. while (start < end) {
  50. c = str.charCodeAt(start) - 48;
  51. if (c >= 0 && c < 10) {
  52. point = 10.0 * point + c;
  53. div = 10.0 * div;
  54. ++start;
  55. } else if (c === 53 || c === 21) { // 'e'/'E'
  56. return parseScientific(neg * (ret + point / div), str, start + 1, end);
  57. } else {
  58. return neg * (ret + point / div);
  59. }
  60. }
  61. return neg * (ret + point / div);
  62. } else if (c === 53 || c === 21) { // 'e'/'E'
  63. return parseScientific(neg * ret, str, start + 1, end);
  64. }
  65. else break;
  66. }
  67. return neg * ret;
  68. }