Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#include "DescParser.h"
#include "..\PakLib\PakInterface.h"

using namespace Sexy;

DescParser::DescParser()
{
        mCmdSep = CMDSEP_SEMICOLON;
}

DescParser::~DescParser()
{
}

bool DescParser::Error(const std::string& theError)
{
        mError = theError;
        return false;
}

DataElement* DescParser::Dereference(const std::string& theString)
{
        std::string aDefineName = StringToUpper(theString);

        DataElementMap::iterator anItr = mDefineMap.find(aDefineName);
        if (anItr != mDefineMap.end())
                return anItr->second;
        else
                return NULL;
}

bool DescParser::IsImmediate(const std::string& theString)
{
        return (((theString[0] >= '0') && (theString[0] <= '9')) || (theString[0] == '-') ||
                (theString[0] == '+') || (theString[0] == '\'') || (theString[0] == '"'));
}

std::string DescParser::Unquote(const std::string& theQuotedString)
{
        if ((theQuotedString[0] == '\'') || (theQuotedString[0] == '"'))
        {
                char aQuoteChar = theQuotedString[0];
                std::string aLiteralString;
                bool lastWasQuote = false;
                                       
                for (ulong i = 0; i < theQuotedString.length(); i++)
                {
                        if (theQuotedString[i] == aQuoteChar)
                        {
                                if (lastWasQuote)
                                        aLiteralString += aQuoteChar;
                               
                                lastWasQuote = true;
                        }
                        else
                        {
                                aLiteralString += theQuotedString[i];
                                lastWasQuote = false;
                        }
                }

                return aLiteralString;
        }
        else
                return theQuotedString;
}

bool DescParser::GetValues(ListDataElement* theSource, ListDataElement* theValues)
{
        theValues->mElementVector.clear();
       
        for (ulong aSourceNum = 0; aSourceNum < theSource->mElementVector.size(); aSourceNum++)
        {
                if (theSource->mElementVector[aSourceNum]->mIsList)
                {
                        ListDataElement* aChildList = new ListDataElement();
                        theValues->mElementVector.push_back(aChildList);

                        if (!GetValues((ListDataElement*) theSource->mElementVector[aSourceNum], aChildList))
                                return false;
                }
                else
                {
                        std::string aString = ((SingleDataElement*) theSource->mElementVector[aSourceNum])->mString;

                        if (aString.length() > 0)
                        {                              
                                if ((aString[0] == '\'') || (aString[0] == '"'))
                                {
                                        SingleDataElement* aChildData = new SingleDataElement(Unquote(aString));
                                        theValues->mElementVector.push_back(aChildData);                                       
                                }
                                else if (IsImmediate(aString))
                                {
                                        theValues->mElementVector.push_back(new SingleDataElement(aString));
                                }
                                else
                                {
                                        std::string aDefineName = StringToUpper(aString);

                                        DataElementMap::iterator anItr = mDefineMap.find(aDefineName);

                                        if (anItr == mDefineMap.end())
                                        {
                                                Error("Unable to Dereference \"" + aString + "\"");
                                                return false;
                                        }
                                       
                                        theValues->mElementVector.push_back(anItr->second->Duplicate());
                                }
                        }

                       
                }
        }

        return true;
}

std::string DescParser::DataElementToString(DataElement* theDataElement)
{
        if (theDataElement->mIsList)
        {
                ListDataElement* aListDataElement = (ListDataElement*) theDataElement;

                std::string aString = "(";

                for (ulong i = 0; i < aListDataElement->mElementVector.size(); i++)
                {
                        if (i != 0)
                                aString += ", ";

                        aString += DataElementToString(aListDataElement->mElementVector[i]);
                }

                aString += ")";

                return aString;
        }
        else
        {
                SingleDataElement* aSingleDataElement = (SingleDataElement*) theDataElement;
                return aSingleDataElement->mString;
        }
}

bool DescParser::DataToString(DataElement* theSource, std::string* theString)
{
        *theString = "";

        if (theSource->mIsList)
                return false;

        std::string aDefName = ((SingleDataElement*) theSource)->mString;

        DataElement* aDataElement = Dereference(aDefName);
       
        if (aDataElement != NULL)
        {
                if (aDataElement->mIsList)
                        return false;

                *theString = Unquote(((SingleDataElement*) aDataElement)->mString);
        }
        else
                *theString = Unquote(aDefName);                        

        return true;
}

bool DescParser::DataToInt(DataElement* theSource, int* theInt)
{
        *theInt = 0;

        std::string aTempString;
        if (!DataToString(theSource, &aTempString))
                return false;
       
        if (!StringToInt(aTempString, theInt))
                return false;

        return true;
}

