You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
2.9 KiB

4 years ago
  1. var zero = '0'.charCodeAt(0);
  2. var plus = '+'.charCodeAt(0);
  3. var minus = '-'.charCodeAt(0);
  4. function isWhitespace(code) {
  5. return code <= 32;
  6. }
  7. function isDigit(code) {
  8. return 48 <= code && code <= 57;
  9. }
  10. function isSign(code) {
  11. return code === minus || code === plus;
  12. }
  13. module.exports = function (opts, a, b) {
  14. var checkSign = opts.sign;
  15. var ia = 0;
  16. var ib = 0;
  17. var ma = a.length;
  18. var mb = b.length;
  19. var ca, cb; // character code
  20. var za, zb; // leading zero count
  21. var na, nb; // number length
  22. var sa, sb; // number sign
  23. var ta, tb; // temporary
  24. var bias;
  25. while (ia < ma && ib < mb) {
  26. ca = a.charCodeAt(ia);
  27. cb = b.charCodeAt(ib);
  28. za = zb = 0;
  29. na = nb = 0;
  30. sa = sb = true;
  31. bias = 0;
  32. // skip over leading spaces
  33. while (isWhitespace(ca)) {
  34. ia += 1;
  35. ca = a.charCodeAt(ia);
  36. }
  37. while (isWhitespace(cb)) {
  38. ib += 1;
  39. cb = b.charCodeAt(ib);
  40. }
  41. // skip and save sign
  42. if (checkSign) {
  43. ta = a.charCodeAt(ia + 1);
  44. if (isSign(ca) && isDigit(ta)) {
  45. if (ca === minus) {
  46. sa = false;
  47. }
  48. ia += 1;
  49. ca = ta;
  50. }
  51. tb = b.charCodeAt(ib + 1);
  52. if (isSign(cb) && isDigit(tb)) {
  53. if (cb === minus) {
  54. sb = false;
  55. }
  56. ib += 1;
  57. cb = tb;
  58. }
  59. }
  60. // compare digits with other symbols
  61. if (isDigit(ca) && !isDigit(cb)) {
  62. return -1;
  63. }
  64. if (!isDigit(ca) && isDigit(cb)) {
  65. return 1;
  66. }
  67. // compare negative and positive
  68. if (!sa && sb) {
  69. return -1;
  70. }
  71. if (sa && !sb) {
  72. return 1;
  73. }
  74. // count leading zeros
  75. while (ca === zero) {
  76. za += 1;
  77. ia += 1;
  78. ca = a.charCodeAt(ia);
  79. }
  80. while (cb === zero) {
  81. zb += 1;
  82. ib += 1;
  83. cb = b.charCodeAt(ib);
  84. }
  85. // count numbers
  86. while (isDigit(ca) || isDigit(cb)) {
  87. if (isDigit(ca) && isDigit(cb) && bias === 0) {
  88. if (sa) {
  89. if (ca < cb) {
  90. bias = -1;
  91. } else if (ca > cb) {
  92. bias = 1;
  93. }
  94. } else {
  95. if (ca > cb) {
  96. bias = -1;
  97. } else if (ca < cb) {
  98. bias = 1;
  99. }
  100. }
  101. }
  102. if (isDigit(ca)) {
  103. ia += 1;
  104. na += 1;
  105. ca = a.charCodeAt(ia);
  106. }
  107. if (isDigit(cb)) {
  108. ib += 1;
  109. nb += 1;
  110. cb = b.charCodeAt(ib);
  111. }
  112. }
  113. // compare number length
  114. if (sa) {
  115. if (na < nb) {
  116. return -1;
  117. }
  118. if (na > nb) {
  119. return 1;
  120. }
  121. } else {
  122. if (na > nb) {
  123. return -1;
  124. }
  125. if (na < nb) {
  126. return 1;
  127. }
  128. }
  129. // compare numbers
  130. if (bias) {
  131. return bias;
  132. }
  133. // compare leading zeros
  134. if (sa) {
  135. if (za > zb) {
  136. return -1;
  137. }
  138. if (za < zb) {
  139. return 1;
  140. }
  141. } else {
  142. if (za < zb) {
  143. return -1;
  144. }
  145. if (za > zb) {
  146. return 1;
  147. }
  148. }
  149. // compare ascii codes
  150. if (ca < cb) {
  151. return -1;
  152. }
  153. if (ca > cb) {
  154. return 1;
  155. }
  156. ia += 1;
  157. ib += 1;
  158. }
  159. // compare length
  160. if (ma < mb) {
  161. return -1;
  162. }
  163. if (ma > mb) {
  164. return 1;
  165. }
  166. };