mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-20 14:48:43 +05:00
Update to new *strip data converter
This commit is contained in:
committed by
Dan Christian Bogos
parent
3e56a5aac7
commit
f0fea43a41
@@ -1151,6 +1151,7 @@ const (
|
||||
MetaString = "*string"
|
||||
MetaPrefix = "*prefix"
|
||||
MetaSuffix = "*suffix"
|
||||
MetaBoth = "*both"
|
||||
MetaEmpty = "*empty"
|
||||
MetaExists = "*exists"
|
||||
MetaTimings = "*timings"
|
||||
|
||||
@@ -589,7 +589,7 @@ func (jsnC JSONConverter) Convert(in any) (any, error) {
|
||||
return string(b), nil
|
||||
}
|
||||
|
||||
// StripConverter strips characters from the left or the right side of a string.
|
||||
// StripConverter strips the prefix, the suffix or both from a string.
|
||||
type StripConverter struct {
|
||||
side string
|
||||
substr string
|
||||
@@ -597,42 +597,53 @@ type StripConverter struct {
|
||||
}
|
||||
|
||||
// NewStripConverter creates a new StripConverter with the specified parameters.
|
||||
// The input params string should have the format "<type>:<side>:<substr>:<amount>", where:
|
||||
// - 'type' must be "*strip".
|
||||
// - 'side' specifies the side of the string to strip, and it must be either "*left" or "*right".
|
||||
// - 'substr' is the substring to be removed from the string.
|
||||
// - 'amount' is the optional number of times 'substr' should be removed from the specified side.
|
||||
//
|
||||
// If 'amount' is omitted, it defaults to 1. If it is -1, all instances of 'substr' will be removed from the
|
||||
// chosen side. If 'substr' is "*any", 'amount' characters will be removed from the specified side
|
||||
// regardless of their value.
|
||||
func NewStripConverter(params string) (DataConverter, error) {
|
||||
sc := new(StripConverter)
|
||||
paramSlice := strings.Split(params, InInFieldSep)
|
||||
switch len(paramSlice) {
|
||||
case 3:
|
||||
sc.amount = 1
|
||||
case 4:
|
||||
var err error
|
||||
sc.amount, err = strconv.Atoi(paramSlice[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(paramSlice) < 3 || len(paramSlice) > 5 {
|
||||
return nil, errors.New("strip converter: invalid number of parameters (should have 3, 4 or 5)")
|
||||
}
|
||||
sc := StripConverter{
|
||||
side: paramSlice[1],
|
||||
substr: paramSlice[2],
|
||||
amount: -1,
|
||||
}
|
||||
var err error
|
||||
switch sc.substr {
|
||||
case EmptyString:
|
||||
return nil, errors.New("strip converter: substr parameter cannot be empty")
|
||||
case "*nil", "*space":
|
||||
if sc.substr == "*nil" {
|
||||
sc.substr = "\u0000"
|
||||
} else {
|
||||
sc.substr = " "
|
||||
}
|
||||
if len(paramSlice) == 4 {
|
||||
sc.amount, err = strconv.Atoi(paramSlice[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err)
|
||||
}
|
||||
sc.substr = strings.Repeat(sc.substr, sc.amount)
|
||||
}
|
||||
case "*char":
|
||||
if len(paramSlice) < 4 {
|
||||
return nil, errors.New("strip converter: usage of *char implies the need of 4 or 5 params")
|
||||
}
|
||||
sc.substr = paramSlice[3] // should probably return error if empty
|
||||
if len(paramSlice) == 5 {
|
||||
sc.amount, err = strconv.Atoi(paramSlice[4])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err)
|
||||
}
|
||||
sc.substr = strings.Repeat(sc.substr, sc.amount)
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("strip converter: invalid number of parameters (should have 3 or 4)")
|
||||
sc.amount, err = strconv.Atoi(paramSlice[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err)
|
||||
}
|
||||
sc.substr = ""
|
||||
}
|
||||
|
||||
if sc.side = paramSlice[1]; !IsSliceMember([]string{MetaLeft, MetaRight}, sc.side) {
|
||||
return nil, errors.New("strip converter: invalid side parameter")
|
||||
}
|
||||
|
||||
sc.substr = paramSlice[2]
|
||||
if sc.substr == MetaAny && sc.amount == -1 {
|
||||
return nil, errors.New("strip converter: invalid combination of substr and amount values")
|
||||
}
|
||||
if sc.substr != MetaAny && sc.amount != -1 {
|
||||
sc.substr = strings.Repeat(paramSlice[2], sc.amount)
|
||||
}
|
||||
return sc, nil
|
||||
}
|
||||
|
||||
@@ -641,31 +652,47 @@ func NewStripConverter(params string) (DataConverter, error) {
|
||||
func (sc StripConverter) Convert(in any) (any, error) {
|
||||
str, ok := in.(string)
|
||||
if !ok {
|
||||
return nil, ErrCastFailed
|
||||
return nil, fmt.Errorf("strip converter: %w", ErrCastFailed)
|
||||
}
|
||||
if sc.amount <= 0 && sc.amount != -1 {
|
||||
return str, nil
|
||||
}
|
||||
switch sc.side {
|
||||
case MetaLeft:
|
||||
if sc.substr == MetaAny {
|
||||
case MetaPrefix:
|
||||
if sc.substr == EmptyString {
|
||||
if sc.amount < len(str) {
|
||||
return str[sc.amount:], nil
|
||||
}
|
||||
return str, nil
|
||||
return EmptyString, nil
|
||||
}
|
||||
if sc.amount != -1 {
|
||||
return strings.TrimPrefix(str, sc.substr), nil
|
||||
}
|
||||
return strings.TrimLeft(str, sc.substr), nil
|
||||
case MetaRight:
|
||||
if sc.substr == MetaAny {
|
||||
case MetaSuffix:
|
||||
if sc.substr == EmptyString {
|
||||
if sc.amount < len(str) {
|
||||
return str[:len(str)-sc.amount], nil
|
||||
}
|
||||
return str, nil
|
||||
return EmptyString, nil
|
||||
}
|
||||
if sc.amount != -1 {
|
||||
return strings.TrimSuffix(str, sc.substr), nil
|
||||
}
|
||||
return strings.TrimRight(str, sc.substr), nil
|
||||
case MetaBoth:
|
||||
if sc.substr == EmptyString {
|
||||
if sc.amount*2 < len(str) {
|
||||
return str[sc.amount : len(str)-sc.amount], nil
|
||||
}
|
||||
return EmptyString, nil
|
||||
}
|
||||
if sc.amount != -1 {
|
||||
str = strings.TrimPrefix(str, sc.substr)
|
||||
return strings.TrimSuffix(str, sc.substr), nil
|
||||
}
|
||||
return strings.Trim(str, sc.substr), nil
|
||||
default:
|
||||
return EmptyString, errors.New("strip converter: invalid side parameter")
|
||||
}
|
||||
return str, nil
|
||||
}
|
||||
|
||||
@@ -1288,97 +1288,253 @@ func TestDataConverterConvertJSONOK(t *testing.T) {
|
||||
|
||||
func TestStripConverter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
params string
|
||||
input string
|
||||
expected string
|
||||
expectErr bool
|
||||
name string
|
||||
params string
|
||||
input string
|
||||
expected string
|
||||
constructorErr bool
|
||||
convertErr bool
|
||||
}{
|
||||
|
||||
{
|
||||
name: "Cut any leading 3 characters",
|
||||
params: "*strip:*left:*any:3",
|
||||
input: "000000435400",
|
||||
expected: "000435400",
|
||||
expectErr: false,
|
||||
name: "Strip 5 leading characters",
|
||||
params: "*strip:*prefix:5",
|
||||
input: "12345TEST12345",
|
||||
expected: "TEST12345",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut leading '00' twice",
|
||||
params: "*strip:*left:00:2",
|
||||
input: "000000435400",
|
||||
expected: "00435400",
|
||||
expectErr: false,
|
||||
name: "Strip 5 trailing characters",
|
||||
params: "*strip:*suffix:5",
|
||||
input: "12345TEST12345",
|
||||
expected: "12345TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut leading '00' default",
|
||||
params: "*strip:*left:00",
|
||||
input: "000000435400",
|
||||
expected: "0000435400",
|
||||
expectErr: false,
|
||||
name: "Strip 5 characters from both sides",
|
||||
params: "*strip:*both:5",
|
||||
input: "12345TEST12345",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut 8 trailing nils",
|
||||
params: "*strip:*right:\u0000:8",
|
||||
input: "password\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
|
||||
expected: "password",
|
||||
expectErr: false,
|
||||
name: "Strip all trailing nils",
|
||||
params: "*strip:*suffix:*nil",
|
||||
input: "TEST\u0000\u0000\u0000\u0000",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut 8 trailing escaped nils",
|
||||
params: "*strip:*right:\\u0000:8",
|
||||
input: "password\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000",
|
||||
expected: "password",
|
||||
expectErr: false,
|
||||
name: "Strip all leading nils",
|
||||
params: "*strip:*prefix:*nil",
|
||||
input: "\u0000\u0000\u0000\u0000TEST",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut all trailing nils",
|
||||
params: "*strip:*right:\u0000:-1",
|
||||
input: "password\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000",
|
||||
expected: "password",
|
||||
expectErr: false,
|
||||
name: "Strip all nils from both sides",
|
||||
params: "*strip:*both:*nil",
|
||||
input: "\u0000\u0000TEST\u0000\u0000",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Cut all escaped trailing nils",
|
||||
params: "*strip:*right:\\u0000:-1",
|
||||
input: "password\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000",
|
||||
expected: "password",
|
||||
expectErr: false,
|
||||
name: "Strip 2 trailing nils",
|
||||
params: "*strip:*suffix:*nil:2",
|
||||
input: "TEST\u0000\u0000\u0000\u0000",
|
||||
expected: "TEST\u0000\u0000",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid substr and amount value combination",
|
||||
params: "*strip:*right:*any:-1",
|
||||
input: "test",
|
||||
expected: "",
|
||||
expectErr: true,
|
||||
name: "Strip 2 leading nils",
|
||||
params: "*strip:*prefix:*nil:2",
|
||||
input: "\u0000\u0000\u0000\u0000TEST",
|
||||
expected: "\u0000\u0000TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid nr of parameters",
|
||||
params: "*strip:*right",
|
||||
input: "test",
|
||||
expected: "",
|
||||
expectErr: true,
|
||||
name: "Strip 1 nil from both sides",
|
||||
params: "*strip:*both:*nil:1",
|
||||
input: "\u0000\u0000TEST\u0000\u0000",
|
||||
expected: "\u0000TEST\u0000",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid side parameter",
|
||||
params: "*strip:*up:abc:2",
|
||||
input: "test",
|
||||
expected: "",
|
||||
expectErr: true,
|
||||
name: "Strip all trailing spaces",
|
||||
params: "*strip:*suffix:*space",
|
||||
input: "TEST ",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip all leading spaces",
|
||||
params: "*strip:*prefix:*space",
|
||||
input: " TEST",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip all spaces from both sides",
|
||||
params: "*strip:*both:*space",
|
||||
input: " TEST ",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 2 trailing spaces",
|
||||
params: "*strip:*suffix:*space:2",
|
||||
input: "TEST ",
|
||||
expected: "TEST ",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 2 leading spaces",
|
||||
params: "*strip:*prefix:*space:2",
|
||||
input: " TEST",
|
||||
expected: " TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 1 space from both sides",
|
||||
params: "*strip:*both:*space:1",
|
||||
input: " TEST ",
|
||||
expected: " TEST ",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip all trailing 'abcd' char groups",
|
||||
params: "*strip:*suffix:*char:abcd",
|
||||
input: "TESTabcdabcdabcdabcd",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip all leading 'abcd' char groups",
|
||||
params: "*strip:*prefix:*char:abcd",
|
||||
input: "abcdabcdabcdabcdTEST",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip all 'abcd' char groups from both sides",
|
||||
params: "*strip:*both:*char:abcd",
|
||||
input: "abcdabcdTESTabcdabcd",
|
||||
expected: "TEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 2 trailing 'abcd' char groups",
|
||||
params: "*strip:*suffix:*char:abcd:2",
|
||||
input: "TESTabcdabcdabcdabcd",
|
||||
expected: "TESTabcdabcd",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 2 leading 'abcd' char groups",
|
||||
params: "*strip:*prefix:*char:abcd:2",
|
||||
input: "abcdabcdabcdabcdTEST",
|
||||
expected: "abcdabcdTEST",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip 1 'abcd' char group from both sides",
|
||||
params: "*strip:*both:*char:abcd:1",
|
||||
input: "abcdabcdTESTabcdabcd",
|
||||
expected: "abcdTESTabcd",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Empty third parameter",
|
||||
params: "*strip:*prefix:",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: true,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid side parameter",
|
||||
params: "*strip:*invalid:*nil",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: false,
|
||||
convertErr: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid nr. of parameters",
|
||||
params: "*strip:*prefix:*char:*nil:abc:3",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: true,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid amount parameter",
|
||||
params: "*strip:*prefix:*char:0:three",
|
||||
input: "000TEST",
|
||||
expected: "",
|
||||
constructorErr: true,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip a prefix longer than the value",
|
||||
params: "*strip:*prefix:5",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip a suffix longer than the value",
|
||||
params: "*strip:*suffix:5",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
{
|
||||
name: "Strip from both ends an amount of characters longer than the value",
|
||||
params: "*strip:*both:3",
|
||||
input: "TEST",
|
||||
expected: "",
|
||||
constructorErr: false,
|
||||
convertErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
sc, err := NewDataConverter(tt.params)
|
||||
if (err != nil) != tt.expectErr {
|
||||
t.Errorf("NewStripConverter error = %v, expectErr %v", err, tt.expectErr)
|
||||
if (err != nil) != tt.constructorErr {
|
||||
t.Errorf("NewStripConverter error = %v, constructorErr %v", err, tt.constructorErr)
|
||||
return
|
||||
}
|
||||
if tt.expectErr {
|
||||
if tt.constructorErr {
|
||||
return
|
||||
}
|
||||
rcv, err := sc.Convert(tt.input)
|
||||
if (err != nil) != tt.expectErr {
|
||||
t.Errorf("Convert error = %v, expectErr %v", err, tt.expectErr)
|
||||
if (err != nil) != tt.convertErr {
|
||||
t.Errorf("Convert error = %v, convertErr %v", err, tt.convertErr)
|
||||
return
|
||||
}
|
||||
if rcv != tt.expected {
|
||||
|
||||
Reference in New Issue
Block a user