gfxconversion/mifconv/src/mifconv_argumentmanager.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:11:11 +0200
changeset 0 f453ebb75370
child 2 1f6339ced17d
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Mifconv argument manager class.
*
*/


#include "mifconv.h"
#include "mifconv_argumentmanager.h"
#include "mifconv_exception.h"
#include "mifconv_util.h"

// Static singleton initialization
MifConvArgumentManager* MifConvArgumentManager::iInstance = 0;

/**
 * Returns pointer to the singleton object
 */
MifConvArgumentManager* MifConvArgumentManager::Instance()
{
    if( iInstance == 0 )
    {
        iInstance = new MifConvArgumentManager();
    }
    return iInstance;
}

/**
 * Free the allocated memory
 */
void MifConvArgumentManager::Reset()
{
    delete iInstance;
    iInstance = 0;
}

/**
 *
 */
inline void MifConvArgumentManager::THROW_USAGE_EXCEPTION() const
{
	MifConvString usageStr;
	SetUsageString(usageStr);
	throw MifConvException(usageStr, MifConvString(__FILE__), __LINE__);
}

inline void MifConvArgumentManager::THROW_ERROR( const MifConvString& errorMsg, const MifConvString& file, int line ) const
{    
    throw MifConvException( MifConvString("ERROR: " + errorMsg + "\nType mifconv -? for help\n"), file, line);
}

/**
 *
 */
MifConvArgumentManager::MifConvArgumentManager()
:
iEpocRoot(DEFAULT_EPOCROOT)
{
    GetMifEnv();
}

/**
 *
 */
MifConvArgumentManager::~MifConvArgumentManager()
{}

/**
 * This function checks if the given argument is boolean type of argument.
 * Boolean type arguments are listed in a <code>MifConvBooleanArguments</code> table
 * and this function checks if the given string matches any of those. Returns the length
 * of the argument name if found, zero otherwise.
 */
size_t MifConvArgumentManager::IsBooleanArgument( const MifConvString& argName ) const
{
	if( IsArgument(argName) )
	{
		try {
			int tblSize = sizeof(MifConvBooleanArguments) / sizeof(MifConvString);
			for( int i = 0; i < tblSize; ++i )
			{
				size_t tmpLen = MifConvBooleanArguments[i].length();
				if( argName.length() > tmpLen )
				{
                    if( MifConvUtil::CompareIgnoreCase(MifConvString(argName.begin()+1, argName.begin() + 1 + tmpLen), MifConvBooleanArguments[i]) == 0 )
					{
						return tmpLen;
					}
				}
			}
		}
		catch(...)
		{
			THROW_USAGE_EXCEPTION();
		}
	}
	return 0;
}

/**
 * This function checks if the given argument is a help argument.
 * Help arguments are listed in a <code>MifConvHelpArguments</code> table
 * and this function checks if the given string matches any of those. Returns the length
 * of the argument name if found, zero otherwise.
 */
size_t MifConvArgumentManager::IsHelpArgument( const MifConvString& argName ) const
{
	if( IsArgument(argName) )
	{
		try {
			int tblSize = sizeof(MifConvHelpArguments) / sizeof(MifConvString);
			for( int i = 0; i < tblSize; ++i )
			{
				size_t tmpLen = MifConvHelpArguments[i].length();

                // Following check separates -H from -Hheadername.mbg parameter:
                if( argName.length() == tmpLen+1 )
				{
                    if( MifConvUtil::CompareIgnoreCase(MifConvString(argName.begin()+1, argName.begin() + 1 + tmpLen), MifConvHelpArguments[i]) == 0 )
					{
						return tmpLen;
					}
				}
			}
		}
		catch(...)
		{
			THROW_USAGE_EXCEPTION();
		}
	}
	return 0;
}

/**
 * This function checks if the given argument is string type of argument.
 * String type arguments are listed in a <code>MifConvStringArguments</code> table
 * and this function checks if the given string matches any of those. Returns the length
 * of the argument name if found, zero otherwise.
 */
size_t MifConvArgumentManager::IsStringArgument( const MifConvString& argName ) const
{    
	if( IsArgument(argName) )
	{
		try {
			int tblSize = sizeof(MifConvStringArguments) / sizeof(MifConvString);
			for( int i = 0; i < tblSize; ++i )
			{
				size_t tmpLen = MifConvStringArguments[i].length();
				if( argName.length() > tmpLen )
				{
                    if( MifConvUtil::CompareIgnoreCase(MifConvString(argName.begin()+1, argName.begin()+1+tmpLen), MifConvStringArguments[i]) == 0 )
					{
						return tmpLen;
					}
				}				
			}
		}
		catch(...)
		{
			THROW_USAGE_EXCEPTION();
		}
	}
	return 0;
}

