forked from ericlagergren/decimal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgetcases.go
130 lines (119 loc) · 2.82 KB
/
getcases.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
// +build ignore
package main
import (
"bufio"
"bytes"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
const prefix = "https://www.research.ibm.com/haifa/projects/verification/fpgen/download/Decimal-"
const suffix = ".fptest"
var urls = [...]string{
prefix + "Basic-Types-Inputs" + suffix,
prefix + "Basic-Types-Intermediate" + suffix,
prefix + "Rounding" + suffix,
prefix + "Overflow" + suffix,
prefix + "Underflow" + suffix,
prefix + "Trailing-And-Leading-Zeros-Input" + suffix,
prefix + "Trailing-And-Leading-Zeros-Result" + suffix,
prefix + "Clamping" + suffix,
prefix + "Mul-Trailing-Zeros" + suffix,
}
func main() {
const dir = "_testdata"
err := os.MkdirAll(dir, 0755)
if err != nil {
log.Fatalln(err)
}
for _, url := range urls {
resp, err := http.Get(url)
if err != nil {
log.Fatalln(err)
}
defer resp.Body.Close()
name := strings.TrimPrefix(url, prefix)
name = strings.Replace(name, "-", "", -1)
out, err := os.Create(filepath.Join(dir, name))
if err != nil {
log.Fatalln(err)
}
defer out.Close()
err = copyLines(out, resp.Body)
if err != nil {
log.Fatalln(err)
}
}
}
// copyLines copies r to w but omits invalid lines.
func copyLines(w io.Writer, r io.Reader) (err error) {
s := bufio.NewScanner(r)
s.Split(scanLines)
// wc -L *.fptest | sort shows max line length is 142. Alloc a few extra
// bytes in case it grows in the future.
s.Buffer(make([]byte, 150), bufio.MaxScanTokenSize)
var p []byte
for s.Scan() {
p = s.Bytes()
if !badLine(p) {
_, err = w.Write(p)
if err != nil {
return err
}
}
}
return s.Err()
}
// badLine returns true if the line is one of the non-test lines. (E.g., is
// a <pre> tags, a copyright date, etc.)
func badLine(p []byte) bool {
if len(p) == 0 {
return true
}
switch p[0] {
case '\n', '\r':
return true
case '<':
return bytes.Contains(p, []byte("pre>"))
case 'D':
return bytes.HasPrefix(p, []byte("Decimal floating point tests: "))
case 'C':
return bytes.HasPrefix(p, []byte("Copyright of IBM Corp. 20"))
default:
return false
}
}
// scanLines is copied from the stdlib but includes newlines.
func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
if i := bytes.IndexByte(data, '\n'); i >= 0 {
// We have a full newline-terminated line.
return i + 1, convCR(data[0:i]), nil
}
// If we're at EOF, we have a final, non-terminated line. Return it.
if atEOF {
return len(data), convCR(data), nil
}
// Request more data.
return 0, nil, nil
}
// convCR converts a trailing carriage return to a line feed.
func convCR(data []byte) []byte {
if len(data) == 0 {
return data
}
switch data[len(data)-1] {
case '\r':
data[len(data)-1] = '\n'
return data
case '\n':
return data
default:
return append(data, '\n')
}
}