From 0beee87db3a351d66944945ac3bf0c74f787f74e Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 5 Nov 2020 16:17:06 +0800 Subject: [PATCH] feature: allow specify offset in name pattern --- pkg/cloudcommon/db/namevalidator.go | 7 ++- pkg/util/stringutils2/namepattern.go | 53 +++++++++++++++++++ pkg/util/stringutils2/namepattern_test.go | 64 +++++++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 pkg/util/stringutils2/namepattern.go create mode 100644 pkg/util/stringutils2/namepattern_test.go diff --git a/pkg/cloudcommon/db/namevalidator.go b/pkg/cloudcommon/db/namevalidator.go index a2ad7f5b1f..379c58c1d0 100644 --- a/pkg/cloudcommon/db/namevalidator.go +++ b/pkg/cloudcommon/db/namevalidator.go @@ -19,12 +19,12 @@ import ( "regexp" "yunion.io/x/jsonutils" - "yunion.io/x/pkg/util/stringutils" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" + "yunion.io/x/onecloud/pkg/util/stringutils2" ) func isNameUnique(manager IModelManager, ownerId mcclient.IIdentityProvider, name string, uniqValues jsonutils.JSONObject) (bool, error) { @@ -123,11 +123,14 @@ func GenerateAlterName(model IModel, hint string) (string, error) { } func GenerateName2(manager IModelManager, ownerId mcclient.IIdentityProvider, hint string, model IModel, baseIndex int) (string, error) { - _, pattern, patternLen := stringutils.ParseNamePattern(hint) + _, pattern, patternLen, offset := stringutils2.ParseNamePattern2(hint) var name string if patternLen == 0 { name = hint } else { + if offset > 0 { + baseIndex = offset + } name = fmt.Sprintf(pattern, baseIndex) baseIndex += 1 } diff --git a/pkg/util/stringutils2/namepattern.go b/pkg/util/stringutils2/namepattern.go new file mode 100644 index 0000000000..a14d0fd10d --- /dev/null +++ b/pkg/util/stringutils2/namepattern.go @@ -0,0 +1,53 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stringutils2 + +import ( + "fmt" + "strconv" + "strings" +) + +// name## +// name##9# +func ParseNamePattern2(name string) (string, string, int, int) { + const RepChar = '#' + var match string + var pattern string + var patternLen int + var offset int + + start := strings.IndexByte(name, RepChar) + if start >= 0 { + end := start + 1 + for end < len(name) && name[end] == RepChar { + end += 1 + } + patternLen = end - start + nend := strings.IndexByte(name[end:], RepChar) + if nend > 0 { + if oi, err := strconv.ParseInt(name[end:end+nend], 10, 64); err == nil { + offset = int(oi) + } + end = end + nend + 1 + } + match = fmt.Sprintf("%s%%%s", name[:start], name[end:]) + pattern = fmt.Sprintf("%s%%0%dd%s", name[:start], patternLen, name[end:]) + } else { + match = fmt.Sprintf("%s-%%", name) + pattern = fmt.Sprintf("%s-%%d", name) + } + return match, pattern, patternLen, offset +} diff --git a/pkg/util/stringutils2/namepattern_test.go b/pkg/util/stringutils2/namepattern_test.go new file mode 100644 index 0000000000..46a76e84f5 --- /dev/null +++ b/pkg/util/stringutils2/namepattern_test.go @@ -0,0 +1,64 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package stringutils2 + +import ( + "testing" +) + +func TestParseNamePattern2(t *testing.T) { + cases := []struct { + input string + match string + pattern string + patternLen int + offset int + }{ + { + input: "testimg###", + match: "testimg%", + pattern: "testimg%03d", + patternLen: 3, + offset: 0, + }, + { + input: "testimg###66#", + match: "testimg%", + pattern: "testimg%03d", + patternLen: 3, + offset: 66, + }, + { + input: "testimg###ab#", + match: "testimg%", + pattern: "testimg%03d", + patternLen: 3, + offset: 0, + }, + { + input: "testimg", + match: "testimg-%", + pattern: "testimg-%d", + patternLen: 0, + offset: 0, + }, + } + for _, c := range cases { + m, p, pl, o := ParseNamePattern2(c.input) + if m != c.match || p != c.pattern || pl != c.patternLen || o != c.offset { + t.Errorf("match got %s want %s, pattern got %s want %s, patternLen got %d want %d, offset got %d want %d", m, c.match, p, c.pattern, pl, c.patternLen, o, c.offset) + } + } +}