/**
 * This function checks if the given argument is string list type of argument.
 * String list type arguments are listed in a <code>MifConvStringListArguments</code> table
 * and this function checks if the given string matches any of those. Returns the length
 * of the argument name if found, zero otherwise.
 */
size_t MifConvArgumentManager::IsStringListArgument( const MifConvString& argName ) const
{
	if( IsArgument(argName) )
	{
		try {
			int tblSize = sizeof(MifConvStringListArguments) / sizeof(MifConvString);
			for( int i = 0; i < tblSize; ++i )
			{
				size_t tmpLen = MifConvStringListArguments[i].length();
				if( argName.length() > tmpLen )
				{
                    if( MifConvUtil::CompareIgnoreCase(MifConvString(argName.begin()+1, argName.begin()+1+tmpLen), MifConvStringListArguments[i]) == 0 )
					{
						return tmpLen;
					}
				}				
			}
		}
		catch(...)
		{
			THROW_USAGE_EXCEPTION();
		}
	}
	return 0;
}

/**
 *
 */
bool MifConvArgumentManager::IsDepthArgument( const MifConvString& argName ) const
{
	if( IsArgument(argName) )
	{
		try {
			int tblSize = sizeof(MifConvDepthArguments) / sizeof(MifConvString);
			for( int i = 0; i < tblSize; ++i )
			{
				size_t tmpLen = MifConvDepthArguments[i].length();
                if( argName.length() > tmpLen )
				{
                    MifConvString trimmedArgument(argName.begin()+1, argName.begin() + 1 + tmpLen);                
                    if( MifConvUtil::CompareIgnoreCase(trimmedArgument, MifConvDepthArguments[i]) == 0 )
					{
						return true;
					}                    
				}
			}
		}
		catch(...)
		{
			THROW_USAGE_EXCEPTION();
		}
	}
	return false;
}

/**
 *
 */
bool MifConvArgumentManager::IsAnimatedFlag( const MifConvString& argName ) const
{
	return IsArgument( argName ) && argName.length() > MifConvAnimatedIconArg.length() && 
        MifConvUtil::CompareIgnoreCase(MifConvString(argName.begin()+1, argName.end() ), MifConvAnimatedIconArg ) == 0;
}

/**
 *
 */
void MifConvArgumentManager::SetTargetFile( const MifConvString& arg )
{
	iTargetFile = arg;
}

/**
 *
 */
const MifConvString& MifConvArgumentManager::TargetFile() const
{
	return iTargetFile;
}

/**
 *
 */
IconDisplayMode MifConvArgumentManager::ConvertToDisplayMode(IconDepth depth) const
{
    MifConvIconDisplayModeMap::const_iterator i = iDisplayModeMap.find(depth);
    if( i != iDisplayModeMap.end() )
        return i->second;

    return DisplayMode_None;    
}

/**
 *
 */
IconDisplayMode MifConvArgumentManager::ConvertToMaskDisplayMode(IconMaskDepth depth) const
{
    MifConvMaskIconDisplayModeMap::const_iterator i = iMaskDisplayModeMap.find(depth);
    if( i != iMaskDisplayModeMap.end() )
        return i->second;

    return DisplayMode_None;    
}

/**
 *
 */
IconDepth MifConvArgumentManager::ConvertToDepth( const MifConvString& depthStr ) const
{
    MifConvIconDepthMap::const_iterator i = iDepthMap.find(depthStr);
    if( i != iDepthMap.end() )
        return i->second;

    return IconDepth_Undefined;    
}
/**
 *
 */
IconMaskDepth MifConvArgumentManager::ConvertToMaskDepth( const MifConvString depthStr ) const
{
    MifConvIconMaskDepthMap::const_iterator i = iMaskDepthMap.find(depthStr);
    if( i != iMaskDepthMap.end() )
        return i->second;

    return IconMaskDepth_Undefined;    
}

/**
 *
 */
