Created
December 1, 2008 02:47
-
-
Save liquidz/30599 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (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