KLibrary - Code Sample

/*
Recursively parses the input string and places the parsed elements and attributes in the output parameter.
*/
const std::streamsize XMLDocument::_parseString(const std::string& input, XML::elements& output)
{
    //Generate a stream from the input
    std::streamsize cLength = std::streamsize(input.length() + 1);
    char* cString = new char[cLength + 1];
    strcpy_s(cString, cLength, input.c_str());
    std::strstream stream(cString, std::streamsize(cLength), std::ios_base::in);
    
    //Store some space for us
    XML::Element out;
    XML::Attribute tAttribute;
    
    char* cbuff = new char[cLength];
    char* endtag = 0;
    char *lbegin, *lend;
    char tend;
    const char* const cend = cbuff + cLength;
    bool noEndTag = false;
    
    //Find element
    stream.getline(cbuff, cLength, '>');
    
        //Find first non-whitespace
    lbegin = cbuff;
    while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n'))
        lbegin++;
    
    if (lbegin[0] != '<')
    {
        //Unable to parse the XML
        delete [] cString;
        delete [] cbuff;
        return 0;
    }
    
        //Find end of tag name
    lend = lbegin;
    do
        lend++;
    while ((lend[0] != ' ') && (lend[0] != '>') && (lend[0] != '\0'));
    tend = lend[0];
    lend[0] = '\0';
    
        //Save element name
    out.element = std::string(++lbegin);
    lend[0] = tend;
    
    //Seperate attributes
    lbegin = lend;
    while ((lbegin[0] != '\0') && (lbegin[0] != '>') && (lbegin < cend))
    {
        //Find first non-whitespace
        while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend))
            lbegin++;
        
        //Find end of attribute name
        lend = lbegin;
        do
            lend++;
        while ((lend[0] != '=') && (lend[0] != '>') && (lend[0] != ' ') && (lend[0] != '\0') && (lend[0] != '\t') && (lend[0] != '\n') && (lend < cend));
        tend = lend[0];
        lend[0] = '\0';
        
        //Handle self-closed tags (ended with a '/>' or a '?>' or a '!>)
        if ((strcmp(lbegin, "/") == 0) || (strcmp(lbegin, "?") == 0) || (strcmp(lbegin, "!") == 0))
        {
            lend[0] = tend;
            noEndTag = true;
            break;
        }
        tAttribute.name = std::string(lbegin);
        
        lend[0] = tend;
        
        //Find the equals...theres a space between the name and the equals, or no equals
        if (lend[0] != '=')
        {
            do
                lend++;
            while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend));
        }
        
        //Handle non-well formed XML (no attribute value)
        if (lend[0] != '=')
            tAttribute.value = tAttribute.name;
        else
        {
            //Ignore white space between the equals and the value
            lbegin = lend;
            do
                lbegin++;
            while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend));
            
            //Handle both quations and no quotations
            lend = lbegin;
            if ((lbegin[0] == '"') || (lbegin[0] == '\''))
            {
                //Find end quotation
                do
                    lend++;
                while ((lend[0] != '"') && (lend[0] != '\'') && (lend[0] != '\0') && (lend < cend));
                lbegin++;
            }
            else
                //Find first white space
                do
                    lend++;
                while ((lend[0] != ' ') && (lend[0] != '\t') && (lend[0] != '\0') && (lend[0] != '\n') && (lend < cend));
                
            tend = lend[0];
            lend[0] = '\0';
            
            //Store the value
            tAttribute.value = std::string(lbegin);
            
            lend[0] = tend;
            lend++;
        }
        
        //Store the attribute
        out.attributes.push_back(tAttribute);
        lbegin = lend;
    }
    
    //Find value
    if (!noEndTag)
    {
        //Calculate end tag
        {
            endtag = new char[cLength + 3];
            endtag[0] = '<';
            endtag[1] = '/';
            endtag[2] = 0;
            
            const char* s = out.element.c_str();
            char* t = endtag;
            t += 2;
            const char* e = endtag + 2 + cLength;
            const char* E = s + out.element.length();
            while ((t < e) && (s < E) && (s[0] != '\0'))
            {
                *t = *s;
                s++;
                t++;
            }
            *t = 0;
        }
        
        //Init varibles
        stream.getline(cbuff, cLength, '<');
        stream.seekg(-1, std::ios_base::cur);
        std::string tVal(cbuff);
        
        //Find end tag
        do
        {
            stream.getline(cbuff, cLength, '>');
            lbegin = cbuff;
            while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n'))
                lbegin++;
            if (strcmp(lbegin, endtag) != 0)
            {
                tVal += cbuff;
                tVal += '>';
            }
            else
                break;
        } while (stream.good() && (!stream.eof()));
        
        //Do some clean-up
        delete [] out.valBuff;
        delete out.value;
        
        /*Check for and parse children from the value*/
        lbegin = cbuff;
        out.buffLength = tVal.length() + 1;
        out.valBuff = new char[out.buffLength + 1];
        strcpy_s(out.valBuff, out.buffLength, tVal.c_str());
        std::strstream t;
        out.value = new std::strstream(out.valBuff, std::streamsize(strlen(out.valBuff)));
        std::streamsize change = 0;
        do
        {
            change  = _parseString(tVal, out.children);
            tVal.erase(0, change);
        } while (change != 0);
    }
}