/*
 *  ppui/Dictionary.cpp
 *
 *  Copyright 2009 Peter Barth
 *
 *  This file is part of Milkytracker.
 *
 *  Milkytracker is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Milkytracker is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

/*
 *  PPDictionary.cpp
 *  MilkyTracker
 *
 *  Created by Peter Barth on Mon Mar 14 2005.
 *
 */

#include "Dictionary.h"
#include "SimpleVector.h"

PPDictionary::PPDictionary() :
	enumerating(false),
	enumerationIndex(0)
{
	keys = new PPSimpleVector<PPDictionaryKey>;
}

PPDictionary::~PPDictionary()
{
	delete keys;
}

// copy c'tor
PPDictionary::PPDictionary(const PPDictionary& source)
{
	keys = source.keys->clone();
}

PPDictionary& PPDictionary::operator=(const PPDictionary& source)
{
	// no self-assignment
	if (this != &source)
	{
		delete keys;	
		
		keys = source.keys->clone();
	}

	return *this;
}


PPDictionaryKey* PPDictionary::getKeyToModify(const PPString& key) const
{
	for (pp_int32 i = 0;  i < keys->size(); i++)
	{
		PPDictionaryKey* theKey = keys->get(i);
		if (theKey != NULL && theKey->getKey().compareTo(key) == 0)
			return theKey;
	}
	return NULL;
}

void PPDictionary::store(const PPString& key, const PPString& value)
{
	PPDictionaryKey* theKey = getKeyToModify(key);
	
	if (theKey)
		theKey->store(value);
	else
		keys->add(new PPDictionaryKey(key, value));
}

void PPDictionary::store(const PPString& key, const pp_uint32 value)
{
	PPDictionaryKey* theKey = getKeyToModify(key);
	
	if (theKey)
		theKey->store(value);
	else
		keys->add(new PPDictionaryKey(key, value));
}

PPDictionaryKey* PPDictionary::restore(const PPString& key)
{
	return getKeyToModify(key);
}

pp_int32 PPDictionary::size() const
{
	return keys->size();
}

PPDictionaryKey* PPDictionary::getFirstKey()
{
	if (keys->size() == 0)
		return NULL;
		
	enumerationIndex = 0;
	enumerating = true;
	PPDictionaryKey* theKey = keys->get(enumerationIndex);
	enumerationIndex++;
	return theKey;
}

PPDictionaryKey* PPDictionary::getNextKey()
{
	if (!enumerating)
		return NULL;

	PPDictionaryKey* theKey = keys->get(enumerationIndex);
	enumerationIndex++;

	if (enumerationIndex == keys->size())
	{
		enumerationIndex = 0;
		enumerating = false;
	}
	
	return theKey;
}

void PPDictionary::stopEnumeration()
{
	enumerating = false;
	enumerationIndex = 0;
}

PPString PPDictionary::serializeToString()
{
	PPString result;
	
	for (pp_int32 i = 0; i < keys->size(); i++)
	{
		PPDictionaryKey* theKey = keys->get(i);
	
		if (i)
			result.append(";");
			
		result.append(theKey->getKey());
		result.append("=");
		result.append(theKey->getStringValue());
	}
	
	return result;
}
	
PPDictionary* PPDictionary::createFromString(const PPString& string)
{
	PPDictionary* dictionary = new PPDictionary();

	const char* str = string;

	pp_uint32 index = 0;
	
	bool invalid = false;
	
	pp_uint32 startIndex = 0;
	while (index < string.length())
	{
		while (str[index] && str[index] != '=')
			index++;
		
		PPString key;
		if (str[index] == '=')
		{
			key = string.subString(startIndex, index);
			startIndex = ++index;
		}
		else
		{
			invalid = true;
			break; 
		}
		
		while (str[index] && str[index] != ';')
			index++;
		
		PPString value;
		if (index > startIndex)
		{
			value = string.subString(startIndex, index);
			startIndex = ++index;
		}
		
		dictionary->store(key, value);
	}
	
	if (invalid || (string.length() == 0))
	{
		delete dictionary;
		dictionary = NULL;
	}
	
	return dictionary;
}

pp_uint32 PPDictionary::convertFloatToIntNonLossy(float value)
{
	pp_uint32 result;
	
	// not compatible
	if (sizeof(float) != sizeof(result))
		return 0;
	
	memcpy(&result, &value, sizeof(result));
	
	return result;
}

float PPDictionary::convertIntToFloatNonLossy(pp_uint32 value)
{
	float result;
	
	// not compatible
	if (sizeof(float) != sizeof(result))
		return 0;
	
	memcpy(&result, &value, sizeof(result));
	
	return result;
}