bool DescParser::DataToStringVector(DataElement* theSource, StringVector* theStringVector)
{
        theStringVector->clear();

        ListDataElement aStaticValues;
        ListDataElement* aValues;

        if (theSource->mIsList)
        {
                if (!GetValues((ListDataElement*) theSource, &aStaticValues))
                        return false;

                aValues = &aStaticValues;
        }
        else
        {
                std::string aDefName = ((SingleDataElement*) theSource)->mString;

                DataElement* aDataElement = Dereference(aDefName);
               
                if (aDataElement == NULL)
                {
                        Error("Unable to Dereference \"" + aDefName + "\"");
                        return false;
                }

                if (!aDataElement->mIsList)
                        return false;

                aValues = (ListDataElement*) aDataElement;
        }      

        for (ulong i = 0; i < aValues->mElementVector.size(); i++)
        {
                if (aValues->mElementVector[i]->mIsList)
                {
                        theStringVector->clear();
                        return false;
                }              

                SingleDataElement* aSingleDataElement = (SingleDataElement*) aValues->mElementVector[i];

                theStringVector->push_back(aSingleDataElement->mString);
        }

        return true;
}

bool DescParser::DataToList(DataElement* theSource, ListDataElement* theValues)
{
        if (theSource->mIsList)
        {
                return GetValues((ListDataElement*) theSource, theValues);             
        }

        DataElement* aDataElement = Dereference(((SingleDataElement*) theSource)->mString);
               
        if ((aDataElement == NULL) || (!aDataElement->mIsList))
                return false;

        ListDataElement* aListElement = (ListDataElement*) aDataElement;

        *theValues = *aListElement;

        return true;
}

bool DescParser::DataToIntVector(DataElement* theSource, IntVector* theIntVector)
{
        theIntVector->clear();
       
        StringVector aStringVector;
        if (!DataToStringVector(theSource, &aStringVector))
                return false;  

        for (ulong i = 0; i < aStringVector.size(); i++)
        {              
                int aIntVal;
                if (!StringToInt(aStringVector[i], &aIntVal))
                        return false;

                theIntVector->push_back(aIntVal);
        }

        return true;
}

bool DescParser::DataToDoubleVector(DataElement* theSource, DoubleVector* theDoubleVector)
{
        theDoubleVector->clear();
       
        StringVector aStringVector;
        if (!DataToStringVector(theSource, &aStringVector))
                return false;  

        for (ulong i = 0; i < aStringVector.size(); i++)
        {              
                double aDoubleVal;
                if (!StringToDouble(aStringVector[i], &aDoubleVal))
                        return false;

                theDoubleVector->push_back(aDoubleVal);
        }

        return true;
}

bool DescParser::ParseToList(const std::string& theString, ListDataElement* theList, bool expectListEnd, int* theStringPos)
{
        bool inSingleQuotes = false;
        bool inDoubleQuotes = false;
        bool escaped = false;  

        SingleDataElement* aCurSingleDataElement = NULL;       

        int aStringPos = 0;
       
        if (theStringPos == NULL)
                theStringPos = &aStringPos;

        while (*theStringPos < (int) theString.length())
        {
                bool addSingleChar = false;
                char aChar = theString[(*theStringPos)++];

                bool isSeperator = (aChar == ' ') || (aChar == '\t') || (aChar == '\n') || (aChar == ',');
               
                if (escaped)
                {
                        addSingleChar = true;
                        escaped = false;
                }
                else
                {
                        if ((aChar == '\'') && (!inDoubleQuotes))
                                inSingleQuotes = !inSingleQuotes;
                        else if ((aChar == '"') && (!inSingleQuotes))
                                inDoubleQuotes = !inDoubleQuotes;

                        if (aChar == '\\')
                        {
                                escaped = true;
                        }
                        else if ((!inSingleQuotes) && (!inDoubleQuotes))
                        {
                                if (aChar == ')')
                                {
                                        if (expectListEnd)
                                                return true;
                                        else
                                        {
                                                Error("Unexpected List End");
                                                return false;
                                        }
                                }
                                else if (aChar == '(')
                                {
                                        if (aCurSingleDataElement != NULL)
                                        {
                                                Error("Unexpected List Start");
                                                return false;
                                        }
                                        else
                                        {
                                                ListDataElement* aChildList = new ListDataElement();

                                                if (!ParseToList(theString, aChildList, true, theStringPos))
                                                        return false;

                                                theList->mElementVector.push_back(aChildList);
                                        }
                                }                              
                                else if (isSeperator)
                                {
                                        if (aCurSingleDataElement != NULL)
                                                aCurSingleDataElement = NULL;                                  
                                }
                                else
                                        addSingleChar = true;
                        }
                        else
                                addSingleChar = true;                                          
                }

                if (addSingleChar)
                {
                        if (aCurSingleDataElement == NULL)
                        {
                                aCurSingleDataElement = new SingleDataElement();
                                theList->mElementVector.push_back(aCurSingleDataElement);
                        }

                        aCurSingleDataElement->mString += aChar;
                }
        }

        if (inSingleQuotes)
        {
                Error("Unterminated Single Quotes");
                return false;
        }

        if (inDoubleQuotes)
        {
                Error("Unterminated Double Quotes");
                return false;
        }

        if (expectListEnd)
        {
                Error("Unterminated List");
                return false;
        }

        return true;
}

