void filter(image& img, const filter_t& filter) { auto fw = filter.size1(); auto fh = filter.size2(); auto num_channels = gil::num_channels<image::pixel_t>(); // Calculates the correlation result for each region. The correlation result // is calculated by multiplying the respective elements in neighbourhood and // filter mask and then taking the sum of those elements. This is done for // each channel of the pixel. nlfilter(img, fw, fh, [&](const ublas::matrix<image::pixel_t>& neighbourhood) { image::pixel_t correlation; for(decltype(fw) i = 0; i < fw; ++i) { for(decltype(fh) j = 0; j < fh; ++j) { const auto& src = neighbourhood(i, j); for(auto c = 0; c < num_channels; ++c) { auto element_corr = src[c] * filter(i, j); if(i == 0 && j == 0) { correlation[c] = element_corr; } else { correlation[c] += element_corr; } } } } return correlation; }); }
// Populates a filter with random values. // Note: A filter with a small r_bits is difficult to fill. static void populate(filter_t &filter, size_t insertion_tries = SIZE_MAX) { auto gen_fp = make_fp_generator(filter); while (!filter.full() && insertion_tries) { filter.insert(gen_fp()); --insertion_tries; } }
virtual void OnRehash(const std::string ¶meter) { // reload our config file on rehash - we must destroy and re-allocate the classes // to call the constructor again and re-read our data. ConfigReader* Conf = new ConfigReader(ServerInstance); std::string filterfile = Conf->ReadValue("filter","file",0); // this automatically re-reads the configuration file into the class ConfigReader* MyConf = new ConfigReader(ServerInstance, filterfile); if ((filterfile == "") || (!MyConf->Verify())) { // bail if the user forgot to create a config file FilterException e; throw(e); } for (filter_t::iterator n = filters.begin(); n != filters.end(); n++) { DELETE(n->second); } filters.clear(); for (int index = 0; index < MyConf->Enumerate("keyword"); index++) { std::string pattern = MyConf->ReadValue("keyword","pattern",index); std::string reason = MyConf->ReadValue("keyword","reason",index); std::string do_action = MyConf->ReadValue("keyword","action",index); if (do_action == "") do_action = "none"; Filter* x = new Filter; x->reason = reason; x->action = do_action; filters[pattern] = x; } ServerInstance->Log(DEFAULT,"m_filter: read configuration from "+filterfile); DELETE(Conf); DELETE(MyConf); }
static auto make_fp_generator(const filter_t &filter) { const size_t fp_bits = filter.quotient_bits() + filter.remainder_bits(); const value_t max_fp = (value_t{1} << fp_bits) - 1; mt19937 gen(823076453); uniform_int_distribution<value_t> dist(0, max_fp); return [ gen = std::move(gen), dist ]() mutable { return dist(gen); }; }
static auto make_insertion_decision_generator(const filter_t &filter) { using param_t = std::bernoulli_distribution::param_type; bernoulli_distribution dist; minstd_rand gen(3782348); return [&filter, gen = std::move(gen), dist ]() mutable { if (filter.empty()) return true; if (filter.full()) return false; const double load_factor = double(filter.size()) / filter.capacity(); return dist(gen, param_t(1.0 - load_factor)); }; }
static void expect_properties(const filter_t &c, const slots_status sstatus, const test_hash hash_fn, const float ml) { switch (sstatus.status) { case slots_status::exactly: EXPECT_EQ(sstatus.slot_count, c.slot_count()); break; case slots_status::at_least: // Note: probably replace EXPECT_LE with EXPECT_EQ will be the same since // the current implementation always use the minimal space it can. EXPECT_LE(sstatus.slot_count, c.slot_count()); break; } EXPECT_EQ(hash_fn, c.hash_function()); EXPECT_EQ(ml, c.max_load_factor()); }
// Checks whether a filter is empty and checks invariants. static void expect_empty(const filter_t &c) { EXPECT_TRUE(c.empty()); EXPECT_EQ(0, c.size()); EXPECT_EQ(0, distance(c.begin(), c.end())); EXPECT_FLOAT_EQ(0.0f, c.load_factor()); EXPECT_LE(c.load_factor(), c.max_load_factor()); }
virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status) { std::string text2 = text+" "; for (filter_t::iterator index = filters.begin(); index != filters.end(); index++) { if ((ServerInstance->MatchText(text2,index->first)) || (ServerInstance->MatchText(text,index->first))) { Filter* f = (Filter*)index->second; std::string target = ""; if (target_type == TYPE_USER) { userrec* t = (userrec*)dest; target = std::string(t->nick); } else if (target_type == TYPE_CHANNEL) { chanrec* t = (chanrec*)dest; target = std::string(t->name); } if (f->action == "block") { ServerInstance->WriteOpers(std::string("FILTER: ")+user->nick+" had their notice filtered, target was "+target+": "+f->reason); user->WriteServ("NOTICE "+std::string(user->nick)+" :Your notice has been filtered and opers notified: "+f->reason); } ServerInstance->Log(DEFAULT,"FILTER: "+std::string(user->nick)+std::string(" had their notice filtered, target was ")+target+": "+f->reason+" Action: "+f->action); if (f->action == "kill") { userrec::QuitUser(ServerInstance,user,f->reason); } return 1; } } return 0; }
TEST(FilterTest, Count) { const filter_t c = {10, 20, 30, 40, 50, 50, 50, 40, 40}; ASSERT_EQ(5, c.size()); EXPECT_EQ(0, c.count(0)); EXPECT_EQ(1, c.count(10)); EXPECT_EQ(1, c.count(20)); EXPECT_EQ(1, c.count(30)); EXPECT_EQ(1, c.count(40)); EXPECT_EQ(1, c.count(50)); EXPECT_EQ(0, c.count(60)); }
TEST(FilterTest, Find) { const filter_t c = {10, 20, 30, 40, 50}; { SCOPED_TRACE("Find existing key"); const auto it = c.find(30); ASSERT_TRUE(it != c.end()); EXPECT_EQ(30, *it); EXPECT_TRUE(it == std::next(c.begin(), 2)); } { SCOPED_TRACE("Find non existing key"); const auto it = c.find(35); EXPECT_TRUE(it == c.end()); } }
// Checks whether lhs and rhs are clones. static bool totally_equal(const filter_t &lhs, const filter_t &rhs) noexcept { return lhs.size() == rhs.size() && lhs.capacity() == rhs.capacity() && lhs.quotient_bits() == rhs.quotient_bits() && lhs.remainder_bits() == rhs.remainder_bits() && equal(lhs, rhs); }
TEST(FilterTest, Iterators) { { const filter_t empty_filter; EXPECT_TRUE(empty_filter.begin() == empty_filter.end()); EXPECT_FALSE(empty_filter.begin() != empty_filter.end()); } { const filter_t c = {50, 70, 90}; ASSERT_TRUE(c.begin() != c.end()); ASSERT_FALSE(c.begin() == c.end()); auto it1 = c.begin(); ASSERT_TRUE(it1 == c.begin()); ASSERT_FALSE(it1 != c.begin()); EXPECT_EQ(50, *it1); auto it2 = ++it1; ASSERT_TRUE(it2 == it1); ASSERT_FALSE(it2 != it1); ASSERT_TRUE(it2 != c.begin() && it2 != c.end()); ASSERT_FALSE(it2 == c.begin() || it2 == c.end()); EXPECT_EQ(70, *it2); EXPECT_EQ(70, *it1); auto it3 = it2++; ASSERT_TRUE(it3 == it1); EXPECT_EQ(70, *it3); EXPECT_EQ(90, *it2++); ASSERT_TRUE(it2 == c.end()); ASSERT_FALSE(it2 != c.end()); } }