From 14d2d747f6f2a03c17b0c4dec7a3d103a52ad382 Mon Sep 17 00:00:00 2001 From: Jinhongyu <30454170+cnjinhy@users.noreply.github.com> Date: Wed, 16 Nov 2022 10:10:59 +0800 Subject: [PATCH] add minus of `start` parameter support for `gstr.Substr`, like the `substr` function in `PHP` (#2297) * Make the substr like the substr in PHP Make the substr like the substr in PHP * Update gstr_z_unit_test.go * Update gstr_z_unit_test.go * Make the SubStrRune like the mb_substr in PHP Make the SubStrRune like the mb_substr in PHP * Update gstr_z_unit_test.go * Update gstr_z_unit_test.go * Update gins_z_unit_view_test.go * Update gview_z_unit_test.go --- frame/gins/gins_z_unit_view_test.go | 6 +-- os/gview/gview_z_unit_test.go | 2 +- text/gstr/gstr_sub.go | 75 +++++++++++++++++++---------- text/gstr/gstr_z_unit_test.go | 16 +++++- 4 files changed, 68 insertions(+), 31 deletions(-) diff --git a/frame/gins/gins_z_unit_view_test.go b/frame/gins/gins_z_unit_view_test.go index 3bff351cf..907c8f13f 100644 --- a/frame/gins/gins_z_unit_view_test.go +++ b/frame/gins/gins_z_unit_view_test.go @@ -22,7 +22,7 @@ func Test_View(t *testing.T) { t.AssertNE(View(), nil) b, e := View().ParseContent(context.TODO(), `{{"我是中国人" | substr 2 -1}}`, nil) t.Assert(e, nil) - t.Assert(b, "中国人") + t.Assert(b, "中国") }) gtest.C(t, func(t *gtest.T) { tpl := "t.tpl" @@ -32,7 +32,7 @@ func Test_View(t *testing.T) { b, e := View().Parse(context.TODO(), "t.tpl", nil) t.Assert(e, nil) - t.Assert(b, "中国人") + t.Assert(b, "中国") }) gtest.C(t, func(t *gtest.T) { path := fmt.Sprintf(`%s/%d`, gfile.Temp(), gtime.TimestampNano()) @@ -45,7 +45,7 @@ func Test_View(t *testing.T) { b, e := View().Parse(context.TODO(), "t.tpl", nil) t.Assert(e, nil) - t.Assert(b, "中国人") + t.Assert(b, "中国") }) } diff --git a/os/gview/gview_z_unit_test.go b/os/gview/gview_z_unit_test.go index 5c75c34c6..8fe06d8d8 100644 --- a/os/gview/gview_z_unit_test.go +++ b/os/gview/gview_z_unit_test.go @@ -141,7 +141,7 @@ func Test_Func(t *testing.T) { str = `{{"我是中国人" | substr 2 -1}};{{"我是中国人" | substr 2 2}}` result, err = gview.ParseContent(context.TODO(), str, nil) t.Assert(err != nil, false) - t.Assert(result, `中国人;中国`) + t.Assert(result, `中国;中国`) str = `{{"我是中国人" | strlimit 2 "..."}}` result, err = gview.ParseContent(context.TODO(), str, nil) diff --git a/text/gstr/gstr_sub.go b/text/gstr/gstr_sub.go index 8eef7edc6..e237cee39 100644 --- a/text/gstr/gstr_sub.go +++ b/text/gstr/gstr_sub.go @@ -55,24 +55,37 @@ func StrTillEx(haystack string, needle string) string { // The parameter `length` is optional, it uses the length of `str` in default. func SubStr(str string, start int, length ...int) (substr string) { strLength := len(str) - // Simple border checks. if start < 0 { - start = 0 - } - if start >= strLength { - start = strLength - } - end := strLength - if len(length) > 0 { - end = start + length[0] - if end < start { - end = strLength + if -start > strLength { + start = 0 + } else { + start = strLength + start } + } else if start > strLength { + return "" } - if end > strLength { - end = strLength + realLength := 0 + if len(length) > 0 { + realLength = length[0] + if realLength < 0 { + if -realLength > strLength-start { + realLength = 0 + } else { + realLength = strLength - start + realLength + } + } else if realLength > strLength-start { + realLength = strLength - start + } + } else { + realLength = strLength - start + } + + if realLength == strLength { + return str + } else { + end := start + realLength + return str[start:end] } - return str[start:end] } // SubStrRune returns a portion of string `str` specified by the `start` and `length` parameters. @@ -85,20 +98,32 @@ func SubStrRune(str string, start int, length ...int) (substr string) { runesLength = len(runes) ) - // Simple border checks. + strLength := runesLength if start < 0 { - start = 0 - } - if start >= runesLength { - start = runesLength - } - end := runesLength - if len(length) > 0 { - end = start + length[0] - if end < start { - end = runesLength + if -start > strLength { + start = 0 + } else { + start = strLength + start } + } else if start > strLength { + return "" } + realLength := 0 + if len(length) > 0 { + realLength = length[0] + if realLength < 0 { + if -realLength > strLength-start { + realLength = 0 + } else { + realLength = strLength - start + realLength + } + } else if realLength > strLength-start { + realLength = strLength - start + } + } else { + realLength = strLength - start + } + end := start + realLength if end > runesLength { end = runesLength } diff --git a/text/gstr/gstr_z_unit_test.go b/text/gstr/gstr_z_unit_test.go index 1afc3a546..63780d8e0 100644 --- a/text/gstr/gstr_z_unit_test.go +++ b/text/gstr/gstr_z_unit_test.go @@ -89,8 +89,12 @@ func Test_SubStr(t *testing.T) { t.Assert(gstr.SubStr("我爱GoFrame", 0), "我爱GoFrame") t.Assert(gstr.SubStr("我爱GoFrame", 6), "GoFrame") t.Assert(gstr.SubStr("我爱GoFrame", 6, 2), "Go") - t.Assert(gstr.SubStr("我爱GoFrame", -1, 30), "我爱GoFrame") + t.Assert(gstr.SubStr("我爱GoFrame", -1, 30), "e") t.Assert(gstr.SubStr("我爱GoFrame", 30, 30), "") + t.Assert(gstr.SubStr("abcdef", 0, -1), "abcde") + t.Assert(gstr.SubStr("abcdef", 2, -1), "cde") + t.Assert(gstr.SubStr("abcdef", 4, -4), "") + t.Assert(gstr.SubStr("abcdef", -3, -1), "de") }) } @@ -99,8 +103,16 @@ func Test_SubStrRune(t *testing.T) { t.Assert(gstr.SubStrRune("我爱GoFrame", 0), "我爱GoFrame") t.Assert(gstr.SubStrRune("我爱GoFrame", 2), "GoFrame") t.Assert(gstr.SubStrRune("我爱GoFrame", 2, 2), "Go") - t.Assert(gstr.SubStrRune("我爱GoFrame", -1, 30), "我爱GoFrame") + t.Assert(gstr.SubStrRune("我爱GoFrame", -1, 30), "e") t.Assert(gstr.SubStrRune("我爱GoFrame", 30, 30), "") + t.Assert(gstr.SubStrRune("abcdef", 0, -1), "abcde") + t.Assert(gstr.SubStrRune("abcdef", 2, -1), "cde") + t.Assert(gstr.SubStrRune("abcdef", 4, -4), "") + t.Assert(gstr.SubStrRune("abcdef", -3, -1), "de") + t.Assert(gstr.SubStrRune("我爱GoFrame呵呵", -3, 100), "e呵呵") + t.Assert(gstr.SubStrRune("abcdef哈哈", -3, -1), "f哈") + t.Assert(gstr.SubStrRune("ab我爱GoFramecdef哈哈", -3, -1), "f哈") + t.Assert(gstr.SubStrRune("我爱GoFrame", 0, 3), "我爱G") }) }