mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-11-30 20:44:28 +01:00
357 lines
6.8 KiB
C++
357 lines
6.8 KiB
C++
#include "main.h"
|
|
#include "./deviceObjectStore.h"
|
|
#include <algorithm>
|
|
|
|
template <typename T>
|
|
struct GenericComparator
|
|
{
|
|
typedef const char* (T::*GETTER)();
|
|
GETTER m_getterFunc;
|
|
const char *m_data;
|
|
GenericComparator(GETTER getterFunc, const char *data)
|
|
{
|
|
m_getterFunc = getterFunc;
|
|
m_data = data;
|
|
}
|
|
bool operator()(const T& obj)
|
|
{
|
|
return strcmp(((obj).*m_getterFunc)(), m_data) == 0;
|
|
}
|
|
};
|
|
|
|
static ifc_deviceobject *
|
|
DeviceObjectStore_FindLocation(const char *name, std::vector<ifc_deviceobject*> &list)
|
|
{
|
|
if (FALSE != IS_STRING_EMPTY(name))
|
|
return NULL;
|
|
|
|
//size_t name_length;
|
|
//name_length = lstrlenA(name) * sizeof(char);
|
|
//
|
|
//return (ifc_deviceobject*)bsearch_s(name, buffer, length,
|
|
// sizeof(ifc_deviceobject*),
|
|
// DeviceObjectStore_FindComparer,
|
|
// (void*)name_length);
|
|
|
|
//auto it = std::find_if(list.begin(), list.begin(), GenericComparator<ifc_deviceobject>(&ifc_deviceobject::GetName, name));
|
|
|
|
const auto it = std::find_if(list.begin(), list.end(),
|
|
[&](ifc_deviceobject* upT) -> bool
|
|
{
|
|
return strcmp(upT->GetName(), name) == 0;
|
|
}
|
|
);
|
|
if (it != list.end())
|
|
{
|
|
return *it;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int DeviceObjectComparer(const char* arg1, const char* arg2)
|
|
{
|
|
return stricmp(arg1, arg2);
|
|
}
|
|
|
|
|
|
// Created for std::sort
|
|
static bool DeviceObjectStore_SortComparer_V2(const void* element1, const void* element2)
|
|
{
|
|
//return DeviceObjectStore_SortComparer(element1, element2) < 0;
|
|
const char* name1 = (((ifc_deviceobject*)element1))->GetName();
|
|
const char* name2 = (((ifc_deviceobject*)element2))->GetName();
|
|
return DeviceObjectComparer(name1, name2) < 0;
|
|
}
|
|
|
|
static ifc_deviceobject *
|
|
DeviceObjectStore_FindUnsortedObject(const char *name, ifc_deviceobject **objects, size_t count)
|
|
{
|
|
size_t index;
|
|
size_t length;
|
|
|
|
if (0 == count)
|
|
return NULL;
|
|
|
|
length = lstrlenA(name) * sizeof(char);
|
|
|
|
for(index = 0; index < count; index++)
|
|
{
|
|
//if (0 == DeviceObjectStore_NameCompare(name, length, objects[index]->GetName()))
|
|
if(0 == DeviceObjectComparer(name, objects[index]->GetName()))
|
|
return objects[index];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DeviceObjectStore::DeviceObjectStore(DeviceObjectCallback addCallback,
|
|
DeviceObjectCallback _removeCallback, void *callbackData)
|
|
{
|
|
this->addCallback = addCallback;
|
|
this->removeCallback = _removeCallback;
|
|
this->callbackData = callbackData;
|
|
|
|
InitializeCriticalSection(&lock);
|
|
}
|
|
|
|
DeviceObjectStore::~DeviceObjectStore()
|
|
{
|
|
RemoveAll();
|
|
DeleteCriticalSection(&lock);
|
|
}
|
|
|
|
void DeviceObjectStore::Lock()
|
|
{
|
|
EnterCriticalSection(&lock);
|
|
}
|
|
|
|
void DeviceObjectStore::Unlock()
|
|
{
|
|
LeaveCriticalSection(&lock);
|
|
}
|
|
|
|
CRITICAL_SECTION *DeviceObjectStore::GetLock()
|
|
{
|
|
return &lock;
|
|
}
|
|
|
|
HRESULT DeviceObjectStore::Add(ifc_deviceobject *object)
|
|
{
|
|
const char *name;
|
|
|
|
if (NULL == object)
|
|
return E_POINTER;
|
|
|
|
name = object->GetName();
|
|
|
|
if (NULL == name || '\0' == *name)
|
|
return E_INVALIDARG;
|
|
|
|
return (1 == AddRange(&object, 1)) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
size_t DeviceObjectStore::AddRange(ifc_deviceobject **objects, size_t count)
|
|
{
|
|
const char *name;
|
|
size_t index, registered, added;
|
|
ifc_deviceobject *object;
|
|
|
|
|
|
if (NULL == objects || 0 == count)
|
|
return 0;
|
|
|
|
Lock();
|
|
|
|
added = 0;
|
|
registered = list.size();
|
|
|
|
for(index = 0; index < count; index++)
|
|
{
|
|
object = objects[index];
|
|
if (NULL != object)
|
|
{
|
|
name = object->GetName();
|
|
|
|
if (NULL != name &&
|
|
'\0' != *name &&
|
|
NULL == DeviceObjectStore_FindLocation(name, list))
|
|
//&& NULL == DeviceObjectStore_FindUnsortedObject(name, buffer + registered, added))
|
|
{
|
|
list.push_back(object);
|
|
object->AddRef();
|
|
|
|
if (NULL != addCallback)
|
|
this->addCallback(this, object, callbackData);
|
|
|
|
added++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != added)
|
|
{
|
|
//qsort(list.first(), list.size(),
|
|
// sizeof(ifc_deviceobject**),
|
|
// DeviceObjectStore_SortComparer);
|
|
|
|
std::sort(list.begin(), list.end(), DeviceObjectStore_SortComparer_V2);
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return added;
|
|
}
|
|
|
|
size_t DeviceObjectStore::AddIndirect(const char **names, size_t count, DeviceObjectCreator callback, void *user)
|
|
{
|
|
size_t index, registered, added;
|
|
ifc_deviceobject *object;
|
|
|
|
if (NULL == names || 0 == count || NULL == callback)
|
|
return 0;
|
|
|
|
Lock();
|
|
|
|
added = 0;
|
|
registered = list.size();
|
|
|
|
|
|
for(index = 0; index < count; index++)
|
|
{
|
|
const char *name = names[index];
|
|
|
|
if (NULL != name &&
|
|
'\0' != *name &&
|
|
NULL == DeviceObjectStore_FindLocation(name, list) )
|
|
//&& NULL == DeviceObjectStore_FindUnsortedObject(name, buffer + registered, added))
|
|
{
|
|
object = callback(name, user);
|
|
if (NULL != object)
|
|
{
|
|
list.push_back(object);
|
|
|
|
if (NULL != addCallback)
|
|
this->addCallback(this, object, callbackData);
|
|
|
|
added++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != added)
|
|
{
|
|
//qsort(list.first(), list.size(),
|
|
// sizeof(ifc_deviceobject**),
|
|
// DeviceObjectStore_SortComparer);
|
|
|
|
std::sort(list.begin(), list.end(), DeviceObjectStore_SortComparer_V2);
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return added;
|
|
}
|
|
|
|
HRESULT DeviceObjectStore::Remove(const char *name)
|
|
{
|
|
HRESULT hr = hr = S_FALSE;
|
|
|
|
if (NULL == name || '\0' == *name)
|
|
return E_INVALIDARG;
|
|
|
|
Lock();
|
|
|
|
//object_ptr = DeviceObjectStore_FindLocation(name, list);
|
|
//if (NULL != object_ptr)
|
|
//{
|
|
// hr = S_OK;
|
|
|
|
// ifc_deviceobject *object = *object_ptr;
|
|
|
|
// size_t index = (size_t)(object_ptr - buffer);
|
|
// list.erase(list.begin() + index);
|
|
|
|
// if (NULL != removeCallback)
|
|
// removeCallback(this, object, callbackData);
|
|
|
|
// object->Release();
|
|
//}
|
|
//else
|
|
//{
|
|
// hr = S_FALSE;
|
|
//}
|
|
|
|
const auto it = std::find_if(list.begin(), list.end(),
|
|
[&](ifc_deviceobject* upT) -> bool
|
|
{
|
|
return strcmp(upT->GetName(), name) == 0;
|
|
}
|
|
);
|
|
|
|
if (it != list.end())
|
|
{
|
|
ifc_deviceobject* object = *it;
|
|
list.erase(it);
|
|
if (NULL != removeCallback)
|
|
{
|
|
removeCallback(this, object, callbackData);
|
|
}
|
|
object->Release();
|
|
hr = S_OK;
|
|
}
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
void DeviceObjectStore::RemoveAll()
|
|
{
|
|
Lock();
|
|
|
|
size_t index = list.size();
|
|
while(index--)
|
|
{
|
|
ifc_deviceobject *object = list[index];
|
|
if (NULL != removeCallback)
|
|
removeCallback(this, object, callbackData);
|
|
|
|
object->Release();
|
|
}
|
|
|
|
list.clear();
|
|
Unlock();
|
|
}
|
|
|
|
HRESULT DeviceObjectStore::Find(const char *name, ifc_deviceobject **object)
|
|
{
|
|
HRESULT hr;
|
|
ifc_deviceobject *object_ptr;
|
|
|
|
if (NULL == name || '\0' == *name)
|
|
return E_INVALIDARG;
|
|
|
|
if (NULL == object)
|
|
return E_POINTER;
|
|
|
|
Lock();
|
|
|
|
object_ptr = DeviceObjectStore_FindLocation(name, list);
|
|
|
|
if (NULL != object_ptr)
|
|
{
|
|
if (NULL != object)
|
|
{
|
|
*object = object_ptr;
|
|
(*object)->AddRef();
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
if (NULL != object)
|
|
*object = NULL;
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT DeviceObjectStore::Enumerate(DeviceObjectEnum **enumerator)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NULL == enumerator)
|
|
return E_POINTER;
|
|
|
|
Lock();
|
|
|
|
hr = DeviceObjectEnum::CreateInstance(list.size() ? &list.at(0) : nullptr, list.size(), enumerator);
|
|
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|