void MifConvArgumentManager::Init( const MifConvStringList& argList )
{	    
    // Build maps for mapping depth, mask and displaymode constants:
    PopulateDepthAndMaskMaps();
    // Allocate search paths where to search source files:    
    MifConvString epocRoot(EpocRoot());
         
    // Global icons folder can contain only .svg files:
    iSearchRules.push_back(MifConvSourceSearchRule(MifConvString(epocRoot + S60_ICONS_PATH), vector<MifConvString>(1, SVG_FILE_EXTENSION)));
    // Global bitmaps folder can contain only .bmp files:
    iSearchRules.push_back(MifConvSourceSearchRule(MifConvString(epocRoot + S60_BITMAPS_PATH), vector<MifConvString>(1, BMP_FILE_EXTENSION)));
    // EPOCROOT, if given in environment variables:
    if( epocRoot.length() > 0 )
    {
        iSearchRules.push_back(MifConvSourceSearchRule(epocRoot+EPOC32_PATH, vector<MifConvString>(1, MIFCONV_WILDCARD)));
    }

    AddArguments(argList);

    // check if the parameter file is given:
    const MifConvString& paramFilename = StringValue(MifConvParameterFileArg);
    if( paramFilename.length() > 0 )
    {
        // Add arguments from the parameter file:
        MifConvStringList paramListFromFile;
        ReadParameterFile( paramFilename, paramListFromFile );
        if( paramListFromFile.size() > 0 )
        {
            AddArguments(paramListFromFile, true);
        }
    }
    // Resolve file type extensions using given flags and investigating the existing files:
	FinalizeArguments();
}

/**
 * Read string argument value:
 */
MifConvString MifConvArgumentManager::ReadStringArgument(const MifConvStringList& argList, MifConvStringList::const_iterator& i, unsigned int argNameLen)
{    
    // Take the actual argument value, for example /TmyTempDir --> myTempDir    
    MifConvString argValue((*i).begin() + argNameLen, (*i).end());
    if( argValue.length() > 0 )
    {
        // String arguments can have spaces when they are enclosed with " marks (For example directory names).
        if( argValue[0] == '\"' )
        {
            MifConvString quotedArgValue(argValue);
            // Check if the last char is also ":
            if( quotedArgValue[ quotedArgValue.length()-1 ] == '\"' )
            {                
                return quotedArgValue;
            }

            // See if the next string ends with \" mark, for example "My Folder" is presented with following argument list:
            // argList[0] = "My
            // argList[1] = Folder"
            while(++i != argList.end())
            {
                MifConvString nextString((*i).begin(), (*i).end());
                quotedArgValue += " " + nextString;
                if( nextString[ nextString.length()-1 ] == '\"' )
                {                    
                    return "\"" + quotedArgValue + "\"";
                }
            }
        }
    }    
    return argValue;
}

/**
 * Read string argument value:
 */
void MifConvArgumentManager::ReadStringListArgument(MifConvStringList::const_iterator& i, unsigned int argNameLen, MifConvStringList& StringValueList)
{    
    // Take the actual argument value, for example /imyInputDir;myTempDir --> myTempDir    
    MifConvString argValue((*i).begin() + argNameLen, (*i).end());    
    MifConvUtil::SplitString( argValue, STRING_LIST_ARGUMENT_SEPARATOR, StringValueList );
}

/**
 *
 */
