;;; -*- Mode: Lisp -*- ;;; ;;; $Header: /home/gene/library/website/docsrc/sfpc/RCS/slurp-file.lisp,v 395.1 2008/04/20 17:25:50 gene Exp $ ;;; ;;; Copyright (C) 2004, 2005 Gene Michael Stover. All rights reserved. ;;; ;;; This library is free software; you can redistribute it ;;; and/or modify it under the terms of version 2.1 of the GNU ;;; Lesser General Public License as published by the Free ;;; Software Foundation. ;;; ;;; This library 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 Lesser General Public License for more ;;; details. ;;; ;;; You should have received a copy of the GNU Lesser General ;;; Public License along with this library; if not, write to the ;;; Free Software Foundation, Inc., 59 Temple Place, Suite 330, ;;; Boston, MA 02111-1307 USA ;;; (defun next-char (strm) (read-char strm nil strm)) (defconstant newline-string (format nil "~%")) (defun xread-line (strm) "Returns a string containing the next line in the file with the end-of-line character(s). On end-of-file, returns STRM." (read-line strm nil strm)) (defun slurp-stream-cons (strm) (do ((x (next-char strm) (next-char strm)) (lst () (cons x lst))) ((eq x strm) (coerce (nreverse lst) 'string)))) (defun slurp-stream-vector-push (strm) "Return a string containing the entire contents of the stream." (let ((str (make-array 1024 :element-type 'character :adjustable t :fill-pointer 0))) (do ((ch (next-char strm) (next-char strm))) ((eq ch strm) str) (vector-push-extend ch str)))) (defun slurp-stream-vector-push2 (strm) "Return a string containing the entire contents of the stream." (let ((str (make-array 1024 :element-type 'character :adjustable t :fill-pointer 0))) (do ((ch (next-char strm) (next-char strm))) ((eq ch strm) str) (vector-push-extend ch str 1024)))) (defun slurp-stream-line (strm) "Slurp the contents of the stream. Return them in a string. This turned out to be slower than the 'simple' version." (do ((str "" (concatenate 'string (concatenate 'string str line) newline-string)) (line (xread-line strm) (xread-line strm))) ((eq line strm) str))) ;;; Suggested by Shawn Betts. (defun slurp-stream-string-stream (stream) "Return the contents of file as a string." (with-output-to-string (out) (do ((line (xread-line stream) (xread-line stream))) ((eq line stream)) (write-line line out)))) (defun slurp-stream-string-stream2 (stream) "Return the contents of file as a string." (with-output-to-string (out) (do ((x (next-char stream) (next-char stream))) ((eq x stream)) (write-char x out)))) (defun slurp-file (pathname fn) (declare (type function fn)) (with-open-file (strm pathname) (funcall fn strm))) (defun timetest (slurper pathname) (declare (type symbol slurper) (type (or pathname string) pathname)) (format t "~&~A" slurper) (force-output) (let* ((start-time (get-universal-time)) (stop-time (get-universal-time)) (fn (symbol-function slurper)) (count 0)) (declare (type function fn)) ;; Side-effect of this loop is to bind values to ;; COUNT & STOP-TIME. (do () ((>= (- stop-time start-time) 10)) (incf count (length (slurp-file pathname fn))) (setq stop-time (get-universal-time))) (format t " & ~A & ~A & ~,2E \\\\ \\hline" count (- stop-time start-time) (/ count (- stop-time start-time))) (force-output)) slurper) (defun testall (pathname) (declare (type (or pathname string) pathname)) (mapc #'(lambda (symbol) (timetest symbol pathname)) (list 'slurp-stream-cons 'slurp-stream-vector-push 'slurp-stream-vector-push2 'slurp-stream-line 'slurp-stream-string-stream 'slurp-stream-string-stream2)) 'testall) (defvar *chars* "0123456789abcdefghijklmnopqrstuvwxyz") (defun random-char () (char *chars* (random (length *chars*)))) (defun make-big-file () (with-open-file (strm "big.tmp" :direction :output :if-exists :rename-and-delete :if-does-not-exist :create) (dotimes (line 800) (format strm "~&") (dotimes (char 1024) (format strm "~C" (random-char))))) 'make-big-file) ;;; --- end of file ---