Skip to content

Commit

Permalink
More fixes to rewritten JsonPointer handler (doh! forgot to run ALL t…
Browse files Browse the repository at this point in the history
…ests)
  • Loading branch information
cowtowncoder committed Oct 7, 2022
1 parent 4f39761 commit 1a5f364
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 12 deletions.
78 changes: 67 additions & 11 deletions src/main/java/com/fasterxml/jackson/core/JsonPointer.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ public class JsonPointer implements Serializable

protected final int _matchingElementIndex;

/**
* @since 2.14
*/
protected int _hashCode;

/*
/**********************************************************
/* Construction
Expand Down Expand Up @@ -288,6 +293,19 @@ public static JsonPointer fromSegment(String... segments)
/**********************************************************
*/

/**
* Functionally same as:
*<code>
* toString().length()
*</code>
* but more efficient as it avoids likely String allocation.
*
* @since 2.14
*/
public int length() {
return _asString.length() - _asStringOffset;
}

public boolean matches() { return _nextSegment == null; }
public String getMatchingProperty() { return _matchingPropertyName; }
public int getMatchingIndex() { return _matchingElementIndex; }
Expand Down Expand Up @@ -537,13 +555,49 @@ public JsonPointer head() {
return _asString.substring(_asStringOffset);
}

@Override public int hashCode() { return _asString.hashCode(); }
@Override public int hashCode() {
int h = _hashCode;
if (h == 0) {
// Alas, this is bit wasteful, creating temporary String, but
// without JDK exposing hash code calculation for a sub-string
// can't do much
h = toString().hashCode();
if (h == 0) {
h = -1;
}
_hashCode = h;
}
return h;
}

@Override public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
if (!(o instanceof JsonPointer)) return false;
return _asString.equals(((JsonPointer) o)._asString);
JsonPointer other = (JsonPointer) o;
// 07-Oct-2022, tatu: Ugh.... this gets way more complicated as we MUST
// compare logical representation so cannot simply compare offset
// and String
return _compare(_asString, _asStringOffset,
other._asString, other._asStringOffset);
}

private final boolean _compare(String str1, int offset1,
String str2, int offset2) {
final int end1 = str1.length();

// Different lengths? Not equal
if ((end1 - offset1) != (str2.length() - offset2)) {
return false;
}

for (; offset1 < end1; ) {
if (str1.charAt(offset1++) != str2.charAt(offset2++)) {
return false;
}
}

return true;
}

/*
Expand Down Expand Up @@ -594,7 +648,8 @@ protected static JsonPointer _parseTail(final String fullPath)
while (i < end) {
char c = fullPath.charAt(i);
if (c == '/') { // common case, got a segment
parent = new PointerParent(parent, startOffset, fullPath.substring(startOffset + 1, i));
parent = new PointerParent(parent, startOffset,
fullPath.substring(startOffset + 1, i));
startOffset = i;
++i;
continue;
Expand All @@ -608,7 +663,7 @@ protected static JsonPointer _parseTail(final String fullPath)
i = _extractEscapedSegment(fullPath, i, sb);
final String segment = sb.toString();
if (i < 0) { // end!
return _buildPath(fullPath, segment, parent);
return _buildPath(fullPath, startOffset, segment, parent);
}
parent = new PointerParent(parent, startOffset, segment);
startOffset = i;
Expand All @@ -618,12 +673,12 @@ protected static JsonPointer _parseTail(final String fullPath)
// otherwise, loop on
}
// end of the road, no escapes
return _buildPath(fullPath, fullPath.substring(1), parent);
return _buildPath(fullPath, startOffset, fullPath.substring(startOffset + 1), parent);
}

private static JsonPointer _buildPath(final String fullPath, String segment,
PointerParent parent) {
JsonPointer curr = new JsonPointer(fullPath, 0, segment, EMPTY);
private static JsonPointer _buildPath(final String fullPath, int fullPathOffset,
String segment, PointerParent parent) {
JsonPointer curr = new JsonPointer(fullPath, fullPathOffset, segment, EMPTY);
for (; parent != null; parent = parent.parent) {
curr = new JsonPointer(fullPath, parent.fullPathOffset, parent.segment, curr);
}
Expand Down Expand Up @@ -685,10 +740,11 @@ protected JsonPointer _constructHead()
return EMPTY;
}
// and from that, length of suffix to drop
int suffixLength = last._asString.length();
int suffixLength = last.length();
JsonPointer next = _nextSegment;
// !!! TODO 07-Oct-2022, tatu: change to iterative, not recursive
return new JsonPointer(_asString.substring(0, _asString.length() - suffixLength), 0,
String fullString = toString();
return new JsonPointer(fullString.substring(0, fullString.length() - suffixLength), 0,
_matchingPropertyName,
_matchingElementIndex, next._constructHead(suffixLength, last));
}
Expand All @@ -699,7 +755,7 @@ protected JsonPointer _constructHead(int suffixLength, JsonPointer last)
return EMPTY;
}
JsonPointer next = _nextSegment;
String str = _asString;
String str = toString();
// !!! TODO 07-Oct-2022, tatu: change to iterative, not recursive
return new JsonPointer(str.substring(0, str.length() - suffixLength), 0,
_matchingPropertyName,
Expand Down
20 changes: 19 additions & 1 deletion src/test/java/com/fasterxml/jackson/core/JsonPointerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ public void testSimplePathLonger() throws Exception
assertEquals(INPUT, ptr.toString());
}

public void testSimpleTail() throws Exception
{
final String INPUT = "/root/leaf";
JsonPointer ptr = JsonPointer.compile(INPUT);

assertEquals("/leaf", ptr.tail().toString());
assertEquals("", ptr.tail().tail().toString());
}

public void testWonkyNumber173() throws Exception
{
JsonPointer ptr = JsonPointer.compile("/1e0");
Expand All @@ -72,11 +81,20 @@ public void testIZeroIndex() throws Exception

public void testLast()
{
final String INPUT = "/Image/15/name";
String INPUT = "/Image/name";

JsonPointer ptr = JsonPointer.compile(INPUT);
JsonPointer leaf = ptr.last();

assertEquals("/name", leaf.toString());
assertEquals("name", leaf.getMatchingProperty());

INPUT = "/Image/15/name";

ptr = JsonPointer.compile(INPUT);
leaf = ptr.last();

assertEquals("/name", leaf.toString());
assertEquals("name", leaf.getMatchingProperty());
}

Expand Down

0 comments on commit 1a5f364

Please sign in to comment.