Skip to content

Commit 078ddfb

Browse files
committed
Merge branch 'refs/heads/main' into dev
# Conflicts: # deployment/deployment.md # deployment/pom.xml # fastdoubleparser-dev/src/main/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/AbstractConfigurableFloatingPointBitsFromByteArrayAscii.java # fastdoubleparser-dev/src/main/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/AbstractConfigurableFloatingPointBitsFromCharSequence.java # fastdoubleparser-dev/src/main/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/NumberFormatSymbolsInfo.java # fastdoubleparser-dev/src/test/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/ConfigurableDoubleParserTest.java # fastdoubleparser-dev/src/test/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/ConfigurableDoubleParserTestDataFactory.java # pom.xml
2 parents a54df48 + 302b4d0 commit 078ddfb

28 files changed

Lines changed: 100686 additions & 364 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
matrix:
1010
os: [ ubuntu-latest ]
11-
java: [ 24-ea ]
11+
java: [ 23 ]
1212
arch: [ x64 ]
1313
dist: [ zulu ]
1414
fail-fast: false

.github/workflows/maven-publish.yml

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,38 @@ on:
99

1010
jobs:
1111
build:
12-
1312
runs-on: ubuntu-latest
14-
permissions:
15-
contents: read
16-
packages: write
1713

1814
steps:
19-
- uses: actions/checkout@v3
20-
- name: Set up JDK 22
21-
uses: actions/setup-java@v3
22-
with:
23-
java-version: '22'
24-
distribution: 'temurin'
25-
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
26-
settings-path: ${{ github.workspace }} # location for the settings.xml file
27-
28-
- name: Build with Maven
29-
run: mvn -B package --file pom.xml
30-
31-
- name: Publish to GitHub Packages Apache Maven
32-
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
33-
env:
34-
GITHUB_TOKEN: ${{ github.token }}
15+
- uses: actions/checkout@v4
16+
- name: Set up JDK 21
17+
uses: actions/setup-java@v4
18+
with:
19+
distribution: 'zulu'
20+
java-version: '23'
21+
22+
- name: Build with Maven
23+
run: mvn -B package --file pom.xml
24+
25+
- name: Publish to GitHub Packages Apache Maven
26+
run: mvn deploy
27+
env:
28+
GITHUB_TOKEN: ${{ github.token }} # GITHUB_TOKEN is the default env for the password
29+
30+
- name: Set up Apache Maven Central
31+
uses: actions/setup-java@v4
32+
with: # running setup-java again overwrites the settings.xml
33+
distribution: 'zulu'
34+
java-version: '23'
35+
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
36+
server-username: MAVEN_USERNAME # env variable for username in deploy
37+
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
38+
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
39+
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
40+
41+
- name: Publish to Apache Maven Central
42+
run: mvn deploy
43+
env:
44+
MAVEN_USERNAME: maven_username123
45+
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
46+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/Main_Dev_ar.xml

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fastdoubleparser-dev/src/main/java/ch.randelshofer.fastdoubleparser/ch/randelshofer/fastdoubleparser/AbstractConfigurableFloatingPointBitsFromByteArrayAscii.java

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,24 @@
1313
*/
1414
abstract class AbstractConfigurableFloatingPointBitsFromByteArrayAscii extends AbstractFloatValueParser {
1515
protected final ByteDigitSet digitSet;
16-
private final ByteSet minusSignChar;
17-
private final ByteSet plusSignChar;
16+
private final ByteSet minusSign;
17+
private final ByteSet plusSign;
1818
private final ByteSet decimalSeparator;
1919
private final ByteSet groupingSeparator;
20-
private final ByteTrie nanTrie;
21-
private final ByteTrie infinityTrie;
22-
private final ByteTrie exponentSeparatorTrie;
20+
private final ByteTrie nan;
21+
private final ByteTrie infinity;
22+
private final ByteTrie exponentSeparator;
2323

2424
public AbstractConfigurableFloatingPointBitsFromByteArrayAscii(NumberFormatSymbols symbols, boolean ignoreCase) {
2525
this.decimalSeparator = ByteSet.copyOf(symbols.decimalSeparator(), ignoreCase);
2626
this.groupingSeparator = ByteSet.copyOf(symbols.groupingSeparator(), ignoreCase);
2727
this.digitSet = ByteDigitSet.copyOf(symbols.digits());
28-
this.minusSignChar = ByteSet.copyOf(symbols.minusSign(), ignoreCase);
29-
this.exponentSeparatorTrie = ByteTrie.copyOf(symbols.exponentSeparator(), ignoreCase);
30-
this.plusSignChar = ByteSet.copyOf(symbols.plusSign(), ignoreCase);
31-
this.nanTrie = ByteTrie.copyOf(symbols.nan(), ignoreCase);
32-
this.infinityTrie = ByteTrie.copyOf(symbols.infinity(), ignoreCase);
28+
this.minusSign = ByteSet.copyOf(symbols.minusSign(), ignoreCase);
29+
this.exponentSeparator = ByteTrie.copyOf(symbols.exponentSeparator(), ignoreCase);
30+
this.plusSign = ByteSet.copyOf(symbols.plusSign(), ignoreCase);
31+
this.nan = ByteTrie.copyOf(symbols.nan(), ignoreCase);
32+
this.infinity = ByteTrie.copyOf(symbols.infinity(), ignoreCase);
33+
3334
}
3435

3536
/**
@@ -43,14 +44,6 @@ public AbstractConfigurableFloatingPointBitsFromByteArrayAscii(NumberFormatSymbo
4344
*/
4445
abstract long negativeInfinity();
4546

46-
private boolean isDecimalSeparator(byte ch) {
47-
return decimalSeparator.containsKey(ch);
48-
}
49-
50-
private boolean isGroupingSeparator(byte ch) {
51-
return groupingSeparator.containsKey(ch);
52-
}
53-
5447
/**
5548
* Parses a {@code FloatingPointLiteral} production with optional leading and trailing
5649
* white space.
@@ -71,19 +64,15 @@ private boolean isGroupingSeparator(byte ch) {
7164
*/
7265
public final long parseFloatingPointLiteral(byte[] str, int offset, int length) {
7366
final int endIndex = checkBounds(str.length, offset, length);
74-
75-
// Start at offset
76-
// -------------------
7767
int index = offset;
78-
if (index == endIndex) {
79-
return SYNTAX_ERROR_BITS;
80-
}
8168
byte ch = str[index];
8269

83-
// Parse optional sign
70+
// Parse optional sign before significand
8471
// -------------------
85-
final boolean isNegative = isMinusSign(ch);
86-
if (isNegative || isPlusSign(ch)) {
72+
boolean isNegative = minusSign.containsKey(ch);
73+
boolean isSignificandSigned = false;
74+
if (isNegative || plusSign.containsKey(ch)) {
75+
isSignificandSigned = true;
8776
++index;
8877
if (index == endIndex) {
8978
return SYNTAX_ERROR_BITS;
@@ -107,11 +96,12 @@ public final long parseFloatingPointLiteral(byte[] str, int offset, int length)
10796
if (digit < 10) {
10897
// This might overflow, we deal with it later.
10998
significand = 10 * significand + digit;
110-
} else if (isDecimalSeparator(ch)) {
99+
} else if (decimalSeparator.containsKey(ch)) {
111100
illegal |= integerDigitCount >= 0;
112101
decimalSeparatorIndex = index;
113102
integerDigitCount = index - significandStartIndex - groupingCount;
114-
} else if (isGroupingSeparator(ch)) {
103+
} else if (groupingSeparator.containsKey(ch)) {
104+
illegal |= decimalSeparatorIndex != -1;
115105
groupingCount++;
116106
} else {
117107
break;
@@ -130,37 +120,63 @@ public final long parseFloatingPointLiteral(byte[] str, int offset, int length)
130120
}
131121
illegal |= digitCount == 0 && significandEndIndex > significandStartIndex;
132122

123+
// Parse optional sign after significand
124+
// -------------------
125+
if (index < endIndex && !isSignificandSigned) {
126+
isNegative = minusSign.containsKey(ch);
127+
if (isNegative || plusSign.containsKey(ch)) {
128+
index++;
129+
}
130+
}
131+
133132
// Parse exponent number
134133
// ---------------------
135134
int expNumber = 0;
136-
int count = exponentSeparatorTrie.match(str, index, endIndex);
137-
if (count > 0) {
138-
index += count;
139-
ch = charAt(str, index, endIndex);
140-
boolean isExponentNegative = isMinusSign(ch);
141-
if (isExponentNegative || isPlusSign(ch)) {
142-
ch = charAt(str, ++index, endIndex);
143-
}
144-
int digit = digitSet.toDigit(ch);
145-
illegal |= digit >= 10;
146-
do {
147-
// Guard against overflow
148-
if (expNumber < AbstractFloatValueParser.MAX_EXPONENT_NUMBER) {
149-
expNumber = 10 * expNumber + digit;
135+
boolean isExponentSigned = false;
136+
if (digitCount > 0) {
137+
int count = exponentSeparator.match(str, index, endIndex);
138+
if (count > 0) {
139+
index += count;
140+
141+
// Parse optional sign before exponent number
142+
ch = charAt(str, index, endIndex);
143+
boolean isExponentNegative = minusSign.containsKey(ch);
144+
if (isExponentNegative || plusSign.containsKey(ch)) {
145+
ch = charAt(str, ++index, endIndex);
146+
isExponentSigned = true;
150147
}
151-
ch = charAt(str, ++index, endIndex);
152-
digit = digitSet.toDigit(ch);
153-
} while (digit < 10);
154-
if (isExponentNegative) {
155-
expNumber = -expNumber;
148+
149+
int digit = digitSet.toDigit(ch);
150+
illegal |= digit >= 10;
151+
do {
152+
// Guard against overflow
153+
if (expNumber < AbstractFloatValueParser.MAX_EXPONENT_NUMBER) {
154+
expNumber = 10 * expNumber + digit;
155+
}
156+
ch = charAt(str, ++index, endIndex);
157+
digit = digitSet.toDigit(ch);
158+
} while (digit < 10);
159+
160+
161+
// Parse optional sign after exponent number
162+
if (!isExponentSigned) {
163+
isExponentNegative = minusSign.containsKey(ch);
164+
if (isExponentNegative || plusSign.containsKey(ch)) {
165+
index++;
166+
}
167+
}
168+
169+
if (isExponentNegative) {
170+
expNumber = -expNumber;
171+
}
172+
exponent += expNumber;
156173
}
157-
exponent += expNumber;
158174
}
159175

160176
// Parse NaN or Infinity (this occurs rarely)
161177
// ---------------------
162178
if (!illegal && digitCount == 0) {
163-
return parseNaNOrInfinity(str, index, endIndex, isNegative);
179+
return parseNaNOrInfinity(str, index, endIndex, isNegative, isSignificandSigned);
164180
}
165181

166182
// Check if FloatingPointLiteral is complete
@@ -200,24 +216,29 @@ public final long parseFloatingPointLiteral(byte[] str, int offset, int length)
200216
exponentOfTruncatedSignificand, expNumber, offset, endIndex);
201217
}
202218

203-
private boolean isMinusSign(byte c) {
204-
return minusSignChar.containsKey(c);
205-
}
206-
207-
private boolean isPlusSign(byte c) {
208-
return plusSignChar.containsKey(c);
209-
}
210-
211-
private long parseNaNOrInfinity(byte[] str, int index, int endIndex, boolean isNegative) {
212-
int nanMatch = nanTrie.match(str, index, endIndex);
219+
private long parseNaNOrInfinity(byte[] str, int index, int endIndex, boolean isNegative, boolean isSignificandSigned) {
220+
int nanMatch = nan.match(str, index, endIndex);
213221
if (nanMatch > 0) {
214-
if (index + nanMatch == endIndex) {
215-
return nan();
222+
index += nanMatch;
223+
if (index < endIndex && !isSignificandSigned) {
224+
byte ch = str[index];
225+
if (minusSign.containsKey(ch) || plusSign.containsKey(ch)) {
226+
index++;
227+
}
216228
}
229+
return (index == endIndex) ? nan() : SYNTAX_ERROR_BITS;
217230
}
218-
int infinityMatch = infinityTrie.match(str, index, endIndex);
231+
int infinityMatch = infinity.match(str, index, endIndex);
219232
if (infinityMatch > 0) {
220-
if (index + infinityMatch == endIndex) {
233+
index += infinityMatch;
234+
if (index < endIndex && !isSignificandSigned) {
235+
byte ch = str[index];
236+
isNegative = minusSign.containsKey(ch);
237+
if (isNegative || plusSign.containsKey(ch)) {
238+
index++;
239+
}
240+
}
241+
if (index == endIndex) {
221242
return isNegative ? negativeInfinity() : positiveInfinity();
222243
}
223244
}

0 commit comments

Comments
 (0)