Skip to content

Instantly share code, notes, and snippets.

@liquidz
Created December 1, 2008 02:47
Show Gist options
  • Select an option

  • Save liquidz/30599 to your computer and use it in GitHub Desktop.

Select an option

Save liquidz/30599 to your computer and use it in GitHub Desktop.
(define-module isbn
(use simply)
(export get-isbn-type isbn10->isbn13 isbn13->isbn10)
)
(select-module isbn)
#| *-- PUBLIC --*
|#
; =get-isbn-type
; --------------------------------------------------
(define (get-isbn-type isbn-str)
(let* ((isbn (isbn-encode isbn-str))
(len (string-length isbn))
)
(cond
[(= len 10)
(if (and (#/^[0123457][0-9]{8}[0-9Xx]$/ isbn) (check-isbn10 isbn))
'isbn10 '()
)
]
[(= len 13)
(if (and (#/^(978|979)[0-9]{10}$/ isbn) (check-isbn13 isbn))
'isbn13 '()
)
]
[else '()]
)
)
)
; =isbn10->isbn13
; --------------------------------------------------
(define (isbn10->isbn13 isbn-str)
(let1 isbn (isbn-encode isbn-str)
(cond
[(eq? 'isbn10 (get-isbn-type isbn))
(let* ((tmp (string-append "978" (substring isbn 0 9)))
(check-digit (get-check-digit-for-isbn13 tmp))
)
(string-append tmp (number->string check-digit))
)
]
[else isbn]
)
)
)
; =isbn13->isbn10
; --------------------------------------------------
(define (isbn13->isbn10 isbn-str)
(let1 isbn (isbn-encode isbn-str)
(cond
[(eq? 'isbn13 (get-isbn-type isbn))
(let* ((tmp (substring isbn 3 12))
(check-digit (get-check-digit-for-isbn10 tmp))
)
(string-append tmp (case check-digit
[(10) "X"]
[(11) 0]
[else (number->string check-digit)]
)
)
)
]
[else isbn]
)
)
)
#| *-- PRIVATE --*
|#
; =isbn-encode
; --------------------------------------------------
(define (isbn-encode isbn)
(regexp-replace-all* isbn #/[\s\-]/ "")
)
; =get-check-digit-for-isbn10
; --------------------------------------------------
(define (get-check-digit-for-isbn10 isbn)
(let loop((ls (string->list (substring isbn 0 9)))
(index 0)
(total 0)
)
(cond
[(null? ls) (- 11 (modulo total 11))]
[else
(loop (cdr ls) (++ index) (+ total (* (- 10 index) (digit->integer (car ls)))))
]
)
)
)
; =get-check-digit-for-isbn13
; --------------------------------------------------
(define (get-check-digit-for-isbn13 isbn)
(let loop((ls (string->list (substring isbn 0 12)))
(index 0)
(total 0)
)
(cond
[(null? ls)
(let* ((res (- 10 (modulo total 10)))
(res-str (number->string res))
)
(if (char=? #\0 (string-ref res-str (- (string-length res-str) 1))) 0 res)
)
]
[else
(loop (cdr ls) (++ index) (+ total (* (digit->integer (car ls)) (if (= 0 (modulo index 2)) 1 3))))
]
)
)
)
; =check=isbn10
; --------------------------------------------------
(define (check-isbn10 isbn)
(let* ((c (char-downcase (string-ref isbn 9)))
(check-digit (if (char=? #\x c) 10 (digit->integer c)))
)
(values
(= check-digit (get-check-digit-for-isbn10 isbn))
check-digit
)
)
)
; =check-isbn13
; --------------------------------------------------
(define (check-isbn13 isbn)
(let1 check-digit (digit->integer (string-ref isbn 12))
(values
(= check-digit (get-check-digit-for-isbn13 isbn))
check-digit
)
)
)
(provide "isbn")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment