Skip to content

Commit

Permalink
add isbn package WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
boutros committed Jul 17, 2017
1 parent 61c42c1 commit 6630743
Show file tree
Hide file tree
Showing 4 changed files with 1,175 additions and 0 deletions.
88 changes: 88 additions & 0 deletions isbn/cmd/gen_ranges.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package main

import (
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"strconv"
"strings"
)

// +build ignore

const url = "http://www.isbn-international.org/export_rangemessage.xml"
const header = `package isbn
type Range struct {
Prefix string
Agency string
Ranges [][2]string
}
var Ranges = map[string]Range{`
const footer = `
}
`

type Group struct {
Prefix string
Agency string
Rules []Rule `xml:">Rule"`
}

type Rule struct {
Range string
Length string
}

func main() {
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()

dec := xml.NewDecoder(res.Body)

var groups []Group
for {
t, err := dec.Token()
if err != nil && err != io.EOF {
log.Fatal(err)
}
if t == nil {
break
}
switch elem := t.(type) {
case xml.StartElement:
if elem.Name.Local == "Group" {
var g Group
dec.DecodeElement(&g, &elem)
groups = append(groups, g)
}
}
}

fmt.Println(header)
for _, g := range groups {
fmt.Printf("%q: Range{\n", g.Prefix[4:])
fmt.Printf("\tPrefix: %q,\n", g.Prefix[:3])
fmt.Printf("\tAgency: %q,\n", g.Agency)
fmt.Printf("\tRanges: [][2]string{")
for _, r := range g.Rules {
if r.Length == "0" {
continue
}
l, _ := strconv.Atoi(r.Length)
ranges := strings.Split(r.Range, "-")
fmt.Printf("{%q,%q},", ranges[0][:l], ranges[1][:l])
}
fmt.Printf("\t},")
fmt.Printf("\t},\n")

}
fmt.Println(footer)
}
46 changes: 46 additions & 0 deletions isbn/isbn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package isbn

import "fmt"

type ISBN [13]byte

func isDigit(c rune) bool {
return c >= '0' && c <= '9'
}

func Parse(s string) (ISBN, error) {
var n ISBN
i := 0
for _, c := range s {
if c == '-' {
continue
}
if isDigit(c) {
n[i] = uint8(c - '0')
i++
if i == 11 {
break
}
}
if i == 10 && c == 'x' || c == 'X' {
n[9] = 10
break
}
}
if i != 10 && i != 13 {
return n, fmt.Errorf("incorrect number of digits: %d != 10|13", i)
}
return ISBN{}, nil
}

func (n ISBN) Is10() bool {
return n[11] == 0 &&
n[10] == 0 &&
n[9] == 0
}

func (n ISBN) Is13() bool { return !n.Is10() }

func (n ISBN) Hyphenate() string {
return "TODO"
}
115 changes: 115 additions & 0 deletions isbn/isbn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package isbn

import "testing"

