Add fbuf.c
authorJanne Blomqvist <jb@gcc.gnu.org>
Thu, 15 May 2008 15:58:20 +0000 (18:58 +0300)
committerJanne Blomqvist <jb@gcc.gnu.org>
Thu, 15 May 2008 15:58:20 +0000 (18:58 +0300)
From-SVN: r135376

libgfortran/io/fbuf.c [new file with mode: 0644]

diff --git a/libgfortran/io/fbuf.c b/libgfortran/io/fbuf.c
new file mode 100644 (file)
index 0000000..ba6f710
--- /dev/null
@@ -0,0 +1,132 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+   Contributed by Janne Blomqvist
+
+This file is part of the GNU Fortran runtime library (libgfortran).
+
+Libgfortran is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+Libgfortran is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Libgfortran; see the file COPYING.  If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+
+#include "io.h"
+#include <string.h>
+#include <stdlib.h>
+
+
+void
+fbuf_init (gfc_unit * u, size_t len)
+{
+  if (len == 0)
+    len = 4096;                        /* Default size one page.  */
+
+  u->fbuf = get_mem (sizeof (fbuf));
+  u->fbuf->buf = u->fbuf->ptr = get_mem (len);
+  u->fbuf->len = len;
+  u->fbuf->act = u->fbuf->flushed = 0;
+}
+
+
+void
+fbuf_reset (gfc_unit * u)
+{
+  u->fbuf->act = u->fbuf->flushed = 0;
+  u->fbuf->ptr = u->fbuf->buf;
+}
+
+
+void
+fbuf_destroy (gfc_unit * u)
+{
+  if (u->fbuf == NULL)
+    return;
+  if (u->fbuf->buf)
+    free_mem (u->fbuf->buf);
+  free_mem (u->fbuf);
+}
+
+
+/* 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.  */
+
+char *
+fbuf_alloc (gfc_unit * u, size_t len)
+{
+  size_t newlen, ptrpos;
+  char *dest;
+  if (u->fbuf->ptr + len > u->fbuf->buf + 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;
+    }
+  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;
+  return dest;
+}
+
+
+int
+fbuf_flush (gfc_unit * u, int record_done)
+{
+  int status;
+  size_t nbytes;
+
+  if (!u->fbuf)
+    return 0;
+  if (u->fbuf->act - u->fbuf->flushed != 0)
+    {
+      if (record_done)
+        nbytes = u->fbuf->act - u->fbuf->flushed;
+      else     
+        nbytes = u->fbuf->ptr - u->fbuf->buf - u->fbuf->flushed;       
+      status = swrite (u->s, u->fbuf->buf + u->fbuf->flushed, &nbytes);
+      u->fbuf->flushed += nbytes;
+    }
+  else
+    status = 0;
+  if (record_done)
+    fbuf_reset (u);
+  return status;
+}
+
+
+int
+fbuf_seek (gfc_unit * u, gfc_offset off)
+{
+  gfc_offset pos = u->fbuf->ptr - u->fbuf->buf + off;
+  if (pos < 0)
+    return -1;
+  u->fbuf->ptr = u->fbuf->buf + pos;
+  if (pos > u->fbuf->act)
+    u->fbuf->act = pos;
+  return 0;
+}