git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / file / nbio / nbio_orbis.c
diff --git a/deps/libretro-common/file/nbio/nbio_orbis.c b/deps/libretro-common/file/nbio/nbio_orbis.c
new file mode 100644 (file)
index 0000000..7f06763
--- /dev/null
@@ -0,0 +1,231 @@
+/* Copyright  (C) 2010-2020 The RetroArch team
+ *
+ * ---------------------------------------------------------------------------------------
+ * The following license statement only applies to this file (nbio_orbis.c).
+ * ---------------------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge,
+ * to any person obtaining a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <file/nbio.h>
+
+#if defined(ORBIS)
+#include <stdio.h>
+#include <stdlib.h>
+#include <orbisFile.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+
+struct nbio_orbis_t
+{
+   void* data;
+   size_t progress;
+   size_t len;
+   int fd;
+   unsigned int mode;
+   /*
+    * possible values:
+    * NBIO_READ, NBIO_WRITE - obvious
+    * -1 - currently doing nothing
+    * -2 - the pointer was reallocated since the last operation
+    */
+   signed char op;
+};
+
+static void *nbio_orbis_open(const char * filename, unsigned int mode)
+{
+   static const int o_flags[]  =   { O_RDONLY, O_RDWR | O_CREAT | O_TRUNC,
+      O_RDWR, O_RDONLY, O_RDWR | O_CREAT | O_TRUNC };
+   void *buf                   = NULL;
+   struct nbio_orbis_t* handle = NULL;
+   size_t len                  = 0;
+   int fd                      = orbisOpen(filename, o_flags[mode], 0644);
+
+   if (fd < 0)
+      return NULL;
+   handle                = (struct nbio_orbis_t*)malloc(sizeof(struct nbio_orbis_t));
+
+   if (!handle)
+      goto error;
+
+   handle->fd             = fd;
+
+   switch (mode)
+   {
+      case NBIO_WRITE:
+      case BIO_WRITE:
+         break;
+      default:
+         len=orbisLseek(handle->fd, 0, SEEK_END);
+         orbisLseek(handle->fd, 0, SEEK_SET);
+         break;
+   }
+
+   handle->mode          = mode;
+
+   if (len)
+      buf                = malloc(len);
+
+   if (len && !buf)
+      goto error;
+
+   handle->data          = buf;
+   handle->len           = len;
+   handle->progress      = handle->len;
+   handle->op            = -2;
+
+   return handle;
+
+error:
+   if (handle)
+      free(handle);
+   orbisClose(fd);
+   return NULL;
+}
+
+static void nbio_orbis_begin_read(void *data)
+{
+
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return;
+
+   if (handle->op >= 0)
+      return;
+
+   orbisLseek(handle->fd, 0, SEEK_SET);
+
+   handle->op       = NBIO_READ;
+   handle->progress = 0;
+}
+
+static void nbio_orbis_begin_write(void *data)
+{
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return;
+
+   if (handle->op >= 0)
+      return;
+
+   orbisLseek(handle->fd, 0, SEEK_SET);
+   handle->op = NBIO_WRITE;
+   handle->progress = 0;
+}
+
+static bool nbio_orbis_iterate(void *data)
+{
+   size_t amount               = 65536;
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+
+   if (!handle)
+      return false;
+
+   if (amount > handle->len - handle->progress)
+      amount = handle->len - handle->progress;
+
+   switch (handle->op)
+   {
+      case NBIO_READ:
+         if (handle->mode == BIO_READ)
+            amount = handle->len;
+         break;
+      case NBIO_WRITE:
+         if (handle->mode == BIO_WRITE)
+         {
+            size_t written = 0;
+            amount = handle->len;
+            written = orbisWrite(handle->fd, (char*)handle->data, amount);
+
+            if (written != amount)
+               return false;
+         }
+         break;
+   }
+
+   handle->progress += amount;
+
+   if (handle->progress == handle->len)
+      handle->op = -1;
+   return (handle->op < 0);
+}
+
+static void nbio_orbis_resize(void *data, size_t len)
+{
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return;
+
+   if (handle->op >= 0)
+      return;
+   if (len < handle->len)
+      return;
+
+   handle->len      = len;
+   handle->data     = realloc(handle->data, handle->len);
+   handle->op       = -1;
+   handle->progress = handle->len;
+}
+
+static void *nbio_orbis_get_ptr(void *data, size_t* len)
+{
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return NULL;
+   if (len)
+      *len = handle->len;
+   if (handle->op == -1)
+      return handle->data;
+   return NULL;
+}
+
+static void nbio_orbis_cancel(void *data)
+{
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return;
+   handle->op = -1;
+   handle->progress = handle->len;
+}
+
+static void nbio_orbis_free(void *data)
+{
+   struct nbio_orbis_t *handle = (struct nbio_orbis_t*)data;
+   if (!handle)
+      return;
+
+   if (handle->op >= 0)
+      return;
+
+   orbisClose(handle->fd);
+   free(handle->data);
+
+   handle->data = NULL;
+   free(handle);
+}
+
+nbio_intf_t nbio_orbis = {
+   nbio_orbis_open,
+   nbio_orbis_begin_read,
+   nbio_orbis_begin_write,
+   nbio_orbis_iterate,
+   nbio_orbis_resize,
+   nbio_orbis_get_ptr,
+   nbio_orbis_cancel,
+   nbio_orbis_free,
+   "nbio_orbis",
+};
+#endif