Added native-code support for SKIP-CHAR-SET.
This commit is contained in:
parent
30ed9fdf0c
commit
755913967b
|
@ -431,7 +431,7 @@ scheme_value read_delim(const char *delims, char *buf, int gobble,
|
|||
|
||||
clearerr(f);
|
||||
|
||||
do {
|
||||
while( 1 ) {
|
||||
int c = getc(f);
|
||||
|
||||
if( EOF == c ) { /* Terminal case: EOF or error. */
|
||||
|
@ -454,5 +454,56 @@ scheme_value read_delim(const char *delims, char *buf, int gobble,
|
|||
|
||||
else *++cptr = c;
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
scheme_value skip_chars(const char *skipchars, scheme_value port, int *nread)
|
||||
{
|
||||
|
||||
scheme_value data = *Port_PortData(port);
|
||||
scheme_value peekc = *PortData_Peek(data);
|
||||
int fd = EXTRACT_FIXNUM(*PortData_Fd(data));
|
||||
FILE *f = fstar_cache[fd];
|
||||
int nr = 0; /* Number of skip chars read. */
|
||||
|
||||
/* This chunk of code is necessary because we have to check
|
||||
** the port's one-char pushback slot before going to the port's
|
||||
** stdio FILE*. Yech.
|
||||
*/
|
||||
if( IsChar(peekc) ) {
|
||||
char c = EXTRACT_CHAR(peekc);
|
||||
if( skipchars[c] ) { /* Is c in cset? */
|
||||
*PortData_Peek(data) = SCHFALSE;
|
||||
nr = 1;
|
||||
}
|
||||
else {
|
||||
*nread = 0;
|
||||
return SCHFALSE;
|
||||
}
|
||||
}
|
||||
|
||||
clearerr(f);
|
||||
|
||||
while( 1 ) {
|
||||
int c = getc(f);
|
||||
|
||||
if( EOF == c ) { /* Terminal case: EOF or error. */
|
||||
*nread = nr;
|
||||
return ferror(f) ? ENTER_FIXNUM(errno) : SCHFALSE;
|
||||
}
|
||||
|
||||
else if( !skipchars[c] ) { /* Terminal case: non-skip char. */
|
||||
*PortData_Peek(data) = ENTER_CHAR(c);
|
||||
*nread = nr;
|
||||
return SCHFALSE;
|
||||
}
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Why, you might ask, do I push back the final char using the Scheme port
|
||||
** instead of using ungetc()? Because ungetc() isn't guaranteed to work for
|
||||
** unbuffered ports. This is regrettable, because it causes C stdio clients
|
||||
** that are ignorant of the Scheme port machinery to miss this char. No
|
||||
** real help for it.
|
||||
*/
|
||||
|
|
|
@ -39,3 +39,5 @@ int write_fdport_substring(scheme_value buf, int start, int end, scheme_value da
|
|||
scheme_value read_delim(const char *delims, char *buf, int gobble,
|
||||
scheme_value port, int start, int end,
|
||||
int *nread);
|
||||
|
||||
scheme_value skip_chars(const char *skipchars, scheme_value port, int *nread);
|
||||
|
|
|
@ -25,3 +25,17 @@ scheme_value df_read_delim(long nargs, scheme_value *args)
|
|||
return ret1;
|
||||
}
|
||||
|
||||
scheme_value df_skip_chars(long nargs, scheme_value *args)
|
||||
{
|
||||
extern scheme_value skip_chars(const char *, scheme_value , int *);
|
||||
scheme_value ret1;
|
||||
scheme_value r1;
|
||||
int r2;
|
||||
|
||||
cig_check_nargs(3, nargs, "skip_chars");
|
||||
r1 = skip_chars(cig_string_body(args[2]), args[1], &r2);
|
||||
ret1 = r1;
|
||||
VECTOR_REF(*args,0) = ENTER_FIXNUM(r2);
|
||||
return ret1;
|
||||
}
|
||||
|
||||
|
|
|
@ -212,18 +212,35 @@
|
|||
fixnum) ; number of chars read into BUF.
|
||||
|
||||
|
||||
;;; This is probably a hell of lot slower than actually reading the string
|
||||
;;; into a buffer and throwing it away, due to the painful slowness of
|
||||
;;; the current char-at-a-time Scheme input.
|
||||
(define-foreign %skip-char-set-fdport/errno (skip_chars (string skip-set)
|
||||
(desc port))
|
||||
desc ; int => errno; #f => win.
|
||||
fixnum) ; number of chars skipped.
|
||||
|
||||
|
||||
(define (skip-char-set skip-chars . maybe-port)
|
||||
(let ((port (optional-arg maybe-port (current-input-port)))
|
||||
(cset (->char-set skip-chars)))
|
||||
|
||||
(cond ((not (input-port? port))
|
||||
(error "Illegal value -- not an input port." port))
|
||||
|
||||
;; Direct C support for Unix file ports -- zippy quick.
|
||||
((fdport? port)
|
||||
(receive (err num-read) (%skip-char-set-fdport/errno cset port)
|
||||
(if err (errno-error err skip-char-set cset port num-read)
|
||||
num-read)))
|
||||
|
||||
;; This is the code for other kinds of ports.
|
||||
;; Mighty slow -- we read each char twice (peek first, then read).
|
||||
(else (let lp ((i 0))
|
||||
(let ((c (peek-char port)))
|
||||
(cond ((and (char? c) (char-set-contains? cset c))
|
||||
(read-char port)
|
||||
(lp (+ i 1)))
|
||||
(else i))))))))
|
||||
|
||||
|
||||
(define (skip-char-set cset . maybe-port)
|
||||
(let ((port (optional-arg maybe-port (current-input-port))))
|
||||
(let lp ()
|
||||
(let ((c (peek-char port)))
|
||||
(cond ((and (char? c) (char-set-contains? cset c))
|
||||
(read-char port)
|
||||
(lp))
|
||||
(else c))))))
|
||||
|
||||
|
||||
;;; (read-line [port delim-action])
|
||||
|
|
Loading…
Reference in New Issue