-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencoder.go
112 lines (93 loc) · 2.53 KB
/
encoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package astconf
import (
"io"
"reflect"
)
// Encoder encodes Go types as asterisk configuration data.
type Encoder struct {
*encoderState // shared state among all encoders in a stack
next *Encoder // the next encoder in the stack
base io.Writer // the underlying writer
w io.Writer // specialized writer wrapping base, may be the same as base
indent int // the current indent level of the encoder
scratch encoderScratch
}
// NewEncoder returns a new Encoder that writes to the given io.Writer.
func NewEncoder(w io.Writer, options ...EncOpt) *Encoder {
e := newEncoder(w)
for _, option := range options {
option(e)
}
return e
}
func newEncoder(w io.Writer) *Encoder {
var e encoder
// Initialize the stack
for i := range e.stack {
var next *Encoder
if i+1 < len(e.stack) {
next = &e.stack[i+1]
}
e.stack[i].init(&e.state, next)
}
// The root encoder is the first encoder in the stack
root := &e.stack[0]
// Prepare the root with a startup writer that will detect when the
// encoder has been started
root.base = w
root.w = newStartupWriter(root)
return root
}
// Printer returns a new Printer that writes to the same io.Writer as e.
func (e *Encoder) Printer() *Printer {
return &Printer{
Writer: e.w,
Indent: e.indent,
Alignment: e.alignment,
Started: e.started,
}
}
// Encode encodes the given value as an asterisk configuration section.
func (e *Encoder) Encode(v interface{}) error {
val := reflect.ValueOf(v)
return valueEncoder(val)(val, e)
}
// init initializes a new Encoder.
func (e *Encoder) init(state *encoderState, next *Encoder) {
e.encoderState = state
e.next = next
}
// reset prepares an encoder for re-use
func (e *Encoder) reset() {
e.indent = 0
}
// derive returns a child encoder that writes to e.w.
func (e *Encoder) derive() *Encoder {
next := e.next
if next == nil {
next = &Encoder{}
next.init(e.encoderState, nil)
}
next.base = e.w
next.w = e.w
next.indent = e.indent
return next
}
// encoder is an internal struct that holds shared encoder state and
// a stack of encoders that can be used by marshaling functions.
type encoder struct {
state encoderState
stack [8]Encoder // Allocate an array of encoders as a contiguous memory block
}
// encoderState holds encoder state that is common to an encoder and
// all of its children.
type encoderState struct {
alignment Alignment
started bool
}
// encoderScratch holds ephemeral encoder data used by encoding functions.
type encoderScratch struct {
name []byte
sep []byte // = or =>
started bool
}