|
1 | 1 | package com.fasterxml.jackson.core.io; |
2 | 2 |
|
3 | 3 | import java.math.BigInteger; |
| 4 | +import java.util.regex.Pattern; |
4 | 5 |
|
5 | 6 | import org.junit.jupiter.api.Test; |
6 | 7 |
|
@@ -105,6 +106,10 @@ void looksLikeValidNumberTrue() |
105 | 106 | assertTrue(NumberInput.looksLikeValidNumber("1.4E-45")); |
106 | 107 | assertTrue(NumberInput.looksLikeValidNumber("1.4e+45")); |
107 | 108 |
|
| 109 | + // Fully populated form: sign, integer part, fraction, signed exponent |
| 110 | + assertTrue(NumberInput.looksLikeValidNumber("+1.2e+3")); |
| 111 | + assertTrue(NumberInput.looksLikeValidNumber("-12.34E-56")); |
| 112 | + |
108 | 113 | // https://github.com/FasterXML/jackson-core/issues/1308 |
109 | 114 | assertTrue(NumberInput.looksLikeValidNumber("0.")); |
110 | 115 | assertTrue(NumberInput.looksLikeValidNumber("6.")); |
@@ -139,5 +144,49 @@ void looksLikeValidNumberFalse() |
139 | 144 | assertFalse(NumberInput.looksLikeValidNumber("+.")); |
140 | 145 | assertFalse(NumberInput.looksLikeValidNumber("-E")); |
141 | 146 | assertFalse(NumberInput.looksLikeValidNumber("+E")); |
| 147 | + |
| 148 | + assertFalse(NumberInput.looksLikeValidNumber("1.2.3")); |
| 149 | + assertFalse(NumberInput.looksLikeValidNumber("1.e5")); |
| 150 | + assertFalse(NumberInput.looksLikeValidNumber("1e")); |
| 151 | + assertFalse(NumberInput.looksLikeValidNumber("1e+")); |
| 152 | + assertFalse(NumberInput.looksLikeValidNumber("1e5x")); |
| 153 | + assertFalse(NumberInput.looksLikeValidNumber("1e5.0")); |
| 154 | + assertFalse(NumberInput.looksLikeValidNumber("--1")); |
| 155 | + assertFalse(NumberInput.looksLikeValidNumber("1 ")); |
| 156 | + assertFalse(NumberInput.looksLikeValidNumber(" 1")); |
| 157 | + assertFalse(NumberInput.looksLikeValidNumber("0x1F")); |
| 158 | + } |
| 159 | + |
| 160 | + // [core#1649]: hand-rolled implementation must accept exactly what the |
| 161 | + // original Regexp-based one did |
| 162 | + @Test |
| 163 | + void looksLikeValidNumberMatchesLegacyRegexps() |
| 164 | + { |
| 165 | + final Pattern patternFloat = Pattern.compile("[+-]?[0-9]*[\\.]?[0-9]+([eE][+-]?[0-9]+)?"); |
| 166 | + final Pattern patternTrailingDot = Pattern.compile("[+-]?[0-9]+[\\.]"); |
| 167 | + // Digit-class bounds ('0', '9') plus the chars just outside it ('/', ':') |
| 168 | + // to catch off-by-one in digit checks; rest are the structural characters |
| 169 | + final char[] alphabet = new char[] { '0', '9', '/', ':', '+', '-', '.', 'e', 'E' }; |
| 170 | + |
| 171 | + // Length 5 needed to reach forms combining both signs ("+1e+1") or |
| 172 | + // integer + fraction + exponent ("1.2e3"); ~66k inputs, runs in ~50 msec |
| 173 | + _verifyAgainstRegexps(patternFloat, patternTrailingDot, alphabet, "", 5); |
| 174 | + } |
| 175 | + |
| 176 | + private void _verifyAgainstRegexps(Pattern patternFloat, Pattern patternTrailingDot, |
| 177 | + char[] alphabet, String prefix, int remainingLength) |
| 178 | + { |
| 179 | + if (!prefix.isEmpty()) { |
| 180 | + boolean exp = patternFloat.matcher(prefix).matches() |
| 181 | + || patternTrailingDot.matcher(prefix).matches(); |
| 182 | + assertEquals(exp, NumberInput.looksLikeValidNumber(prefix), |
| 183 | + "Mismatch for input '"+prefix+"'"); |
| 184 | + } |
| 185 | + if (remainingLength > 0) { |
| 186 | + for (char c : alphabet) { |
| 187 | + _verifyAgainstRegexps(patternFloat, patternTrailingDot, alphabet, |
| 188 | + prefix + c, remainingLength - 1); |
| 189 | + } |
| 190 | + } |
142 | 191 | } |
143 | 192 | } |
0 commit comments