diff options
author | jb <jb@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-05-16 17:42:44 +0000 |
---|---|---|
committer | jb <jb@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-05-16 17:42:44 +0000 |
commit | 8eeccdd32f5b60caa1706c406d4681128a6c1c4c (patch) | |
tree | b8d80d6121e1e056d1aaacd9882dd2ff45f168cb /libgfortran | |
parent | c4755a91ea781e9d1eabc5c743d21f556eb58342 (diff) | |
download | gcc-8eeccdd32f5b60caa1706c406d4681128a6c1c4c.tar.gz |
Part 1.1 of PR25561.
2008-05-15 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/25561
* io/io.h (struct fbuf): Change pointer to position offset.
* io/fbuf.c (fbuf_init): Reduce default size of buffer, ptr=>pos
changes.
(fbuf_reset): ptr=>pos changes.
(fbuf_alloc): If the request doesn't fit, don't waste memory by
keeping flushed bytes. ptr=>pos changes.
(fbuf_flush): ptr=>pos changes.
(fbuf_seek): Don't seek past the left tab limit, don't update active
byte count.
* io/open.c (new_unit): If RECL has been specified, used that as
initial buffer size.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@135433 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgfortran')
-rw-r--r-- | libgfortran/ChangeLog | 15 | ||||
-rw-r--r-- | libgfortran/io/fbuf.c | 86 | ||||
-rw-r--r-- | libgfortran/io/io.h | 2 | ||||
-rw-r--r-- | libgfortran/io/open.c | 8 |
4 files changed, 82 insertions, 29 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index f83115ec0ce..4d095a6ddcd 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,5 +1,20 @@ 2008-05-16 Janne Blomqvist <jb@gcc.gnu.org> + PR libfortran/25561 + * io/io.h (struct fbuf): Change pointer to position offset. + * io/fbuf.c (fbuf_init): Reduce default size of buffer, ptr=>pos + changes. + (fbuf_reset): ptr=>pos changes. + (fbuf_alloc): If the request doesn't fit, don't waste memory by + keeping flushed bytes. ptr=>pos changes. + (fbuf_flush): ptr=>pos changes. + (fbuf_seek): Don't seek past the left tab limit, don't update active + byte count. + * io/open.c (new_unit): If RECL has been specified, used that as + initial buffer size. + +2008-05-16 Janne Blomqvist <jb@gcc.gnu.org> + PR libfortran/35632 * io/open.c (new_unit): Set stream position to correct value. diff --git a/libgfortran/io/fbuf.c b/libgfortran/io/fbuf.c index e34fc75f937..a0d033bf875 100644 --- a/libgfortran/io/fbuf.c +++ b/libgfortran/io/fbuf.c @@ -37,20 +37,19 @@ void fbuf_init (gfc_unit * u, size_t len) { if (len == 0) - len = 4096; /* Default size one page. */ + len = 512; /* Default size. */ u->fbuf = get_mem (sizeof (fbuf)); - u->fbuf->buf = u->fbuf->ptr = get_mem (len); + u->fbuf->buf = get_mem (len); u->fbuf->len = len; - u->fbuf->act = u->fbuf->flushed = 0; + u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0; } void fbuf_reset (gfc_unit * u) { - u->fbuf->act = u->fbuf->flushed = 0; - u->fbuf->ptr = u->fbuf->buf; + u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0; } @@ -67,33 +66,65 @@ fbuf_destroy (gfc_unit * u) /* Return a pointer to the current position in the buffer, and increase the pointer by len. Makes sure that the buffer is big enough, - reallocating if necessary. */ + reallocating if necessary. If the buffer is not big enough, there are + three cases to consider: + 1. If we haven't flushed anything, realloc + 2. If we have flushed enough that by discarding the flushed bytes + the request fits into the buffer, do that. + 3. Else allocate a new buffer, memcpy unflushed active bytes from old + buffer. */ char * fbuf_alloc (gfc_unit * u, size_t len) { - size_t newlen, ptrpos; + size_t newlen; char *dest; - if (u->fbuf->ptr + len > u->fbuf->buf + u->fbuf->len) + if (u->fbuf->pos + len > u->fbuf->len) { - /* Round up to nearest multiple of the current buffer length. */ - ptrpos = u->fbuf->ptr - u->fbuf->buf; - newlen = ((ptrpos + len) / u->fbuf->len + 1) * u->fbuf->len; - dest = realloc (u->fbuf->buf, newlen); - if (dest == NULL) - return NULL; - u->fbuf->buf = dest; - u->fbuf->ptr = dest + ptrpos; - u->fbuf->len = newlen; + if (u->fbuf->flushed == 0) + { + /* Round up to nearest multiple of the current buffer length. */ + newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len; + dest = realloc (u->fbuf->buf, newlen); + if (dest == NULL) + return NULL; + u->fbuf->buf = dest; + u->fbuf->len = newlen; + } + else if (u->fbuf->act - u->fbuf->flushed + len < u->fbuf->len) + { + memmove (u->fbuf->buf, u->fbuf->buf + u->fbuf->flushed, + u->fbuf->act - u->fbuf->flushed); + u->fbuf->act -= u->fbuf->flushed; + u->fbuf->pos -= u->fbuf->flushed; + u->fbuf->flushed = 0; + } + else + { + /* Most general case, flushed != 0, request doesn't fit. */ + newlen = ((u->fbuf->pos - u->fbuf->flushed + len) + / u->fbuf->len + 1) * u->fbuf->len; + dest = get_mem (newlen); + memcpy (dest, u->fbuf->buf + u->fbuf->flushed, + u->fbuf->act - u->fbuf->flushed); + u->fbuf->act -= u->fbuf->flushed; + u->fbuf->pos -= u->fbuf->flushed; + u->fbuf->flushed = 0; + u->fbuf->buf = dest; + u->fbuf->len = newlen; + } } - dest = u->fbuf->ptr; - u->fbuf->ptr += len; - if ((size_t) (u->fbuf->ptr - u->fbuf->buf) > u->fbuf->act) - u->fbuf->act = u->fbuf->ptr - u->fbuf->buf; + + dest = u->fbuf->buf + u->fbuf->pos; + u->fbuf->pos += len; + if (u->fbuf->pos > u->fbuf->act) + u->fbuf->act = u->fbuf->pos; return dest; } + + int fbuf_flush (gfc_unit * u, int record_done) { @@ -107,7 +138,7 @@ fbuf_flush (gfc_unit * u, int record_done) if (record_done) nbytes = u->fbuf->act - u->fbuf->flushed; else - nbytes = u->fbuf->ptr - u->fbuf->buf - u->fbuf->flushed; + nbytes = u->fbuf->pos - u->fbuf->flushed; status = swrite (u->s, u->fbuf->buf + u->fbuf->flushed, &nbytes); u->fbuf->flushed += nbytes; } @@ -122,11 +153,12 @@ fbuf_flush (gfc_unit * u, int record_done) int fbuf_seek (gfc_unit * u, gfc_offset off) { - gfc_offset pos = u->fbuf->ptr - u->fbuf->buf + off; - if (pos < 0) + gfc_offset pos = u->fbuf->pos + off; + /* Moving to the left past the flushed marked would imply moving past + the left tab limit, which is never allowed. So return error if + that is attempted. */ + if (pos < u->fbuf->flushed) return -1; - u->fbuf->ptr = u->fbuf->buf + pos; - if (pos > (gfc_offset) u->fbuf->act) - u->fbuf->act = pos; + u->fbuf->pos = pos; return 0; } diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h index e554d8cccbc..7f9f38f80c0 100644 --- a/libgfortran/io/io.h +++ b/libgfortran/io/io.h @@ -537,7 +537,7 @@ typedef struct fbuf size_t len; /* Length of buffer. */ size_t act; /* Active bytes in buffer. */ size_t flushed; /* Flushed bytes from beginning of buffer. */ - char *ptr; /* Current position in buffer. */ + size_t pos; /* Current position in buffer. */ } fbuf; diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c index d95eccbc12d..84575f7bb01 100644 --- a/libgfortran/io/open.c +++ b/libgfortran/io/open.c @@ -628,9 +628,15 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags) free_mem (opp->file); if (flags->form == FORM_FORMATTED && (flags->action != ACTION_READ)) - fbuf_init (u, 0); + { + if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN)) + fbuf_init (u, u->recl); + else + fbuf_init (u, 0); + } else u->fbuf = NULL; + return u; |