void MifConvArgumentManager::AddArguments( const MifConvStringList& argList, bool paramsFromFile )
{
	MifConvStringList::const_iterator i = argList.begin();

	if( i == argList.end() )
	{		
        THROW_ERROR("No arguments", MifConvString(__FILE__), __LINE__);	
	}

    // Check if help is needed:
    while( i != argList.end() )
    {
        if( IsHelpArgument(*i) )
        {
            THROW_USAGE_EXCEPTION();
        }
        ++i;
    }

    i = argList.begin();

	while( i != argList.end() )
	{	        
		unsigned int argLen = 0;
		if( i == argList.begin() && paramsFromFile == false )
		{
			// First command line argument must be the target file.
            // If the given list (argList) is read from the file, then
            // the first one is not target file.
			if( !IsArgument(*i) )
			{           
			    MifConvString targetFile(ReadStringArgument( argList, i, 0 ));			    
			    // Make sure that the file extension is .mif:
			    targetFile = MifConvUtil::FilenameWithoutExtension(targetFile);
			    targetFile += MifConvString(FILE_EXTENSION_SEPARATOR) + MifConvString(MIF_FILE_EXTENSION);
				SetTargetFile(targetFile);                
			}
			else
			{
                THROW_ERROR( "Target file must be given as first argument.", MifConvString(__FILE__), __LINE__ );                
			}
			++i;
            if( i == argList.end() )
            {
                THROW_ERROR("Missing arguments", MifConvString(__FILE__), __LINE__);
            }
		}
		else if( IsBooleanArgument(*i) )
		{
			// Insert boolean type argument to the boolean arguments list:
			MifConvString argName((*i).begin()+1, (*i).end());
            MifConvUtil::ToLower(argName); // Lower the cases to make comparison easier later
            std::pair<BooleanArgMap::iterator, bool> res = iBooleanArguments.insert(std::make_pair<MifConvString, MifConvBooleanArgument>(
				argName, MifConvBooleanArgument( argName, true )));
            if( res.second == false )
            {
                // parameter already exists in the map, update the value:
                res.first->second = MifConvBooleanArgument( argName, true );
            }
			++i;
		}
		else if( (argLen = (unsigned int) IsStringArgument(*i) ) > 0 )
		{			
			MifConvString argName((*i).begin()+1, (*i).begin() + 1 + argLen);
            MifConvUtil::ToLower(argName); // Lower the cases to make comparison easier later			
            MifConvString argValue(ReadStringArgument( argList, i, argLen+1 ));            
			if( argValue.length() == 0 )
			{
				// Do not accept string arguments with zero length (E.g. "/H")
                THROW_ERROR( "Missing argument value for " + *i, MifConvString(__FILE__), __LINE__ );                
			}
			// Insert string type argument to the string arguments list:
			std::pair<StringArgMap::iterator, bool> res = iStringArguments.insert(std::make_pair<MifConvString, MifConvStringArgument>(
				argName, MifConvStringArgument( argName, argValue )));
            if( res.second == false )
            {
                // parameter already exists in the map, update the value:
                res.first->second = MifConvStringArgument( argName, argValue );
            }
			++i;
		}
        else if( (argLen = (unsigned int) IsStringListArgument(*i)) > 0 )
        {
            MifConvString argName((*i).begin()+1, (*i).begin() + 1 + argLen);
            MifConvUtil::ToLower(argName); // Lower the cases to make comparison easier later			
            MifConvStringList argValue;
            ReadStringListArgument( i, argLen+1, argValue );

            if( argValue.size() == 0 )
			{
				// Do not accept string arguments with zero length (E.g. "/H")
                THROW_ERROR( "Missing argument value for " + *i, MifConvString(__FILE__), __LINE__ );                
			}
			// Insert string list type argument to the string arguments list:
			std::pair<StringListArgMap::iterator, bool> res = iStringListArguments.insert(std::make_pair<MifConvString, MifConvStringListArgument>(
				argName, MifConvStringListArgument( argName, argValue )));
            if( res.second == false )
            {
                // parameter already exists in the map, update the value:
                res.first->second = MifConvStringListArgument( argName, argValue );
            }
			++i;
        }
		else if( IsDepthArgument(*i) )
		{
			// Let's build source file argument...
			// ... first is depth and mask:
			MifConvString depthAndMask(*i);
            MifConvUtil::ToLower(depthAndMask); // Lower the cases to make comparison easier later
			++i;
            // Check that there is still an argument:
            if( i == argList.end() )
            {
                THROW_ERROR( "Missing source file argument.", MifConvString(__FILE__), __LINE__ );                
            }

			// Then we check if animated flag is given next:
			bool isAnimated = IsAnimatedFlag(*i);

			if( isAnimated )
			{
				// This was an animated flag, so next must be filename:
				++i;
                // Check that there is still an argument:
                if( i == argList.end() )
                {
                    THROW_ERROR( "Missing source file argument.", MifConvString(__FILE__), __LINE__ );
                    //THROW_USAGE_EXCEPTION();
                }
			}
			
			// One more check... Check that the next string is not an argument (starting with '-' or '/')
			// It should be a filename for the source icon.
			if( IsArgument(*i) )
			{
                THROW_ERROR( "Missing source file argument.", MifConvString(__FILE__), __LINE__ );                
			}

            MifConvSourceFile srcFile;
            srcFile.SetDepthAndMask(depthAndMask);
            srcFile.SetDisplayMode(ConvertToDisplayMode(srcFile.Depth()));
            srcFile.SetMaskDisplayMode(ConvertToMaskDisplayMode(srcFile.MaskDepth()));
            srcFile.SetFilename(ReadStringArgument( argList, i, 0 ));
            srcFile.SetAnimated(isAnimated);
            iSourceFiles.push_back(srcFile);			
			++i;
		}
		else if( IsAnimatedFlag(*i) )
		{
			// Icon animated flag found
			// Let's see if the next is depth argument:
			++i;
			MifConvString depthAndMask;
			if( IsDepthArgument(*i) )
			{
				depthAndMask = *i;
                MifConvUtil::ToLower(depthAndMask);
				++i;
			}

			// One more check... Check that the next string is not an argument (starting with '-' or '/')
			if( IsArgument(*i) )
			{
                THROW_ERROR( "Missing source file argument.", MifConvString(__FILE__), __LINE__ );                
			}

            MifConvSourceFile srcFile;
            srcFile.SetDepthAndMask(depthAndMask);
            srcFile.SetDisplayMode(ConvertToDisplayMode(srcFile.Depth()));
            srcFile.SetMaskDisplayMode(ConvertToMaskDisplayMode(srcFile.MaskDepth()));
            srcFile.SetFilename(*i);
            srcFile.SetAnimated(true);
            iSourceFiles.push_back(srcFile);
			++i;
		}
		else
		{
            THROW_ERROR( "Invalid argument: " + *i, MifConvString(__FILE__), __LINE__ );            
        }
	}
}

