Apply GPLv3 to all sources
[Yara.git] / lib / Yara / Renderer.cpp
blobce3d01ebaac563f8c2ec869f81fed7c8481cba3a
1 /*
2 * Yara: Yet Another RSS Aggregator
3 * Copyright (C) 2007 Ronald Landheer-Cieslak
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "Renderer.h"
18 #include <algorithm>
19 #include <memory>
20 #include "Parser.h"
21 #include "Template.h"
22 #include "Private/RenderingChannelInserter.h"
23 #include "Private/RenderingItemInserter.h"
25 namespace Yara
27 namespace
29 template < typename InfoType, typename InserterType >
30 void render__(std::ostream & target, const InfoType & info, const std::string & input, InserterType (*getter)(const std::string &))
32 std::string::const_iterator begin(input.begin());
33 std::string::const_iterator where(input.begin());
34 std::string::const_iterator end(input.end());
36 while (where != end)
38 std::string::size_type tag_start(input.find("$$__", std::distance(begin, where)));
39 std::string::size_type tag_end(input.find("__$$", tag_start));
40 if (tag_start != std::string::npos && tag_end != std::string::npos)
42 // when we get here, we can at least push out everything
43 // between the current value of where and the start of the
44 // current tag
45 std::copy(where, where + (tag_start - std::distance(begin, where)), std::ostream_iterator< char >(target));
46 // the tag itself is between tag_start + 4 (the size of "$$__") and tag_end
47 std::string tag(begin + tag_start + 4/* sizeof $$__ */, begin + tag_end);
48 InserterType inserter(getter(tag));
49 if (!inserter)
51 // we haven't found the tag. The policy is therefore to add it
52 // to the target stream and look again
53 std::advance(where, tag_start);
54 std::copy(where, where + 4/* sizeof $$__ */, std::ostream_iterator< char >(target));
55 std::advance(where, 4/* sizeof $$__ */);
57 else
58 { // we've found a real tag. We'll use its inserter to add it to the target
59 // stream and advance the where iterator to the end of the tag
60 inserter(target, info);
61 std::advance(where, tag_end + 4 - std::distance(begin, where));
64 else
66 std::copy(where, end, std::ostream_iterator< char >(target));
67 where = end;
73 struct Renderer::Data
75 Data(const Template & _template)
76 : template_(new Template(_template))
77 { /* no-op */ }
79 std::auto_ptr< Template > template_;
82 Renderer::Renderer(const Template & _template)
83 : data_(new Data(_template))
84 { /* no-op */ }
86 Renderer::~Renderer()
88 delete data_;
91 void Renderer::render(std::ostream & target, const Parser & parser)
93 Details::ChannelInfo channel_info(parser.getChannelInfo());
95 render__(target, channel_info, data_->template_->getHeader(), Private::getRenderingChannelInserter);
96 unsigned int item_count(parser.getItemCount());
97 for (unsigned int item_index(0); item_index < item_count; ++item_index)
99 Details::ItemInfo item(parser.getItem(item_index));
100 render__(target, item, data_->template_->getItem(), Private::getRenderingItemInserter);
102 render__(target, channel_info, data_->template_->getFooter(), Private::getRenderingChannelInserter);