Skip to content

Commit

Permalink
Merge branch '2.18'
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Apr 20, 2024
2 parents 6f2f569 + 8b87cc1 commit ebe8b8d
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 20 deletions.
8 changes: 5 additions & 3 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ a pure JSON library.

2.18.0 (not yet released)

#1230: Improve performance of `float` and `double` parsing from `TextBuffer`
(implemented by @pjfanning)
#1251: `InternCache` replace synchronized with `ReentrantLock` - the cache
size limit is no longer strictly enforced for performance reasons but
we should never go far about the limit
(contributed by @pjfanning)
(implemented by @pjfanning)
#1252: `ThreadLocalBufferManager` replace synchronized with `ReentrantLock`
(contributed by @pjfanning)
(implemented by @pjfanning)
#1257: Increase InternCache default max size from 100 to 200
#1262: Add diagnostic method pooledCount() in RecyclerPool
#1262: Add diagnostic method `pooledCount()` in `RecyclerPool`
#1266: Change default recycler pool to `bewConcurrentDequePool()` in 2.18

2.17.1 (not yet released)
Expand Down
52 changes: 52 additions & 0 deletions src/main/java/tools/jackson/core/io/NumberInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,32 @@ public static double parseDouble(final String s, final boolean useFastParser) th
return useFastParser ? JavaDoubleParser.parseDouble(s) : Double.parseDouble(s);
}

/**
* @param array a char array containing a number to parse
* @param useFastParser whether to use {@code FastDoubleParser}
* @return closest matching double
* @throws NumberFormatException if value cannot be represented by a double
* @since 2.18
*/
public static double parseDouble(final char[] array, final boolean useFastParser) throws NumberFormatException {
return parseDouble(array, 0, array.length, useFastParser);
}

/**
* @param array a char array containing a number to parse
* @param offset the offset to apply when parsing the number in the char array
* @param len the length of the number in the char array
* @param useFastParser whether to use {@code FastDoubleParser}
* @return closest matching double
* @throws NumberFormatException if value cannot be represented by a double
* @since 2.18
*/
public static double parseDouble(final char[] array, final int offset,
final int len, final boolean useFastParser) throws NumberFormatException {
return useFastParser ? JavaDoubleParser.parseDouble(array, offset, len) :
Double.parseDouble(new String(array, offset, len));
}

/**
* @param s a string representing a number to parse
* @return closest matching float
Expand Down Expand Up @@ -411,6 +437,32 @@ public static float parseFloat(final String s, final boolean useFastParser) thro
return Float.parseFloat(s);
}

/**
* @param array a char array containing a number to parse
* @param useFastParser whether to use {@code FastDoubleParser}
* @return closest matching float
* @throws NumberFormatException if value cannot be represented by a float
* @since 2.18
*/
public static float parseFloat(final char[] array, final boolean useFastParser) throws NumberFormatException {
return parseFloat(array, 0, array.length, useFastParser);
}

/**
* @param array a char array containing a number to parse
* @param offset the offset to apply when parsing the number in the char array
* @param len the length of the number in the char array
* @param useFastParser whether to use {@code FastDoubleParser}
* @return closest matching float
* @throws NumberFormatException if value cannot be represented by a float
* @since 2.18
*/
public static float parseFloat(final char[] array, final int offset,
final int len, final boolean useFastParser) throws NumberFormatException {
return useFastParser ? JavaFloatParser.parseFloat(array, offset, len) :
Float.parseFloat(new String(array, offset, len));
}

/**
* @param s a string representing a number to parse
* @return a BigDecimal
Expand Down
76 changes: 59 additions & 17 deletions src/main/java/tools/jackson/core/util/TextBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ private char[] buf(int needed)
private void clearSegments()
{
_hasSegments = false;
/* Let's start using _last_ segment from list; for one, it's
* the biggest one, and it's also most likely to be cached
*/
// Let's start using _last_ segment from list; for one, it's
// the biggest one, and it's also most likely to be cached

