Skip to content

Commit b6cd0fb

Browse files
committed
Merge branch 'release/v1.3.0'
2 parents 6324de2 + dfd746a commit b6cd0fb

File tree

3 files changed

+72
-22
lines changed

3 files changed

+72
-22
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ A set of a ***high performance string tools*** that helps to build strings from
66
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/wissance/stringFormatter?style=plastic)
77
![GitHub issues](https://img.shields.io/github/issues/wissance/stringFormatter?style=plastic)
88
![GitHub Release Date](https://img.shields.io/github/release-date/wissance/stringFormatter)
9-
![GitHub release (latest by date)](https://img.shields.io/github/downloads/wissance/stringFormatter/v1.2.2/total?style=plastic)
9+
![GitHub release (latest by date)](https://img.shields.io/github/downloads/wissance/stringFormatter/v1.3.0/total?style=plastic)
1010

11-
![String Formatter: a convenient string formatting tool](/img/sf_cover.png)
11+
![String Formatter: a convenient string formatting tool](img/sf_cover.png)
1212

1313
## 1. Features
1414

15-
1. Text formatting with template using traditional for `C#, Python programmers style` - `{0}`, `{name}` that faster then fmt does:
16-
![String Formatter: a convenient string formatting tool](/img/benchmarks_adv.png)
15+
1. Text formatting with template using traditional for `C#, Python programmers style` - `{0}`, `{name}` that faster then `fmt` does:
16+
![String Formatter: a convenient string formatting tool](img/benchmarks_adv.png)
1717
2. Additional text utilities:
1818
- convert ***map to string*** using one of predefined formats (see `text_utils.go`)
1919

formatter.go

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
)
88

99
const argumentFormatSeparator = ":"
10+
const bytesPerArgDefault = 20
1011

1112
// Format
1213
/* Func that makes string formatting from template
@@ -35,7 +36,8 @@ func Format(template string, args ...any) string {
3536

3637
templateLen := len(template)
3738
formattedStr := &strings.Builder{}
38-
formattedStr.Grow(templateLen + 22*len(args))
39+
argsLen := bytesPerArgDefault * len(args)
40+
formattedStr.Grow(templateLen + argsLen + 1)
3941
j := -1 //nolint:ineffassign
4042

4143
nestedBrackets := false
@@ -55,6 +57,13 @@ func Format(template string, args ...any) string {
5557
continue
5658
}
5759
// find end of placeholder
60+
// process empty pair - {}
61+
if template[i+1] == '}' {
62+
i++
63+
formattedStr.WriteString("{}")
64+
continue
65+
}
66+
// process non-empty placeholder
5867
j = i + 2
5968
for {
6069
if j >= templateLen {
@@ -117,13 +126,9 @@ func Format(template string, args ...any) string {
117126
strVal := getItemAsStr(&args[argNumber], &argFormatOptions)
118127
formattedStr.WriteString(strVal)
119128
} else {
120-
if argNumberStr != "" {
121-
formattedStr.WriteByte('{')
122-
formattedStr.WriteString(argNumberStr)
123-
formattedStr.WriteByte('}')
124-
} else {
125-
// complicated case when we have brackets in line and open line at the end
126-
formattedStr.WriteByte('{')
129+
formattedStr.WriteString(template[i:j])
130+
if j < templateLen-1 {
131+
formattedStr.WriteByte(template[j])
127132
}
128133
}
129134
i = j
@@ -156,7 +161,8 @@ func FormatComplex(template string, args map[string]any) string {
156161

157162
templateLen := len(template)
158163
formattedStr := &strings.Builder{}
159-
formattedStr.Grow(templateLen + 22*len(args))
164+
argsLen := bytesPerArgDefault * len(args)
165+
formattedStr.Grow(templateLen + argsLen + 1)
160166
j := -1 //nolint:ineffassign
161167
nestedBrackets := false
162168
formattedStr.WriteString(template[:start])
@@ -170,10 +176,18 @@ func FormatComplex(template string, args map[string]any) string {
170176
break
171177
}
172178

173-
if template[i+1] == '{' { // todo: umv: this not considering {{0}}
179+
if template[i+1] == '{' {
174180
formattedStr.WriteByte('{')
175181
continue
176182
}
183+
// find end of placeholder
184+
// process empty pair - {}
185+
if template[i+1] == '}' {
186+
i++
187+
formattedStr.WriteString("{}")
188+
continue
189+
}
190+
// process non-empty placeholder
177191

178192
// find end of placeholder
179193
j = i + 2
@@ -212,16 +226,20 @@ func FormatComplex(template string, args map[string]any) string {
212226
}
213227
if ok || (argFormatOptions != "" && !nestedBrackets) {
214228
// get number from placeholder
215-
strVal := getItemAsStr(&arg, &argFormatOptions)
229+
strVal := ""
230+
if arg != nil {
231+
strVal = getItemAsStr(&arg, &argFormatOptions)
232+
} else {
233+
formattedStr.WriteString(template[i:j])
234+
if j < templateLen-1 {
235+
formattedStr.WriteByte(template[j])
236+
}
237+
}
216238
formattedStr.WriteString(strVal)
217239
} else {
218-
if argNumberStr != "" {
219-
formattedStr.WriteByte('{')
220-
formattedStr.WriteString(argNumberStr)
221-
formattedStr.WriteByte('}')
222-
} else {
223-
// complicated case when we have brackets in line and open line at the end
224-
formattedStr.WriteByte('{')
240+
formattedStr.WriteString(template[i:j])
241+
if j < templateLen-1 {
242+
formattedStr.WriteByte(template[j])
225243
}
226244
}
227245
i = j

formatter_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,27 @@ func TestFormat(t *testing.T) {
129129
args: []any{},
130130
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) }",
131131
},
132+
133+
"no bracket at the end of line with {} inside": {
134+
template: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) ",
135+
args: []any{},
136+
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) ",
137+
},
138+
"open bracket at the end of line of go line with multiple {} inside": {
139+
template: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}, additionalData interface{}) {",
140+
args: []any{},
141+
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}, additionalData interface{}) {",
142+
},
143+
"commentaries after bracket": {
144+
template: "switch app.appConfig.ServerCfg.Schema { //nolint:exhaustive",
145+
args: []any{},
146+
expected: "switch app.appConfig.ServerCfg.Schema { //nolint:exhaustive",
147+
},
148+
"bracket in the middle": {
149+
template: "in the middle - { at the end - nothing",
150+
args: []any{},
151+
expected: "in the middle - { at the end - nothing",
152+
},
132153
} {
133154
t.Run(name, func(t *testing.T) {
134155
assert.Equal(t, test.expected, stringFormatter.Format(test.template, test.args...))
@@ -219,11 +240,22 @@ func TestFormatComplex(t *testing.T) {
219240
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) {",
220241
},
221242

243+
"open bracket at the end of line of go line with multiple {} inside": {
244+
template: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}, additionalData interface{}) {",
245+
args: map[string]any{},
246+
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}, additionalData interface{}) {",
247+
},
248+
222249
"close bracket at the end of line of go line with {} inside": {
223250
template: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) }",
224251
args: map[string]any{},
225252
expected: "func afterHandle(respWriter *http.ResponseWriter, statusCode int, data interface{}) }",
226253
},
254+
"commentaries after bracket": {
255+
template: "switch app.appConfig.ServerCfg.Schema { //nolint:exhaustive",
256+
args: map[string]any{},
257+
expected: "switch app.appConfig.ServerCfg.Schema { //nolint:exhaustive",
258+
},
227259
} {
228260
t.Run(name, func(t *testing.T) {
229261
assert.Equal(t, test.expected, stringFormatter.FormatComplex(test.template, test.args))

0 commit comments

Comments
 (0)