changeset 4483:a926f8995d0b

sample for OrthancPluginRegisterStorageArea2()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 28 Jan 2021 16:59:40 +0100
parents 8efeaba1b7f9
children 64f06e7d5fc7
files OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Plugins/Samples/StorageArea/Plugin.cpp
diffstat 3 files changed, 146 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Jan 28 15:54:30 2021 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Thu Jan 28 16:59:40 2021 +0100
@@ -264,6 +264,11 @@
         remove_(remove),
         errorDictionary_(errorDictionary)
       {
+        if (create_ == NULL ||
+            remove_ == NULL)
+        {
+          throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement all the required primitives");
+        }
       }
 
       virtual void Create(const std::string& uuid,
@@ -317,6 +322,10 @@
         read_(callbacks.read),
         free_(callbacks.free)
       {
+        if (read_ == NULL)
+        {
+          throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"Read\" primitive");
+        }
       }
 
       virtual void Read(std::string& content,
@@ -369,6 +378,10 @@
         readWhole_(callbacks.readWhole),
         readRange_(callbacks.readRange)
       {
+        if (readWhole_ == NULL)
+        {
+          throw OrthancException(ErrorCode_Plugin, "Storage area plugin doesn't implement the \"ReadWhole\" primitive");
+        }
       }
 
       virtual void Read(std::string& content,
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Thu Jan 28 15:54:30 2021 +0100
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h	Thu Jan 28 16:59:40 2021 +0100
@@ -1274,12 +1274,12 @@
    * reads a portion of a file from the storage area. Orthanc
    * indicates the start position and the length of the range.
    *
-   * @param target Memory buffer where to store the content of the range. It must be allocated by the
-   * plugin using OrthancPluginCreateMemoryBuffer64(). The core of Orthanc will free it.
+   * @param target Memory buffer where to store the content of the range.
+   * The memory buffer is allocated and freed by Orthanc. The length of the range
+   * of interest corresponds to the size of this buffer.
    * @param uuid The UUID of the file of interest.
    * @param type The content type corresponding to this file. 
    * @param rangeStart Start position of the requested range in the file.
-   * @param rangeSize Length of the range of interest.
    * @return 0 if success, other value if error.
    * @ingroup Callbacks
    **/
@@ -1287,8 +1287,7 @@
     OrthancPluginMemoryBuffer64* target,
     const char* uuid,
     OrthancPluginContentType type,
-    uint64_t rangeStart,
-    uint64_t rangeSize);
+    uint64_t rangeStart);
 
 
 
--- a/OrthancServer/Plugins/Samples/StorageArea/Plugin.cpp	Thu Jan 28 15:54:30 2021 +0100
+++ b/OrthancServer/Plugins/Samples/StorageArea/Plugin.cpp	Thu Jan 28 16:59:40 2021 +0100
@@ -25,6 +25,10 @@
 #include <stdio.h>
 #include <string>
 
+
+#define USE_LEGACY_API 0
+
+
 static OrthancPluginContext* context = NULL;
 
 
@@ -34,6 +38,47 @@
 }
 
 
+static bool ReadFile(std::string& content,
+                     const std::string& path)
+{
+  FILE* fp = fopen(path.c_str(), "rb");
+  if (!fp)
+  {
+    return false;
+  }
+
+  if (fseek(fp, 0, SEEK_END) < 0)
+  {
+    fclose(fp);
+    return false;
+  }
+
+  long size = ftell(fp);
+
+  if (fseek(fp, 0, SEEK_SET) < 0)
+  {
+    fclose(fp);
+    return false;
+  }
+  else
+  {
+    content.resize(size);
+
+    if (size != 0)
+    {
+      bool success = (fread(&content[0], size, 1, fp) == 1);
+      fclose(fp);
+      return success;
+    }
+    else
+    {
+      fclose(fp);
+      return true;
+    }
+  }
+}
+
+
 static OrthancPluginErrorCode StorageCreate(const char* uuid,
                                             const void* content,
                                             int64_t size,
@@ -54,53 +99,108 @@
 }
 
 
+#if USE_LEGACY_API == 1
 static OrthancPluginErrorCode StorageRead(void** content,
                                           int64_t* size,
                                           const char* uuid,
                                           OrthancPluginContentType type)
 {
-  std::string path = GetPath(uuid);
+  const std::string path = GetPath(uuid);
+
+  std::string s;
+  if (ReadFile(s, path))
+  {
+    *size = s.size();
 
-  FILE* fp = fopen(path.c_str(), "rb");
-  if (!fp)
+    if (s.size() == 0)
+    {
+      *content = NULL;
+    }
+    else
+    {
+      *content = malloc(s.size());
+      if (*content == NULL)
+      {
+        return OrthancPluginErrorCode_StorageAreaPlugin;
+      }
+
+      if (!s.empty())
+      {
+        memcpy(*content, s.c_str(), s.size());
+      }
+    }
+
+    return OrthancPluginErrorCode_Success;
+  }
+  else
   {
     return OrthancPluginErrorCode_StorageAreaPlugin;
   }
+}
 
-  if (fseek(fp, 0, SEEK_END) < 0)
-  {
-    fclose(fp);
-    return OrthancPluginErrorCode_StorageAreaPlugin;
-  }
+#else
 
-  *size = ftell(fp);
+static OrthancPluginErrorCode StorageReadWhole(OrthancPluginMemoryBuffer64* target,
+                                               const char* uuid,
+                                               OrthancPluginContentType type)
+{
+  const std::string path = GetPath(uuid);
 
-  if (fseek(fp, 0, SEEK_SET) < 0)
+  std::string s;
+  if (ReadFile(s, path))
   {
-    fclose(fp);
-    return OrthancPluginErrorCode_StorageAreaPlugin;
-  }
+    if (OrthancPluginCreateMemoryBuffer64(context, target, s.size()) != OrthancPluginErrorCode_Success)
+    {
+      return OrthancPluginErrorCode_NotEnoughMemory;
+    }
 
-  bool ok = true;
+    if (!s.empty())
+    {
+      memcpy(target->data, s.c_str(), s.size());
+    }
 
-  if (*size == 0)
-  {
-    *content = NULL;
+    return OrthancPluginErrorCode_Success;
   }
   else
   {
-    *content = malloc(*size);
-    if (*content == NULL ||
-        fread(*content, *size, 1, fp) != 1)
+    return OrthancPluginErrorCode_StorageAreaPlugin;
+  }  
+}
+
+static OrthancPluginErrorCode StorageReadRange(OrthancPluginMemoryBuffer64* target,
+                                               const char* uuid,
+                                               OrthancPluginContentType type,
+                                               uint64_t rangeStart)
+{
+  const size_t rangeSize = target->size;  // The buffer is allocated by Orthanc
+  const std::string path = GetPath(uuid);
+
+  std::string s;
+
+  if (rangeSize == 0)
+  {
+    return OrthancPluginErrorCode_Success;
+  }
+  else if (ReadFile(s, path))
+  {
+    if (rangeStart + rangeSize > s.size())
     {
-      ok = false;
+      return OrthancPluginErrorCode_BadRange;
     }
-  }
+    else
+    {
+      memcpy(target->data, &s[rangeStart], rangeSize);
+    }
 
-  fclose(fp);
+    return OrthancPluginErrorCode_Success;
+  }
+  else
+  {
+    return OrthancPluginErrorCode_StorageAreaPlugin;
+  }  
+}
 
-  return ok ? OrthancPluginErrorCode_Success : OrthancPluginErrorCode_StorageAreaPlugin;
-}
+#endif
 
 
 static OrthancPluginErrorCode StorageRemove(const char* uuid,
@@ -139,7 +239,11 @@
       return -1;
     }
 
+#if USE_LEGACY_API == 1
     OrthancPluginRegisterStorageArea(context, StorageCreate, StorageRead, StorageRemove);
+#else
+    OrthancPluginRegisterStorageArea2(context, StorageCreate, StorageReadWhole, StorageReadRange, StorageRemove);
+#endif
 
     return 0;
   }