-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhelpers.go
158 lines (131 loc) · 3.59 KB
/
helpers.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
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (c) 2017 Andrey Gayvoronsky <[email protected]>
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package ooxml
import (
"archive/zip"
"encoding/xml"
"io"
"reflect"
"regexp"
"strconv"
)
//MarshalPreparation is interface that must be implemented by complex data if it requires some preparation steps before marshaling
type MarshalPreparation interface {
BeforeMarshalXML() interface{}
}
//MarshalFixation is interface that must be implemented by complex data if it requires some after marshal fixation
type MarshalFixation interface {
AfterMarshalXML(content []byte) []byte
}
//GetLettersFn is a strings.Map walker to return [a-zA-Z] runes from string
func GetLettersFn(rune rune) rune {
switch {
case 'A' <= rune && rune <= 'Z':
return rune
case 'a' <= rune && rune <= 'z':
return rune - 32
}
return -1
}
//GetNumbersFn is a strings.Map walker to return [0-9] runes from string
func GetNumbersFn(rune rune) rune {
if rune >= 48 && rune < 58 {
return rune
}
return -1
}
//UnmarshalZipFile unpacks a zip file into target object
func UnmarshalZipFile(f *zip.File, target interface{}) error {
xmlReader, err := f.Open()
if err != nil {
return err
}
defer xmlReader.Close()
decoder := xml.NewDecoder(xmlReader)
return decoder.Decode(target)
}
//MarshalZipFile add a file with content of marshaled source to zip
func MarshalZipFile(fileName string, source interface{}, to *zip.Writer) error {
if prep, ok := source.(MarshalPreparation); ok {
source = prep.BeforeMarshalXML()
//if BeforeMarshalXML returns nil, then consider it like file must not be added to package
if source == nil {
return nil
}
}
writer, err := to.Create(fileName)
if err != nil {
return err
}
content, err := xml.Marshal(source)
if fix, ok := source.(MarshalFixation); ok {
content = fix.AfterMarshalXML(content)
}
if err == nil {
_, err = writer.Write([]byte(xml.Header + string(content)))
if err != nil {
return err
}
}
return err
}
//CopyZipFile copies a zip file as is to a new zip
func CopyZipFile(from *zip.File, to *zip.Writer) error {
writer, err := to.Create(from.Name)
if err != nil {
return err
}
reader, err := from.Open()
if err != nil {
return err
}
defer reader.Close()
_, err = io.Copy(writer, reader)
return err
}
//UniqueName returns next valid unique name with a valid length
func UniqueName(name string, names []string, nameLimit int) string {
sanityChecked := 0
regTitle := regexp.MustCompile(`[\d]+$`)
for i := 1; sanityChecked < 2; i++ {
sanityChecked++
if len(name) > nameLimit {
name = name[:nameLimit]
sanityChecked = 0
}
for _, nextName := range names {
//non unique name?
if name == nextName {
sanityChecked = 0
suffix := strconv.Itoa(i)
title := regTitle.ReplaceAllString(name, "")
//next name is too large?
if len(title+suffix) > nameLimit {
title = title[:nameLimit-len(suffix)]
}
name = title + suffix
break
}
}
}
return name
}
//IsEmptyValue returns true if reflected value is 'empty'
func IsEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}
return false
}