⛏️ index : haiku.git

/*
 * Copyright 2004-2007, Waldemar Kornewald <wkornew@gmx.net>
 * Distributed under the terms of the MIT License.
 */

#include "MessageDriverSettingsUtils.h"

#include <PPPDefs.h>
#include <settings_tools.h>
#include <File.h>
#include <Message.h>
#include <String.h>

#include <cstdio>


static bool AddParameters(const BMessage& message, driver_settings *to);


bool
FindMessageParameter(const char *name, const BMessage& message, BMessage *save,
	int32 *startIndex)
{
	// XXX: this should be removed when we can replace BMessage with something better
	BString string;
	int32 index = startIndex ? *startIndex : 0;
	for (; message.FindMessage(MDSU_PARAMETERS, index, save) == B_OK; index++) {
		if (save->FindString(MDSU_NAME, &string) == B_OK
				&& string.ICompare(name) == 0) {
			if (startIndex)
				*startIndex = index;
			return true;
		}
	}
	
	return false;
}


static
bool
AddValues(const BMessage& message, driver_parameter *parameter)
{
	const char *value;
	for (int32 index = 0; message.FindString(MDSU_VALUES, index, &value) == B_OK;
			index++)
		if (!add_driver_parameter_value(value, parameter))
			return false;
	
	return true;
}


inline
bool
AddParameters(const BMessage& message, driver_parameter *to)
{
	if (!to)
		return false;
	
	return AddParameters(message,
		reinterpret_cast<driver_settings*>(&to->parameter_count));
}


static
bool
AddParameters(const BMessage& message, driver_settings *to)
{
	const char *name;
	BMessage current;
	driver_parameter *parameter;
	for (int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index,
			&current) == B_OK; index++) {
		name = current.FindString(MDSU_NAME);
		parameter = new_driver_parameter(name);
		if (!AddValues(current, parameter))
			return false;
		
		AddParameters(current, parameter);
		add_driver_parameter(parameter, to);
	}
	
	return true;
}


driver_settings*
MessageToDriverSettings(const BMessage& message)
{
	driver_settings *settings = new_driver_settings();
	
	if (!AddParameters(message, settings)) {
		free_driver_settings(settings);
		return NULL;
	}
	
	return settings;
}


static
bool
AddParameter(const driver_parameter *parameter, BMessage *message)
{
	if (!parameter || !message)
		return false;
	
	if (parameter->name)
		message->AddString(MDSU_NAME, parameter->name);
	else
		return false;
	
	for (int32 index = 0; index < parameter->value_count; index++)
		if (parameter->values[index])
			message->AddString(MDSU_VALUES, parameter->values[index]);
	
	for (int32 index = 0; index < parameter->parameter_count; index++) {
		BMessage parameterMessage;
		AddParameter(&parameter->parameters[index], &parameterMessage);
		message->AddMessage(MDSU_PARAMETERS, &parameterMessage);
	}
	
	return true;
}


bool
ReadMessageDriverSettings(const char *name, BMessage *message)
{
	if (!name || !message)
		return false;
	
	void *handle = load_driver_settings(name);
	if (!handle)
		return false;
	const driver_settings *settings = get_driver_settings(handle);
	if (!settings) {
		unload_driver_settings(handle);
		return false;
	}
	
	for (int32 index = 0; index < settings->parameter_count; index++) {
		BMessage parameter;
		AddParameter(&settings->parameters[index], &parameter);
		message->AddMessage(MDSU_PARAMETERS, &parameter);
	}
	
	unload_driver_settings(handle);
	
	return true;
}


static
void
EscapeWord(BString& word)
{
	word.ReplaceAll("\\", "\\\\");
	word.ReplaceAll("#", "\\#");
	word.ReplaceAll("\"", "\\\"");
	word.ReplaceAll("\'", "\\\'");
}


static
bool
WriteParameter(BFile& file, const BMessage& parameter, int32 level)
{
	const char *name;
	if (parameter.FindString(MDSU_NAME, &name) != B_OK || !name)
		return false;
	
	BString line, word(name);
	EscapeWord(word);
	bool needsEscaping = word.FindFirst(' ') >= 0;
	line.SetTo('\t', level);
	if (needsEscaping)
		line << '\"';
	line << word;
	if (needsEscaping)
		line << '\"';
	
	for (int32 index = 0; parameter.FindString(MDSU_VALUES, index, &name) == B_OK;
			index++)
		if (name) {
			line << ' ';
			word = name;
			EscapeWord(word);
			needsEscaping = word.FindFirst(' ') >= 0;
			if (needsEscaping)
				line << '\"';
			line << word;
			if (needsEscaping)
				line << '\"';
		}
	
	type_code type;
	int32 parameterCount;
	parameter.GetInfo(MDSU_PARAMETERS, &type, &parameterCount);
	
	if (parameterCount > 0)
		line << " {";
	
	line << '\n';
	file.Write(line.String(), line.Length());
	
	if (parameterCount > 0) {
		BMessage subParameter;
		for (int32 index = 0; parameter.FindMessage(MDSU_PARAMETERS, index,
				&subParameter) == B_OK; index++)
			WriteParameter(file, subParameter, level + 1);
		
		line.SetTo('\t', level);
		line << "}\n";
		file.Write(line.String(), line.Length());
	}
	
	return true;
}


bool
WriteMessageDriverSettings(BFile& file, const BMessage& message)
{
	if (file.InitCheck() != B_OK || !file.IsWritable())
		return false;
	
	file.SetSize(0);
	file.Seek(0, SEEK_SET);
	
	BMessage parameter;
	for (int32 index = 0; message.FindMessage(MDSU_PARAMETERS, index, &parameter) == B_OK;
			index++) {
		if (index > 0)
			file.Write("\n", 1);
		WriteParameter(file, parameter, 0);
	}
	
	return true;
}