#| rep.net.domain-name -- domain name utility functions $Id: domain-name.jl,v 1.2 2000/09/19 20:00:16 john Exp $ Copyright (C) 2000 John Harper This file is part of librep. librep is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. librep is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with librep; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |# (define-structure rep.net.domain-name (export domain-parts domain-above domain-above-p domain-below-p domain-equal-p map-domains map-domains-downwards) (open rep rep.regexp) (define (domain-parts domain) "Return the list of domain components that the string DOMAIN consists of." (string-split "\\." domain)) (define (domain-above domain) "Return the name of parent domain of the string DOMAIN." (and (string-match "\\." domain) (substring domain (match-end)))) ;; Returns +ve if D1 is a superset of D2, -ve if D1 is a subset of D2, ;; zero if (= D1 D2), or false if D1 and D2 aren't similar (define (compare-domains d1 d2) (let loop ((p1 (domain-parts d1)) (p2 (domain-parts d2)) (ret 0)) (cond ((> (length p1) (length p2)) (loop (cdr p1) p2 (1+ ret))) ((< (length p1) (length p2)) (loop p1 (cdr p2) (1- ret))) ((and p1 p2) (if (string= (car p1) (car p2)) (loop (cdr p1) (cdr p2) ret) nil)) (t ret)))) (define (domain-above-p d1 d2) "Return true if domain name D1 is `above' domain name D2." (let ((value (compare-domains d1 d2))) (and value (< value 0)))) (define (domain-below-p d1 d2) "Return true if domain name D1 is `below' domain name D2." (let ((value (compare-domains d1 d2))) (and value (> value 0)))) (define (domain-equal-p d1 d2) "Return true if the domain names D1 and D2 are the same" (string= d1 d2)) (define (map-domains fun domain) "Call (FUN NAME) for each sub-domain of DOMAIN (starting with DOMAIN)." (when domain (fun domain) (map-domains fun (domain-above domain)))) (define (map-domains-downwards fun domain) "Call (FUN NAME) for each sub-domain of DOMAIN (ending with DOMAIN)." (let ((parts (nreverse (domain-parts domain)))) (let loop ((current (car parts)) (todo (cdr parts))) (fun current) (when todo (loop (concat (car todo) ?. current) (cdr todo)))))))