+/*
+ * 2ooM: The Master of Orion II Reverse Engineering Project
+ * Default file operations structures for liblbx.
+ * Copyright (C) 2010 Nick Bowler
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <stdio.h>
+
+#include "misc.h"
+#include "lbx.h"
+
+/* Default I/O operations for ordinary files. */
+static size_t file_read(void *buf, size_t size, void *handle)
+{
+ return fread(buf, 1, size, (FILE *)handle);
+}
+
+static int file_seek(void *handle, long offset, int whence)
+{
+ return fseek((FILE *)handle, offset, whence);
+}
+
+static long file_tell(void *handle)
+{
+ return ftell((FILE *)handle);
+}
+
+static int file_eof(void *handle)
+{
+ return feof((FILE *)handle);
+}
+
+const struct lbx_file_ops lbx_default_fops = {
+ .read = file_read,
+ .seek = file_seek,
+ .tell = file_tell,
+ .eof = file_eof,
+};
+
+/* Read function for pipes that tracks the number of bytes read. */
+static size_t pipe_read(void *buf, size_t size, void *handle)
+{
+ struct lbx_pipe_state *state = handle;
+ size_t rc;
+
+ rc = fread(buf, 1, size, state->f);
+ state->offset += rc;
+ return rc;
+}
+
+/* Seek function for pipes that reads data into the void. */
+static int pipe_seek(void *handle, long offset, int whence)
+{
+ struct lbx_pipe_state *state = handle;
+ long distance;
+
+ distance = offset - state->offset;
+ if (distance < 0)
+ return -1;
+
+ while (distance > 0) {
+ static unsigned char oblivion[1024];
+ size_t rc, amount = MIN(sizeof oblivion, distance);
+
+ rc = pipe_read(oblivion, amount, handle);
+ distance -= rc;
+
+ if (rc < amount)
+ return -1;
+ }
+
+ return 0;
+}
+
+static long pipe_tell(void *handle)
+{
+ struct lbx_pipe_state *state = handle;
+
+ return state->offset;
+}
+
+static int pipe_eof(void *handle)
+{
+ struct lbx_pipe_state *state = handle;
+
+ return feof(state->f);
+}
+
+const struct lbx_file_ops lbx_pipe_fops = {
+ .read = pipe_read,
+ .seek = pipe_seek,
+ .tell = pipe_tell,
+ .eof = pipe_eof,
+};