From efe3070e04a8a64318881b71aa30c3e01a699ded Mon Sep 17 00:00:00 2001 From: Trial97 Date: Thu, 18 Mar 2021 17:10:07 +0200 Subject: [PATCH] Updated GetPathIndexSlice function --- utils/pathitem.go | 3 ++ utils/pathitem_test.go | 6 +++ utils/pathitemlist_test.go | 98 ++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/utils/pathitem.go b/utils/pathitem.go index 7bb3a4ef4..dc400be5c 100644 --- a/utils/pathitem.go +++ b/utils/pathitem.go @@ -173,5 +173,8 @@ func GetPathIndexSlice(spath string) (opath string, idx []string) { } idxVal := spath[idxStart+1 : len(spath)-1] opath = spath[:idxStart] + if strings.Index(idxVal, IdxCombination) == -1 { + return opath, []string{idxVal} + } return opath, strings.Split(idxVal, IdxCombination) } diff --git a/utils/pathitem_test.go b/utils/pathitem_test.go index be7e355f3..9555e393d 100644 --- a/utils/pathitem_test.go +++ b/utils/pathitem_test.go @@ -65,6 +65,12 @@ func TestNewPathItems(t *testing.T) { if rply := NewPathItems(pathSlice); !reflect.DeepEqual(expected, rply) { t.Errorf("Expected: %s, received: %s", ToJSON(expected), ToJSON(rply)) } + + pathSlice = strings.Split("*req.Field1[*raw][0].Account", NestingSep) + expected = PathItems{{Field: MetaReq}, {Field: "Field1", Index: []string{"*raw", "0"}}, {Field: AccountField}} + if rply := NewPathItems(pathSlice); !reflect.DeepEqual(expected, rply) { + t.Errorf("Expected: %s, received: %s", ToJSON(expected), ToJSON(rply)) + } } func TestPathItemString(t *testing.T) { diff --git a/utils/pathitemlist_test.go b/utils/pathitemlist_test.go index 4d3d365b3..6dd82ae7c 100644 --- a/utils/pathitemlist_test.go +++ b/utils/pathitemlist_test.go @@ -19,7 +19,9 @@ along with this program. If not, see package utils import ( + "bytes" "reflect" + "strings" "testing" ) @@ -491,17 +493,97 @@ func TestPathItemListPushFrontList(t *testing.T) { } } -// const benchPath = "~*req.Field1[0][1].Field2[*raw].Field5.Field6[10].Field7[path1][path2][path3]" -const benchPath = "~*req.Field1[0].Field2[*raw].Field5.Field6[10].Field7[path1]" +// const benchPath = "~*req.Field1[0][-1][*raw][10][path1][path2][path3]" +// const benchPath = "~*req.Field1[*raw]" + +const benchPath = "Field1[1000000000000000]" + +// Benchmark results: +// goos: linux +// goarch: amd64 +// pkg: github.com/cgrates/cgrates/utils +// cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz +// BenchmarkGetPathIndexSlice +// BenchmarkGetPathIndexSlice 16462084 360.8 ns/op 160 B/op 2 allocs/op +// BenchmarkGetPathIndexSliceSplit +// BenchmarkGetPathIndexSliceSplit 16291755 359.4 ns/op 112 B/op 1 allocs/op +// BenchmarkGetPathIndexSliceStringsIndex +// BenchmarkGetPathIndexSliceStringsIndex 10418586 597.2 ns/op 240 B/op 4 allocs/op +// BenchmarkGetPathIndexString +// BenchmarkGetPathIndexString 96080587 61.19 ns/op 16 B/op 1 allocs/op +// PASS +// ok github.com/cgrates/cgrates/utils 25.372s + +func GetPathIndexSlice1(spath string) (opath string, idx []string) { + idxStart := strings.Index(spath, IdxStart) + if idxStart == -1 || !strings.HasSuffix(spath, IdxEnd) { + return spath, nil + } + idxVal := spath[idxStart+1 : len(spath)-1] + opath = spath[:idxStart] + if len(idxVal) <= 3 { + return opath, []string{idxVal} + } + idxValB := []byte(idxVal) + n := bytes.Count(idxValB, []byte{']'}) // we number only ] as an optimization + if n <= 0 { + return opath, []string{idxVal} + } + idx = make([]string, n+1) // alloc the memory for the slice + for i := 0; i < n; i++ { // expect a valid path + ix := bytes.IndexByte(idxValB, ']') // safe to asume that ix is not -1 as we counted before + if ix == len(idxValB)-1 || + idxValB[ix+1] != '[' { // this is clearly an error so stop + return spath, nil + } + idx[i] = idxVal[:ix] + idxValB = idxValB[ix+2:] + idxVal = idxVal[ix+2:] + } + idx[n] = idxVal + return +} + +func GetPathIndexSliceStringsIndex(spath string) (opath string, idx []string) { + idxStart := strings.Index(spath, IdxStart) + if idxStart == -1 || !strings.HasSuffix(spath, IdxEnd) { + return spath, nil + } + idxVal := spath[idxStart+1 : len(spath)-1] + opath = spath[:idxStart] + if len(idxVal) <= 3 { + return opath, []string{idxVal} + } + + for ix := strings.Index(idxVal, IdxCombination); ix != -1; ix = strings.Index(idxVal, IdxCombination) { + idx = append(idx, idxVal[:ix]) + idxVal = idxVal[ix+1:] + + } + idx = append(idx, string(idxVal)) + + return +} + +func BenchmarkGetPathIndexSlice(b *testing.B) { + for i := 0; i < b.N; i++ { + GetPathIndexSlice1(benchPath) + } +} + +func BenchmarkGetPathIndexSliceSplit(b *testing.B) { + for i := 0; i < b.N; i++ { + GetPathIndexSlice(benchPath) + } +} +func BenchmarkGetPathIndexSliceStringsIndex(b *testing.B) { + for i := 0; i < b.N; i++ { + GetPathIndexSliceStringsIndex(benchPath) + } +} func BenchmarkGetPathIndexString(b *testing.B) { for i := 0; i < b.N; i++ { GetPathIndexString(benchPath) } } - -func BenchmarkGetPathIndexSlice(b *testing.B) { - for i := 0; i < b.N; i++ { - GetPathIndexSlice(benchPath) - } -}