/**
 * Resolves correct type for the source file. Sets also mask filenames for bmp-files:
 */
void MifConvArgumentManager::ResolveSourceFileTypes()
{
    bool extensionFlag = BooleanValue(MifConvUseExtensionArg);

    // check if the input directory is given:
    const MifConvStringList& inputDirList = StringListValue(MifConvIconSourceDirectory);

    // Add user-defined input directory to search directory list, put MIFCONV_WILDCARD
    // as filetype rule, because user defined directory can contain all supported filetypes:
    int indexcounter = 0;
    for( MifConvStringList::const_iterator iDir = inputDirList.begin(); iDir != inputDirList.end(); ++iDir )
    {
        MifConvSourceSearchRule customRule(*iDir, MifConvStringList(1, MIFCONV_WILDCARD));
        MifConvUtil::ReplaceChar(customRule.SearchPath(), INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
        MifConvUtil::RemoveDuplicateDirSeparators(customRule.SearchPath());
        iSearchRules.insert(iSearchRules.begin()+indexcounter, customRule);
        
        ++indexcounter;
    }
    
    for( MifConvSourceFileList::iterator src = iSourceFiles.begin(); src != iSourceFiles.end(); ++ src )
    {
        if( extensionFlag )
        {
            MifConvString extension = MifConvUtil::FileExtension(src->Filename());
            if( !FindAndSetPathAndType( *src, extension ) )
            {                 
                THROW_ERROR_COMMON("File not found " + src->Filename(), MifConvString(__FILE__), __LINE__ );
            }
        }
        else
        {
            // "Use extension" -flag not given, so resolve extensions for source files
            if( !FindAndSetPathAndType( *src, SVGB_BINARY_FILE_EXTENSION ) )
            { 
                if( !FindAndSetPathAndType( *src, SVG_FILE_EXTENSION ) )
                {                
                    if( !FindAndSetPathAndType( *src, BMP_FILE_EXTENSION ) )
                    {                
                        THROW_ERROR_COMMON("File not found " + src->Filename(), MifConvString(__FILE__), __LINE__ );
                    }
                }
            }
        }
    }
}

/**
 *
 */
void MifConvArgumentManager::GetMifEnv()
{    
    // Read EPOCROOT environment variable
    char* tmpPtr = 0;
    tmpPtr = getenv(EPOCROOT_ENV.c_str());
    if( tmpPtr )
    {        
        iEpocRoot = MifConvString(tmpPtr);
        MifConvUtil::ReplaceChar(iEpocRoot, INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
        // Make sure that the last char is directory separator
        if( iEpocRoot.length() > 0 && iEpocRoot.at( iEpocRoot.length()-1) != DIR_SEPARATOR2 )
        {
            iEpocRoot += DIR_SEPARATOR;
        }
    }
}

/**
 *
 */
const MifConvString& MifConvArgumentManager::EpocRoot() const
{
    return iEpocRoot;
}

/**
 *
 */
bool MifConvArgumentManager::FindAndSetPathAndType( MifConvSourceFile& srcFile, const MifConvString& extension )
{    
    // Search the filename first "as is":
    MifConvString tmp( MifConvUtil::FilenameWithoutExtension( srcFile.Filename() ) + MifConvString(FILE_EXTENSION_SEPARATOR) + extension );     
    if( MifConvUtil::FileExists(tmp) )
    {
        srcFile.SetFilename(tmp);
        MifConvUtil::FindAndSetBitmapMaskFile(srcFile);
        return true;
    }

    // If the absolute path was given, return false, because the file was not found with given path and filename. 
    // Otherwise continue searching.
    if( //(srcFile.Filename().length() > 0 && srcFile.Filename().at(0) == DIR_SEPARATOR2) ||
        (srcFile.Filename().length() > 1 && srcFile.Filename().at(1) == ':') )
    {        
        return false;
    }

    // Search from the pre-defined locations:        
    for( SearchRules::iterator i = iSearchRules.begin(); i != iSearchRules.end(); ++i )
    {
        bool validPath = false;
        const MifConvStringList& allowedTypes = i->AllowedFileTypes();

        // See if the file with given extension is allowed to locate in search path.
        // For example, epoc32\s60\icons folder can contain only .svg files and epoc32\s60\bitmaps 
        // can contain only .bmp files:
        for( MifConvStringList::const_iterator typeIter = allowedTypes.begin(); typeIter != allowedTypes.end(); ++typeIter )
        {
            if( *typeIter == MIFCONV_WILDCARD || *typeIter == extension )
            {        
                validPath = true;
                break;
            }
        }

        if( validPath )
        {            
            MifConvString searchPath(i->SearchPath());

            // Make sure that the last char is directory separator
            if( searchPath.length() > 0 && searchPath.at( searchPath.length()-1) != DIR_SEPARATOR2 )
            {
                searchPath += DIR_SEPARATOR;
            }

            searchPath += MifConvUtil::FilenameWithoutExtension( srcFile.Filename() ) + MifConvString(FILE_EXTENSION_SEPARATOR) + extension;

            MifConvUtil::RemoveDuplicateDirSeparators(searchPath);

            if( MifConvUtil::FileExists( searchPath ) )
            {
                srcFile.SetFilename(searchPath);
                MifConvUtil::FindAndSetBitmapMaskFile(srcFile);                
                return true; 
            }  
        }            
    }
    return false;
}

/**
 *
 */
void MifConvArgumentManager::ProcessArgumentPaths()
{
	// Fix directory separators first:
    for( StringArgMap::iterator i = iStringArguments.begin(); i != iStringArguments.end(); ++i )
    {
        MifConvString tmp = i->second.Value();
        MifConvUtil::ReplaceChar(tmp, INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
        MifConvUtil::RemoveDuplicateDirSeparators(tmp);
        i->second.SetValue(tmp);
    }

    // Fix directory separators in source filenames also:
    for( MifConvSourceFileList::iterator j = iSourceFiles.begin(); j != iSourceFiles.end(); ++j )
    {
        MifConvString tmp = j->Filename();
        MifConvUtil::ReplaceChar(tmp, INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
        MifConvUtil::RemoveDuplicateDirSeparators(tmp);
        j->SetFilename(tmp);
    }
    
    // Fix directory separators in search rule directories also:
    for( SearchRules::iterator k = iSearchRules.begin(); k != iSearchRules.end(); ++k )
    {
        MifConvString& tmp = k->SearchPath();
        MifConvUtil::ReplaceChar(tmp, INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
        MifConvUtil::RemoveDuplicateDirSeparators(tmp);
    }

    // Fix target file also:
    MifConvUtil::ReplaceChar(iTargetFile, INCORRECT_DIR_SEPARATOR2, DIR_SEPARATOR2);
    MifConvUtil::RemoveDuplicateDirSeparators(iTargetFile);
}

/**
 *
 */
void MifConvArgumentManager::FinalizeArguments()
{
	ProcessArgumentPaths();
	ResolveSourceFileTypes();
}

/**
 *
 */
void MifConvArgumentManager::SetUsageString( MifConvString& usageStr ) const
{
	usageStr = "";

    usageStr += "Copyright (c) " + MifConvYears + " Nokia Corporation and/or its subsidiary(-ies). All rights reserved.\n";
    usageStr += "\n";
    usageStr += "Usage: mifconv <MIFFILE> [-F<file>] <options> <sources>]\n";
    usageStr += "\n";
    usageStr += "Where:\n";
    usageStr += "  MIFFILE            Specifies the target MIF file to be created\n";
    usageStr += "  -F<file>           Specifies a parameter file, which can contain any of the options\n";
    usageStr += "                        and sources separated by spaces or newlines\n";
    usageStr += "\n";
    usageStr += "Options:\n";
    usageStr += "  -H<file>           Specifies a name of the MIF header file (default extension MBG)\n";
    usageStr += "  -I<dir;dir;...>    Specifies a set of custom source directories where source files\n";
    usageStr += "                        will be searched. As a fallback, global source directories are\n";
    usageStr += "                        used\n";
    usageStr += "  -E                 Specifies that source icons are only loaded with given file\n";
    usageStr += "                        extensions. By default, Mifconv prefers source icons with\n";
    usageStr += "                        extension .SVG over .BMP, regardless of which is given as\n";
    usageStr += "                        a parameter\n";
    usageStr += "  -X                 Disables SVG compression. If this flag is set, SVG icons are\n";
    usageStr += "                        added to MIF file without compressing them first\n";
    usageStr += "  -P<file>           Specifies a path to custom palette file for bitmap files\n";
    usageStr += "  -T<dir>            Specifies a path where temporary files are created\n";
    usageStr += "  -B<file>           Specifies a path for non-default BMConv utility\n";
    usageStr += "  -S<file>           Specifies a path for non-default SVGTBinenCode utility\n";
    usageStr += "  -V<string>         Specifies a non-platform default format version of SVGT binary\n";
    usageStr += "                        conversion. It can be any of the following value:\n";
    usageStr += "                             1      BGR / float encoding\n";
    usageStr += "                             2      BGR / fixed point encoding\n";
    usageStr += "                             3      RGB / fixed point encoding\n";
    usageStr += "                             4      RGB / float encoding\n";
    usageStr += "Sources:\n";
    usageStr += "  [-A] <DEPTH[,MASK]> <FILE> [ [-A] <DEPTH[,MASK]> <FILE> ... ]\n";
    usageStr += "        [-A]         Specifies animated flag for the icon\n";
    usageStr += "        [DEPTH]      Specifies icon depth, it can be any of these values\n";
    usageStr += "                        -1,-2,-4,-8,-c4,-c8,-c12,-c16,-c24,-c32\n";
    usageStr += "        [MASK]       Specifies icon mask depth, it can be any of these values\n";
    usageStr += "                        1,8\n";
    usageStr += "        [FILE]       Specifies path to the input file, supported file extensions are\n";
    usageStr += "                        SVG, SVGB, BMP\n";
    usageStr += "\n";
    usageStr += "Other info:\n";
#ifdef WIN32
    usageStr += "  * '-' or '/' can be used as parameter switch prefix\n";
#endif    
    usageStr += "  * Value of icon mask and depth is meaningful only for bitmap files, but the mask\n";
    usageStr += "    value defines if mask entry will be available or not in the header file\n";
    usageStr += "  * If mask parameter is defined for a BMP file, Mifconv automatically pics\n";
    usageStr += "    a file ending _mask_soft for value 8 and _mask for value 1 of mask\n";
    usageStr += "\n";
    usageStr += "Examples:\n";
    usageStr += "  mifconv mybuttons.mif -Hmybuttons.mbg -c8,8 button1 -c8,8 button2\n";
}

/**
 *
 */
const MifConvString& MifConvArgumentManager::StringValue( const MifConvString& argName ) const
{
	StringArgMap::const_iterator i = iStringArguments.find(argName);
	if( i != iStringArguments.end() )
	{
		return i->second.Value();
	}
	
	return iDummyString;
}

/**
 *
 */
const MifConvStringList& MifConvArgumentManager::StringListValue( const MifConvString& argName ) const
{
	StringListArgMap::const_iterator i = iStringListArguments.find(argName);
	if( i != iStringListArguments.end() )
	{
		return i->second.Value();
	}
	
	return iDummyStringList;
}

/**
 *
 */
bool MifConvArgumentManager::BooleanValue( const MifConvString& argName ) const
{
	BooleanArgMap::const_iterator i = iBooleanArguments.find(argName);
	if( i != iBooleanArguments.end() )
	{
		return i->second.Value();
	}
	
	return false;
}

/**
 *
 */
const MifConvSourceFileList& MifConvArgumentManager::SourceFiles() const
{
	return iSourceFiles;
}

/**
 *
 */
bool MifConvArgumentManager::IsArgument( const MifConvString& str ) const
{
	try {
		return str.at(0) == OPTION_PREFIX1_CHAR || str.at(0) == OPTION_PREFIX2_CHAR;
	}
	catch(...)
	{
		THROW_ERROR("Zero or corrupted string in MifConvArgumentManager::IsArgument()\n", MifConvString(__FILE__), __LINE__);
	}
	return false;
}

/**
 *
 */
void MifConvArgumentManager::PopulateDepthAndMaskMaps()
{
    // Insert value-string pairs for the icon depths:
    iDepthMap.insert(std::make_pair(MifConvDepth_1,    IconDepth_1));
    iDepthMap.insert(std::make_pair(MifConvDepth_2,    IconDepth_2));
    iDepthMap.insert(std::make_pair(MifConvDepth_4,    IconDepth_4));
    iDepthMap.insert(std::make_pair(MifConvDepth_8,    IconDepth_8));
    iDepthMap.insert(std::make_pair(MifConvDepth_c4,   IconDepth_c4));
    iDepthMap.insert(std::make_pair(MifConvDepth_c8,   IconDepth_c8));
    iDepthMap.insert(std::make_pair(MifConvDepth_c12,  IconDepth_c12));
    iDepthMap.insert(std::make_pair(MifConvDepth_c16,  IconDepth_c16));
    iDepthMap.insert(std::make_pair(MifConvDepth_c24,  IconDepth_c24));
    iDepthMap.insert(std::make_pair(MifConvDepth_c32,  IconDepth_c32));
    
    // Insert value-string pairs for the icon masks:
    iMaskDepthMap.insert(std::make_pair(MifConvMaskDepth_1, IconMaskDepth_1));
    iMaskDepthMap.insert(std::make_pair(MifConvMaskDepth_8, IconMaskDepth_8));

    // Insert value-pairs for display modes:
    iDisplayModeMap.insert(std::make_pair(IconDepth_1,      DisplayMode_Gray2));
    iDisplayModeMap.insert(std::make_pair(IconDepth_2,      DisplayMode_Gray4));
    iDisplayModeMap.insert(std::make_pair(IconDepth_4,      DisplayMode_Gray16));
    iDisplayModeMap.insert(std::make_pair(IconDepth_8,      DisplayMode_Gray256));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c4,     DisplayMode_Color16));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c8,     DisplayMode_Color256));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c12,    DisplayMode_Color4K));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c16,    DisplayMode_Color64K));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c24,    DisplayMode_Color16M));
    iDisplayModeMap.insert(std::make_pair(IconDepth_c32,    DisplayMode_Color16MU));

    iMaskDisplayModeMap.insert(std::make_pair(IconMaskDepth_1,  DisplayMode_Gray2));
    iMaskDisplayModeMap.insert(std::make_pair(IconMaskDepth_8,  DisplayMode_Gray256));
}

