1
0

Implemented cCompositeChat::ParseText(), incl. self-test.

This commit is contained in:
madmaxoft 2014-02-16 23:31:47 +01:00
parent b0dbe51210
commit 4a24e39ac1
2 changed files with 211 additions and 1 deletions

View File

@ -10,6 +10,96 @@
#if SELF_TEST
/** A simple self-test that verifies that the composite chat parser is working properly. */
class SelfTest_CompositeChat
{
public:
SelfTest_CompositeChat(void)
{
fprintf(stderr, "cCompositeChat self test...\n");
TestParser1();
TestParser2();
TestParser3();
TestParser4();
TestParser5();
fprintf(stderr, "cCompositeChat self test finished.\n");
}
void TestParser1(void)
{
cCompositeChat Msg;
Msg.ParseText("Testing @2color codes and http://links parser");
const cCompositeChat::cParts & Parts = Msg.GetParts();
assert(Parts.size() == 4);
assert(Parts[0]->m_PartType == cCompositeChat::ptText);
assert(Parts[1]->m_PartType == cCompositeChat::ptText);
assert(Parts[2]->m_PartType == cCompositeChat::ptUrl);
assert(Parts[3]->m_PartType == cCompositeChat::ptText);
assert(Parts[0]->m_Style == "");
assert(Parts[1]->m_Style == "@2");
assert(Parts[2]->m_Style == "@2");
assert(Parts[3]->m_Style == "@2");
}
void TestParser2(void)
{
cCompositeChat Msg;
Msg.ParseText("@3Advanced stuff: @5overriding color codes and http://links.with/@4color-in-them handling");
const cCompositeChat::cParts & Parts = Msg.GetParts();
assert(Parts.size() == 4);
assert(Parts[0]->m_PartType == cCompositeChat::ptText);
assert(Parts[1]->m_PartType == cCompositeChat::ptText);
assert(Parts[2]->m_PartType == cCompositeChat::ptUrl);
assert(Parts[3]->m_PartType == cCompositeChat::ptText);
assert(Parts[0]->m_Style == "@3");
assert(Parts[1]->m_Style == "@5");
assert(Parts[2]->m_Style == "@5");
assert(Parts[3]->m_Style == "@5");
}
void TestParser3(void)
{
cCompositeChat Msg;
Msg.ParseText("http://links.starting the text");
const cCompositeChat::cParts & Parts = Msg.GetParts();
assert(Parts.size() == 2);
assert(Parts[0]->m_PartType == cCompositeChat::ptUrl);
assert(Parts[1]->m_PartType == cCompositeChat::ptText);
assert(Parts[0]->m_Style == "");
assert(Parts[1]->m_Style == "");
}
void TestParser4(void)
{
cCompositeChat Msg;
Msg.ParseText("links finishing the text: http://some.server");
const cCompositeChat::cParts & Parts = Msg.GetParts();
assert(Parts.size() == 2);
assert(Parts[0]->m_PartType == cCompositeChat::ptText);
assert(Parts[1]->m_PartType == cCompositeChat::ptUrl);
assert(Parts[0]->m_Style == "");
assert(Parts[1]->m_Style == "");
}
void TestParser5(void)
{
cCompositeChat Msg;
Msg.ParseText("http://only.links");
const cCompositeChat::cParts & Parts = Msg.GetParts();
assert(Parts.size() == 1);
assert(Parts[0]->m_PartType == cCompositeChat::ptUrl);
assert(Parts[0]->m_Style == "");
}
} gTest;
#endif // SELF_TEST
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCompositeChat:
@ -101,7 +191,99 @@ void cCompositeChat::AddSuggestCommandPart(const AString & a_Text, const AString
void cCompositeChat::ParseText(const AString & a_ParseText)
{
// TODO
size_t len = a_ParseText.length();
size_t first = 0; // First character of the currently parsed block
AString CurrentStyle;
AString CurrentText;
for (size_t i = 0; i < len; i++)
{
switch (a_ParseText[i])
{
case '@':
{
// Color code
i++;
if (i >= len)
{
// Not enough following text
break;
}
if (a_ParseText[i] == '@')
{
// "@@" escape, just put a "@" into the current text and keep parsing as text
if (i > first + 1)
{
CurrentText.append(a_ParseText.c_str() + first, i - first - 1);
}
first = i + 1;
continue;
}
else
{
// True color code. Create a part for the CurrentText and start parsing anew:
if (i >= first)
{
CurrentText.append(a_ParseText.c_str() + first, i - first - 1);
first = i + 1;
}
if (!CurrentText.empty())
{
m_Parts.push_back(new cTextPart(CurrentText, CurrentStyle));
CurrentText.clear();
}
AddStyle(CurrentStyle, a_ParseText.substr(i - 1, 2));
}
break;
}
case ':':
{
const char * LinkPrefixes[] =
{
"http",
"https"
};
for (size_t Prefix = 0; Prefix < ARRAYCOUNT(LinkPrefixes); Prefix++)
{
size_t PrefixLen = strlen(LinkPrefixes[Prefix]);
if (
(i >= first + PrefixLen) && // There is enough space in front of the colon for the prefix
(strncmp(a_ParseText.c_str() + i - PrefixLen, LinkPrefixes[Prefix], PrefixLen) == 0) // the prefix matches
)
{
// Add everything before this as a text part:
if (i > first + PrefixLen)
{
CurrentText.append(a_ParseText.c_str() + first, i - first - PrefixLen);
first = i - PrefixLen;
}
if (!CurrentText.empty())
{
AddTextPart(CurrentText, CurrentStyle);
CurrentText.clear();
}
// Go till the last non-whitespace char in the text:
for (; i < len; i++)
{
if (isspace(a_ParseText[i]))
{
break;
}
}
AddUrlPart(a_ParseText.substr(first, i - first), a_ParseText.substr(first, i - first), CurrentStyle);
first = i;
break;
}
} // for Prefix - LinkPrefix[]
break;
} // case ':'
} // switch (a_ParseText[i])
} // for i - a_ParseText[]
if (first < len)
{
AddTextPart(a_ParseText.substr(first, len - first), CurrentStyle);
}
}
@ -117,6 +299,29 @@ void cCompositeChat::SetMessageType(eMessageType a_MessageType)
void cCompositeChat::AddStyle(AString & a_Style, const AString & a_AddStyle)
{
if (a_AddStyle.empty())
{
return;
}
if (a_AddStyle[0] == '@')
{
size_t idx = a_Style.find('@');
if ((idx != AString::npos) && (idx != a_Style.length()))
{
a_Style.erase(idx, 2);
}
a_Style.append(a_AddStyle);
return;
}
a_Style.append(a_AddStyle);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cCompositeChat::cBasePart:

View File

@ -165,6 +165,11 @@ protected:
/** The message type, as indicated by prefixes. */
eMessageType m_MessageType;
/** Adds a_AddStyle to a_Style; overwrites the existing style if appropriate.
If the style already contains something that a_AddStyle overrides, it is erased first. */
void AddStyle(AString & a_Style, const AString & a_AddStyle);
} ; // tolua_export