1/*
2 * Copyright 2007-2013, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Ingo Weinhold <ingo_weinhold@gmx.de>
7 */
8
9
10#include <DriverSettings.h>
11
12#include <stdlib.h>
13#include <string.h>
14
15#include <new>
16
17#include <driver_settings.h>
18#include <Path.h>
19#include <String.h>
20
21#include <Referenceable.h>
22
23
24// The parameter values that shall be evaluated to true.
25static const char* const kTrueValueStrings[]
26	= { "1", "true", "yes", "on", "enable", "enabled" };
27static const int32 kTrueValueStringCount
28	= sizeof(kTrueValueStrings) / sizeof(const char*);
29
30
31namespace BPrivate {
32
33
34// #pragma mark - BDriverParameterIterator
35
36
37class BDriverParameterIterator::Delegate : public BReferenceable {
38public:
39								Delegate() : BReferenceable() {}
40	virtual						~Delegate() {}
41
42	virtual	Delegate*			Clone() const = 0;
43
44	virtual	bool				HasNext() const = 0;
45	virtual	BDriverParameter	Next() = 0;
46};
47
48
49BDriverParameterIterator::BDriverParameterIterator()
50	:
51	fDelegate(NULL)
52{
53}
54
55
56BDriverParameterIterator::BDriverParameterIterator(Delegate* delegate)
57	:
58	fDelegate(delegate)
59{
60}
61
62
63BDriverParameterIterator::BDriverParameterIterator(
64	const BDriverParameterIterator& other)
65	:
66	fDelegate(NULL)
67{
68	_SetTo(other.fDelegate, true);
69}
70
71
72BDriverParameterIterator::~BDriverParameterIterator()
73{
74	_SetTo(NULL, false);
75}
76
77
78bool
79BDriverParameterIterator::HasNext() const
80{
81	return fDelegate != NULL ? fDelegate->HasNext() : false;
82}
83
84
85BDriverParameter
86BDriverParameterIterator::Next()
87{
88	if (fDelegate == NULL)
89		return BDriverParameter();
90
91	if (fDelegate->CountReferences() > 1) {
92		Delegate* clone = fDelegate->Clone();
93		if (clone == NULL)
94			return BDriverParameter();
95		_SetTo(clone, false);
96	}
97
98	return fDelegate->Next();
99}
100
101
102BDriverParameterIterator&
103BDriverParameterIterator::operator=(const BDriverParameterIterator& other)
104{
105	_SetTo(other.fDelegate, true);
106	return *this;
107}
108
109
110void
111BDriverParameterIterator::_SetTo(Delegate* delegate, bool addReference)
112{
113	if (fDelegate != NULL)
114		fDelegate->ReleaseReference();
115	fDelegate = delegate;
116	if (fDelegate != NULL && addReference)
117		fDelegate->AcquireReference();
118}
119
120
121// #pragma mark - BDriverParameterContainer
122
123
124class BDriverParameterContainer::Iterator
125	: public BDriverParameterIterator::Delegate {
126public:
127	Iterator(const driver_parameter* parameters, int32 count)
128		:
129		Delegate(),
130		fParameters(parameters),
131		fCount(count)
132	{
133	}
134
135	virtual ~Iterator()
136	{
137	}
138
139	virtual Delegate* Clone() const
140	{
141		return new(std::nothrow) Iterator(fParameters, fCount);
142	}
143
144	virtual bool HasNext() const
145	{
146		return fParameters != NULL && fCount > 0;
147	}
148
149	virtual	BDriverParameter Next()
150	{
151		if (fParameters == NULL || fCount <= 0)
152			return BDriverParameter();
153
154		fCount--;
155		return BDriverParameter(fParameters++);
156	}
157
158private:
159	const driver_parameter*	fParameters;
160	int32					fCount;
161};
162
163
164class BDriverParameterContainer::NameIterator
165	: public BDriverParameterIterator::Delegate {
166public:
167	NameIterator(const driver_parameter* parameters, int32 count,
168		const BString& name)
169		:
170		Delegate(),
171		fParameters(parameters),
172		fCount(count),
173		fName(name)
174	{
175		_FindNext(false);
176	}
177
178	virtual ~NameIterator()
179	{
180	}
181
182	virtual Delegate* Clone() const
183	{
184		return new(std::nothrow) NameIterator(fParameters, fCount, fName);
185	}
186
187	virtual bool HasNext() const
188	{
189		return fParameters != NULL && fCount > 0;
190	}
191
192	virtual	BDriverParameter Next()
193	{
194		if (fParameters == NULL || fCount <= 0)
195			return BDriverParameter();
196
197		const driver_parameter* parameter = fParameters;
198		_FindNext(true);
199		return BDriverParameter(parameter);
200	}
201
202private:
203	void _FindNext(bool skipCurrent)
204	{
205		if (fParameters == NULL || fCount < 1)
206			return;
207		if (skipCurrent) {
208			fParameters++;
209			fCount--;
210		}
211		while (fCount > 0 && fName != fParameters->name) {
212			fParameters++;
213			fCount--;
214		}
215	}
216
217private:
218	const driver_parameter*	fParameters;
219	int32					fCount;
220	BString					fName;
221};
222
223
224BDriverParameterContainer::BDriverParameterContainer()
225{
226}
227
228
229BDriverParameterContainer::~BDriverParameterContainer()
230{
231}
232
233
234int32
235BDriverParameterContainer::CountParameters() const
236{
237	int32 count;
238	return GetParametersAndCount(count) != NULL ? count : 0;
239
240}
241
242
243const driver_parameter*
244BDriverParameterContainer::Parameters() const
245{
246	int32 count;
247	return GetParametersAndCount(count);
248}
249
250
251BDriverParameter
252BDriverParameterContainer::ParameterAt(int32 index) const
253{
254	int32 count;
255	const driver_parameter* parameters = GetParametersAndCount(count);
256	if (parameters == NULL || index < 0 || index >= count)
257		return BDriverParameter();
258
259	return BDriverParameter(parameters + index);
260}
261
262
263bool
264BDriverParameterContainer::FindParameter(const char* name,
265	BDriverParameter* _parameter) const
266{
267	if (name == NULL)
268		return false;
269
270	int32 count;
271	if (const driver_parameter* parameters = GetParametersAndCount(count)) {
272		for (int32 i = 0; i < count; i++) {
273			if (strcmp(name, parameters[i].name) == 0) {
274				if (_parameter != NULL)
275					_parameter->SetTo(parameters + i);
276				return true;
277			}
278		}
279	}
280	return false;
281}
282
283
284BDriverParameter
285BDriverParameterContainer::GetParameter(const char* name) const
286{
287	BDriverParameter parameter;
288	FindParameter(name, &parameter);
289	return parameter;
290}
291
292
293BDriverParameterIterator
294BDriverParameterContainer::ParameterIterator() const
295{
296	int32 count;
297	if (const driver_parameter* parameters = GetParametersAndCount(count)) {
298		if (Iterator* iterator = new(std::nothrow) Iterator(parameters, count))
299			return BDriverParameterIterator(iterator);
300	}
301	return BDriverParameterIterator();
302}
303
304
305BDriverParameterIterator
306BDriverParameterContainer::ParameterIterator(const char* name) const
307{
308	int32 count;
309	if (const driver_parameter* parameters = GetParametersAndCount(count)) {
310		NameIterator* iterator
311			= new(std::nothrow) NameIterator(parameters, count, name);
312		if (iterator != NULL)
313			return BDriverParameterIterator(iterator);
314	}
315	return BDriverParameterIterator();
316}
317
318
319const char*
320BDriverParameterContainer::GetParameterValue(const char* name,
321	const char* unknownValue, const char* noValue) const
322{
323	BDriverParameter parameter;
324	if (!FindParameter(name, &parameter))
325		return unknownValue;
326	return parameter.ValueAt(0, noValue);
327}
328
329
330bool
331BDriverParameterContainer::GetBoolParameterValue(const char* name,
332	bool unknownValue, bool noValue) const
333{
334	BDriverParameter parameter;
335	if (!FindParameter(name, &parameter))
336		return unknownValue;
337	return parameter.BoolValueAt(0, noValue);
338}
339
340
341int32
342BDriverParameterContainer::GetInt32ParameterValue(const char* name,
343	int32 unknownValue, int32 noValue) const
344{
345	BDriverParameter parameter;
346	if (!FindParameter(name, &parameter))
347		return unknownValue;
348	return parameter.Int32ValueAt(0, noValue);
349}
350
351
352int64
353BDriverParameterContainer::GetInt64ParameterValue(const char* name,
354	int64 unknownValue, int64 noValue) const
355{
356	BDriverParameter parameter;
357	if (!FindParameter(name, &parameter))
358		return unknownValue;
359	return parameter.Int64ValueAt(0, noValue);
360}
361
362
363// #pragma mark - BDriverSettings
364
365
366BDriverSettings::BDriverSettings()
367	:
368	BDriverParameterContainer(),
369	fSettingsHandle(NULL),
370	fSettings(NULL)
371{
372}
373
374
375BDriverSettings::~BDriverSettings()
376{
377	Unset();
378}
379
380
381status_t
382BDriverSettings::Load(const char* driverNameOrAbsolutePath)
383{
384	Unset();
385
386	fSettingsHandle = load_driver_settings(driverNameOrAbsolutePath);
387	if (fSettingsHandle == NULL)
388		return B_ENTRY_NOT_FOUND;
389
390	fSettings = get_driver_settings(fSettingsHandle);
391	if (fSettings == NULL) {
392		Unset();
393		return B_ERROR;
394	}
395
396	return B_OK;
397}
398
399
400status_t
401BDriverSettings::Load(const entry_ref& ref)
402{
403	Unset();
404
405	BPath path;
406	status_t error = path.SetTo(&ref);
407	return error == B_OK ? Load(path.Path()) : error;
408}
409
410
411status_t
412BDriverSettings::SetToString(const char* string)
413{
414	Unset();
415
416	fSettingsHandle = parse_driver_settings_string(string);
417	if (fSettingsHandle == NULL)
418		return B_BAD_DATA;
419
420	fSettings = get_driver_settings(fSettingsHandle);
421	if (fSettings == NULL) {
422		Unset();
423		return B_ERROR;
424	}
425
426	return B_OK;
427}
428
429
430void
431BDriverSettings::Unset()
432{
433	if (fSettingsHandle != NULL)
434		unload_driver_settings(fSettingsHandle);
435
436	fSettingsHandle = NULL;
437	fSettings = NULL;
438}
439
440
441const driver_parameter*
442BDriverSettings::GetParametersAndCount(int32& _count) const
443{
444	if (fSettings == NULL)
445		return NULL;
446
447	_count = fSettings->parameter_count;
448	return fSettings->parameters;
449}
450
451
452// #pragma mark - BDriverParameter
453
454
455BDriverParameter::BDriverParameter()
456	:
457	BDriverParameterContainer(),
458	fParameter(NULL)
459{
460}
461
462
463BDriverParameter::BDriverParameter(const driver_parameter* parameter)
464	:
465	BDriverParameterContainer(),
466	fParameter(parameter)
467{
468}
469
470
471BDriverParameter::BDriverParameter(const BDriverParameter& other)
472	:
473	BDriverParameterContainer(),
474	fParameter(other.fParameter)
475{
476}
477
478
479BDriverParameter::~BDriverParameter()
480{
481}
482
483
484void
485BDriverParameter::SetTo(const driver_parameter* parameter)
486{
487	fParameter = parameter;
488}
489
490
491bool
492BDriverParameter::IsValid() const
493{
494	return fParameter != NULL;
495}
496
497
498const char*
499BDriverParameter::Name() const
500{
501	return fParameter != NULL ? fParameter->name : NULL;
502}
503
504
505int32
506BDriverParameter::CountValues() const
507{
508	return fParameter != NULL ? fParameter->value_count : 0;
509}
510
511
512const char* const*
513BDriverParameter::Values() const
514{
515	return fParameter != NULL ? fParameter->values : 0;
516}
517
518
519const char*
520BDriverParameter::ValueAt(int32 index, const char* noValue) const
521{
522	if (fParameter == NULL || index < 0 || index >= fParameter->value_count)
523		return noValue;
524	return fParameter->values[index];
525}
526
527
528bool
529BDriverParameter::BoolValueAt(int32 index, bool noValue) const
530{
531	const char* value = ValueAt(index, NULL);
532	if (value == NULL)
533		return noValue;
534
535	for (int32 i = 0; i < kTrueValueStringCount; i++) {
536		if (strcmp(value, kTrueValueStrings[i]) == 0)
537			return true;
538	}
539	return false;
540}
541
542
543int32
544BDriverParameter::Int32ValueAt(int32 index, int32 noValue) const
545{
546	const char* value = ValueAt(index, NULL);
547	if (value == NULL)
548		return noValue;
549	return atol(value);
550}
551
552
553int64
554BDriverParameter::Int64ValueAt(int32 index, int64 noValue) const
555{
556	const char* value = ValueAt(index, NULL);
557	if (value == NULL)
558		return noValue;
559	return strtoll(value, NULL, 10);
560}
561
562
563const driver_parameter*
564BDriverParameter::GetParametersAndCount(int32& _count) const
565{
566	if (fParameter == NULL)
567		return NULL;
568
569	_count = fParameter->parameter_count;
570	return fParameter->parameters;
571}
572
573
574BDriverParameter&
575BDriverParameter::operator=(const BDriverParameter& other)
576{
577	fParameter = other.fParameter;
578	return *this;
579}
580
581
582}	// namespace BPrivate
583