1// line 1 "format_fsm.rl"
2// This file is generated from format_fsm.rl. DO NOT EDIT.
3
4// line 5 "format_fsm.rl"
5
6package stdlib
7
8import (
9	"bytes"
10	"fmt"
11	"unicode/utf8"
12
13	"github.com/zclconf/go-cty/cty"
14	"github.com/zclconf/go-cty/cty/function"
15)
16
17// line 21 "format_fsm.go"
18var _formatfsm_actions []byte = []byte{
19	0, 1, 0, 1, 1, 1, 2, 1, 4,
20	1, 5, 1, 6, 1, 7, 1, 8,
21	1, 9, 1, 10, 1, 11, 1, 14,
22	1, 16, 1, 17, 1, 18, 2, 3,
23	4, 2, 12, 10, 2, 12, 16, 2,
24	12, 18, 2, 13, 14, 2, 15, 10,
25	2, 15, 18,
26}
27
28var _formatfsm_key_offsets []byte = []byte{
29	0, 0, 14, 27, 34, 36, 39, 43,
30	51,
31}
32
33var _formatfsm_trans_keys []byte = []byte{
34	32, 35, 37, 43, 45, 46, 48, 91,
35	49, 57, 65, 90, 97, 122, 32, 35,
36	43, 45, 46, 48, 91, 49, 57, 65,
37	90, 97, 122, 91, 48, 57, 65, 90,
38	97, 122, 49, 57, 93, 48, 57, 65,
39	90, 97, 122, 46, 91, 48, 57, 65,
40	90, 97, 122, 37,
41}
42
43var _formatfsm_single_lengths []byte = []byte{
44	0, 8, 7, 1, 0, 1, 0, 2,
45	1,
46}
47
48var _formatfsm_range_lengths []byte = []byte{
49	0, 3, 3, 3, 1, 1, 2, 3,
50	0,
51}
52
53var _formatfsm_index_offsets []byte = []byte{
54	0, 0, 12, 23, 28, 30, 33, 36,
55	42,
56}
57
58var _formatfsm_indicies []byte = []byte{
59	1, 2, 3, 4, 5, 6, 7, 10,
60	8, 9, 9, 0, 1, 2, 4, 5,
61	6, 7, 10, 8, 9, 9, 0, 13,
62	11, 12, 12, 0, 14, 0, 15, 14,
63	0, 9, 9, 0, 16, 19, 17, 18,
64	18, 0, 20, 3,
65}
66
67var _formatfsm_trans_targs []byte = []byte{
68	0, 2, 2, 8, 2, 2, 3, 2,
69	7, 8, 4, 3, 8, 4, 5, 6,
70	3, 7, 8, 4, 1,
71}
72
73var _formatfsm_trans_actions []byte = []byte{
74	7, 17, 9, 3, 15, 13, 25, 11,
75	43, 29, 19, 27, 49, 46, 21, 0,
76	37, 23, 40, 34, 1,
77}
78
79var _formatfsm_eof_actions []byte = []byte{
80	0, 31, 31, 31, 31, 31, 31, 31,
81	5,
82}
83
84const formatfsm_start int = 8
85const formatfsm_first_final int = 8
86const formatfsm_error int = 0
87
88const formatfsm_en_main int = 8
89
90// line 20 "format_fsm.rl"
91
92func formatFSM(format string, a []cty.Value) (string, error) {
93	var buf bytes.Buffer
94	data := format
95	nextArg := 1 // arg numbers are 1-based
96	var verb formatVerb
97	highestArgIdx := 0 // zero means "none", since arg numbers are 1-based
98
99	// line 159 "format_fsm.rl"
100
101	// Ragel state
102	p := 0          // "Pointer" into data
103	pe := len(data) // End-of-data "pointer"
104	cs := 0         // current state (will be initialized by ragel-generated code)
105	ts := 0
106	te := 0
107	eof := pe
108
109	// Keep Go compiler happy even if generated code doesn't use these
110	_ = ts
111	_ = te
112	_ = eof
113
114	// line 123 "format_fsm.go"
115	{
116		cs = formatfsm_start
117	}
118
119	// line 128 "format_fsm.go"
120	{
121		var _klen int
122		var _trans int
123		var _acts int
124		var _nacts uint
125		var _keys int
126		if p == pe {
127			goto _test_eof
128		}
129		if cs == 0 {
130			goto _out
131		}
132	_resume:
133		_keys = int(_formatfsm_key_offsets[cs])
134		_trans = int(_formatfsm_index_offsets[cs])
135
136		_klen = int(_formatfsm_single_lengths[cs])
137		if _klen > 0 {
138			_lower := int(_keys)
139			var _mid int
140			_upper := int(_keys + _klen - 1)
141			for {
142				if _upper < _lower {
143					break
144				}
145
146				_mid = _lower + ((_upper - _lower) >> 1)
147				switch {
148				case data[p] < _formatfsm_trans_keys[_mid]:
149					_upper = _mid - 1
150				case data[p] > _formatfsm_trans_keys[_mid]:
151					_lower = _mid + 1
152				default:
153					_trans += int(_mid - int(_keys))
154					goto _match
155				}
156			}
157			_keys += _klen
158			_trans += _klen
159		}
160
161		_klen = int(_formatfsm_range_lengths[cs])
162		if _klen > 0 {
163			_lower := int(_keys)
164			var _mid int
165			_upper := int(_keys + (_klen << 1) - 2)
166			for {
167				if _upper < _lower {
168					break
169				}
170
171				_mid = _lower + (((_upper - _lower) >> 1) & ^1)
172				switch {
173				case data[p] < _formatfsm_trans_keys[_mid]:
174					_upper = _mid - 2
175				case data[p] > _formatfsm_trans_keys[_mid+1]:
176					_lower = _mid + 2
177				default:
178					_trans += int((_mid - int(_keys)) >> 1)
179					goto _match
180				}
181			}
182			_trans += _klen
183		}
184
185	_match:
186		_trans = int(_formatfsm_indicies[_trans])
187		cs = int(_formatfsm_trans_targs[_trans])
188
189		if _formatfsm_trans_actions[_trans] == 0 {
190			goto _again
191		}
192
193		_acts = int(_formatfsm_trans_actions[_trans])
194		_nacts = uint(_formatfsm_actions[_acts])
195		_acts++
196		for ; _nacts > 0; _nacts-- {
197			_acts++
198			switch _formatfsm_actions[_acts-1] {
199			case 0:
200				// line 31 "format_fsm.rl"
201
202				verb = formatVerb{
203					ArgNum: nextArg,
204					Prec:   -1,
205					Width:  -1,
206				}
207				ts = p
208
209			case 1:
210				// line 40 "format_fsm.rl"
211
212				buf.WriteByte(data[p])
213
214			case 4:
215				// line 51 "format_fsm.rl"
216
217				// We'll try to slurp a whole UTF-8 sequence here, to give the user
218				// better feedback.
219				r, _ := utf8.DecodeRuneInString(data[p:])
220				return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
221
222			case 5:
223				// line 58 "format_fsm.rl"
224
225				verb.Sharp = true
226
227			case 6:
228				// line 61 "format_fsm.rl"
229
230				verb.Zero = true
231
232			case 7:
233				// line 64 "format_fsm.rl"
234
235				verb.Minus = true
236
237			case 8:
238				// line 67 "format_fsm.rl"
239
240				verb.Plus = true
241
242			case 9:
243				// line 70 "format_fsm.rl"
244
245				verb.Space = true
246
247			case 10:
248				// line 74 "format_fsm.rl"
249
250				verb.ArgNum = 0
251
252			case 11:
253				// line 77 "format_fsm.rl"
254
255				verb.ArgNum = (10 * verb.ArgNum) + (int(data[p]) - '0')
256
257			case 12:
258				// line 81 "format_fsm.rl"
259
260				verb.HasWidth = true
261
262			case 13:
263				// line 84 "format_fsm.rl"
264
265				verb.Width = 0
266
267			case 14:
268				// line 87 "format_fsm.rl"
269
270				verb.Width = (10 * verb.Width) + (int(data[p]) - '0')
271
272			case 15:
273				// line 91 "format_fsm.rl"
274
275				verb.HasPrec = true
276
277			case 16:
278				// line 94 "format_fsm.rl"
279
280				verb.Prec = 0
281
282			case 17:
283				// line 97 "format_fsm.rl"
284
285				verb.Prec = (10 * verb.Prec) + (int(data[p]) - '0')
286
287			case 18:
288				// line 101 "format_fsm.rl"
289
290				verb.Mode = rune(data[p])
291				te = p + 1
292				verb.Raw = data[ts:te]
293				verb.Offset = ts
294
295				if verb.ArgNum > highestArgIdx {
296					highestArgIdx = verb.ArgNum
297				}
298
299				err := formatAppend(&verb, &buf, a)
300				if err != nil {
301					return buf.String(), err
302				}
303				nextArg = verb.ArgNum + 1
304
305				// line 330 "format_fsm.go"
306			}
307		}
308
309	_again:
310		if cs == 0 {
311			goto _out
312		}
313		p++
314		if p != pe {
315			goto _resume
316		}
317	_test_eof:
318		{
319		}
320		if p == eof {
321			__acts := _formatfsm_eof_actions[cs]
322			__nacts := uint(_formatfsm_actions[__acts])
323			__acts++
324			for ; __nacts > 0; __nacts-- {
325				__acts++
326				switch _formatfsm_actions[__acts-1] {
327				case 2:
328					// line 44 "format_fsm.rl"
329
330				case 3:
331					// line 47 "format_fsm.rl"
332
333					return buf.String(), fmt.Errorf("invalid format string starting at offset %d", p)
334
335				case 4:
336					// line 51 "format_fsm.rl"
337
338					// We'll try to slurp a whole UTF-8 sequence here, to give the user
339					// better feedback.
340					r, _ := utf8.DecodeRuneInString(data[p:])
341					return buf.String(), fmt.Errorf("unrecognized format character %q at offset %d", r, p)
342
343					// line 369 "format_fsm.go"
344				}
345			}
346		}
347
348	_out:
349		{
350		}
351	}
352
353	// line 177 "format_fsm.rl"
354
355	// If we fall out here without being in a final state then we've
356	// encountered something that the scanner can't match, which should
357	// be impossible (the scanner matches all bytes _somehow_) but we'll
358	// flag it anyway rather than just losing data from the end.
359	if cs < formatfsm_first_final {
360		return buf.String(), fmt.Errorf("extraneous characters beginning at offset %d", p)
361	}
362
363	if highestArgIdx < len(a) {
364		// Extraneous args are an error, to more easily detect mistakes
365		firstBad := highestArgIdx + 1
366		if highestArgIdx == 0 {
367			// Custom error message for this case
368			return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; no verbs in format string")
369		}
370		return buf.String(), function.NewArgErrorf(firstBad, "too many arguments; only %d used by format string", highestArgIdx)
371	}
372
373	return buf.String(), nil
374}
375