[pan2] Changed a deque<FilterInfo> into a deque<FilterInfo *>
- From: Petr Kovář <pmkovar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2] Changed a deque<FilterInfo> into a deque<FilterInfo *>
- Date: Sat, 12 Mar 2016 23:56:23 +0000 (UTC)
commit 0b399ecfd28bf6018cf3e24a9c1e4a24ddb0f662
Author: Olaf Seibert <rhialto falu nl>
Date: Sun Mar 6 22:46:33 2016 +0100
Changed a deque<FilterInfo> into a deque<FilterInfo *>
and adjust everything that the compiler now dislikes.
To fix the memory management (the pointed-to objects should be copied
too), use the copy-and-swap-idiom.
pan/data-impl/article-filter.cc | 12 +++---
pan/gui/header-pane.cc | 81 ++++++++++++++++++++-------------------
pan/usenet-utils/filter-info.cc | 65 +++++++++++++++++++++++++++----
pan/usenet-utils/filter-info.h | 19 ++++++++-
pan/usenet-utils/scorefile.cc | 26 ++++++------
5 files changed, 133 insertions(+), 70 deletions(-)
---
diff --git a/pan/data-impl/article-filter.cc b/pan/data-impl/article-filter.cc
index effdf69..b0380aa 100644
--- a/pan/data-impl/article-filter.cc
+++ b/pan/data-impl/article-filter.cc
@@ -62,10 +62,10 @@ ArticleFilter :: test_article (const Data & data,
{
case FilterInfo::AGGREGATE_AND:
pass = true;
- foreach_const (FilterInfo::aggregates_t, criteria._aggregates, it) {
+ foreach_const (FilterInfo::aggregatesp_t, criteria._aggregates, it) {
// assume test passes if test needs body but article not cached
- if (!it->_needs_body || cache.contains(article.message_id) )
- if (!test_article (data, *it, group, article)) {
+ if (!(*it)->_needs_body || cache.contains(article.message_id) )
+ if (!test_article (data, **it, group, article)) {
pass = false;
break;
}
@@ -77,10 +77,10 @@ ArticleFilter :: test_article (const Data & data,
pass = true;
else {
pass = false;
- foreach_const (FilterInfo::aggregates_t, criteria._aggregates, it) {
+ foreach_const (FilterInfo::aggregatesp_t, criteria._aggregates, it) {
// assume test fails if test needs body but article not cached
- if (!it->_needs_body || cache.contains(article.message_id) )
- if (test_article (data, *it, group, article)) {
+ if (!(*it)->_needs_body || cache.contains(article.message_id) )
+ if (test_article (data, **it, group, article)) {
pass = true;
break;
}
diff --git a/pan/gui/header-pane.cc b/pan/gui/header-pane.cc
index 81192fe..3b4c3fa 100644
--- a/pan/gui/header-pane.cc
+++ b/pan/gui/header-pane.cc
@@ -1390,62 +1390,62 @@ HeaderPane :: rebuild_filter (const std::string& text, int mode)
f.set_type_aggregate_and ();
// entry field filter...
- FilterInfo entry_filter;
if (!text.empty())
{
+ FilterInfo *entry_filter = new FilterInfo;
if (mode == SUBJECT)
- entry_filter.set_type_text ("Subject", d);
+ entry_filter->set_type_text ("Subject", d);
else if (mode == AUTHOR)
- entry_filter.set_type_text ("From", d);
+ entry_filter->set_type_text ("From", d);
else if (mode == MESSAGE_ID)
- entry_filter.set_type_text ("Message-ID", d);
+ entry_filter->set_type_text ("Message-ID", d);
else if (mode == SUBJECT_OR_AUTHOR) {
- FilterInfo f1, f2;
- entry_filter.set_type_aggregate_or ();
- f1.set_type_text ("Subject", d);
- f2.set_type_text ("From", d);
- entry_filter._aggregates.push_back (f1);
- entry_filter._aggregates.push_back (f2);
+ FilterInfo *f1 = new FilterInfo, *f2 = new FilterInfo;
+ entry_filter->set_type_aggregate_or ();
+ f1->set_type_text ("Subject", d);
+ f2->set_type_text ("From", d);
+ entry_filter->_aggregates.push_back (f1);
+ entry_filter->_aggregates.push_back (f2);
} else if (mode == SUBJECT_OR_AUTHOR_REGEX) {
- FilterInfo f1, f2;
- entry_filter.set_type_aggregate_or ();
+ FilterInfo *f1 = new FilterInfo, *f2 = new FilterInfo;
+ entry_filter->set_type_aggregate_or ();
d.type = TextMatch::REGEX;
- f1.set_type_text ("Subject", d);
- f2.set_type_text ("From", d);
- entry_filter._aggregates.push_back (f1);
- entry_filter._aggregates.push_back (f2);
+ f1->set_type_text ("Subject", d);
+ f2->set_type_text ("From", d);
+ entry_filter->_aggregates.push_back (f1);
+ entry_filter->_aggregates.push_back (f2);
}
f._aggregates.push_back (entry_filter);
}
if (_action_manager.is_action_active("match-only-read-articles")) {
//std::cerr << LINE_ID << " AND is read" << std::endl;
- FilterInfo tmp;
- tmp.set_type_is_read ();
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_is_read ();
f._aggregates.push_back (tmp);
}
if (_action_manager.is_action_active("match-only-unread-articles")) {
//std::cerr << LINE_ID << " AND is unread" << std::endl;
- FilterInfo tmp;
- tmp.set_type_is_unread ();
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_is_unread ();
f._aggregates.push_back (tmp);
}
if (_action_manager.is_action_active("match-only-cached-articles")) {
//std::cerr << LINE_ID << " AND is cached" << std::endl;
- FilterInfo tmp;
- tmp.set_type_cached ();
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_cached ();
f._aggregates.push_back (tmp);
}
if (_action_manager.is_action_active("match-only-binary-articles")) {
//std::cerr << LINE_ID << " AND has an attachment" << std::endl;
- FilterInfo tmp;
- tmp.set_type_binary ();
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_binary ();
f._aggregates.push_back (tmp);
}
if (_action_manager.is_action_active("match-only-my-articles")) {
//std::cerr << LINE_ID << " AND was posted by me" << std::endl;
- FilterInfo tmp;
- tmp.set_type_posted_by_me ();
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_posted_by_me ();
f._aggregates.push_back (tmp);
}
@@ -1474,7 +1474,7 @@ HeaderPane :: rebuild_filter (const std::string& text, int mode)
//for (size_t i=0; i<ranges.size(); ++i) std::cerr << LINE_ID << " range [" << ranges[i].first << "..." <<
ranges[i].second << "]" << std::endl;
- std::deque<FilterInfo> filters;
+ std::deque<FilterInfo *> filters;
for (size_t i=0; i<ranges.size(); ++i) {
const range_t& range (ranges[i]);
const bool low_bound (range.first == INT_MIN);
@@ -1482,22 +1482,23 @@ HeaderPane :: rebuild_filter (const std::string& text, int mode)
if (low_bound && hi_bound) {
// everything matches -- do nothing
} else if (hi_bound) {
- FilterInfo tmp;
- tmp.set_type_score_ge (range.first);
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_score_ge (range.first);
//std::cerr << LINE_ID << " AND has a score >= " << range.first << std::endl;
filters.push_back (tmp);
} else if (low_bound) {
- FilterInfo tmp;
- tmp.set_type_score_le (range.second);
+ FilterInfo *tmp = new FilterInfo;
+ tmp->set_type_score_le (range.second);
//std::cerr << LINE_ID << " AND has a score <= " << range.second << std::endl;
filters.push_back (tmp);
} else { // not bound on either side; need an aggregate
- FilterInfo s, tmp;
- s.set_type_aggregate_and ();
- tmp.set_type_score_ge (range.first);
- s._aggregates.push_back (tmp);
- tmp.set_type_score_le (range.second);
- s._aggregates.push_back (tmp);
+ FilterInfo *tmp = new FilterInfo;
+ FilterInfo *s = new FilterInfo;
+ s->set_type_aggregate_and ();
+ tmp->set_type_score_ge (range.first);
+ s->_aggregates.push_back (tmp);
+ tmp->set_type_score_le (range.second);
+ s->_aggregates.push_back (tmp);
//std::cerr << LINE_ID << " AND has a in [" << range.first << "..." << range.second << ']' << std::endl;
filters.push_back (s);
}
@@ -1505,9 +1506,9 @@ HeaderPane :: rebuild_filter (const std::string& text, int mode)
if (filters.size()==1) // can fit in an `and' parent
f._aggregates.push_back (filters[0]);
else if (!filters.empty()) { // needs an `or' parent
- FilterInfo s;
- s.set_type_aggregate_or ();
- s._aggregates.swap (filters);
+ FilterInfo *s = new FilterInfo;
+ s->set_type_aggregate_or ();
+ s->_aggregates.swap (filters);
f._aggregates.push_back (s);
}
//std::cerr << LINE_ID << " number of filters: " << f._aggregates.size() << std::endl;
diff --git a/pan/usenet-utils/filter-info.cc b/pan/usenet-utils/filter-info.cc
index 21e525c..7fd7906 100644
--- a/pan/usenet-utils/filter-info.cc
+++ b/pan/usenet-utils/filter-info.cc
@@ -31,6 +31,52 @@ using namespace pan;
****
***/
+/*
+ * Copy-and-swap idiom according to
+ * http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
+ */
+
+FilterInfo :: FilterInfo (const FilterInfo &that)
+ : _type(that._type)
+ , _ge(that._ge)
+ , _header(that._header)
+ , _text(that._text)
+ , _negate(that._negate)
+ , _needs_body(that._needs_body)
+{
+ foreach_const (aggregatesp_t, that._aggregates, it) {
+ _aggregates.push_back (new FilterInfo(**it));
+ }
+}
+
+void
+swap (FilterInfo &first, FilterInfo &second)
+{
+ using std::swap;
+
+ swap (first._type, second._type);
+ swap (first._ge, second._ge);
+ swap (first._header, second._header);
+ swap (first._text, second._text);
+ swap (first._aggregates, second._aggregates);
+ swap (first._negate, second._negate);
+ swap (first._needs_body, second._needs_body);
+}
+
+FilterInfo &FilterInfo::operator = (FilterInfo other)
+{
+ swap (*this, other);
+
+ return *this;
+}
+
+FilterInfo :: ~FilterInfo ()
+{
+ foreach (aggregatesp_t, _aggregates, it) {
+ delete *it;
+ }
+}
+
void
FilterInfo :: clear ()
{
@@ -38,6 +84,9 @@ FilterInfo :: clear ()
_ge = 0;
_header.clear ();
_text.clear ();
+ foreach (aggregatesp_t, _aggregates, it) {
+ delete *it;
+ }
_aggregates.clear ();
_negate = false;
_needs_body = false;
@@ -289,29 +338,29 @@ FilterInfo :: describe () const
{
ret = _("Any of these tests fail:");
ret += "\n";
- foreach_const (aggregates_t, _aggregates, it)
- ret += " " + it->describe() + "\n";
+ foreach_const (aggregatesp_t, _aggregates, it)
+ ret += " " + (*it)->describe() + "\n";
}
else if (_type==AGGREGATE_AND)
{
ret = _("All of these tests pass:");
ret += "\n";
- foreach_const (aggregates_t, _aggregates, it)
- ret += " " + it->describe() + "\n";
+ foreach_const (aggregatesp_t, _aggregates, it)
+ ret += " " + (*it)->describe() + "\n";
}
else if (_type==AGGREGATE_OR && _negate)
{
ret = _("None of these tests pass:");
ret += "\n";
- foreach_const (aggregates_t, _aggregates, it)
- ret += " " + it->describe() + "\n";
+ foreach_const (aggregatesp_t, _aggregates, it)
+ ret += " " + (*it)->describe() + "\n";
}
else if (_type==AGGREGATE_OR)
{
ret = _("Any of these tests pass:");
ret += "\n";
- foreach_const (aggregates_t, _aggregates, it)
- ret += " " + it->describe() + "\n";
+ foreach_const (aggregatesp_t, _aggregates, it)
+ ret += " " + (*it)->describe() + "\n";
}
return ret;
diff --git a/pan/usenet-utils/filter-info.h b/pan/usenet-utils/filter-info.h
index 32e3967..871a8aa 100644
--- a/pan/usenet-utils/filter-info.h
+++ b/pan/usenet-utils/filter-info.h
@@ -25,6 +25,16 @@
#include <pan/general/string-view.h>
#include <pan/general/text-match.h>
+/**
+ * Pre-declaring swap(...) is a bit involved, given the use
+ * of the namespace pan and it needs to be outside.
+ */
+namespace pan {
+ class FilterInfo;
+};
+
+void swap(pan::FilterInfo &first, pan::FilterInfo &second);
+
namespace pan
{
/**
@@ -56,7 +66,10 @@ namespace pan
public:
bool empty() const { return _type == TYPE_ERR; }
FilterInfo () { clear(); }
- virtual ~FilterInfo () { }
+ FilterInfo (const FilterInfo &that);
+ friend void ::swap(FilterInfo &first, FilterInfo &second);
+ FilterInfo &operator = (FilterInfo other);
+ virtual ~FilterInfo ();
public:
@@ -74,11 +87,11 @@ namespace pan
TextMatch _text;
/** Convenience typedef. */
- typedef std::deque<FilterInfo> aggregates_t;
+ typedef std::deque<FilterInfo *> aggregatesp_t;
/** When `_type' is AGGREGATE_OR or AGGREGATE_AND,
these are the filters being or'ed or and'ed together. */
- aggregates_t _aggregates;
+ aggregatesp_t _aggregates;
/** When this is true, the results of the test should be negated. */
bool _negate;
diff --git a/pan/usenet-utils/scorefile.cc b/pan/usenet-utils/scorefile.cc
index ac9d68c..0e0b979 100644
--- a/pan/usenet-utils/scorefile.cc
+++ b/pan/usenet-utils/scorefile.cc
@@ -103,7 +103,7 @@ struct pan::Scorefile::ParseContext
test = &item->test;
if (test)
foreach_const (std::vector<int>, test_offsets, it)
- test = &test->_aggregates[*it];
+ test = test->_aggregates[*it];
return test;
}
@@ -258,11 +258,11 @@ Scorefile :: parse_file (ParseContext& context, const StringView& filename)
line.eat_chars (1); // skip past the '{'
const bool only_one_test_must_pass (line.len>=2 && !memcmp(line.str,"::",2));
- FilterInfo test;
+ FilterInfo *test = new FilterInfo;
if (only_one_test_must_pass)
- test.set_type_aggregate_or ();
+ test->set_type_aggregate_or ();
else
- test.set_type_aggregate_and ();
+ test->set_type_aggregate_and ();
FilterInfo * parent (context.get_current_test ());
context.test_offsets.push_back (parent->_aggregates.size());
@@ -331,9 +331,9 @@ Scorefile :: parse_file (ParseContext& context, const StringView& filename)
StringView val (line.substr (delimiter+1, 0));
val.trim ();
- FilterInfo::aggregates_t& aggregates (context.get_current_test()->_aggregates);
- aggregates.resize (aggregates.size() + 1);
- FilterInfo& test (aggregates.back());
+ FilterInfo::aggregatesp_t& aggregates (context.get_current_test()->_aggregates);
+ aggregates.push_back (new FilterInfo);
+ FilterInfo& test (*aggregates.back());
if (!key.strncasecmp ("Lines", 5))
{
@@ -390,14 +390,14 @@ Scorefile :: parse_file (ParseContext& context, const StringView& filename)
namespace
{
- void normalize_test (FilterInfo& test)
+ void normalize_test (FilterInfo *test)
{
- if ((test._type!=test.AGGREGATE_AND) && (test._type!=test.AGGREGATE_OR))
+ if ((test->_type!=test->AGGREGATE_AND) && (test->_type!=test->AGGREGATE_OR))
return;
- if (test._aggregates.size() == 1)
- test = test._aggregates[0];
- else foreach (FilterInfo::aggregates_t, test._aggregates, it)
+ if (test->_aggregates.size() == 1) {
+ *test = *test->_aggregates[0];
+ } else foreach (FilterInfo::aggregatesp_t, test->_aggregates, it)
normalize_test (*it);
}
}
@@ -418,7 +418,7 @@ Scorefile :: parse_file (const StringView& filename)
foreach (sections_t, _sections, sit)
foreach (items_t, sit->items, it)
- normalize_test (it->test);
+ normalize_test (&it->test);
size_t item_count (0);
foreach (sections_t, _sections, sit)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]