forked from shenghui0779/sdk-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
helper.go
146 lines (113 loc) ยท 2.79 KB
/
helper.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package wx
import (
"bytes"
"encoding/json"
"encoding/xml"
"fmt"
"io"
"strings"
)
// WXML deal with xml for wechat
type WXML map[string]string
// X is a convenient alias for a map[string]interface{}.
type X map[string]interface{}
// CDATA XML CDATA section which is defined as blocks of text that are not parsed by the parser, but are otherwise recognized as markup.
type CDATA string
// MarshalXML encodes the receiver as zero or more XML elements.
func (c CDATA) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return e.EncodeElement(struct {
string `xml:",cdata"`
}{string(c)}, start)
}
// FormatMap2XML format map to xml
func FormatMap2XML(m WXML) (string, error) {
var builder strings.Builder
builder.WriteString("<xml>")
for k, v := range m {
builder.WriteString(fmt.Sprintf("<%s>", k))
if err := xml.EscapeText(&builder, []byte(v)); err != nil {
return "", err
}
builder.WriteString(fmt.Sprintf("</%s>", k))
}
builder.WriteString("</xml>")
return builder.String(), nil
}
// ParseXML2Map parse xml to map
func ParseXML2Map(b []byte) (WXML, error) {
m := make(WXML)
xmlReader := bytes.NewReader(b)
var (
d = xml.NewDecoder(xmlReader)
tk xml.Token
depth = 0 // current xml.Token depth
key string
buf bytes.Buffer
err error
)
for {
tk, err = d.Token()
if err != nil {
if err == io.EOF {
return m, nil
}
return nil, err
}
switch v := tk.(type) {
case xml.StartElement:
depth++
switch depth {
case 2:
key = v.Name.Local
buf.Reset()
case 3:
if err = d.Skip(); err != nil {
return nil, err
}
depth--
key = "" // key == "" indicates that the node with depth==2 has children
}
case xml.CharData:
if depth == 2 && key != "" {
buf.Write(v)
}
case xml.EndElement:
if depth == 2 && key != "" {
m[key] = buf.String()
}
depth--
}
}
}
// EncodeUint32ToBytes ๆๆดๆฐ uint32 ๆ ผๅผๅๆ 4 ๅญ่็็ฝ็ปๅญ่ๅบ
func EncodeUint32ToBytes(i uint32) []byte {
b := make([]byte, 4)
b[0] = byte(i >> 24)
b[1] = byte(i >> 16)
b[2] = byte(i >> 8)
b[3] = byte(i)
return b
}
// DecodeBytesToUint32 ไป 4 ๅญ่็็ฝ็ปๅญ่ๅบ้่งฃๆๅบๆดๆฐ uint32
func DecodeBytesToUint32(b []byte) uint32 {
if len(b) != 4 {
return 0
}
return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
}
// MarshalWithNoEscapeHTML marshal with no escape HTML
func MarshalWithNoEscapeHTML(v interface{}) ([]byte, error) {
var buf bytes.Buffer
jsonEncoder := json.NewEncoder(&buf)
jsonEncoder.SetEscapeHTML(false)
if err := jsonEncoder.Encode(v); err != nil {
return nil, err
}
b := buf.Bytes()
// ๅปๆ go std ็ปๆซๅฐพๅ ็ '\n'
// @see https://github.com/golang/go/issues/7767
if l := len(b); l != 0 && b[l-1] == '\n' {
b = b[:l-1]
}
return b, nil
}