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);
|
clearerr(f);
|
||||||
|
|
||||||
do {
|
while( 1 ) {
|
||||||
int c = getc(f);
|
int c = getc(f);
|
||||||
|
|
||||||
if( EOF == c ) { /* Terminal case: EOF or error. */
|
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;
|
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 read_delim(const char *delims, char *buf, int gobble,
|
||||||
scheme_value port, int start, int end,
|
scheme_value port, int start, int end,
|
||||||
int *nread);
|
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;
|
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.
|
fixnum) ; number of chars read into BUF.
|
||||||
|
|
||||||
|
|
||||||
;;; This is probably a hell of lot slower than actually reading the string
|
(define-foreign %skip-char-set-fdport/errno (skip_chars (string skip-set)
|
||||||
;;; into a buffer and throwing it away, due to the painful slowness of
|
(desc port))
|
||||||
;;; the current char-at-a-time Scheme input.
|
desc ; int => errno; #f => win.
|
||||||
|
fixnum) ; number of chars skipped.
|
||||||
|
|
||||||
(define (skip-char-set cset . maybe-port)
|
|
||||||
(let ((port (optional-arg maybe-port (current-input-port))))
|
(define (skip-char-set skip-chars . maybe-port)
|
||||||
(let lp ()
|
(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)))
|
(let ((c (peek-char port)))
|
||||||
(cond ((and (char? c) (char-set-contains? cset c))
|
(cond ((and (char? c) (char-set-contains? cset c))
|
||||||
(read-char port)
|
(read-char port)
|
||||||
(lp))
|
(lp (+ i 1)))
|
||||||
(else c))))))
|
(else i))))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; (read-line [port delim-action])
|
;;; (read-line [port delim-action])
|
||||||
|
|
Loading…
Reference in New Issue