Moved is_windows_item() to anonymous namespace,

fixed tabs, added parsing break in OnEndElement()
This commit is contained in:
Alex Novichkov
2014-01-24 09:09:34 +04:00
parent ec85b3cfee
commit 826deeaa9d

View File

@@ -56,28 +56,25 @@ namespace
#define ATTR_URL "url"
#define ATTR_VERSION NS_SPARKLE_NAME("version")
#define ATTR_SHORTVERSION NS_SPARKLE_NAME("shortVersionString")
#define ATTR_OS NS_SPARKLE_NAME("os")
#define OS_MARKER "windows"
#define ATTR_OS NS_SPARKLE_NAME("os")
#define OS_MARKER "windows"
// context data for the parser
struct ContextData
{
ContextData(Appcast& a, XML_Parser& p)
: appcast(a),
parser(p),
ContextData(XML_Parser& p)
: parser(p),
in_channel(0), in_item(0), in_relnotes(0), in_title(0), in_description(0)
{}
// appcast we're parsing into
Appcast& appcast;
// the parser we're using
XML_Parser& parser;
// is inside <channel>, <item> or <sparkle:releaseNotesLink>, <title>, or <description> respectively?
int in_channel, in_item, in_relnotes, in_title, in_description;
std::vector<Appcast> items;
// parsed <item>s
std::vector<Appcast> items;
};
@@ -92,8 +89,8 @@ void XMLCALL OnStartElement(void *data, const char *name, const char **attrs)
else if ( ctxt.in_channel && strcmp(name, NODE_ITEM) == 0 )
{
ctxt.in_item++;
Appcast item;
ctxt.items.push_back(item);
Appcast item;
ctxt.items.push_back(item);
}
else if ( ctxt.in_item )
{
@@ -111,20 +108,20 @@ void XMLCALL OnStartElement(void *data, const char *name, const char **attrs)
}
else if (strcmp(name, NODE_ENCLOSURE) == 0 )
{
const int size = ctxt.items.size();
const int size = ctxt.items.size();
for ( int i = 0; attrs[i]; i += 2 )
{
const char *name = attrs[i];
const char *value = attrs[i+1];
if ( strcmp(name, ATTR_URL) == 0 )
ctxt.items[size-1].DownloadURL = value;
if ( strcmp(name, ATTR_URL) == 0 )
ctxt.items[size-1].DownloadURL = value;
else if ( strcmp(name, ATTR_VERSION) == 0 )
ctxt.items[size-1].Version = value;
else if ( strcmp(name, ATTR_SHORTVERSION) == 0 )
ctxt.items[size-1].ShortVersionString = value;
else if ( strcmp(name, ATTR_OS) == 0 )
ctxt.items[size-1].Os = value;
else if ( strcmp(name, ATTR_OS) == 0 )
ctxt.items[size-1].Os = value;
}
}
}
@@ -149,13 +146,17 @@ void XMLCALL OnEndElement(void *data, const char *name)
}
else if ( ctxt.in_channel && strcmp(name, NODE_ITEM) == 0 )
{
ctxt.in_item--;
ctxt.in_item--;
if (ctxt.items[ctxt.items.size()-1].Os == OS_MARKER) {
// we've found os-specific <item>, no need to continue parsing
XML_StopParser(ctxt.parser, XML_TRUE);
}
}
else if ( strcmp(name, NODE_CHANNEL) == 0 )
{
ctxt.in_channel--;
// we've reached the end of <channel> element,
// so we stop parsing
// we've reached the end of <channel> element,
// so we stop parsing
XML_StopParser(ctxt.parser, XML_TRUE);
}
}
@@ -164,7 +165,7 @@ void XMLCALL OnEndElement(void *data, const char *name)
void XMLCALL OnText(void *data, const char *s, int len)
{
ContextData& ctxt = *static_cast<ContextData*>(data);
const int size = ctxt.items.size();
const int size = ctxt.items.size();
if ( ctxt.in_relnotes )
ctxt.items[size-1].ReleaseNotesURL.append(s, len);
@@ -174,6 +175,11 @@ void XMLCALL OnText(void *data, const char *s, int len)
ctxt.items[size-1].Description.append(s, len);
}
bool is_windows_item(const Appcast &item)
{
return item.Os == OS_MARKER;
}
} // anonymous namespace
@@ -181,18 +187,13 @@ void XMLCALL OnText(void *data, const char *s, int len)
Appcast class
*--------------------------------------------------------------------------*/
bool is_windows_item(const Appcast &item)
{
return item.Os == OS_MARKER;
}
void Appcast::Load(const std::string& xml)
{
XML_Parser p = XML_ParserCreateNS(NULL, NS_SEP);
if ( !p )
throw std::runtime_error("Failed to create XML parser.");
ContextData ctxt(*this, p);
ContextData ctxt(p);
XML_SetUserData(p, &ctxt);
XML_SetElementHandler(p, OnStartElement, OnEndElement);
@@ -210,12 +211,12 @@ void Appcast::Load(const std::string& xml)
XML_ParserFree(p);
// Search for first <item> which has "sparkle:os=windows" attribute.
// If none, use the first item.
std::vector<Appcast>::iterator it = std::find_if(ctxt.items.begin(), ctxt.items.end(), is_windows_item);
if (it == ctxt.items.end())
it = ctxt.items.begin();
*this = *it;
// Search for first <item> which has "sparkle:os=windows" attribute.
// If none, use the first item.
std::vector<Appcast>::iterator it = std::find_if(ctxt.items.begin(), ctxt.items.end(), is_windows_item);
if (it == ctxt.items.end())
it = ctxt.items.begin();
*this = *it;
}
} // namespace winsparkle