diff options
Diffstat (limited to 'vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go')
-rw-r--r-- | vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go new file mode 100644 index 0000000..d7c89fa --- /dev/null +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/string.go | |||
@@ -0,0 +1,234 @@ | |||
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 | } | ||