Nikolay Sivov : scrrun: Implement IEnumVARIANT support for dictionary.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Mar 19 09:59:02 CDT 2015
Module: wine
Branch: master
Commit: ba482174299ff165c49e4d7d226f9799a2d8c5f3
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ba482174299ff165c49e4d7d226f9799a2d8c5f3
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Wed Mar 18 15:11:32 2015 +0300
scrrun: Implement IEnumVARIANT support for dictionary.
---
dlls/scrrun/dictionary.c | 78 ++++++++++++++++++++++++---
dlls/scrrun/tests/dictionary.c | 118 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 188 insertions(+), 8 deletions(-)
diff --git a/dlls/scrrun/dictionary.c b/dlls/scrrun/dictionary.c
index b74f2a7..5c770b6 100644
--- a/dlls/scrrun/dictionary.c
+++ b/dlls/scrrun/dictionary.c
@@ -71,6 +71,7 @@ typedef struct
LONG count;
struct list pairs;
struct list buckets[BUCKET_COUNT];
+ struct list notifier;
} dictionary;
struct dictionary_enum {
@@ -78,6 +79,8 @@ struct dictionary_enum {
LONG ref;
dictionary *dict;
+ struct list *cur;
+ struct list notify;
};
static inline dictionary *impl_from_IDictionary(IDictionary *iface)
@@ -248,6 +251,7 @@ static ULONG WINAPI dict_enum_Release(IEnumVARIANT *iface)
ref = InterlockedDecrement(&This->ref);
if(ref == 0) {
+ list_remove(&This->notify);
IDictionary_Release(&This->dict->IDictionary_iface);
heap_free(This);
}
@@ -258,29 +262,67 @@ static ULONG WINAPI dict_enum_Release(IEnumVARIANT *iface)
static HRESULT WINAPI dict_enum_Next(IEnumVARIANT *iface, ULONG count, VARIANT *keys, ULONG *fetched)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
- FIXME("(%p)->(%u %p %p): stub\n", This, count, keys, fetched);
- return E_NOTIMPL;
+ struct keyitem_pair *pair;
+ ULONG i = 0;
+
+ TRACE("(%p)->(%u %p %p)\n", This, count, keys, fetched);
+
+ if (fetched)
+ *fetched = 0;
+
+ if (!count)
+ return S_OK;
+
+ while (This->cur && i < count) {
+ pair = LIST_ENTRY(This->cur, struct keyitem_pair, entry);
+ VariantCopy(&keys[i], &pair->key);
+ This->cur = list_next(&This->dict->pairs, This->cur);
+ i++;
+ }
+
+ if (fetched)
+ *fetched = i;
+
+ return i < count ? S_FALSE : S_OK;
}
static HRESULT WINAPI dict_enum_Skip(IEnumVARIANT *iface, ULONG count)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
- FIXME("(%p)->(%u): stub\n", This, count);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%u)\n", This, count);
+
+ if (!count)
+ return S_OK;
+
+ if (!This->cur)
+ return S_FALSE;
+
+ while (count--) {
+ This->cur = list_next(&This->dict->pairs, This->cur);
+ if (!This->cur) break;
+ }
+
+ return count == 0 ? S_OK : S_FALSE;
}
static HRESULT WINAPI dict_enum_Reset(IEnumVARIANT *iface)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
- FIXME("(%p): stub\n", This);
- return E_NOTIMPL;
+
+ TRACE("(%p)\n", This);
+
+ This->cur = list_head(&This->dict->pairs);
+ return S_OK;
}
+static HRESULT create_dict_enum(dictionary*, IUnknown**);
+
static HRESULT WINAPI dict_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **cloned)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
- FIXME("(%p)->(%p): stub\n", This, cloned);
- return E_NOTIMPL;
+ TRACE("(%p)->(%p)\n", This, cloned);
+ return create_dict_enum(This->dict, (IUnknown**)cloned);
}
static const IEnumVARIANTVtbl dictenumvtbl = {
@@ -305,6 +347,8 @@ static HRESULT create_dict_enum(dictionary *dict, IUnknown **ret)
This->IEnumVARIANT_iface.lpVtbl = &dictenumvtbl;
This->ref = 1;
+ This->cur = list_head(&dict->pairs);
+ list_add_tail(&dict->notifier, &This->notify);
This->dict = dict;
IDictionary_AddRef(&dict->IDictionary_iface);
@@ -312,6 +356,21 @@ static HRESULT create_dict_enum(dictionary *dict, IUnknown **ret)
return S_OK;
}
+static void notify_remove_pair(struct list *notifier, struct list *pair)
+{
+ struct dictionary_enum *dict_enum;
+ struct list *cur;
+
+ LIST_FOR_EACH(cur, notifier) {
+ dict_enum = LIST_ENTRY(cur, struct dictionary_enum, notify);
+ if (!pair)
+ dict_enum->cur = list_head(&dict_enum->dict->pairs);
+ else if (dict_enum->cur == pair) {
+ dict_enum->cur = list_next(&dict_enum->dict->pairs, dict_enum->cur);
+ }
+ }
+}
+
static HRESULT WINAPI dictionary_QueryInterface(IDictionary *iface, REFIID riid, void **obj)
{
dictionary *This = impl_from_IDictionary(iface);
@@ -616,6 +675,7 @@ static HRESULT WINAPI dictionary_Remove(IDictionary *iface, VARIANT *key)
if (!(pair = get_keyitem_pair(This, key)))
return CTL_E_ELEMENT_NOT_FOUND;
+ notify_remove_pair(&This->notifier, &pair->entry);
list_remove(&pair->entry);
list_remove(&pair->bucket);
This->count--;
@@ -634,6 +694,7 @@ static HRESULT WINAPI dictionary_RemoveAll(IDictionary *iface)
if (This->count == 0)
return S_OK;
+ notify_remove_pair(&This->notifier, NULL);
LIST_FOR_EACH_ENTRY_SAFE(pair, pair2, &This->pairs, struct keyitem_pair, entry) {
list_remove(&pair->entry);
list_remove(&pair->bucket);
@@ -796,6 +857,7 @@ HRESULT WINAPI Dictionary_CreateInstance(IClassFactory *factory,IUnknown *outer,
This->method = BinaryCompare;
This->count = 0;
list_init(&This->pairs);
+ list_init(&This->notifier);
memset(This->buckets, 0, sizeof(This->buckets));
*obj = &This->IDictionary_iface;
diff --git a/dlls/scrrun/tests/dictionary.c b/dlls/scrrun/tests/dictionary.c
index 927ac05..1869861 100644
--- a/dlls/scrrun/tests/dictionary.c
+++ b/dlls/scrrun/tests/dictionary.c
@@ -618,6 +618,123 @@ static void test_Add(void)
IDictionary_Release(dict);
}
+static void test_IEnumVARIANT(void)
+{
+ IUnknown *enum1, *enum2;
+ IEnumVARIANT *enumvar;
+ VARIANT key, item;
+ IDictionary *dict;
+ ULONG fetched;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_Dictionary, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+ &IID_IDictionary, (void**)&dict);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+if (0) /* crashes on native */
+ hr = IDictionary__NewEnum(dict, NULL);
+
+ hr = IDictionary__NewEnum(dict, &enum1);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IDictionary__NewEnum(dict, &enum2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(enum1 != enum2, "got %p, %p\n", enum2, enum1);
+ IUnknown_Release(enum2);
+
+ hr = IUnknown_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enumvar);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ IUnknown_Release(enum1);
+
+ /* dictionary is empty */
+ hr = IEnumVARIANT_Skip(enumvar, 1);
+ ok(hr == S_FALSE, "got 0x%08x\n", hr);
+
+ hr = IEnumVARIANT_Skip(enumvar, 0);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ V_VT(&key) = VT_I2;
+ V_I2(&key) = 1;
+ V_VT(&item) = VT_I4;
+ V_I4(&item) = 100;
+ hr = IDictionary_Add(dict, &key, &item);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IEnumVARIANT_Skip(enumvar, 0);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IEnumVARIANT_Reset(enumvar);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IEnumVARIANT_Skip(enumvar, 1);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IEnumVARIANT_Skip(enumvar, 1);
+ ok(hr == S_FALSE, "got 0x%08x\n", hr);
+
+ V_VT(&key) = VT_I2;
+ V_I2(&key) = 4000;
+ V_VT(&item) = VT_I4;
+ V_I4(&item) = 200;
+ hr = IDictionary_Add(dict, &key, &item);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ V_VT(&key) = VT_I2;
+ V_I2(&key) = 0;
+ V_VT(&item) = VT_I4;
+ V_I4(&item) = 300;
+ hr = IDictionary_Add(dict, &key, &item);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IEnumVARIANT_Reset(enumvar);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ VariantInit(&key);
+ hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
+ ok(V_I2(&key) == 1, "got %d\n", V_I2(&key));
+ ok(fetched == 1, "got %u\n", fetched);
+
+ hr = IEnumVARIANT_Reset(enumvar);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IDictionary_Remove(dict, &key);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ VariantInit(&key);
+ hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
+ ok(V_I2(&key) == 4000, "got %d\n", V_I2(&key));
+ ok(fetched == 1, "got %u\n", fetched);
+
+ VariantInit(&key);
+ hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(V_VT(&key) == VT_I2, "got %d\n", V_VT(&key));
+ ok(V_I2(&key) == 0, "got %d\n", V_I2(&key));
+ ok(fetched == 1, "got %u\n", fetched);
+
+ /* enumeration reached the bottom, add one more pair */
+ VariantInit(&key);
+ hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
+ ok(hr == S_FALSE, "got 0x%08x\n", hr);
+
+ V_VT(&key) = VT_I2;
+ V_I2(&key) = 13;
+ V_VT(&item) = VT_I4;
+ V_I4(&item) = 350;
+ hr = IDictionary_Add(dict, &key, &item);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ /* still doesn't work until Reset() */
+ VariantInit(&key);
+ hr = IEnumVARIANT_Next(enumvar, 1, &key, &fetched);
+ ok(hr == S_FALSE, "got 0x%08x\n", hr);
+
+ IEnumVARIANT_Release(enumvar);
+ IDictionary_Release(dict);
+}
+
START_TEST(dictionary)
{
IDispatch *disp;
@@ -642,6 +759,7 @@ START_TEST(dictionary)
test_Remove();
test_Item();
test_Add();
+ test_IEnumVARIANT();
CoUninitialize();
}
More information about the wine-cvs
mailing list