/
string.go
117 lines (94 loc) · 1.91 KB
/
string.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
113
114
115
116
117
// Copyright (c) 2016 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sexp
import (
"bytes"
"encoding/json"
"fmt"
)
func Stringify(x interface{}, multiline bool) string {
return stringify(x, multiline, "")
}
func stringify(x interface{}, multiline bool, indent string) (s string) {
indent += " "
switch x := x.(type) {
case []interface{}:
s += "("
wrap := false
for i, item := range x {
if _, ok := item.([]interface{}); ok {
wrap = true
}
if wrap && multiline {
s += "\n" + indent
} else if i > 0 {
s += " "
}
s += stringify(item, multiline, indent)
}
s += ")"
default:
s += fmt.Sprint(x)
}
return
}
func Unparse(expr []interface{}) []byte {
var buf bytes.Buffer
unparse(expr, &buf)
return buf.Bytes()
}
func unparse(expr interface{}, buf *bytes.Buffer) {
switch x := expr.(type) {
case string:
if _, err := buf.Write([]byte(x)); err != nil {
panic(err)
}
case Quoted:
var data []byte
var err error
manual := false
for _, b := range []byte(x.String()) {
if b < 32 || b > 127 {
manual = true
break
}
}
if manual {
data = []byte{'"'}
for _, b := range []byte(x.String()) {
if b < 32 || b > 127 {
data = append(data, fmt.Sprintf("\\%02x", b)...)
} else {
data = append(data, b)
}
}
data = append(data, '"')
} else {
data, err = json.Marshal(x.String())
if err != nil {
panic(err)
}
}
if _, err := buf.Write(data); err != nil {
panic(err)
}
case []interface{}:
if _, err := buf.Write([]byte("(")); err != nil {
panic(err)
}
for i, child := range x {
unparse(child, buf)
if i < len(x)-1 {
if _, err := buf.Write([]byte(" ")); err != nil {
panic(err)
}
}
}
if _, err := buf.Write([]byte(") ")); err != nil {
panic(err)
}
default:
panic(expr)
}
}