92 lines
1.8 KiB
Go
92 lines
1.8 KiB
Go
package openname
|
|
|
|
import (
|
|
"archive/zip"
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
)
|
|
|
|
type Handler func(*Record) error
|
|
|
|
type Filter func(*Record) bool
|
|
|
|
func (f Filter) Complement() Filter {
|
|
return func(r *Record) bool {
|
|
return !f(r)
|
|
}
|
|
}
|
|
|
|
func FilterType(t string) Filter {
|
|
return func(r *Record) bool {
|
|
return r.Type == t
|
|
}
|
|
}
|
|
|
|
func FilterLocalType(t string) Filter {
|
|
return func(r *Record) bool {
|
|
return r.LocalType == t
|
|
}
|
|
}
|
|
|
|
func FilterWithinRadius(x, y, radius float64) Filter {
|
|
return func(r *Record) bool {
|
|
dx := x - r.GeomX
|
|
dy := y - r.GeomY
|
|
return math.Sqrt(dx*dx+dy*dy) <= radius
|
|
}
|
|
}
|
|
|
|
func FilterAreaGt(a float64) Filter {
|
|
return func(r *Record) bool {
|
|
return r.Area() > a
|
|
}
|
|
}
|
|
|
|
// ProcessFile reads the compressed OS Open Names data set and calls the handler for each record.
|
|
func ProcessFile(filename string, handler Handler, filters ...Filter) error {
|
|
r, err := zip.OpenReader(filename)
|
|
if err != nil {
|
|
return fmt.Errorf("error opening %s for reading: %v", filename, err)
|
|
}
|
|
defer r.Close()
|
|
|
|
for _, f := range r.File {
|
|
if !(strings.HasPrefix(f.Name, "DATA/") && strings.HasSuffix(f.Name, ".csv")) {
|
|
continue
|
|
}
|
|
rc, err := f.Open()
|
|
if err != nil {
|
|
return fmt.Errorf("error opening %s: %v", filename, err)
|
|
}
|
|
s, err := NewScanner(rc)
|
|
if err != nil {
|
|
rc.Close()
|
|
return fmt.Errorf("error reading %s: %v", f.Name, err)
|
|
}
|
|
for s.Scan() {
|
|
r := s.Record()
|
|
if wanted := applyFilters(r, filters); !wanted {
|
|
continue
|
|
}
|
|
if err := handler(r); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err = s.Err(); err != nil {
|
|
rc.Close()
|
|
return fmt.Errorf("error parsing %s: %v", f.Name, err)
|
|
}
|
|
rc.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func applyFilters(r *Record, filters []Filter) bool {
|
|
for _, f := range filters {
|
|
if !f(r) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|