-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcstr.go
126 lines (112 loc) · 2.36 KB
/
cstr.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
// based on linux bin2hex
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"os"
"strings"
)
var (
spaces = flag.Int("s", 4, "number of spaces a tab represents")
useTab = flag.Bool("t", true, "don't convert tab into spaces")
useInt = flag.Bool("i", false, "use int type for length")
useArray = flag.Bool("a", true, "output array of strings instead of a long string")
fixedSize = flag.Bool("f", false, "fixed size output array")
doAlign = flag.Bool("l", false, "align output")
)
func main() {
flag.Parse()
if flag.NArg() < 1 {
usage()
}
fmt.Printf("/* automatically generated by cstr */\n")
if !*useInt {
fmt.Println("#include <stddef.h>\n")
}
r := bufio.NewReader(os.Stdin)
if *useArray {
printArray(r)
} else {
printString(r)
}
}
func printArray(r *bufio.Reader) {
var lines []string
for {
line, err := fgetln(r)
if err != nil {
break
}
lines = append(lines, line)
}
lineWidth := 0
for i := range lines {
if *fixedSize && len(lines[i]) > 0 {
lines[i] = lines[i][:len(lines[i])-1]
}
lineWidth = max(lineWidth, len(lines[i]))
}
if *doAlign {
for i := range lines {
if len(lines[i]) < lineWidth {
lines[i] += strings.Repeat(" ", lineWidth-len(lines[i]))
}
}
}
if !*fixedSize {
fmt.Printf("const char *%s[] = {\n", flag.Arg(0))
} else {
fmt.Printf("const char %s[][%d] = {\n", flag.Arg(0), lineWidth)
}
for _, line := range lines {
fmt.Printf("\t%q,\n", line)
}
if !*fixedSize {
fmt.Printf("\tNULL,\n")
}
fmt.Printf("};\n")
}
func printString(r *bufio.Reader) {
fmt.Printf("const char %s[] = {\n", flag.Arg(0))
i := uint64(0)
for {
line, err := fgetln(r)
if err != nil {
break
}
i += uint64(len(line))
fmt.Printf("\t%q\n", line)
}
typ := "size_t"
if *useInt {
typ = "int"
}
fmt.Printf("\n};\n%s %s_len = %d;\n", typ, flag.Arg(0), i)
}
func usage() {
fmt.Fprintln(os.Stderr, "usage: name")
flag.PrintDefaults()
os.Exit(1)
}
func fgetln(r *bufio.Reader) (string, error) {
b := new(bytes.Buffer)
for {
r, _, err := r.ReadRune()
if err != nil {
return b.String(), err
}
if !*useTab {
if r == '\t' {
b.WriteString(strings.Repeat(" ", *spaces))
continue
}
}
b.WriteRune(r)
if r == '\n' {
break
}
}
return b.String(), nil
}