@@ -43,7 +43,10 @@ func (n *node) NextNode() (Node, bool) {
4343
4444// Value returns node's value, it returns nil if there is no
4545func (n * node ) Value () (interface {}, bool ) {
46- return n .Leaf .Val , n .Leaf != nil
46+ if n .Leaf != nil {
47+ return n .Leaf .Val , true
48+ }
49+ return nil , false
4750}
4851
4952// Extra returns node's Extra Info
@@ -73,7 +76,7 @@ type RTree struct {
7376}
7477
7578// return common prefix's offset of s1 and s2, in byte
76- // s1[:offset] == s2[:offset]
79+ // s1[:offset+1 ] == s2[:offset+1 ]
7780func commonPrefixOffset (s1 , s2 string ) int {
7881 i := 0
7982 runes1 , runes2 := []rune (s1 ), []rune (s2 )
@@ -454,7 +457,96 @@ func (T *RTree) GetAllPrefixMatches(key string) map[string]interface{} {
454457 return resultMap
455458}
456459
457- // GetBestMatch returns the longest match in the tree according to the key
460+ type traverseLog struct {
461+ n * node
462+ base string
463+ }
464+
465+ // GetLongerMatches returns at most `limmit` matches which are longer than the key
466+ // if no match is found, it returns an empty map
467+ func (T * RTree ) GetLongerMatches (key string , limit int ) map [string ]interface {} {
468+ T .m .RLock ()
469+ defer T .m .RUnlock ()
470+
471+ resultMap := map [string ]interface {}{}
472+ if T .root == nil {
473+ return resultMap
474+ } else if len (key ) == 0 {
475+ return resultMap
476+ }
477+
478+ var ok bool
479+ var rune1 rune
480+ var matchedNode * node
481+ node1 := T .root
482+ pathSuffix := key
483+ baseOffset := 0 // key[:baseOffset] is matched
484+ for {
485+ if node1 == nil {
486+ return resultMap
487+ }
488+
489+ rune1 = getRune1 (pathSuffix )
490+ matchedNode , ok = node1 .Idx [rune1 ]
491+ if ! ok {
492+ return resultMap
493+ }
494+
495+ offset := commonPrefixOffset (matchedNode .Prefix , pathSuffix )
496+ if offset == - 1 {
497+ // this is impossible
498+ panic (errImpossible (matchedNode .Prefix , key ))
499+ } else if offset == len (matchedNode .Prefix )- 1 && offset < len (pathSuffix )- 1 {
500+ pathSuffix = pathSuffix [offset + 1 :]
501+ node1 = matchedNode .Children
502+ baseOffset += offset + 1
503+ continue
504+ } else if offset == len (pathSuffix )- 1 {
505+ break
506+ }
507+ return resultMap
508+ }
509+
510+ if matchedNode .Leaf != nil {
511+ resultMap [key [:baseOffset ]+ matchedNode .Prefix ] = matchedNode .Leaf .Val
512+ }
513+ // start from next level becasue matchedNode's siblings are not results
514+ // traverse from the matchedNode and return values
515+ queue := []* traverseLog {& traverseLog {
516+ n : matchedNode .Children ,
517+ base : key [:baseOffset ] + matchedNode .Prefix ,
518+ }}
519+ for len (queue ) > 0 {
520+ tlog := queue [0 ]
521+ queue = queue [1 :]
522+ if tlog .n == nil {
523+ continue
524+ }
525+
526+ if tlog .n .Leaf != nil {
527+ resultMap [tlog .base + tlog .n .Prefix ] = tlog .n .Leaf .Val
528+ if len (resultMap ) > limit {
529+ break
530+ }
531+ }
532+ if tlog .n .Next != nil {
533+ queue = append (queue , & traverseLog {
534+ n : tlog .n .Next ,
535+ base : tlog .base ,
536+ })
537+ }
538+ if tlog .n .Children != nil {
539+ queue = append (queue , & traverseLog {
540+ n : tlog .n .Children ,
541+ base : tlog .base + tlog .n .Prefix ,
542+ })
543+ }
544+ }
545+
546+ return resultMap
547+ }
548+
549+ // GetBestMatch returns the longest match from all existings values which key is short than the input key
458550// if there is no match, it returns empty string, nil and false
459551func (T * RTree ) GetBestMatch (key string ) (string , interface {}, bool ) {
460552 T .m .RLock ()
0 commit comments