]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / zclconf / go-cty / cty / function / stdlib / string.go
1 package stdlib
2
3 import (
4 "strings"
5
6 "github.com/zclconf/go-cty/cty"
7 "github.com/zclconf/go-cty/cty/function"
8 "github.com/zclconf/go-cty/cty/gocty"
9 "github.com/apparentlymart/go-textseg/textseg"
10 )
11
12 var UpperFunc = function.New(&function.Spec{
13 Params: []function.Parameter{
14 {
15 Name: "str",
16 Type: cty.String,
17 AllowDynamicType: true,
18 },
19 },
20 Type: function.StaticReturnType(cty.String),
21 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
22 in := args[0].AsString()
23 out := strings.ToUpper(in)
24 return cty.StringVal(out), nil
25 },
26 })
27
28 var LowerFunc = function.New(&function.Spec{
29 Params: []function.Parameter{
30 {
31 Name: "str",
32 Type: cty.String,
33 AllowDynamicType: true,
34 },
35 },
36 Type: function.StaticReturnType(cty.String),
37 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
38 in := args[0].AsString()
39 out := strings.ToLower(in)
40 return cty.StringVal(out), nil
41 },
42 })
43
44 var ReverseFunc = function.New(&function.Spec{
45 Params: []function.Parameter{
46 {
47 Name: "str",
48 Type: cty.String,
49 AllowDynamicType: true,
50 },
51 },
52 Type: function.StaticReturnType(cty.String),
53 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
54 in := []byte(args[0].AsString())
55 out := make([]byte, len(in))
56 pos := len(out)
57
58 inB := []byte(in)
59 for i := 0; i < len(in); {
60 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
61 cluster := in[i : i+d]
62 pos -= len(cluster)
63 copy(out[pos:], cluster)
64 i += d
65 }
66
67 return cty.StringVal(string(out)), nil
68 },
69 })
70
71 var StrlenFunc = function.New(&function.Spec{
72 Params: []function.Parameter{
73 {
74 Name: "str",
75 Type: cty.String,
76 AllowDynamicType: true,
77 },
78 },
79 Type: function.StaticReturnType(cty.Number),
80 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
81 in := args[0].AsString()
82 l := 0
83
84 inB := []byte(in)
85 for i := 0; i < len(in); {
86 d, _, _ := textseg.ScanGraphemeClusters(inB[i:], true)
87 l++
88 i += d
89 }
90
91 return cty.NumberIntVal(int64(l)), nil
92 },
93 })
94
95 var SubstrFunc = function.New(&function.Spec{
96 Params: []function.Parameter{
97 {
98 Name: "str",
99 Type: cty.String,
100 AllowDynamicType: true,
101 },
102 {
103 Name: "offset",
104 Type: cty.Number,
105 AllowDynamicType: true,
106 },
107 {
108 Name: "length",
109 Type: cty.Number,
110 AllowDynamicType: true,
111 },
112 },
113 Type: function.StaticReturnType(cty.String),
114 Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
115 in := []byte(args[0].AsString())
116 var offset, length int
117
118 var err error
119 err = gocty.FromCtyValue(args[1], &offset)
120 if err != nil {
121 return cty.NilVal, err
122 }
123 err = gocty.FromCtyValue(args[2], &length)
124 if err != nil {
125 return cty.NilVal, err
126 }
127
128 if offset < 0 {
129 totalLenNum, err := Strlen(args[0])
130 if err != nil {
131 // should never happen
132 panic("Stdlen returned an error")
133 }
134
135 var totalLen int
136 err = gocty.FromCtyValue(totalLenNum, &totalLen)
137 if err != nil {
138 // should never happen
139 panic("Stdlen returned a non-int number")
140 }
141
142 offset += totalLen
143 }
144
145 sub := in
146 pos := 0
147 var i int
148
149 // First we'll seek forward to our offset
150 if offset > 0 {
151 for i = 0; i < len(sub); {
152 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
153 i += d
154 pos++
155 if pos == offset {
156 break
157 }
158 if i >= len(in) {
159 return cty.StringVal(""), nil
160 }
161 }
162
163 sub = sub[i:]
164 }
165
166 if length < 0 {
167 // Taking the remainder of the string is a fast path since
168 // we can just return the rest of the buffer verbatim.
169 return cty.StringVal(string(sub)), nil
170 }
171
172 // Otherwise we need to start seeking forward again until we
173 // reach the length we want.
174 pos = 0
175 for i = 0; i < len(sub); {
176 d, _, _ := textseg.ScanGraphemeClusters(sub[i:], true)
177 i += d
178 pos++
179 if pos == length {
180 break
181 }
182 }
183
184 sub = sub[:i]
185
186 return cty.StringVal(string(sub)), nil
187 },
188 })
189
190 // Upper is a Function that converts a given string to uppercase.
191 func Upper(str cty.Value) (cty.Value, error) {
192 return UpperFunc.Call([]cty.Value{str})
193 }
194
195 // Lower is a Function that converts a given string to lowercase.
196 func Lower(str cty.Value) (cty.Value, error) {
197 return LowerFunc.Call([]cty.Value{str})
198 }
199
200 // Reverse is a Function that reverses the order of the characters in the
201 // given string.
202 //
203 // As usual, "character" for the sake of this function is a grapheme cluster,
204 // so combining diacritics (for example) will be considered together as a
205 // single character.
206 func Reverse(str cty.Value) (cty.Value, error) {
207 return ReverseFunc.Call([]cty.Value{str})
208 }
209
210 // Strlen is a Function that returns the length of the given string in
211 // characters.
212 //
213 // As usual, "character" for the sake of this function is a grapheme cluster,
214 // so combining diacritics (for example) will be considered together as a
215 // single character.
216 func Strlen(str cty.Value) (cty.Value, error) {
217 return StrlenFunc.Call([]cty.Value{str})
218 }
219
220 // Substr is a Function that extracts a sequence of characters from another
221 // string and creates a new string.
222 //
223 // As usual, "character" for the sake of this function is a grapheme cluster,
224 // so combining diacritics (for example) will be considered together as a
225 // single character.
226 //
227 // The "offset" index may be negative, in which case it is relative to the
228 // end of the given string.
229 //
230 // The "length" may be -1, in which case the remainder of the string after
231 // the given offset will be returned.
232 func Substr(str cty.Value, offset cty.Value, length cty.Value) (cty.Value, error) {
233 return SubstrFunc.Call([]cty.Value{str, offset, length})
234 }