diff options
author | Thomas Voss <mail@thomasvoss.com> | 2025-06-06 01:32:41 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2025-06-06 01:32:41 +0200 |
commit | 2c726e551d90d20bcd2d78545c369864cc9038e5 (patch) | |
tree | 520615a33c966c729e70e549e859a2c01dc4ba40 /cmd | |
parent | 9379ea42a9b0afd1abf705bf3300f03d8bbe79f9 (diff) |
Use CSV’s for mintages
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/mfmt/main.go | 189 | ||||
-rw-r--r-- | cmd/mfmt/main_test.go | 140 | ||||
-rw-r--r-- | cmd/mfmt/util_test.go | 35 |
3 files changed, 0 insertions, 364 deletions
diff --git a/cmd/mfmt/main.go b/cmd/mfmt/main.go deleted file mode 100644 index c4e2277..0000000 --- a/cmd/mfmt/main.go +++ /dev/null @@ -1,189 +0,0 @@ -/* Simple formatter for mintage files. This is not perfect and doesn’t - check for syntactic correctness, it’s just to get stuff aligned - nicely. Maybe in the future I will construct a military-grade - formatter. */ - -package main - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "regexp" - "strings" -) - -const ws = " \t" - -var ( - rv int - - reMintageYear = regexp.MustCompile(`^\d{4}(-[^ \t]+)?`) - reMintageRowC = regexp.MustCompile(`^[ \t]*(([0-9.]+|\?)[ \t]+){2}([0-9.]+|\?)$`) - reMintageRowS = regexp.MustCompile(`^[ \t]*(([0-9.]+|\?)[ \t]+){7}([0-9.]+|\?)$`) -) - -func main() { - if len(os.Args) == 1 { - mfmt("-", os.Stdin, os.Stdout) - } - for _, arg := range os.Args[1:] { - f, err := os.OpenFile(arg, os.O_RDWR, 0) - if err != nil { - warn(err) - continue - } - defer f.Close() - - buf := bytes.NewBuffer(make([]byte, 0, 8192)) - mfmt(arg, f, buf) - - if _, err = f.Seek(0, io.SeekStart); err != nil { - warn(err) - continue - } - - if _, err = f.Write(buf.Bytes()); err != nil { - warn(err) - continue - } - - if err = f.Truncate(int64(buf.Len())); err != nil { - warn(err) - } - } - os.Exit(rv) -} - -func mfmt(file string, r io.Reader, w io.Writer) { - var ( - buf [3]string - bufsz int - longestNums [8]int - ) - - scanner := bufio.NewScanner(r) - for linenr := 1; scanner.Scan(); linenr++ { - line := strings.Trim(scanner.Text(), ws) - - switch { - case len(line) == 0, line[0] == '#': - fmt.Fprintln(w, line) - case reMintageRowS.MatchString(line): - switch bufsz { - case len(buf): - bufsz = 0 - clear(longestNums[:]) - fallthrough - default: - setLongestNum(longestNums[:], line) - buf[bufsz] = line - if bufsz++; bufsz == len(buf) { - fmtMintageRow(buf[0], longestNums[:], w) - fmtMintageRow(buf[1], longestNums[:], w) - fmtMintageRow(buf[2], longestNums[:], w) - } - } - case reMintageRowC.MatchString(line): - var ns [3]int - setLongestNum(ns[:], line) - fmtMintageRow(line, ns[:], w) - case reMintageYear.MatchString(line): - fmtMintageYear(line, w) - default: - warn(fmt.Sprintf("%s:%d: potential syntax error", file, linenr)) - fmt.Fprintln(w, line) - } - } -} - -func setLongestNum(longest []int, line string) { - for i, x := range strings.FieldsFunc(line, func(r rune) bool { - return strings.ContainsRune(ws, r) - }) { - n := len(strings.ReplaceAll(x, ".", "")) - n += (n - 1) / 3 // Thousands separators - longest[i] = max(longest[i], n) - } -} - -func fmtMintageYear(line string, w io.Writer) { - switch i := strings.IndexAny(line, ws); i { - case -1: - fmt.Fprintln(w, line) - default: - fmt.Fprintf(w, "%s %s\n", line[:i], strings.TrimLeft(line[i:], ws)) - } -} - -func fmtMintageRow(line string, longest []int, w io.Writer) { - tokens := strings.FieldsFunc(line, func(r rune) bool { - return strings.ContainsRune(ws, r) - }) - - for i, tok := range tokens { - s := formatMintage(tok) - - if i == 0 { - fmt.Fprintf(w, "\t%*s", longest[i], s) - } else { - fmt.Fprintf(w, "%*s", longest[i]+1, s) - } - } - - fmt.Fprintln(w) -} - -func formatMintage(s string) string { - if s == "?" { - return s - } - - n := atoiWithDots(s) - digits := intlen(n) - dots := (digits - 1) / 3 - out := make([]byte, digits+dots) - - for i, j := len(out)-1, 0; ; i-- { - out[i] = byte(n%10) + 48 - if n /= 10; n == 0 { - return string(out) - } - if j++; j == 3 { - i, j = i-1, 0 - out[i] = '.' - } - } -} - -func intlen(v int) int { - switch { - case v == 0: - return 1 - default: - n := 0 - for x := v; x != 0; x /= 10 { - n++ - } - return n - } -} - -func atoiWithDots(s string) int { - n := 0 - for _, ch := range s { - if ch == '.' { - continue - } - n = n*10 + int(ch) - '0' - } - return n -} - -func warn(e any) { - fmt.Fprintf(os.Stderr, "%s: %s\n", filepath.Base(os.Args[0]), e) - rv = 1 -} diff --git a/cmd/mfmt/main_test.go b/cmd/mfmt/main_test.go deleted file mode 100644 index ef91473..0000000 --- a/cmd/mfmt/main_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package main - -import ( - "bytes" - "testing" -) - -func runTest(t *testing.T, in, out string, nilErr bool) { -} - -func TestComplete(t *testing.T) { - in := ` -2014 -60.000 60.000 860.000 860.000 860.000 340.000 511.843 360.000 -70.000 70.000 70.000 70.000 70.000 70.000 70.000 70.000 -3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 - -# Ref: https://example.com -2015 - 0 0 0 0 0 0 0 1.072.400 -40.000 40.000 40.000 40.000 40.000 40.000 40.000 40.000 - ? ? ? ? ? ? ? ? - -2016 - 0 0 0 0 0 0 2.339.200 0 -35.000 35.000 35.000 35.000 35.000 35.000 35.000 35.000 - ? ? ? ? ? ? ? ? - -2017 -2.582.395 1.515.000 2.191.421 1.103.000 1.213.000 968.800 17.000 794.588 -22.000 22.000 22.000 22.000 22.000 22.000 22.000 22.000 - ? ? ? ? ? ? ? ? - -2018 -2.430.000 2.550.000 1.800.000 980.000 1.014.000 890.000 0 868.000 -20.000 20.000 20.000 20.000 20.000 20.000 20.000 20.000 - ? ? ? ? ? ? ? ? - -2019 -2.447.000 1.727.000 2.100.000 1.610.000 1.570.000 930.000 0 1.058.310 -15.000 15.000 15.000 15.000 15.000 15.000 15.000 15.000 - ? ? ? ? ? ? ? ? - -2020 - 0 0 0 860.000 175.000 740.000 0 1.500.000 -12.000 12.000 12.000 12.000 12.000 12.000 12.000 12.000 - ? ? ? ? ? ? ? ? - -2021 - 200.000 700.000 0 1.400.000 1.420.000 600.000 50.000 1.474.500 -10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2022 - 700.000 450.000 400.000 700.000 700.000 380.000 0 1.708.000 -10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2023 - 0 0 0 0 0 0 0 2.075.250 -10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2024 - ? ? ? ? ? ? ? ? - ? ? ? ? ? ? ? ? - ? ? ? ? ? ? ? ? - - 2014 "Council of Europe" - ? ? ? -` - out := ` -2014 - 60.000 60.000 860.000 860.000 860.000 340.000 511.843 360.000 - 70.000 70.000 70.000 70.000 70.000 70.000 70.000 70.000 - 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 - -# Ref: https://example.com -2015 - 0 0 0 0 0 0 0 1.072.400 - 40.000 40.000 40.000 40.000 40.000 40.000 40.000 40.000 - ? ? ? ? ? ? ? ? - -2016 - 0 0 0 0 0 0 2.339.200 0 - 35.000 35.000 35.000 35.000 35.000 35.000 35.000 35.000 - ? ? ? ? ? ? ? ? - -2017 - 2.582.395 1.515.000 2.191.421 1.103.000 1.213.000 968.800 17.000 794.588 - 22.000 22.000 22.000 22.000 22.000 22.000 22.000 22.000 - ? ? ? ? ? ? ? ? - -2018 - 2.430.000 2.550.000 1.800.000 980.000 1.014.000 890.000 0 868.000 - 20.000 20.000 20.000 20.000 20.000 20.000 20.000 20.000 - ? ? ? ? ? ? ? ? - -2019 - 2.447.000 1.727.000 2.100.000 1.610.000 1.570.000 930.000 0 1.058.310 - 15.000 15.000 15.000 15.000 15.000 15.000 15.000 15.000 - ? ? ? ? ? ? ? ? - -2020 - 0 0 0 860.000 175.000 740.000 0 1.500.000 - 12.000 12.000 12.000 12.000 12.000 12.000 12.000 12.000 - ? ? ? ? ? ? ? ? - -2021 - 200.000 700.000 0 1.400.000 1.420.000 600.000 50.000 1.474.500 - 10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2022 - 700.000 450.000 400.000 700.000 700.000 380.000 0 1.708.000 - 10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2023 - 0 0 0 0 0 0 0 2.075.250 - 10.500 10.500 10.500 10.500 10.500 10.500 10.500 10.500 - ? ? ? ? ? ? ? ? - -2024 - ? ? ? ? ? ? ? ? - ? ? ? ? ? ? ? ? - ? ? ? ? ? ? ? ? - -2014 "Council of Europe" - ? ? ? -` - - r := bytes.NewReader([]byte(in)) - w := new(bytes.Buffer) - - mfmt("-", r, w) - if w.String() != out { - t.Fatalf(`Expected w.String()="%s"; got "%s"`, out, w.String()) - } -} diff --git a/cmd/mfmt/util_test.go b/cmd/mfmt/util_test.go deleted file mode 100644 index 8366a50..0000000 --- a/cmd/mfmt/util_test.go +++ /dev/null @@ -1,35 +0,0 @@ -/* This file contains tests for utility functions used in the mfmt - binary. Tests of the actual application are in main_test.go. */ - -package main - -import "testing" - -func TestFormatInt(t *testing.T) { - for _, x := range [...]struct{ x, y string }{ - {"?", "?"}, - {"0", "0"}, - {"123", "123"}, - {"81758", "81.758"}, - {"752759237528", "752.759.237.528"}, - } { - s := formatMintage(x.x) - if s != x.y { - t.Fatalf(`Expected s="%s"; got "%s"`, x.y, s) - } - } -} - -func TestIntLen(t *testing.T) { - for _, x := range [...]struct{ x, y int }{ - {0, len("0")}, - {123, len("123")}, - {81758, len("81758")}, - {752759237528, len("752759237528")}, - } { - n := intlen(x.x) - if n != x.y { - t.Fatalf("Expected n=%d; got %d", x.y, n) - } - } -} |