github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/json/path.gno (about)

     1  package json
     2  
     3  import (
     4  	"errors"
     5  )
     6  
     7  // ParsePath takes a JSONPath string and returns a slice of strings representing the path segments.
     8  func ParsePath(path string) ([]string, error) {
     9  	buf := newBuffer([]byte(path))
    10  	result := make([]string, 0)
    11  
    12  	for {
    13  		b, err := buf.current()
    14  		if err != nil {
    15  			break
    16  		}
    17  
    18  		switch {
    19  		case b == dollarSign || b == atSign:
    20  			result = append(result, string(b))
    21  			buf.step()
    22  
    23  		case b == dot:
    24  			buf.step()
    25  
    26  			if next, _ := buf.current(); next == dot {
    27  				buf.step()
    28  				result = append(result, "..")
    29  
    30  				extractNextSegment(buf, &result)
    31  			} else {
    32  				extractNextSegment(buf, &result)
    33  			}
    34  
    35  		case b == bracketOpen:
    36  			start := buf.index
    37  			buf.step()
    38  
    39  			for {
    40  				if buf.index >= buf.length || buf.data[buf.index] == bracketClose {
    41  					break
    42  				}
    43  
    44  				buf.step()
    45  			}
    46  
    47  			if buf.index >= buf.length {
    48  				return nil, errors.New("unexpected end of path")
    49  			}
    50  
    51  			segment := string(buf.sliceFromIndices(start+1, buf.index))
    52  			result = append(result, segment)
    53  
    54  			buf.step()
    55  
    56  		default:
    57  			buf.step()
    58  		}
    59  	}
    60  
    61  	return result, nil
    62  }
    63  
    64  // extractNextSegment extracts the segment from the current index
    65  // to the next significant character and adds it to the resulting slice.
    66  func extractNextSegment(buf *buffer, result *[]string) {
    67  	start := buf.index
    68  	buf.skipToNextSignificantToken()
    69  
    70  	if buf.index <= start {
    71  		return
    72  	}
    73  
    74  	segment := string(buf.sliceFromIndices(start, buf.index))
    75  	if segment != "" {
    76  		*result = append(*result, segment)
    77  	}
    78  }