/**
 *
 */
void MifConvArgumentManager::ReadParameterFile(const MifConvString& paramFilename, MifConvStringList& paramList)
{
    // Check if the file exists:
    if( MifConvUtil::FileExists(paramFilename) == false )
    {
        THROW_ERROR_COMMON("Unable to open file for reading! " + paramFilename, MifConvString(__FILE__), __LINE__ );
    }

    MifConvFileData paramFileData = MifConvUtil::FileContents(paramFilename);    

    MifConvString tmpString;
    for(size_t i = 0; i < paramFileData.second; ++i )
    {
        if( MifConvUtil::IsWhiteSpace(paramFileData.first[i]) == false )
        {
            tmpString += paramFileData.first[i];
        }
        else if( tmpString.length() > 0 )
        {
            paramList.push_back( tmpString );            
            tmpString = MifConvString();       
        }
    }

    if( tmpString.length() > 0 )
    {
        paramList.push_back( tmpString );
        tmpString = MifConvString();
    }
    delete[] paramFileData.first;
}

/**
 * Helper class for source search rules
 */

MifConvSourceSearchRule::MifConvSourceSearchRule(const MifConvString& path, const MifConvStringList& types)
:
iSearchPath(path),
iAllowedFileTypes(types)
{}

MifConvSourceSearchRule::~MifConvSourceSearchRule()
{}

const MifConvString& MifConvSourceSearchRule::SearchPath() const 
{ 
    return iSearchPath; 
}

MifConvString& MifConvSourceSearchRule::SearchPath() 
{ 
    return iSearchPath; 
}

const MifConvStringList& MifConvSourceSearchRule::AllowedFileTypes() const
{
    return iAllowedFileTypes;
}