bool DescParser::ParseDescriptorLine(const std::string& theDescriptorLine)
{
        ListDataElement aParams;
        if (!ParseToList(theDescriptorLine, &aParams, false, NULL))
                return false;
       
        if (aParams.mElementVector.size() > 0)
        {
                if (aParams.mElementVector[0]->mIsList)
                {
                        Error("Missing Command");
                        return false;
                }

                if (!HandleCommand(aParams))
                        return false;
        }

        return true;
}

bool DescParser::LoadDescriptor(const std::string& theFileName)
{
        mCurrentLineNum = 0;
        int aLineCount = 0;
        bool hasErrors = false;

        //Apparently VC6 doesn't have a clear() function for basic_strings
        //mError.clear();
        mError.erase();
        mError.erase(mError.begin());

        PFILE *aStream = p_fopen(theFileName.c_str(),"r");
        if (aStream==NULL)
                return false;  

        char aBuffChar = 0;

        while (!p_feof(aStream))
        {              
                int aChar;
                                               
                bool skipLine = false;
                bool atLineStart = true;
                bool inSingleQuotes = false;
                bool inDoubleQuotes = false;
                bool escaped = false;
                bool isIndented = false;

                for (;;)
                {
                        if (aBuffChar != 0)
                        {
                                aChar = aBuffChar;
                                aBuffChar = 0;
                        }
                        else
                        {
                                aChar = p_fgetc(aStream);
                                if (aChar==EOF)
                                        break;
                        }
                       
                        if (aChar != '\r')
                        {
                                if (aChar == '\n')
                                        aLineCount++;

                                if (((aChar == ' ') || (aChar == '\t')) && (atLineStart))
                                        isIndented = true;

                                if ((!atLineStart) || ((aChar != ' ') && (aChar != '\t') && (aChar != '\n')))
                                {
                                        if (atLineStart)
                                        {
                                                if ((mCmdSep & CMDSEP_NO_INDENT) && (!isIndented) && (mCurrentLine.size() > 0))
                                                {
                                                        // Start a new non-indented line
                                                        aBuffChar = aChar;
                                                        break;
                                                }

                                                if (aChar == '#')
                                                        skipLine = true;

                                                atLineStart = false;
                                        }                                      

                                        if (aChar == '\n')             
                                        {
                                                isIndented = false;
                                                atLineStart = true;                            
                                        }

                                        if ((aChar == '\n') && (skipLine))
                                        {
                                                skipLine = false;                                              
                                        }
                                        else if (!skipLine)
                                        {
                                                if (aChar == '\\' && (inSingleQuotes || inDoubleQuotes) && !escaped)
                                                        escaped = true;
                                                else
                                                {
                                                        if ((aChar == '\'') && (!inDoubleQuotes) && (!escaped))
                                                                inSingleQuotes = !inSingleQuotes;

                                                        if ((aChar == '"') && (!inSingleQuotes) && (!escaped))
                                                                inDoubleQuotes = !inDoubleQuotes;
                                                       
                                                        if ((aChar == ';') && (mCmdSep & CMDSEP_SEMICOLON) && (!inSingleQuotes) && (!inDoubleQuotes))
                                                                break;
                                                       
                                                        if(escaped) // stay escaped for when this is actually parsed
                                                        {
                                                                mCurrentLine += '\\';
                                                                escaped = false;
                                                        }

                                                        if (mCurrentLine.size() == 0)
                                                                mCurrentLineNum = aLineCount + 1;

                                                        mCurrentLine += aChar;
                                                }
                                        }
                                }
                        }
                }

                if (mCurrentLine.length() > 0)
                {
                        if (!ParseDescriptorLine(mCurrentLine))
                        {
                                hasErrors = true;
                                break;
                        }

                        //Apparently VC6 doesn't have a clear() function for basic_strings
                        //mCurrentLine.clear();
                        mCurrentLine.erase();
                }
        }

        //Apparently VC6 doesn't have a clear() function for basic_strings
        //mCurrentLine.clear();
        mCurrentLine.erase();
        mCurrentLineNum = 0;

        p_fclose(aStream);
        return !hasErrors;
}