2323 * Commit: 17fb1065d2b256d20f68bed0b7bca6c2942aff49
2424 */
2525class Chi implements RouteTree {
26+ private static final String EMPTY_STRING = "" ;
2627 private static final byte ntStatic = 0 ;// /home
2728 private static final byte ntRegexp = 1 ; // /{id:[0-9]+}
2829 private static final byte ntParam = 2 ; // /{user}
@@ -51,130 +52,18 @@ public void put(String method, Route route) {
5152 }
5253 }
5354
54- static class ZeroCopyString {
55- public static final ZeroCopyString EMPTY = new ZeroCopyString (new char [0 ], 0 , 0 );
56-
57- private final int offset ;
58- private final int length ;
59- private int hash = 0 ;
60- private final char [] value ;
61-
62- public ZeroCopyString (String source ) {
63- this .offset = 0 ;
64- this .length = source .length ();
65- this .value = source .toCharArray ();
66- }
67-
68- @ Override public boolean equals (Object anObject ) {
69- if (this == anObject ) {
70- return true ;
71- }
72- if (anObject instanceof ZeroCopyString ) {
73- ZeroCopyString anotherString = (ZeroCopyString ) anObject ;
74- int n = length ;
75- if (n == anotherString .length ) {
76- char v1 [] = value ;
77- char v2 [] = anotherString .value ;
78- int i = 0 ;
79- while (n -- != 0 ) {
80- if (v1 [i + offset ] != v2 [i + anotherString .offset ])
81- return false ;
82- i ++;
83- }
84- return true ;
85- }
86- }
87- return false ;
88- }
89-
90- public int hashCode () {
91- int h = hash ;
92- if (h == 0 && length > 0 ) {
93- char val [] = value ;
94- int len = offset + length ;
95- for (int i = offset ; i < len ; i ++) {
96- h = 31 * h + val [i ];
97- }
98- hash = h ;
99- }
100- return h ;
101- }
102-
103- protected ZeroCopyString (char [] source , int offset , int length ) {
104- this .offset = offset ;
105- this .length = length ;
106- this .value = source ;
107- }
108-
109- public int length () {
110- return length ;
111- }
112-
113- public ZeroCopyString substring (int beginIndex ) {
114- return (beginIndex == 0 )
115- ? this
116- : new ZeroCopyString (value , offset + beginIndex , length - beginIndex );
117- }
118-
119- public ZeroCopyString substring (int beginIndex , int endIndex ) {
120- int len = endIndex - beginIndex ;
121- return (beginIndex == 0 && len == length )
122- ? this
123- : new ZeroCopyString (value , offset + beginIndex , endIndex - beginIndex );
124- }
125-
126- public char charAt (int index ) {
127- return value [offset + index ];
128- }
129-
130- public int indexOf (int ch ) {
131- int fromIndex = offset ;
132- final int max = Math .min (value .length , offset + length );
133-
134- final char [] value = this .value ;
135- for (int i = fromIndex ; i < max ; i ++) {
136- if (value [i ] == ch ) {
137- return i - offset ;
138- }
139- }
140- return -1 ;
141- }
142-
143- public boolean startsWith (ZeroCopyString prefix ) {
144- char ta [] = value ;
145- int to = offset ;
146- char pa [] = prefix .value ;
147- int po = prefix .offset ;
148- int pc = prefix .length ;
149- // Note: toffset might be near -1>>>1.
150- if (pc > length ) {
151- return false ;
152- }
153- while (--pc >= 0 ) {
154- if (ta [to ++] != pa [po ++]) {
155- return false ;
156- }
157- }
158- return true ;
159- }
160-
161- @ Override public String toString () {
162- return new String (value , offset , length );
163- }
164- }
165-
16655 static class Segment {
16756 byte nodeType ;
16857 // String key = "";
169- ZeroCopyString rexPat = ZeroCopyString . EMPTY ;
58+ String rexPat = EMPTY_STRING ;
17059 char tail ;
17160 int startIndex ;
17261 int endIndex ;
17362
17463 public Segment () {
17564 }
17665
177- public Segment (byte nodeType , /*String key,*/ ZeroCopyString regex , char tail , int startIndex ,
66+ public Segment (byte nodeType , /*String key,*/ String regex , char tail , int startIndex ,
17867 int endIndex ) {
17968 this .nodeType = nodeType ;
18069 // this.key = key;
@@ -196,7 +85,7 @@ private static class Node implements Comparable<Node> {
19685 char tail ;
19786
19887 // prefix is the common prefix we ignore
199- ZeroCopyString prefix ;
88+ String prefix ;
20089
20190 // regexp matcher for regexp nodes
20291 Pattern rex ;
@@ -230,7 +119,7 @@ public Node tail(char tail) {
230119 return this ;
231120 }
232121
233- public Node prefix (ZeroCopyString prefix ) {
122+ public Node prefix (String prefix ) {
234123 this .prefix = prefix ;
235124 return this ;
236125 }
@@ -264,10 +153,10 @@ public Node prefix(ZeroCopyString prefix) {
264153 return node .toString ();
265154 }
266155
267- Node insertRoute (String method , ZeroCopyString pattern , Route route ) {
156+ Node insertRoute (String method , String pattern , Route route ) {
268157 Node n = this ;
269158 Node parent ;
270- ZeroCopyString search = pattern ;
159+ String search = pattern ;
271160
272161 while (true ) {
273162 // Handle key exhaustion
@@ -291,11 +180,11 @@ Node insertRoute(String method, ZeroCopyString pattern, Route route) {
291180 seg = new Segment ();
292181 }
293182
294- ZeroCopyString prefix ;
183+ String prefix ;
295184 if (seg .nodeType == ntRegexp ) {
296185 prefix = seg .rexPat ;
297186 } else {
298- prefix = ZeroCopyString . EMPTY ;
187+ prefix = EMPTY_STRING ;
299188 }
300189
301190 // Look for the edge to attach to
@@ -358,7 +247,7 @@ Node insertRoute(String method, ZeroCopyString pattern, Route route) {
358247 // For a URL router like chi's, we split the static, param, regexp and wildcard segments
359248 // into different nodes. In addition, addChild will recursively call itself until every
360249 // pattern segment is added to the url pattern tree as individual nodes, depending on type.
361- Node addChild (Node child , ZeroCopyString search ) {
250+ Node addChild (Node child , String search ) {
362251 Node n = this ;
363252 // String search = prefix.toString();
364253
@@ -449,7 +338,7 @@ void replaceChild(char label, char tail, Node child) {
449338 throw new IllegalArgumentException ("chi: replacing missing child" );
450339 }
451340
452- Node getEdge (int ntyp , char label , char tail , ZeroCopyString prefix ) {
341+ Node getEdge (int ntyp , char label , char tail , String prefix ) {
453342 Node n = this ;
454343 Node [] nds = n .children [ntyp ];
455344 for (int i = 0 ; nds != null && i < nds .length ; i ++) {
@@ -495,13 +384,13 @@ void setEndpoint(String method, Route route) {
495384
496385 // Recursive edge traversal by checking all nodeTyp groups along the way.
497386 // It's like searching through a multi-dimensional radix trie.
498- Route findRoute (RouterMatch rctx , String method , ZeroCopyString path ) {
387+ Route findRoute (RouterMatch rctx , String method , String path ) {
499388
500389 for (int ntyp = 0 ; ntyp < NODE_SIZE ; ntyp ++) {
501390 Node [] nds = this .children [ntyp ];
502391 if (nds != null ) {
503392 Node xn = null ;
504- ZeroCopyString xsearch = path ;
393+ String xsearch = path ;
505394
506395 char label = path .length () > 0 ? path .charAt (0 ) : ZERO_CHAR ;
507396
@@ -558,7 +447,7 @@ Route findRoute(RouterMatch rctx, String method, ZeroCopyString path) {
558447 rctx .value (xsearch );
559448 }
560449 xn = nds [0 ];
561- xsearch = ZeroCopyString . EMPTY ;
450+ xsearch = EMPTY_STRING ;
562451 }
563452
564453 if (xn == null ) {
@@ -625,7 +514,7 @@ boolean isLeaf() {
625514 }
626515
627516 // longestPrefix finds the filesize of the shared prefix of two strings
628- int longestPrefix (ZeroCopyString k1 , ZeroCopyString k2 ) {
517+ int longestPrefix (String k1 , String k2 ) {
629518 int len = Math .min (k1 .length (), k2 .length ());
630519 for (int i = 0 ; i < len ; i ++) {
631520 if (k1 .charAt (i ) != k2 .charAt (i )) {
@@ -661,12 +550,12 @@ private Node[] append(Node[] src, Node child) {
661550
662551 // patNextSegment returns the next segment details from a pattern:
663552 // node type, param key, regexp string, param tail byte, param starting index, param ending index
664- Segment patNextSegment (ZeroCopyString pattern ) {
553+ Segment patNextSegment (String pattern ) {
665554 int ps = pattern .indexOf ('{' );
666555 int ws = pattern .indexOf ('*' );
667556
668557 if (ps < 0 && ws < 0 ) {
669- return new Segment (ntStatic , ZeroCopyString . EMPTY , (char ) 0 , 0 ,
558+ return new Segment (ntStatic , EMPTY_STRING , (char ) 0 , 0 ,
670559 pattern .length ()); // we return the entire thing
671560 }
672561
@@ -685,7 +574,7 @@ Segment patNextSegment(ZeroCopyString pattern) {
685574 // Read to closing } taking into account opens and closes in curl count (cc)
686575 int cc = 0 ;
687576 int pe = ps ;
688- ZeroCopyString range = pattern .substring (ps );
577+ String range = pattern .substring (ps );
689578 for (int i = 0 ; i < range .length (); i ++) {
690579 char c = range .charAt (i );
691580 if (c == '{' ) {
@@ -703,7 +592,7 @@ Segment patNextSegment(ZeroCopyString pattern) {
703592 "Router: route param closing delimiter '}' is missing" );
704593 }
705594
706- ZeroCopyString key = pattern .substring (ps + 1 , pe );
595+ String key = pattern .substring (ps + 1 , pe );
707596 pe ++; // set end to next position
708597
709598 if (pe < pattern .length ()) {
@@ -727,14 +616,14 @@ Segment patNextSegment(ZeroCopyString pattern) {
727616 }
728617 }
729618
730- return new Segment (nt , new ZeroCopyString ( rexpat ) , tail , ps , pe );
619+ return new Segment (nt , rexpat , tail , ps , pe );
731620 }
732621
733622 // Wildcard pattern as finale
734623 // EDIT: should we panic if there is stuff after the * ???
735624 // We allow naming a wildcard: *path
736625 //String key = ws == pattern.length() - 1 ? "*" : pattern.substring(ws + 1).toString();
737- return new Segment (ntCatchAll , ZeroCopyString . EMPTY , (char ) 0 , ws , pattern .length ());
626+ return new Segment (ntCatchAll , EMPTY_STRING , (char ) 0 , ws , pattern .length ());
738627 }
739628
740629 public void destroy () {
@@ -782,7 +671,7 @@ public void insert(String method, String pattern, Route route) {
782671 StaticRoute staticRoute = staticPaths .computeIfAbsent (pattern , k -> new StaticRoute ());
783672 staticRoute .put (method , route );
784673 }
785- root .insertRoute (method , new ZeroCopyString ( pattern ) , route );
674+ root .insertRoute (method , pattern , route );
786675 }
787676
788677 private String baseCatchAll (String pattern ) {
@@ -803,7 +692,7 @@ public void destroy() {
803692
804693 public boolean exists (String method , String path ) {
805694 if (!staticPaths .getOrDefault (path , NO_MATCH ).methods .containsKey (method )) {
806- return root .findRoute (new RouterMatch (), method , new ZeroCopyString ( path ) ) != null ;
695+ return root .findRoute (new RouterMatch (), method , path ) != null ;
807696 }
808697 return true ;
809698 }
@@ -813,7 +702,7 @@ public boolean exists(String method, String path) {
813702 if (match == null ) {
814703 // use radix tree
815704 RouterMatch result = new RouterMatch ();
816- Route route = root .findRoute (result , method , new ZeroCopyString ( path ) );
705+ Route route = root .findRoute (result , method , path );
817706 if (route == null ) {
818707 return result .missing (method , path , encoder );
819708 }
0 commit comments