const std::streamsize XMLDocument::_parseString(const std::string& input, XML::elements& output)
{
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);
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;
stream.getline(cbuff, cLength, '>');
lbegin = cbuff;
while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n'))
lbegin++;
if (lbegin[0] != '<')
{
delete [] cString;
delete [] cbuff;
return 0;
}
lend = lbegin;
do
lend++;
while ((lend[0] != ' ') && (lend[0] != '>') && (lend[0] != '\0'));
tend = lend[0];
lend[0] = '\0';
out.element = std::string(++lbegin);
lend[0] = tend;
lbegin = lend;
while ((lbegin[0] != '\0') && (lbegin[0] != '>') && (lbegin < cend))
{
while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend))
lbegin++;
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';
if ((strcmp(lbegin, "/") == 0) || (strcmp(lbegin, "?") == 0) || (strcmp(lbegin, "!") == 0))
{
lend[0] = tend;
noEndTag = true;
break;
}
tAttribute.name = std::string(lbegin);
lend[0] = tend;
if (lend[0] != '=')
{
do
lend++;
while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend));
}
if (lend[0] != '=')
tAttribute.value = tAttribute.name;
else
{
lbegin = lend;
do
lbegin++;
while ((lbegin[0] == ' ') || (lbegin[0] == '\t') || (lbegin[0] == '\n') && (lbegin < cend));
lend = lbegin;
if ((lbegin[0] == '"') || (lbegin[0] == '\''))
{
do
lend++;
while ((lend[0] != '"') && (lend[0] != '\'') && (lend[0] != '\0') && (lend < cend));
lbegin++;
}
else
do
lend++;
while ((lend[0] != ' ') && (lend[0] != '\t') && (lend[0] != '\0') && (lend[0] != '\n') && (lend < cend));
tend = lend[0];
lend[0] = '\0';
tAttribute.value = std::string(lbegin);
lend[0] = tend;
lend++;
}
out.attributes.push_back(tAttribute);
lbegin = lend;
}
if (!noEndTag)
{
{
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;
}
stream.getline(cbuff, cLength, '<');
stream.seekg(-1, std::ios_base::cur);
std::string tVal(cbuff);
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()));
delete [] out.valBuff;
delete out.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);
}
}