⛏️ index : haiku.git

/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2016, Rene Gollent, rene@gollent.com.
 * Distributed under the terms of the MIT License.
 */


#include "DebuggerSettingsManager.h"

#include <new>

#include <Directory.h>
#include <File.h>
#include <FindDirectory.h>

#include <AutoDeleter.h>
#include <AutoLocker.h>

#include "TeamSettings.h"


static const char* const kSettingsDirPath		= "Debugger";
static const char* const kGlobalSettingsName	= "Global";
static const int32 kMaxRecentTeamSettings		= 10;


DebuggerSettingsManager::DebuggerSettingsManager()
	:
	SettingsManager(),
	fLock("settings manager"),
	fRecentTeamSettings(kMaxRecentTeamSettings),
	fUiSettingsFactory(NULL)
{
}


DebuggerSettingsManager::~DebuggerSettingsManager()
{
	_Unset();
}


status_t
DebuggerSettingsManager::Init(TeamUiSettingsFactory* factory)
{
	// check the lock
	status_t error = fLock.InitCheck();
	if (error != B_OK)
		return error;

	fUiSettingsFactory = factory;

	// get and create our settings directory
	if (find_directory(B_USER_SETTINGS_DIRECTORY, &fSettingsPath, true) == B_OK
		&& fSettingsPath.Append(kSettingsDirPath) == B_OK
		&& create_directory(fSettingsPath.Path(), 0700) == B_OK
		&& fSettingsPath.Append(kGlobalSettingsName) == B_OK) {
		// load the settings
		_LoadSettings();
	} else {
		// something went wrong -- clear the path
		fSettingsPath.Unset();
	}

	return B_OK;
}


status_t
DebuggerSettingsManager::LoadTeamSettings(const char* teamName, TeamSettings& settings)
{
	AutoLocker<BLocker> locker(fLock);

	int32 index = _TeamSettingsIndex(teamName);
	if (index < 0)
		return B_ENTRY_NOT_FOUND;

	try {
		settings = *fRecentTeamSettings.ItemAt(index);
		return B_OK;
	} catch (std::bad_alloc&) {
		return B_NO_MEMORY;
	}
}


status_t
DebuggerSettingsManager::SaveTeamSettings(const TeamSettings& _settings)
{
	AutoLocker<BLocker> locker(fLock);

	TeamSettings* settings;
	int32 index = _TeamSettingsIndex(_settings.TeamName());
	if (index >= 0) {
		settings = fRecentTeamSettings.RemoveItemAt(index);
	} else {
		settings = new(std::nothrow) TeamSettings;
		if (settings == NULL)
			return B_NO_MEMORY;

		// enforce recent limit
		while (fRecentTeamSettings.CountItems() >= kMaxRecentTeamSettings)
			delete fRecentTeamSettings.RemoveItemAt(0);

	}
	ObjectDeleter<TeamSettings> settingsDeleter(settings);

	try {
		*settings = _settings;
		if (!fRecentTeamSettings.AddItem(settings))
			return B_NO_MEMORY;
		settingsDeleter.Detach();

		return _SaveSettings();
	} catch (std::bad_alloc&) {
		return B_NO_MEMORY;
	}
}


void
DebuggerSettingsManager::_Unset()
{
	fRecentTeamSettings.MakeEmpty();
}


status_t
DebuggerSettingsManager::_LoadSettings()
{
	_Unset();

	if (fSettingsPath.Path() == NULL)
		return B_ENTRY_NOT_FOUND;

	// read the settings file
	BFile file;
	status_t error = file.SetTo(fSettingsPath.Path(), B_READ_ONLY);
	if (error != B_OK)
		return error;

	BMessage archive;
	error = archive.Unflatten(&file);
	if (error != B_OK)
		return error;

	// unarchive the recent team settings
	BMessage childArchive;
	for (int32 i = 0; archive.FindMessage("teamSettings", i, &childArchive)
			== B_OK; i++) {
		TeamSettings* settings = new(std::nothrow) TeamSettings;
		if (settings == NULL)
			return B_NO_MEMORY;

		error = settings->SetTo(childArchive, *fUiSettingsFactory);
		if (error != B_OK) {
			delete settings;
			continue;
		}

		if (!fRecentTeamSettings.AddItem(settings)) {
			delete settings;
			return B_NO_MEMORY;
		}
	}

	return B_OK;
}


status_t
DebuggerSettingsManager::_SaveSettings()
{
	if (fSettingsPath.Path() == NULL)
		return B_ENTRY_NOT_FOUND;

	// archive the recent team settings
	BMessage archive;
	for (int32 i = 0; TeamSettings* settings = fRecentTeamSettings.ItemAt(i);
			i++) {
		BMessage childArchive;
		status_t error = settings->WriteTo(childArchive);
		if (error != B_OK)
			return error;

		error = archive.AddMessage("teamSettings", &childArchive);
		if (error != B_OK)
			return error;
	}

	// open the settings file
	BFile file;
	status_t error = file.SetTo(fSettingsPath.Path(),
		B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
	if (error != B_OK)
		return error;

	return archive.Flatten(&file);
}


int32
DebuggerSettingsManager::_TeamSettingsIndex(const char* teamName) const
{
	for (int32 i = 0; TeamSettings* settings = fRecentTeamSettings.ItemAt(i);
			i++) {
		if (settings->TeamName() == teamName)
			return i;
	}

	return -1;
}