mirror of
https://github.com/depp/syncfiles.git
synced 2024-11-29 03:51:28 +00:00
5ad207f785
This simplifies the conversion test, since we don't need to be careful about which data we run the conversion test in. It will also simplify the command-line conversion tool and its distribution. The classic Mac OS version of this program will continue to embed conversion tables in the resource fork.
207 lines
3.5 KiB
Go
207 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"math"
|
|
"os"
|
|
"os/exec"
|
|
"path"
|
|
"strconv"
|
|
)
|
|
|
|
const (
|
|
width = 80
|
|
formatOff = "/* clang-format off */\n"
|
|
formatOn = "/* clang-format on */\n"
|
|
)
|
|
|
|
type csource struct {
|
|
filename string
|
|
file *os.File
|
|
writer *bufio.Writer
|
|
}
|
|
|
|
func createCSource(filename string) (s csource, err error) {
|
|
if !flagQuiet {
|
|
fmt.Fprintln(os.Stderr, "Writing:", filename)
|
|
}
|
|
|
|
fp, err := os.Create(filename)
|
|
if err != nil {
|
|
return s, err
|
|
}
|
|
w := bufio.NewWriter(fp)
|
|
w.WriteString(header)
|
|
return csource{
|
|
filename: filename,
|
|
file: fp,
|
|
writer: w,
|
|
}, nil
|
|
}
|
|
|
|
func (s *csource) close() {
|
|
if s.file != nil {
|
|
s.file.Close()
|
|
s.file = nil
|
|
}
|
|
if s.filename != "" {
|
|
os.Remove(s.filename)
|
|
}
|
|
}
|
|
|
|
func (s *csource) flush() error {
|
|
if s.file == nil {
|
|
panic("already closed")
|
|
}
|
|
err := s.writer.Flush()
|
|
s.writer = nil
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = s.file.Close()
|
|
s.file = nil
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if flagFormat {
|
|
cmd := exec.Command("clang-format", "-i", s.filename)
|
|
if err := cmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
s.filename = ""
|
|
return nil
|
|
}
|
|
|
|
func (s *csource) include(name string) {
|
|
fmt.Fprintf(s.writer, "#include \"%s\"\n", path.Join(srcdirname, name))
|
|
}
|
|
|
|
func (s *csource) bytes(data []byte, final bool) {
|
|
if len(data) == 0 {
|
|
return
|
|
}
|
|
line := make([]byte, 0, width+8)
|
|
for i, x := range data {
|
|
cur := line
|
|
line = strconv.AppendUint(line, uint64(x), 10)
|
|
if i < len(data)-1 || !final {
|
|
line = append(line, ',')
|
|
}
|
|
if len(line) > width-4 {
|
|
s.writer.WriteString("\n\t")
|
|
s.writer.Write(cur)
|
|
nline := line[len(cur):]
|
|
copy(line, nline)
|
|
line = line[:len(nline)]
|
|
}
|
|
}
|
|
s.writer.WriteString("\n\t")
|
|
s.writer.Write(line)
|
|
}
|
|
|
|
func (s *csource) ints(data []int) {
|
|
if len(data) == 0 {
|
|
return
|
|
}
|
|
line := make([]byte, 0, width+16)
|
|
for i, x := range data {
|
|
cur := line
|
|
line = strconv.AppendInt(line, int64(x), 10)
|
|
if i < len(data)-1 {
|
|
line = append(line, ',')
|
|
}
|
|
if len(line) > width-4 {
|
|
s.writer.WriteString("\n\t")
|
|
s.writer.Write(cur)
|
|
nline := line[len(cur):]
|
|
copy(line, nline)
|
|
line = line[:len(nline)]
|
|
}
|
|
}
|
|
s.writer.WriteString("\n\t")
|
|
s.writer.Write(line)
|
|
}
|
|
|
|
func (s *csource) strings(data []string) {
|
|
for i, x := range data {
|
|
s.writer.WriteString("\n\t\"")
|
|
var last byte
|
|
for _, c := range []byte(x) {
|
|
if 32 <= c && c <= 126 {
|
|
if c == '\\' || c == '"' {
|
|
s.writer.WriteByte('\\')
|
|
} else if '0' <= c && c <= '9' && last == 0 && i == 0 {
|
|
s.writer.WriteString("00")
|
|
}
|
|
s.writer.WriteByte(c)
|
|
} else {
|
|
var e string
|
|
switch c {
|
|
case 0:
|
|
e = `\0`
|
|
case '\t':
|
|
e = `\t`
|
|
case '\n':
|
|
e = `\n`
|
|
case '\r':
|
|
e = `\r`
|
|
}
|
|
if e == "" {
|
|
fmt.Fprintf(s.writer, "\\x%02x", c)
|
|
} else {
|
|
s.writer.WriteString(e)
|
|
}
|
|
}
|
|
last = c
|
|
}
|
|
if i < len(data)-1 {
|
|
s.writer.WriteString(`\0`)
|
|
}
|
|
s.writer.WriteByte('"')
|
|
}
|
|
}
|
|
|
|
func intType(maxval int) string {
|
|
if maxval <= math.MaxUint8 {
|
|
return "UInt8"
|
|
}
|
|
if maxval <= math.MaxUint16 {
|
|
return "UInt16"
|
|
}
|
|
return "UInt32"
|
|
}
|
|
|
|
func arrayIntType(arr []int) string {
|
|
var max int
|
|
for _, x := range arr {
|
|
if x > max {
|
|
max = x
|
|
}
|
|
}
|
|
return intType(max)
|
|
}
|
|
|
|
type stringtable struct {
|
|
data []string
|
|
offset int
|
|
offsets map[string]int
|
|
}
|
|
|
|
func newStringtable() (s stringtable) {
|
|
s.offsets = make(map[string]int)
|
|
return
|
|
}
|
|
|
|
func (t *stringtable) add(s string) int {
|
|
if offset, exist := t.offsets[s]; exist {
|
|
return offset
|
|
}
|
|
t.data = append(t.data, s)
|
|
offset := t.offset
|
|
t.offset += len(s) + 1
|
|
t.offsets[s] = offset
|
|
return offset
|
|
}
|