// Verify that valid ISBNs are parsed and can be pretty-printed,
// while invalid ISBNs fails to parse with an error.
func TestParseAndPrintISBNs(t *testing.T) {
tests := []struct {
in string
want string
err string
}{
{"", "", "incorrect number of digits: 0 != 10|13"},
{"1234", "", "incorrect number of digits: 4 != 10|13"},
{"9986163293", "9986-16-329-3", ""},
{"9963645062", "9963-645-06-2", ""},
{"9879818423", "987-98184-2-3", ""},
{"9864171917", "986-417-191-7", ""},
{"9844580897", "984-458-089-7", ""},
{"9835201579", "983-52-0157-9", ""},
{"9823010013", "982-301-001-3", ""},
{"9813018399", "981-3018-39-9", ""},
{"9800101942", "980-01-0194-2", ""},
{"9795534831", "979-553-483-1", ""},
{"9789996520471", "978-99965-2-047-1", ""},
{"9789993710561", "978-99937-1-056-1", ""},
{"9789934015960", "978-9934015960", ""},
{"9789933101473", "978-9933101473", ""},
{"9789930943106", "978-9930943106", ""},
{"9789929801646", "978-9929801646", ""},
{"9789928400529", "978-9928400529", ""},
{"9789880038273", "978-988-00-3827-3", ""},
{"9789609962674", "978-960-99626-7-4", ""},
{"9786180207897", "978-618-02-0789-7", ""},
{"9786155014994", "978-615-5014-99-4", ""},
{"9786144040188", "978-614-404-018-8", ""},
{"9786124516597", "978-612-45165-9-7", ""},
{"9786082030234", "978-608-203-023-4", ""},
{"9786074550351", "978-607-455-035-1", ""},
{"9786068126357", "978-606-8126-35-7", ""},
{"9786035000451", "978-603-500-045-1", ""},
{"9786028328227", "978-602-8328-22-7", ""},
{"9786017151133", "978-601-7151-13-3", ""},
{"9786001191251", "978-600-119-125-1", ""},
{"9783718622", "978-37186-2-2", ""},
{"9777345208", "977-734-520-8", ""},
{"9766401403", "976-640-140-3", ""},
{"9752933815", "975-293-381-5", ""},
{"9748585476", "974-85854-7-6", ""},
{"9734301799", "973-43-0179-9", ""},
{"9723702746", "972-37-0274-6", ""},
{"9718845100", "971-8845-10-0", ""},
{"9702002427", "970-20-0242-7", ""},
{"9693520203", "969-35-2020-3", ""},
{"9686031022", "968-6031-02-2", ""},
{"9679787532", "967-978-753-2", ""},
{"966954405X", "966-95440-5-X", ""},
{"9653590022", "965-359-002-2", ""},
{"9646194702", "964-6194-70-2", ""},
{"9637971513", "963-7971-51-3", ""},
{"9620401956", "962-04-0195-6", ""},
{"9616403230", "961-6403-23-0", ""},
{"9591003633", "959-10-0363-3", ""},
{"958046278X", "958-04-6278-X", ""},
{"9570174293", "957-01-7429-3", ""},
{"9567291489", "956-7291-48-9", ""},
{"955203051X", "955-20-3051-X", ""},
{"954430603X", "954-430-603-X", ""},
{"9531571058", "953-157-105-8", ""},
{"9524712946", "952-471-294-6", ""},
{"9510113697", "951-0-11369-7", ""},
{"9500404427", "950-04-0442-7", ""},
{"9350252147", "93-5025-214-7", ""},
{"9267103709", "92-67-10370-9", ""},
{"9118116922", "91-1-811692-2", ""},
{"9056911872", "90-5691-187-2", ""},
{"8804473282", "88-04-47328-2", ""},
{"8759522771", "87-595-2277-1", ""},
{"8634108465", "86-341-0846-5", ""},
{"8575310151", "85-7531-015-1", ""},
{"8486546087", "84-86546-08-7", ""},
{"8308015875", "83-08-01587-5", ""},
{"8253009836", "82-530-0983-6", ""},
{"8172153996", "81-7215-399-6", ""},
{"8085983443", "80-85983-44-3", ""},
{"7301102992", "7-301-10299-2", ""},
{"6090112488", "609-01-1248-8", ""},
{"6053840572", "605-384-057-2", ""},
{"6046945100", "604-69-4510-0", ""},
{"5852700010", "5-85270-001-0", ""},
{"4198301271", "4-19-830127-1", ""},
{"3796519008", "3-7965-1900-8", ""},
{"2226052577", "2-226-05257-7", ""},
{"1581820089", "1-58182-008-9", ""},
{"0330284983", "0-330-28498-3", ""},
}

for _, test := range tests {
n, err := Parse(test.in)
if err != nil && err.Error() != test.err {
t.Errorf("Parse(%q) => %v; want %v", test.in, err, test.err)
continue
}
if err == nil && test.err != "" {
t.Errorf("Parse(%q) => %v; want %v", test.in, n, test.err)
continue
}
if test.err != "" {
continue
}
if got := n.Hyphenate(); got != test.want {
t.Errorf("Hypenate(%q) => %v; want %v", test.in, got, test.want)
}
}
}
Loading

0 comments on commit 6630743

Please sign in to comment.