Commit d29d39c3 authored by avi's avatar avi Committed by Commit bot

Remove ScopedVector from importer.

BUG=554289

Review-Url: https://codereview.chromium.org/2305813002
Cr-Commit-Position: refs/heads/master@{#416326}
parent 10f51929
...@@ -218,20 +218,19 @@ class FirefoxObserver : public ProfileWriter, ...@@ -218,20 +218,19 @@ class FirefoxObserver : public ProfileWriter,
} }
} }
void AddKeywords(ScopedVector<TemplateURL> template_urls, void AddKeywords(TemplateURLService::OwnedTemplateURLVector template_urls,
bool unique_on_host_and_path) override { bool unique_on_host_and_path) override {
for (size_t i = 0; i < template_urls.size(); ++i) { for (const auto& turl : template_urls) {
// The order might not be deterministic, look in the expected list for // The order might not be deterministic, look in the expected list for
// that template URL. // that template URL.
bool found = false; bool found = false;
const base::string16& imported_keyword = template_urls[i]->keyword(); const base::string16& imported_keyword = turl->keyword();
for (size_t j = 0; j < arraysize(kFirefoxKeywords); ++j) { for (const auto& keyword : kFirefoxKeywords) {
const base::string16 expected_keyword = base::WideToUTF16( const base::string16 expected_keyword =
use_keyword_in_json_ ? base::WideToUTF16(use_keyword_in_json_ ? keyword.keyword_in_json
kFirefoxKeywords[j].keyword_in_json : : keyword.keyword_in_sqlite);
kFirefoxKeywords[j].keyword_in_sqlite);
if (imported_keyword == expected_keyword) { if (imported_keyword == expected_keyword) {
EXPECT_EQ(kFirefoxKeywords[j].url, template_urls[i]->url()); EXPECT_EQ(keyword.url, turl->url());
found = true; found = true;
break; break;
} }
......
...@@ -402,7 +402,7 @@ class MalformedFavoritesRegistryTestObserver ...@@ -402,7 +402,7 @@ class MalformedFavoritesRegistryTestObserver
void AddPasswordForm(const autofill::PasswordForm& form) override {} void AddPasswordForm(const autofill::PasswordForm& form) override {}
void AddHistoryPage(const history::URLRows& page, void AddHistoryPage(const history::URLRows& page,
history::VisitSource visit_source) override {} history::VisitSource visit_source) override {}
void AddKeywords(ScopedVector<TemplateURL> template_urls, void AddKeywords(TemplateURLService::OwnedTemplateURLVector template_urls,
bool unique_on_host_and_path) override {} bool unique_on_host_and_path) override {}
void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks, void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks,
const base::string16& top_level_folder_name) override { const base::string16& top_level_folder_name) override {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -96,53 +97,51 @@ class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter { ...@@ -96,53 +97,51 @@ class FirefoxURLParameterFilter : public TemplateURLParser::ParameterFilter {
}; };
// Attempts to create a TemplateURL from the provided data. |title| is optional. // Attempts to create a TemplateURL from the provided data. |title| is optional.
// If TemplateURL creation fails, returns NULL. // If TemplateURL creation fails, returns null.
// This function transfers ownership of the created TemplateURL to the caller. std::unique_ptr<TemplateURL> CreateTemplateURL(const base::string16& url,
TemplateURL* CreateTemplateURL(const base::string16& url, const base::string16& keyword,
const base::string16& keyword, const base::string16& title) {
const base::string16& title) {
if (url.empty() || keyword.empty()) if (url.empty() || keyword.empty())
return NULL; return nullptr;
TemplateURLData data; TemplateURLData data;
data.SetKeyword(keyword); data.SetKeyword(keyword);
// We set short name by using the title if it exists. // We set short name by using the title if it exists.
// Otherwise, we use the shortcut. // Otherwise, we use the shortcut.
data.SetShortName(title.empty() ? keyword : title); data.SetShortName(title.empty() ? keyword : title);
data.SetURL(TemplateURLRef::DisplayURLToURLRef(url)); data.SetURL(TemplateURLRef::DisplayURLToURLRef(url));
return new TemplateURL(data); return base::MakeUnique<TemplateURL>(data);
} }
// Parses the OpenSearch XML files in |xml_files| and populates |search_engines| // Parses the OpenSearch XML files in |xml_files| and populates |search_engines|
// with the resulting TemplateURLs. // with the resulting TemplateURLs.
void ParseSearchEnginesFromFirefoxXMLData( void ParseSearchEnginesFromFirefoxXMLData(
const std::vector<std::string>& xml_data, const std::vector<std::string>& xml_data,
std::vector<TemplateURL*>* search_engines) { TemplateURLService::OwnedTemplateURLVector* search_engines) {
DCHECK(search_engines); DCHECK(search_engines);
typedef std::map<std::string, TemplateURL*> SearchEnginesMap; std::map<std::string, std::unique_ptr<TemplateURL>> search_engine_for_url;
SearchEnginesMap search_engine_for_url;
FirefoxURLParameterFilter param_filter; FirefoxURLParameterFilter param_filter;
// The first XML file represents the default search engine in Firefox 3, so we // The first XML file represents the default search engine in Firefox 3, so we
// need to keep it on top of the list. // need to keep it on top of the list.
SearchEnginesMap::const_iterator default_turl = search_engine_for_url.end(); auto default_turl = search_engine_for_url.end();
for (std::vector<std::string>::const_iterator xml_iter = for (std::vector<std::string>::const_iterator xml_iter =
xml_data.begin(); xml_iter != xml_data.end(); ++xml_iter) { xml_data.begin(); xml_iter != xml_data.end(); ++xml_iter) {
TemplateURL* template_url = TemplateURLParser::Parse( std::unique_ptr<TemplateURL> template_url = TemplateURLParser::Parse(
UIThreadSearchTermsData(NULL), true, UIThreadSearchTermsData(nullptr), true, xml_iter->data(),
xml_iter->data(), xml_iter->length(), &param_filter); xml_iter->length(), &param_filter);
if (template_url) { if (template_url) {
SearchEnginesMap::iterator iter = auto iter = search_engine_for_url.find(template_url->url());
search_engine_for_url.find(template_url->url());
if (iter == search_engine_for_url.end()) { if (iter == search_engine_for_url.end()) {
iter = search_engine_for_url.insert( iter = search_engine_for_url
std::make_pair(template_url->url(), template_url)).first; .insert(std::make_pair(template_url->url(),
std::move(template_url)))
.first;
} else { } else {
// We have already found a search engine with the same URL. We give // We have already found a search engine with the same URL. We give
// priority to the latest one found, as GetSearchEnginesXMLFiles() // priority to the latest one found, as GetSearchEnginesXMLFiles()
// returns a vector with first Firefox default search engines and then // returns a vector with first Firefox default search engines and then
// the user's ones. We want to give priority to the user ones. // the user's ones. We want to give priority to the user ones.
delete iter->second; iter->second = std::move(template_url);
iter->second = template_url;
} }
if (default_turl == search_engine_for_url.end()) if (default_turl == search_engine_for_url.end())
default_turl = iter; default_turl = iter;
...@@ -150,12 +149,13 @@ void ParseSearchEnginesFromFirefoxXMLData( ...@@ -150,12 +149,13 @@ void ParseSearchEnginesFromFirefoxXMLData(
} }
// Put the results in the |search_engines| vector. // Put the results in the |search_engines| vector.
for (SearchEnginesMap::iterator t_iter = search_engine_for_url.begin(); for (auto t_iter = search_engine_for_url.begin();
t_iter != search_engine_for_url.end(); ++t_iter) { t_iter != search_engine_for_url.end(); ++t_iter) {
if (t_iter == default_turl) if (t_iter == default_turl)
search_engines->insert(search_engines->begin(), default_turl->second); search_engines->insert(search_engines->begin(),
std::move(default_turl->second));
else else
search_engines->push_back(t_iter->second); search_engines->push_back(std::move(t_iter->second));
} }
} }
...@@ -222,14 +222,12 @@ void InProcessImporterBridge::SetHistoryItems( ...@@ -222,14 +222,12 @@ void InProcessImporterBridge::SetHistoryItems(
void InProcessImporterBridge::SetKeywords( void InProcessImporterBridge::SetKeywords(
const std::vector<importer::SearchEngineInfo>& search_engines, const std::vector<importer::SearchEngineInfo>& search_engines,
bool unique_on_host_and_path) { bool unique_on_host_and_path) {
ScopedVector<TemplateURL> owned_template_urls; TemplateURLService::OwnedTemplateURLVector owned_template_urls;
for (const auto& search_engine : search_engines) { for (const auto& search_engine : search_engines) {
TemplateURL* owned_template_url = std::unique_ptr<TemplateURL> owned_template_url = CreateTemplateURL(
CreateTemplateURL(search_engine.url, search_engine.url, search_engine.keyword, search_engine.display_name);
search_engine.keyword,
search_engine.display_name);
if (owned_template_url) if (owned_template_url)
owned_template_urls.push_back(owned_template_url); owned_template_urls.push_back(std::move(owned_template_url));
} }
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&ProfileWriter::AddKeywords, writer_, base::Bind(&ProfileWriter::AddKeywords, writer_,
...@@ -238,16 +236,12 @@ void InProcessImporterBridge::SetKeywords( ...@@ -238,16 +236,12 @@ void InProcessImporterBridge::SetKeywords(
void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData( void InProcessImporterBridge::SetFirefoxSearchEnginesXMLData(
const std::vector<std::string>& search_engine_data) { const std::vector<std::string>& search_engine_data) {
std::vector<TemplateURL*> search_engines; TemplateURLService::OwnedTemplateURLVector search_engines;
ParseSearchEnginesFromFirefoxXMLData(search_engine_data, &search_engines); ParseSearchEnginesFromFirefoxXMLData(search_engine_data, &search_engines);
ScopedVector<TemplateURL> owned_template_urls;
std::copy(search_engines.begin(), search_engines.end(),
std::back_inserter(owned_template_urls));
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(&ProfileWriter::AddKeywords, writer_, base::Bind(&ProfileWriter::AddKeywords, writer_,
base::Passed(&owned_template_urls), true)); base::Passed(&search_engines), true));
} }
void InProcessImporterBridge::SetPasswordForm( void InProcessImporterBridge::SetPasswordForm(
......
...@@ -315,19 +315,19 @@ static void BuildHostPathMap(TemplateURLService* model, ...@@ -315,19 +315,19 @@ static void BuildHostPathMap(TemplateURLService* model,
} }
} }
void ProfileWriter::AddKeywords(ScopedVector<TemplateURL> template_urls, void ProfileWriter::AddKeywords(
bool unique_on_host_and_path) { TemplateURLService::OwnedTemplateURLVector template_urls,
bool unique_on_host_and_path) {
TemplateURLService* model = TemplateURLService* model =
TemplateURLServiceFactory::GetForProfile(profile_); TemplateURLServiceFactory::GetForProfile(profile_);
HostPathMap host_path_map; HostPathMap host_path_map;
if (unique_on_host_and_path) if (unique_on_host_and_path)
BuildHostPathMap(model, &host_path_map); BuildHostPathMap(model, &host_path_map);
for (ScopedVector<TemplateURL>::iterator i = template_urls.begin(); for (auto& turl : template_urls) {
i != template_urls.end(); ++i) {
// TemplateURLService requires keywords to be unique. If there is already a // TemplateURLService requires keywords to be unique. If there is already a
// TemplateURL with this keyword, don't import it again. // TemplateURL with this keyword, don't import it again.
if (model->GetTemplateURLForKeyword((*i)->keyword()) != nullptr) if (model->GetTemplateURLForKeyword(turl->keyword()) != nullptr)
continue; continue;
// For search engines if there is already a keyword with the same // For search engines if there is already a keyword with the same
...@@ -335,16 +335,14 @@ void ProfileWriter::AddKeywords(ScopedVector<TemplateURL> template_urls, ...@@ -335,16 +335,14 @@ void ProfileWriter::AddKeywords(ScopedVector<TemplateURL> template_urls,
// search providers (such as two Googles, or two Yahoos) as well as making // search providers (such as two Googles, or two Yahoos) as well as making
// sure the search engines we provide aren't replaced by those from the // sure the search engines we provide aren't replaced by those from the
// imported browser. // imported browser.
if (unique_on_host_and_path && if (unique_on_host_and_path && (host_path_map.find(BuildHostPathKey(
(host_path_map.find(BuildHostPathKey( turl.get(), model->search_terms_data(),
*i, model->search_terms_data(), true)) != host_path_map.end())) true)) != host_path_map.end()))
continue; continue;
// Only add valid TemplateURLs to the model. // Only add valid TemplateURLs to the model.
if ((*i)->url_ref().IsValid(model->search_terms_data())) { if (turl->url_ref().IsValid(model->search_terms_data()))
model->Add(base::WrapUnique(*i)); model->Add(std::move(turl));
*i = nullptr; // Prevent the vector from deleting *i later.
}
} }
} }
......
...@@ -9,17 +9,16 @@ ...@@ -9,17 +9,16 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/favicon_base/favicon_usage_data.h" #include "components/favicon_base/favicon_usage_data.h"
#include "components/history/core/browser/history_types.h" #include "components/history/core/browser/history_types.h"
#include "components/search_engines/template_url_service.h"
#include "url/gurl.h" #include "url/gurl.h"
struct ImportedBookmarkEntry; struct ImportedBookmarkEntry;
class Profile; class Profile;
class TemplateURL;
namespace autofill { namespace autofill {
struct PasswordForm; struct PasswordForm;
...@@ -78,16 +77,16 @@ class ProfileWriter : public base::RefCountedThreadSafe<ProfileWriter> { ...@@ -78,16 +77,16 @@ class ProfileWriter : public base::RefCountedThreadSafe<ProfileWriter> {
virtual void AddFavicons(const favicon_base::FaviconUsageDataList& favicons); virtual void AddFavicons(const favicon_base::FaviconUsageDataList& favicons);
// Adds the TemplateURLs in |template_urls| to the local store. The local // Adds the TemplateURLs in |template_urls| to the local store.
// store becomes the owner of the TemplateURLs. Some TemplateURLs in // Some TemplateURLs in |template_urls| may conflict (same keyword or same
// |template_urls| may conflict (same keyword or same host name in the URL) // host name in the URL) with existing TemplateURLs in the local store, in
// with existing TemplateURLs in the local store, in which case the existing // which case the existing ones take precedence and the duplicates in
// ones take precedence and the duplicates in |template_urls| are deleted. // |template_urls| are deleted. If |unique_on_host_and_path| is true, a
// If |unique_on_host_and_path| is true, a TemplateURL is only added if there // TemplateURL is only added if there is not an existing TemplateURL that has
// is not an existing TemplateURL that has a replaceable search url with the // a replaceable search url with the same host+path combination.
// same host+path combination. virtual void AddKeywords(
virtual void AddKeywords(ScopedVector<TemplateURL> template_urls, TemplateURLService::OwnedTemplateURLVector template_urls,
bool unique_on_host_and_path); bool unique_on_host_and_path);
// Adds the imported autofill entries to the autofill database. // Adds the imported autofill entries to the autofill database.
virtual void AddAutofillFormDataEntries( virtual void AddAutofillFormDataEntries(
......
...@@ -101,8 +101,8 @@ void TemplateURLParserTest::ParseFile( ...@@ -101,8 +101,8 @@ void TemplateURLParserTest::ParseFile(
std::string contents; std::string contents;
ASSERT_TRUE(base::ReadFileToString(full_path, &contents)); ASSERT_TRUE(base::ReadFileToString(full_path, &contents));
template_url_.reset(TemplateURLParser::Parse( template_url_ = TemplateURLParser::Parse(
SearchTermsData(), false, contents.data(), contents.length(), filter)); SearchTermsData(), false, contents.data(), contents.length(), filter);
} }
......
...@@ -111,9 +111,9 @@ void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete( ...@@ -111,9 +111,9 @@ void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete(
return; return;
} }
template_url_.reset(TemplateURLParser::Parse( template_url_ = TemplateURLParser::Parse(
fetcher_->template_url_service_->search_terms_data(), false, fetcher_->template_url_service_->search_terms_data(), false, data.data(),
data.data(), data.length(), NULL)); data.length(), nullptr);
if (!template_url_.get() || if (!template_url_.get() ||
!template_url_->url_ref().SupportsReplacement( !template_url_->url_ref().SupportsReplacement(
fetcher_->template_url_service_->search_terms_data())) { fetcher_->template_url_service_->search_terms_data())) {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
...@@ -140,12 +141,13 @@ class TemplateURLParsingContext { ...@@ -140,12 +141,13 @@ class TemplateURLParsingContext {
static void EndElementImpl(void* ctx, const xmlChar* name); static void EndElementImpl(void* ctx, const xmlChar* name);
static void CharactersImpl(void* ctx, const xmlChar* ch, int len); static void CharactersImpl(void* ctx, const xmlChar* ch, int len);
// Returns a heap-allocated TemplateURL representing the result of parsing. // Returns a TemplateURL representing the result of parsing. This will be
// This will be NULL if parsing failed or if the results were invalid for some // null if parsing failed or if the results were invalid for some reason (e.g.
// reason (e.g. the resulting URL was not HTTP[S], a name wasn't supplied, // the resulting URL was not HTTP[S], a name wasn't supplied, a resulting
// a resulting TemplateURLRef was invalid, etc.). // TemplateURLRef was invalid, etc.).
TemplateURL* GetTemplateURL(const SearchTermsData& search_terms_data, std::unique_ptr<TemplateURL> GetTemplateURL(
bool show_in_default_list); const SearchTermsData& search_terms_data,
bool show_in_default_list);
private: private:
// Key is UTF8 encoded. // Key is UTF8 encoded.
...@@ -299,14 +301,14 @@ void TemplateURLParsingContext::CharactersImpl(void* ctx, ...@@ -299,14 +301,14 @@ void TemplateURLParsingContext::CharactersImpl(void* ctx,
base::StringPiece(reinterpret_cast<const char*>(ch), len)); base::StringPiece(reinterpret_cast<const char*>(ch), len));
} }
TemplateURL* TemplateURLParsingContext::GetTemplateURL( std::unique_ptr<TemplateURL> TemplateURLParsingContext::GetTemplateURL(
const SearchTermsData& search_terms_data, const SearchTermsData& search_terms_data,
bool show_in_default_list) { bool show_in_default_list) {
// TODO(jcampan): Support engines that use POST; see http://crbug.com/18107 // TODO(jcampan): Support engines that use POST; see http://crbug.com/18107
if (method_ == TemplateURLParsingContext::POST || if (method_ == TemplateURLParsingContext::POST ||
data_.short_name().empty() || !IsHTTPRef(data_.url()) || data_.short_name().empty() || !IsHTTPRef(data_.url()) ||
!IsHTTPRef(data_.suggestions_url)) !IsHTTPRef(data_.suggestions_url))
return NULL; return nullptr;
if (suggestion_method_ == TemplateURLParsingContext::POST) if (suggestion_method_ == TemplateURLParsingContext::POST)
data_.suggestions_url.clear(); data_.suggestions_url.clear();
...@@ -324,15 +326,16 @@ TemplateURL* TemplateURLParsingContext::GetTemplateURL( ...@@ -324,15 +326,16 @@ TemplateURL* TemplateURLParsingContext::GetTemplateURL(
data_.show_in_default_list = show_in_default_list; data_.show_in_default_list = show_in_default_list;
// Bail if the search URL is empty or if either TemplateURLRef is invalid. // Bail if the search URL is empty or if either TemplateURLRef is invalid.
std::unique_ptr<TemplateURL> template_url(new TemplateURL(data_)); std::unique_ptr<TemplateURL> template_url =
base::MakeUnique<TemplateURL>(data_);
if (template_url->url().empty() || if (template_url->url().empty() ||
!template_url->url_ref().IsValid(search_terms_data) || !template_url->url_ref().IsValid(search_terms_data) ||
(!template_url->suggestions_url().empty() && (!template_url->suggestions_url().empty() &&
!template_url->suggestions_url_ref().IsValid(search_terms_data))) { !template_url->suggestions_url_ref().IsValid(search_terms_data))) {
return NULL; return nullptr;
} }
return template_url.release(); return template_url;
} }
// static // static
...@@ -490,7 +493,7 @@ TemplateURLParsingContext::ElementType ...@@ -490,7 +493,7 @@ TemplateURLParsingContext::ElementType
// TemplateURLParser ---------------------------------------------------------- // TemplateURLParser ----------------------------------------------------------
// static // static
TemplateURL* TemplateURLParser::Parse( std::unique_ptr<TemplateURL> TemplateURLParser::Parse(
const SearchTermsData& search_terms_data, const SearchTermsData& search_terms_data,
bool show_in_default_list, bool show_in_default_list,
const char* data, const char* data,
...@@ -511,6 +514,6 @@ TemplateURL* TemplateURLParser::Parse( ...@@ -511,6 +514,6 @@ TemplateURL* TemplateURLParser::Parse(
static_cast<int>(length)); static_cast<int>(length));
xmlSubstituteEntitiesDefault(last_sub_entities_value); xmlSubstituteEntitiesDefault(last_sub_entities_value);
return error ? return error ? nullptr : context.GetTemplateURL(search_terms_data,
NULL : context.GetTemplateURL(search_terms_data, show_in_default_list); show_in_default_list);
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <stddef.h> #include <stddef.h>
#include <memory>
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
...@@ -30,19 +31,19 @@ class TemplateURLParser { ...@@ -30,19 +31,19 @@ class TemplateURLParser {
}; };
// Decodes the chunk of data representing a TemplateURL, creates the // Decodes the chunk of data representing a TemplateURL, creates the
// TemplateURL, and returns it. The caller owns the returned object. // TemplateURL, and returns it. Returns null if the data does not describe a
// Returns NULL if data does not describe a valid TemplateURL, the // valid TemplateURL, the URLs referenced do not point to valid http/https
// URLs referenced do not point to valid http/https resources, or for some // resources, or for some other reason we do not support the described
// other reason we do not support the described TemplateURL. // TemplateURL. |parameter_filter| can be used if you want to filter some
// |parameter_filter| can be used if you want to filter some parameters out of // parameters out of the URL. For example, when importing from another
// the URL. For example, when importing from another browser, we remove any // browser, we remove any parameter identifying that browser. If set to null,
// parameter identifying that browser. If set to NULL, the URL is not // the URL is not modified.
// modified. static std::unique_ptr<TemplateURL> Parse(
static TemplateURL* Parse(const SearchTermsData& search_terms_data, const SearchTermsData& search_terms_data,
bool show_in_default_list, bool show_in_default_list,
const char* data, const char* data,
size_t length, size_t length,
ParameterFilter* parameter_filter); ParameterFilter* parameter_filter);
private: private:
// No one should create one of these. // No one should create one of these.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment