Nikolay Sivov : opcservices: Keep parts in a set.

Alexandre Julliard julliard at winehq.org
Wed Sep 5 16:15:27 CDT 2018


Module: wine
Branch: master
Commit: 8fd70ff2bf06f4bc23b75747c6ccde09ebda8db5
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8fd70ff2bf06f4bc23b75747c6ccde09ebda8db5

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed Sep  5 08:37:23 2018 +0300

opcservices: Keep parts in a set.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/opcservices/opc_private.h | 26 ++++++++++++++++++++++++++
 dlls/opcservices/package.c     | 23 +++++++++++++++++++++--
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/dlls/opcservices/opc_private.h b/dlls/opcservices/opc_private.h
index 4784b6c..30bcb00 100644
--- a/dlls/opcservices/opc_private.h
+++ b/dlls/opcservices/opc_private.h
@@ -19,5 +19,31 @@
 #include "msopc.h"
 #include "wine/heap.h"
 
+static inline BOOL opc_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+    size_t new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+    return TRUE;
+}
+
 extern HRESULT opc_package_create(IOpcPackage **package) DECLSPEC_HIDDEN;
 extern HRESULT opc_part_uri_create(const WCHAR *uri, IOpcPartUri **part_uri) DECLSPEC_HIDDEN;
diff --git a/dlls/opcservices/package.c b/dlls/opcservices/package.c
index cd4741d..869fb03 100644
--- a/dlls/opcservices/package.c
+++ b/dlls/opcservices/package.c
@@ -53,6 +53,10 @@ struct opc_part_set
 {
     IOpcPartSet IOpcPartSet_iface;
     LONG refcount;
+
+    struct opc_part **parts;
+    size_t size;
+    size_t count;
 };
 
 struct opc_relationship
@@ -220,7 +224,7 @@ static const IOpcPartVtbl opc_part_vtbl =
     opc_part_GetCompressionOptions,
 };
 
-static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type,
+static HRESULT opc_part_create(struct opc_part_set *set, IOpcPartUri *name, const WCHAR *content_type,
         DWORD compression_options, IOpcPart **out)
 {
     struct opc_part *part;
@@ -228,6 +232,9 @@ static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type,
     if (!name)
         return E_POINTER;
 
+    if (!opc_array_reserve((void **)&set->parts, &set->size, set->count + 1, sizeof(*set->parts)))
+        return E_OUTOFMEMORY;
+
     if (!(part = heap_alloc_zero(sizeof(*part))))
         return E_OUTOFMEMORY;
 
@@ -242,6 +249,9 @@ static HRESULT opc_part_create(IOpcPartUri *name, const WCHAR *content_type,
         return E_OUTOFMEMORY;
     }
 
+    set->parts[set->count++] = part;
+    IOpcPart_AddRef(&part->IOpcPart_iface);
+
     *out = &part->IOpcPart_iface;
     TRACE("Created part %p.\n", *out);
     return S_OK;
@@ -281,7 +291,14 @@ static ULONG WINAPI opc_part_set_Release(IOpcPartSet *iface)
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
+    {
+        size_t i;
+
+        for (i = 0; i < part_set->count; ++i)
+            IOpcPart_Release(&part_set->parts[i]->IOpcPart_iface);
+        heap_free(part_set->parts);
         heap_free(part_set);
+    }
 
     return refcount;
 }
@@ -296,10 +313,12 @@ static HRESULT WINAPI opc_part_set_GetPart(IOpcPartSet *iface, IOpcPartUri *name
 static HRESULT WINAPI opc_part_set_CreatePart(IOpcPartSet *iface, IOpcPartUri *name, LPCWSTR content_type,
         OPC_COMPRESSION_OPTIONS compression_options, IOpcPart **part)
 {
+    struct opc_part_set *part_set = impl_from_IOpcPartSet(iface);
+
     TRACE("iface %p, name %p, content_type %s, compression_options %#x, part %p.\n", iface, name,
             debugstr_w(content_type), compression_options, part);
 
-    return opc_part_create(name, content_type, compression_options, part);
+    return opc_part_create(part_set, name, content_type, compression_options, part);
 }
 
 static HRESULT WINAPI opc_part_set_DeletePart(IOpcPartSet *iface, IOpcPartUri *name)




More information about the wine-cvs mailing list