~ubuntu-branches/debian/sid/golang-github-kubernetes-gengo/sid

« back to all changes in this revision

Viewing changes to vendor/k8s.io/kubernetes/third_party/forked/golang/expansion/expand.go

  • Committer: Package Import Robot
  • Author(s): Tim Potter
  • Date: 2017-02-21 08:56:15 UTC
  • Revision ID: package-import@ubuntu.com-20170221085615-qwe3pgnuuwibrsvn
Tags: 0.0~git20161024.0.6a1c24d-1
Initial release (Closes: #858311)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package expansion
 
2
 
 
3
import (
 
4
        "bytes"
 
5
)
 
6
 
 
7
const (
 
8
        operator        = '$'
 
9
        referenceOpener = '('
 
10
        referenceCloser = ')'
 
11
)
 
12
 
 
13
// syntaxWrap returns the input string wrapped by the expansion syntax.
 
14
func syntaxWrap(input string) string {
 
15
        return string(operator) + string(referenceOpener) + input + string(referenceCloser)
 
16
}
 
17
 
 
18
// MappingFuncFor returns a mapping function for use with Expand that
 
19
// implements the expansion semantics defined in the expansion spec; it
 
20
// returns the input string wrapped in the expansion syntax if no mapping
 
21
// for the input is found.
 
22
func MappingFuncFor(context ...map[string]string) func(string) string {
 
23
        return func(input string) string {
 
24
                for _, vars := range context {
 
25
                        val, ok := vars[input]
 
26
                        if ok {
 
27
                                return val
 
28
                        }
 
29
                }
 
30
 
 
31
                return syntaxWrap(input)
 
32
        }
 
33
}
 
34
 
 
35
// Expand replaces variable references in the input string according to
 
36
// the expansion spec using the given mapping function to resolve the
 
37
// values of variables.
 
38
func Expand(input string, mapping func(string) string) string {
 
39
        var buf bytes.Buffer
 
40
        checkpoint := 0
 
41
        for cursor := 0; cursor < len(input); cursor++ {
 
42
                if input[cursor] == operator && cursor+1 < len(input) {
 
43
                        // Copy the portion of the input string since the last
 
44
                        // checkpoint into the buffer
 
45
                        buf.WriteString(input[checkpoint:cursor])
 
46
 
 
47
                        // Attempt to read the variable name as defined by the
 
48
                        // syntax from the input string
 
49
                        read, isVar, advance := tryReadVariableName(input[cursor+1:])
 
50
 
 
51
                        if isVar {
 
52
                                // We were able to read a variable name correctly;
 
53
                                // apply the mapping to the variable name and copy the
 
54
                                // bytes into the buffer
 
55
                                buf.WriteString(mapping(read))
 
56
                        } else {
 
57
                                // Not a variable name; copy the read bytes into the buffer
 
58
                                buf.WriteString(read)
 
59
                        }
 
60
 
 
61
                        // Advance the cursor in the input string to account for
 
62
                        // bytes consumed to read the variable name expression
 
63
                        cursor += advance
 
64
 
 
65
                        // Advance the checkpoint in the input string
 
66
                        checkpoint = cursor + 1
 
67
                }
 
68
        }
 
69
 
 
70
        // Return the buffer and any remaining unwritten bytes in the
 
71
        // input string.
 
72
        return buf.String() + input[checkpoint:]
 
73
}
 
74
 
 
75
// tryReadVariableName attempts to read a variable name from the input
 
76
// string and returns the content read from the input, whether that content
 
77
// represents a variable name to perform mapping on, and the number of bytes
 
78
// consumed in the input string.
 
79
//
 
80
// The input string is assumed not to contain the initial operator.
 
81
func tryReadVariableName(input string) (string, bool, int) {
 
82
        switch input[0] {
 
83
        case operator:
 
84
                // Escaped operator; return it.
 
85
                return input[0:1], false, 1
 
86
        case referenceOpener:
 
87
                // Scan to expression closer
 
88
                for i := 1; i < len(input); i++ {
 
89
                        if input[i] == referenceCloser {
 
90
                                return input[1:i], true, i + 1
 
91
                        }
 
92
                }
 
93
 
 
94
                // Incomplete reference; return it.
 
95
                return string(operator) + string(referenceOpener), false, 1
 
96
        default:
 
97
                // Not the beginning of an expression, ie, an operator
 
98
                // that doesn't begin an expression.  Return the operator
 
99
                // and the first rune in the string.
 
100
                return (string(operator) + string(input[0])), false, 1
 
101
        }
 
102
}