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.

From-SVN: r135433
This commit is contained in:
Janne Blomqvist 2008-05-16 20:42:44 +03:00
parent 65686652e4
commit 8947fd62fa
4 changed files with 82 additions and 29 deletions

View File

@ -1,3 +1,18 @@
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> 2008-05-16 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/35632 PR libfortran/35632

View File

@ -37,20 +37,19 @@ void
fbuf_init (gfc_unit * u, size_t len) fbuf_init (gfc_unit * u, size_t len)
{ {
if (len == 0) if (len == 0)
len = 4096; /* Default size one page. */ len = 512; /* Default size. */
u->fbuf = get_mem (sizeof (fbuf)); 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->len = len;
u->fbuf->act = u->fbuf->flushed = 0; u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0;
} }
void void
fbuf_reset (gfc_unit * u) fbuf_reset (gfc_unit * u)
{ {
u->fbuf->act = u->fbuf->flushed = 0; u->fbuf->act = u->fbuf->flushed = u->fbuf->pos = 0;
u->fbuf->ptr = u->fbuf->buf;
} }
@ -67,33 +66,65 @@ fbuf_destroy (gfc_unit * u)
/* Return a pointer to the current position in the buffer, and increase /* Return a pointer to the current position in the buffer, and increase
the pointer by len. Makes sure that the buffer is big enough, 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 * char *
fbuf_alloc (gfc_unit * u, size_t len) fbuf_alloc (gfc_unit * u, size_t len)
{ {
size_t newlen, ptrpos; size_t newlen;
char *dest; 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. */ if (u->fbuf->flushed == 0)
ptrpos = u->fbuf->ptr - u->fbuf->buf; {
newlen = ((ptrpos + len) / u->fbuf->len + 1) * u->fbuf->len; /* Round up to nearest multiple of the current buffer length. */
dest = realloc (u->fbuf->buf, newlen); newlen = ((u->fbuf->pos + len) / u->fbuf->len + 1) * u->fbuf->len;
if (dest == NULL) dest = realloc (u->fbuf->buf, newlen);
return NULL; if (dest == NULL)
u->fbuf->buf = dest; return NULL;
u->fbuf->ptr = dest + ptrpos; u->fbuf->buf = dest;
u->fbuf->len = newlen; 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; dest = u->fbuf->buf + u->fbuf->pos;
if ((size_t) (u->fbuf->ptr - u->fbuf->buf) > u->fbuf->act) u->fbuf->pos += len;
u->fbuf->act = u->fbuf->ptr - u->fbuf->buf; if (u->fbuf->pos > u->fbuf->act)
u->fbuf->act = u->fbuf->pos;
return dest; return dest;
} }
int int
fbuf_flush (gfc_unit * u, int record_done) fbuf_flush (gfc_unit * u, int record_done)
{ {
@ -107,7 +138,7 @@ fbuf_flush (gfc_unit * u, int record_done)
if (record_done) if (record_done)
nbytes = u->fbuf->act - u->fbuf->flushed; nbytes = u->fbuf->act - u->fbuf->flushed;
else 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); status = swrite (u->s, u->fbuf->buf + u->fbuf->flushed, &nbytes);
u->fbuf->flushed += nbytes; u->fbuf->flushed += nbytes;
} }
@ -122,11 +153,12 @@ fbuf_flush (gfc_unit * u, int record_done)
int int
fbuf_seek (gfc_unit * u, gfc_offset off) fbuf_seek (gfc_unit * u, gfc_offset off)
{ {
gfc_offset pos = u->fbuf->ptr - u->fbuf->buf + off; gfc_offset pos = u->fbuf->pos + off;
if (pos < 0) /* 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; return -1;
u->fbuf->ptr = u->fbuf->buf + pos; u->fbuf->pos = pos;
if (pos > (gfc_offset) u->fbuf->act)
u->fbuf->act = pos;
return 0; return 0;
} }

View File

@ -537,7 +537,7 @@ typedef struct fbuf
size_t len; /* Length of buffer. */ size_t len; /* Length of buffer. */
size_t act; /* Active bytes in buffer. */ size_t act; /* Active bytes in buffer. */
size_t flushed; /* Flushed bytes from beginning of buffer. */ size_t flushed; /* Flushed bytes from beginning of buffer. */
char *ptr; /* Current position in buffer. */ size_t pos; /* Current position in buffer. */
} }
fbuf; fbuf;

View File

@ -628,11 +628,17 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
free_mem (opp->file); free_mem (opp->file);
if (flags->form == FORM_FORMATTED && (flags->action != ACTION_READ)) 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 else
u->fbuf = NULL; u->fbuf = NULL;
return u; return u;
cleanup: cleanup: