#include <new>
#include <stdlib.h>
#include <string.h>
#include <driver_settings.h>
#include <Referenceable.h>
#include "DriverSettings.h"
#include "String.h"
static const char* kTrueValueStrings[]
= { "1", "true", "yes", "on", "enable", "enabled" };
static const int32 kTrueValueStringCount
= sizeof(kTrueValueStrings) / sizeof(const char*);
class DriverParameterIterator::Delegate : public BReferenceable {
public:
Delegate() : BReferenceable() {}
virtual ~Delegate() {}
virtual Delegate* Clone() const = 0;
virtual bool HasNext() const = 0;
virtual bool GetNext(DriverParameter* parameter) = 0;
};
DriverParameterIterator::DriverParameterIterator()
: fDelegate(NULL)
{
}
DriverParameterIterator::DriverParameterIterator(Delegate* delegate)
: fDelegate(delegate)
{
}
DriverParameterIterator::DriverParameterIterator(
const DriverParameterIterator& other)
: fDelegate(NULL)
{
_SetTo(other.fDelegate, true);
}
DriverParameterIterator::~DriverParameterIterator()
{
_SetTo(NULL, false);
}
bool
DriverParameterIterator::HasNext() const
{
return (fDelegate ? fDelegate->HasNext() : false);
}
bool
DriverParameterIterator::GetNext(DriverParameter* parameter)
{
if (!fDelegate)
return false;
if (fDelegate->CountReferences() > 1) {
Delegate* clone = fDelegate->Clone();
if (!clone)
return false;
_SetTo(clone, false);
}
return fDelegate->GetNext(parameter);
}
DriverParameterIterator&
DriverParameterIterator::operator=(const DriverParameterIterator& other)
{
_SetTo(other.fDelegate, true);
return *this;
}
void
DriverParameterIterator::_SetTo(Delegate* delegate, bool addReference)
{
if (fDelegate)
fDelegate->ReleaseReference();
fDelegate = delegate;
if (fDelegate && addReference)
fDelegate->AcquireReference();
}
class DriverParameterContainer::Iterator
: public DriverParameterIterator::Delegate {
public:
Iterator(const driver_parameter* parameters, int32 count)
: Delegate(),
fParameters(parameters),
fCount(count)
{
}
virtual ~Iterator()
{
}
virtual Delegate* Clone() const
{
return new(std::nothrow) Iterator(fParameters, fCount);
}
virtual bool HasNext() const
{
return (fParameters && fCount > 0);
}
virtual bool GetNext(DriverParameter* parameter)
{
if (fParameters && fCount > 0) {
if (parameter)
parameter->SetTo(fParameters);
fParameters++;
fCount--;
return true;
}
return false;
}
private:
const driver_parameter* fParameters;
int32 fCount;
};
class DriverParameterContainer::NameIterator
: public DriverParameterIterator::Delegate {
public:
NameIterator(const driver_parameter* parameters, int32 count,
const char* name)
: Delegate(),
fParameters(parameters),
fCount(count),
fName(name)
{
_FindNext(false);
}
virtual ~NameIterator()
{
}
virtual Delegate* Clone() const
{
return new(std::nothrow) NameIterator(fParameters, fCount,
fName.GetString());
}
virtual bool HasNext() const
{
return (fParameters && fCount > 0);
}
virtual bool GetNext(DriverParameter* parameter)
{
if (fParameters && fCount > 0) {
if (parameter)
parameter->SetTo(fParameters);
_FindNext(true);
return true;
}
return false;
}
private:
void _FindNext(bool skipCurrent)
{
if (!fParameters || fCount < 1)
return;
if (skipCurrent) {
fParameters++;
fCount--;
}
while (fCount > 0 && fName != fParameters->name) {
fParameters++;
fCount--;
}
}
private:
const driver_parameter* fParameters;
int32 fCount;
String fName;
};
DriverParameterContainer::DriverParameterContainer()
{
}
DriverParameterContainer::~DriverParameterContainer()
{
}
int32
DriverParameterContainer::CountParameters() const
{
int32 count;
return (GetParametersAndCount(&count) ? count : 0);
}
const driver_parameter*
DriverParameterContainer::GetParameters() const
{
int32 count;
return GetParametersAndCount(&count);
}
bool
DriverParameterContainer::GetParameterAt(int32 index,
DriverParameter* parameter) const
{
int32 count;
if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
if (index >= 0 && index < count) {
if (parameter)
parameter->SetTo(parameters + index);
return true;
}
}
return false;
}
bool
DriverParameterContainer::FindParameter(const char* name,
DriverParameter* parameter) const
{
if (!name)
return false;
int32 count;
if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
for (int32 i = 0; i < count; i++) {
if (strcmp(name, parameters[i].name) == 0) {
if (parameter)
parameter->SetTo(parameters + i);
return true;
}
}
}
return false;
}
DriverParameterIterator
DriverParameterContainer::GetParameterIterator() const
{
int32 count;
if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
if (Iterator* iterator = new(std::nothrow) Iterator(parameters, count))
return DriverParameterIterator(iterator);
}
return DriverParameterIterator();
}
DriverParameterIterator
DriverParameterContainer::GetParameterIterator(const char* name) const
{
int32 count;
if (const driver_parameter* parameters = GetParametersAndCount(&count)) {
NameIterator* iterator = new(std::nothrow) NameIterator(parameters, count,
name);
if (iterator)
return DriverParameterIterator(iterator);
}
return DriverParameterIterator();
}
const char*
DriverParameterContainer::GetParameterValue(const char* name,
const char* unknownValue, const char* noValue) const
{
DriverParameter parameter;
if (!FindParameter(name, ¶meter))
return unknownValue;
return parameter.ValueAt(0, noValue);
}
bool
DriverParameterContainer::GetBoolParameterValue(const char* name,
bool unknownValue, bool noValue) const
{
DriverParameter parameter;
if (!FindParameter(name, ¶meter))
return unknownValue;
return parameter.BoolValueAt(0, noValue);
}
int32
DriverParameterContainer::GetInt32ParameterValue(const char* name,
int32 unknownValue, int32 noValue) const
{
DriverParameter parameter;
if (!FindParameter(name, ¶meter))
return unknownValue;
return parameter.Int32ValueAt(0, noValue);
}
int64
DriverParameterContainer::GetInt64ParameterValue(const char* name,
int64 unknownValue, int64 noValue) const
{
DriverParameter parameter;
if (!FindParameter(name, ¶meter))
return unknownValue;
return parameter.Int64ValueAt(0, noValue);
}
DriverSettings::DriverSettings()
: DriverParameterContainer(),
fSettingsHandle(NULL),
fSettings(NULL)
{
}
DriverSettings::~DriverSettings()
{
Unset();
}
status_t
DriverSettings::Load(const char* driverName)
{
Unset();
fSettingsHandle = load_driver_settings(driverName);
if (!fSettingsHandle)
return B_ENTRY_NOT_FOUND;
fSettings = get_driver_settings(fSettingsHandle);
if (!fSettings) {
Unset();
return B_ERROR;
}
return B_OK;
}
void
DriverSettings::Unset()
{
if (fSettingsHandle)
unload_driver_settings(fSettingsHandle);
fSettingsHandle = NULL;
fSettings = NULL;
}
const driver_parameter*
DriverSettings::GetParametersAndCount(int32* count) const
{
if (!fSettings)
return NULL;
*count = fSettings->parameter_count;
return fSettings->parameters;
}
DriverParameter::DriverParameter()
: DriverParameterContainer(),
fParameter(NULL)
{
}
DriverParameter::~DriverParameter()
{
}
void
DriverParameter::SetTo(const driver_parameter* parameter)
{
fParameter = parameter;
}
const char*
DriverParameter::GetName() const
{
return (fParameter ? fParameter->name : NULL);
}
int32
DriverParameter::CountValues() const
{
return (fParameter ? fParameter->value_count : 0);
}
const char* const*
DriverParameter::GetValues() const
{
return (fParameter ? fParameter->values : 0);
}
const char*
DriverParameter::ValueAt(int32 index, const char* noValue) const
{
if (!fParameter || index < 0 || index >= fParameter->value_count)
return noValue;
return fParameter->values[index];
}
bool
DriverParameter::BoolValueAt(int32 index, bool noValue) const
{
const char* value = ValueAt(index, NULL);
if (!value)
return noValue;
for (int32 i = 0; i < kTrueValueStringCount; i++) {
if (strcmp(value, kTrueValueStrings[i]) == 0)
return true;
}
return false;
}
int32
DriverParameter::Int32ValueAt(int32 index, int32 noValue) const
{
const char* value = ValueAt(index, NULL);
if (!value)
return noValue;
return atol(value);
}
int64
DriverParameter::Int64ValueAt(int32 index, int64 noValue) const
{
const char* value = ValueAt(index, NULL);
if (!value)
return noValue;
return strtoll(value, NULL, 10);
}
const driver_parameter*
DriverParameter::GetParametersAndCount(int32* count) const
{
if (!fParameter)
return NULL;
*count = fParameter->parameter_count;
return fParameter->parameters;
}