@@ -65,9 +65,17 @@ public class JsonPointer implements Serializable
65
65
/**
66
66
* We will retain representation of the pointer, as a String,
67
67
* so that {@link #toString} should be as efficient as possible.
68
+ *<p>
69
+ * NOTE: starting with 2.14, there is no accompanying
70
+ * {@link #_asStringOffset} that MUST be considered with this String;
68
71
*/
69
72
protected final String _asString ;
70
73
74
+ /**
75
+ * @since 2.14
76
+ */
77
+ protected final int _asStringOffset ;
78
+
71
79
protected final String _matchingPropertyName ;
72
80
73
81
protected final int _matchingElementIndex ;
@@ -88,21 +96,26 @@ protected JsonPointer() {
88
96
_matchingPropertyName = null ;
89
97
_matchingElementIndex = -1 ;
90
98
_asString = "" ;
99
+ _asStringOffset = 0 ;
91
100
}
92
101
93
102
// Constructor used for creating non-empty Segments
94
- protected JsonPointer (String fullString , String segment , JsonPointer next ) {
103
+ protected JsonPointer (String fullString , int fullStringOffset ,
104
+ String segment , JsonPointer next )
105
+ {
95
106
_asString = fullString ;
107
+ _asStringOffset = fullStringOffset ;
96
108
_nextSegment = next ;
97
109
// Ok; may always be a property
98
110
_matchingPropertyName = segment ;
99
111
// but could be an index, if parsable
100
112
_matchingElementIndex = _parseIndex (segment );
101
113
}
102
114
103
- // @since 2.5
104
- protected JsonPointer ( String fullString , String segment , int matchIndex , JsonPointer next ) {
115
+ protected JsonPointer ( String fullString , int fullStringOffset ,
116
+ String segment , int matchIndex , JsonPointer next ) {
105
117
_asString = fullString ;
118
+ _asStringOffset = fullStringOffset ;
106
119
_nextSegment = next ;
107
120
_matchingPropertyName = segment ;
108
121
_matchingElementIndex = matchIndex ;
@@ -199,11 +212,11 @@ public static JsonPointer forPath(JsonStreamContext context,
199
212
if (seg == null ) { // is this legal?
200
213
seg = "" ;
201
214
}
202
- tail = new JsonPointer (_fullPath (tail , seg ), seg , tail );
215
+ tail = new JsonPointer (_fullPath (tail , seg ), 0 , seg , tail );
203
216
} else if (context .inArray () || includeRoot ) {
204
217
int ix = context .getCurrentIndex ();
205
218
String ixStr = String .valueOf (ix );
206
- tail = new JsonPointer (_fullPath (tail , ixStr ), ixStr , ix , tail );
219
+ tail = new JsonPointer (_fullPath (tail , ixStr ), 0 , ixStr , ix , tail );
207
220
}
208
221
// NOTE: this effectively drops ROOT node(s); should have 1 such node,
209
222
// as the last one, but we don't have to care (probably some paths have
@@ -517,7 +530,13 @@ public JsonPointer head() {
517
530
/**********************************************************
518
531
*/
519
532
520
- @ Override public String toString () { return _asString ; }
533
+ @ Override public String toString () {
534
+ if (_asStringOffset <= 0 ) {
535
+ return _asString ;
536
+ }
537
+ return _asString .substring (_asStringOffset );
538
+ }
539
+
521
540
@ Override public int hashCode () { return _asString .hashCode (); }
522
541
523
542
@ Override public boolean equals (Object o ) {
@@ -563,21 +582,21 @@ private final static int _parseIndex(String str) {
563
582
return NumberInput .parseInt (str );
564
583
}
565
584
566
- protected static JsonPointer _parseTail (String fullPath )
585
+ protected static JsonPointer _parseTail (final String fullPath )
567
586
{
568
587
PointerParent parent = null ;
569
588
570
589
// first char is the contextual slash, skip
571
590
int i = 1 ;
572
- int end = fullPath .length ();
591
+ final int end = fullPath .length ();
592
+ int startOffset = 0 ;
573
593
574
594
while (i < end ) {
575
595
char c = fullPath .charAt (i );
576
596
if (c == '/' ) { // common case, got a segment
577
- parent = new PointerParent (parent , fullPath , fullPath .substring (1 , i ));
578
- fullPath = fullPath .substring (i );
579
- i = 1 ;
580
- end = fullPath .length ();
597
+ parent = new PointerParent (parent , startOffset , fullPath .substring (startOffset + 1 , i ));
598
+ startOffset = i ;
599
+ ++i ;
581
600
continue ;
582
601
}
583
602
++i ;
@@ -591,10 +610,9 @@ protected static JsonPointer _parseTail(String fullPath)
591
610
if (i < 0 ) { // end!
592
611
return _buildPath (fullPath , segment , parent );
593
612
}
594
- parent = new PointerParent (parent , fullPath , segment );
595
- fullPath = fullPath .substring (i );
596
- i = 1 ;
597
- end = fullPath .length ();
613
+ parent = new PointerParent (parent , startOffset , segment );
614
+ startOffset = i ;
615
+ ++i ;
598
616
continue ;
599
617
}
600
618
// otherwise, loop on
@@ -603,11 +621,11 @@ protected static JsonPointer _parseTail(String fullPath)
603
621
return _buildPath (fullPath , fullPath .substring (1 ), parent );
604
622
}
605
623
606
- private static JsonPointer _buildPath (String fullPath , String segment ,
624
+ private static JsonPointer _buildPath (final String fullPath , String segment ,
607
625
PointerParent parent ) {
608
- JsonPointer curr = new JsonPointer (fullPath , segment , EMPTY );
626
+ JsonPointer curr = new JsonPointer (fullPath , 0 , segment , EMPTY );
609
627
for (; parent != null ; parent = parent .parent ) {
610
- curr = new JsonPointer (parent .fullPath , parent .segment , curr );
628
+ curr = new JsonPointer (fullPath , parent .fullPathOffset , parent .segment , curr );
611
629
}
612
630
return curr ;
613
631
}
@@ -669,7 +687,9 @@ protected JsonPointer _constructHead()
669
687
// and from that, length of suffix to drop
670
688
int suffixLength = last ._asString .length ();
671
689
JsonPointer next = _nextSegment ;
672
- return new JsonPointer (_asString .substring (0 , _asString .length () - suffixLength ), _matchingPropertyName ,
690
+ // !!! TODO 07-Oct-2022, tatu: change to iterative, not recursive
691
+ return new JsonPointer (_asString .substring (0 , _asString .length () - suffixLength ), 0 ,
692
+ _matchingPropertyName ,
673
693
_matchingElementIndex , next ._constructHead (suffixLength , last ));
674
694
}
675
695
@@ -680,7 +700,9 @@ protected JsonPointer _constructHead(int suffixLength, JsonPointer last)
680
700
}
681
701
JsonPointer next = _nextSegment ;
682
702
String str = _asString ;
683
- return new JsonPointer (str .substring (0 , str .length () - suffixLength ), _matchingPropertyName ,
703
+ // !!! TODO 07-Oct-2022, tatu: change to iterative, not recursive
704
+ return new JsonPointer (str .substring (0 , str .length () - suffixLength ), 0 ,
705
+ _matchingPropertyName ,
684
706
_matchingElementIndex , next ._constructHead (suffixLength , last ));
685
707
}
686
708
@@ -696,12 +718,12 @@ protected JsonPointer _constructHead(int suffixLength, JsonPointer last)
696
718
*/
697
719
private static class PointerParent {
698
720
public final PointerParent parent ;
699
- public final String fullPath ;
721
+ public final int fullPathOffset ;
700
722
public final String segment ;
701
723
702
- PointerParent (PointerParent pp , String fp , String sgm ) {
724
+ PointerParent (PointerParent pp , int fpo , String sgm ) {
703
725
parent = pp ;
704
- fullPath = fp ;
726
+ fullPathOffset = fpo ;
705
727
segment = sgm ;
706
728
}
707
729
}
0 commit comments