// 28-Aug-2009, tatu: Actually, the current segment should
// be the biggest one, already
//_currentSegment = _segments.get(_segments.size() - 1);
Expand Down Expand Up @@ -516,37 +516,79 @@ public char[] contentsAsArray() throws JacksonException {
/**
* Convenience method for converting contents of the buffer
* into a Double value.
*<p>
* NOTE! Caller <b>MUST</b> validate contents before calling this method,
* to ensure textual version is valid JSON floating-point token -- this
* method is not guaranteed to do any validation and behavior with invalid
* content is not defined (either throws an exception or returns arbitrary
* number).
*
* @param useFastParser whether to use {@code FastDoubleParser}
* @return Buffered text value parsed as a {@link Double}, if possible
*
* @throws NumberFormatException if contents are not a valid Java number
* @throws NumberFormatException may (but is not guaranteed!) be thrown
* if contents are not a valid JSON floating-point number representation
*/
public double contentsAsDouble(final boolean useFastParser) throws NumberFormatException {
try {
return NumberInput.parseDouble(contentsAsString(), useFastParser);
} catch (JacksonException e) {
// JsonParseException is used to denote a string that is too long
throw new NumberFormatException(e.getMessage());
public double contentsAsDouble(final boolean useFastParser) throws NumberFormatException
{
// Order in which check is somewhat arbitrary... try likeliest ones
// that do not require allocation first

// except _resultString first since it works best with JDK (non-fast parser)
if (_resultString != null) {
return NumberInput.parseDouble(_resultString, useFastParser);
}
if (_inputStart >= 0) { // shared?
return NumberInput.parseDouble(_inputBuffer, _inputStart, _inputLen, useFastParser);
}
if (_currentSize == 0) { // all content in current segment!
return NumberInput.parseDouble(_currentSegment, 0, _currentSize, useFastParser);
}
if (_resultArray != null) {
return NumberInput.parseDouble(_resultArray, useFastParser);
}

// Otherwise, segmented so need to use slow path
return NumberInput.parseDouble(contentsAsString(), useFastParser);
}

/**
* Convenience method for converting contents of the buffer
* into a Float value.
*<p>
* NOTE! Caller <b>MUST</b> validate contents before calling this method,
* to ensure textual version is valid JSON floating-point token -- this
* method is not guaranteed to do any validation and behavior with invalid
* content is not defined (either throws an exception or returns arbitrary
* number).
*
* @param useFastParser whether to use {@code FastDoubleParser}
* @return Buffered text value parsed as a {@link Float}, if possible
*
* @throws NumberFormatException if contents are not a valid Java number
* @throws NumberFormatException may (but is not guaranteed!) be thrown
* if contents are not a valid JSON floating-point number representation
*/
public float contentsAsFloat(final boolean useFastParser) throws NumberFormatException {
try {
return NumberInput.parseFloat(contentsAsString(), useFastParser);
} catch (JacksonException e) {
// JsonParseException is used to denote a string that is too long
throw new NumberFormatException(e.getMessage());
public float contentsAsFloat(final boolean useFastParser) throws NumberFormatException
{
// Order in which check is somewhat arbitrary... try likeliest ones
// that do not require allocation first

// except _resultString first since it works best with JDK (non-fast parser)
if (_resultString != null) {
return NumberInput.parseFloat(_resultString, useFastParser);
}
if (_inputStart >= 0) { // shared?
return NumberInput.parseFloat(_inputBuffer, _inputStart, _inputLen, useFastParser);
}
if (_currentSize == 0) { // all content in current segment!
return NumberInput.parseFloat(_currentSegment, 0, _currentSize, useFastParser);
}
if (_resultArray != null) {
return NumberInput.parseFloat(_resultArray, useFastParser);
}

// Otherwise, segmented so need to use slow path
return NumberInput.parseFloat(contentsAsString(), useFastParser);
}

/**
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/tools/jackson/core/util/TestTextBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.*;

class TestTextBuffer
Expand Down Expand Up @@ -211,4 +213,27 @@ void getSizeFinishCurrentSegmentAndResetWith() throws Exception {
assertEquals(2, textBuffer.size());
}

public void testContentsAsFloat() throws IOException {
TextBuffer textBuffer = new TextBuffer(null);
textBuffer.resetWithString("1.2345678");
assertEquals(1.2345678f, textBuffer.contentsAsFloat(false));
}

public void testContentsAsFloatFastParser() throws IOException {
TextBuffer textBuffer = new TextBuffer(null);
textBuffer.resetWithString("1.2345678");
assertEquals(1.2345678f, textBuffer.contentsAsFloat(true));
}

public void testContentsAsDouble() throws IOException {
TextBuffer textBuffer = new TextBuffer(null);
textBuffer.resetWithString("1.234567890123456789");
assertEquals(1.234567890123456789d, textBuffer.contentsAsDouble(false));
}

public void testContentsAsDoubleFastParser() throws IOException {
TextBuffer textBuffer = new TextBuffer(null);
textBuffer.resetWithString("1.234567890123456789");
assertEquals(1.234567890123456789d, textBuffer.contentsAsDouble(true));
}
}

0 comments on commit ebe8b8d

Please sign in to comment.