Subject: Re: string assembly in lisp?? help??
From: Erik Naggum <erik@naggum.no>
Date: 1999/03/19
Newsgroups: comp.lang.lisp
Message-ID: <3130830258347173@naggum.no>

* Lars Marius Garshol <larsga@ifi.uio.no>
| Is there a standardized way to do this?  It really would be nice to have
| extensible strings for this, since in my case I'm doing this in an OMG
| IDL parser (which preferably shouldn't barf on long names).

  from the description of the system class STRING in ANSI X3.226:

A string is a specialized vector whose elements are of type CHARACTER or a
subtype of type CHARACTER.  When used as a type specifier for object
creation, STRING means (VECTOR CHARACTER).

  so CHARACTER is already standard.  there is no need to use BASE-CHAR, and
  no need to worry about portability problems.

  in my view, however, the actual task at hand is to extract a subsequence
  of a stream's input buffer.  I do this with a mark in the stream and
  avoid copying until absolutely necessary.  this, however, requires access
  to and meddling with stream internals.

  a less "internal" solution is to use WITH-OUTPUT-TO-STRING and simply
  write characters to it until the terminating condition is met, to wit:

(with-output-to-string (name)
  (stream-copy <input-stream> name <condition>))
=> <string>

  the function STREAM-COPY could be defined like this:

(defun stream-copy (input output &key (count -1) end-test filter transform)
  "Copy characters from INPUT to OUTPUT.
COUNT is the maximum number of characters to copy.
END-TEST if specified, causes termination when true for a character.
FILTER if specified, causes only characters for which it is true to be copied.
TRANSFORM if specified, causes its value to be copied instead of character."
  (loop
    (when (zerop count)
      (return))
    (let ((character (read-char input nil :eof)))
      (when (eq :eof character)
	(return))
      (when (and end-test (funcall end-test character))
	(unread-char character input)
	(return))
      (when (or (null filter) (funcall filter character))
	(write-char (if transform
		      (funcall transform character)
		      character)
		    output)))
    (decf count)))

#:Erik