mirror of https://github.com/aria2/aria2
util::parseIntSegments: Return SegList<int>
parent
007b890fe4
commit
c0e4381780
|
@ -195,8 +195,8 @@ void BtSetup::setup(std::vector<std::unique_ptr<Command>>& commands,
|
||||||
sgl.add(usedPort, usedPort+1);
|
sgl.add(usedPort, usedPort+1);
|
||||||
ret = command->bindPort(port, sgl);
|
ret = command->bindPort(port, sgl);
|
||||||
} else {
|
} else {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments
|
||||||
util::parseIntSegments(sgl, e->getOption()->get(PREF_LISTEN_PORT));
|
(e->getOption()->get(PREF_LISTEN_PORT));
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
ret = command->bindPort(port, sgl);
|
ret = command->bindPort(port, sgl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,8 +123,8 @@ std::vector<std::unique_ptr<Command>> DHTSetup::setup
|
||||||
// this. We did the same thing in TCP socket. See BtSetup.cc.
|
// this. We did the same thing in TCP socket. See BtSetup.cc.
|
||||||
bool rv;
|
bool rv;
|
||||||
if(port == 0) {
|
if(port == 0) {
|
||||||
SegList<int> sgl;
|
auto sgl =
|
||||||
util::parseIntSegments(sgl, e->getOption()->get(PREF_DHT_LISTEN_PORT));
|
util::parseIntSegments(e->getOption()->get(PREF_DHT_LISTEN_PORT));
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
rv = connection->bind(port, addr, sgl);
|
rv = connection->bind(port, addr, sgl);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -123,7 +123,7 @@ void DownloadContext::setFilePathWithIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadContext::setFileFilter(SegList<int>& sgl)
|
void DownloadContext::setFileFilter(SegList<int> sgl)
|
||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// sgl must be normalized before the call.
|
// sgl must be normalized before the call.
|
||||||
void setFileFilter(SegList<int>& sgl);
|
void setFileFilter(SegList<int> sgl);
|
||||||
|
|
||||||
// Sets file path for specified index. index starts from 1. The
|
// Sets file path for specified index. index starts from 1. The
|
||||||
// index is the same used in setFileFilter(). path is not escaped by
|
// index is the same used in setFileFilter(). path is not escaped by
|
||||||
|
|
|
@ -186,8 +186,7 @@ Metalink2RequestGroup::createRequestGroup
|
||||||
(preferredProtocol, -MetalinkResource::getLowestPriority());
|
(preferredProtocol, -MetalinkResource::getLowestPriority());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments(optionTemplate->get(PREF_SELECT_FILE));
|
||||||
util::parseIntSegments(sgl, optionTemplate->get(PREF_SELECT_FILE));
|
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
if(sgl.hasNext()) {
|
if(sgl.hasNext()) {
|
||||||
size_t inspoint = 0;
|
size_t inspoint = 0;
|
||||||
|
|
|
@ -117,8 +117,7 @@ IntegerRangeOptionHandler::~IntegerRangeOptionHandler() {}
|
||||||
void IntegerRangeOptionHandler::parseArg
|
void IntegerRangeOptionHandler::parseArg
|
||||||
(Option& option, const std::string& optarg) const
|
(Option& option, const std::string& optarg) const
|
||||||
{
|
{
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments(optarg);
|
||||||
util::parseIntSegments(sgl, optarg);
|
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
while(sgl.hasNext()) {
|
while(sgl.hasNext()) {
|
||||||
int v = sgl.next();
|
int v = sgl.next();
|
||||||
|
|
|
@ -1457,10 +1457,9 @@ void changeOption
|
||||||
dctx->setDigest(hashType, util::fromHex(p.second.first, p.second.second));
|
dctx->setDigest(hashType, util::fromHex(p.second.first, p.second.second));
|
||||||
}
|
}
|
||||||
if(option.defined(PREF_SELECT_FILE)) {
|
if(option.defined(PREF_SELECT_FILE)) {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments(grOption->get(PREF_SELECT_FILE));
|
||||||
util::parseIntSegments(sgl, grOption->get(PREF_SELECT_FILE));
|
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
dctx->setFileFilter(sgl);
|
dctx->setFileFilter(std::move(sgl));
|
||||||
}
|
}
|
||||||
if(option.defined(PREF_SPLIT)) {
|
if(option.defined(PREF_SPLIT)) {
|
||||||
group->setNumConcurrentCommand(grOption->getAsInt(PREF_SPLIT));
|
group->setNumConcurrentCommand(grOption->getAsInt(PREF_SPLIT));
|
||||||
|
|
|
@ -49,6 +49,12 @@ public:
|
||||||
: index_(0), val_(std::numeric_limits<T>::min())
|
: index_(0), val_(std::numeric_limits<T>::min())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
// Don't allow copying
|
||||||
|
SegList(const SegList&) = delete;
|
||||||
|
SegList& operator=(const SegList&) = delete;
|
||||||
|
|
||||||
|
SegList(SegList&&) = default;
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
segs_.clear();
|
segs_.clear();
|
||||||
|
@ -62,11 +68,11 @@ public:
|
||||||
void normalize()
|
void normalize()
|
||||||
{
|
{
|
||||||
if(!segs_.empty()) {
|
if(!segs_.empty()) {
|
||||||
std::sort(segs_.begin(), segs_.end());
|
std::sort(std::begin(segs_), std::end(segs_));
|
||||||
std::vector<std::pair<T, T> > s;
|
std::vector<std::pair<T, T>> s;
|
||||||
s.push_back(segs_.front());
|
s.push_back(segs_.front());
|
||||||
for(size_t i = 1, len = segs_.size(); i < len; ++i) {
|
for(size_t i = 1, len = segs_.size(); i < len; ++i) {
|
||||||
const std::pair<T, T>& x = segs_[i];
|
auto& x = segs_[i];
|
||||||
if(x.first <= s.back().second) {
|
if(x.first <= s.back().second) {
|
||||||
if(s.back().second < x.second) {
|
if(s.back().second < x.second) {
|
||||||
s.back().second = x.second;
|
s.back().second = x.second;
|
||||||
|
@ -88,7 +94,7 @@ public:
|
||||||
if(segs_.empty()) {
|
if(segs_.empty()) {
|
||||||
val_ = std::max(val_, a);
|
val_ = std::max(val_, a);
|
||||||
}
|
}
|
||||||
segs_.push_back(std::make_pair(a, b));
|
segs_.emplace_back(a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +109,7 @@ public:
|
||||||
T next()
|
T next()
|
||||||
{
|
{
|
||||||
T res;
|
T res;
|
||||||
size_t len = segs_.size();
|
auto len = segs_.size();
|
||||||
if(index_ < len) {
|
if(index_ < len) {
|
||||||
res = val_++;
|
res = val_++;
|
||||||
if(val_ == segs_[index_].second) {
|
if(val_ == segs_[index_].second) {
|
||||||
|
@ -131,12 +137,9 @@ public:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<T, T> > segs_;
|
std::vector<std::pair<T, T>> segs_;
|
||||||
size_t index_;
|
size_t index_;
|
||||||
T val_;
|
T val_;
|
||||||
// Don't allow copying
|
|
||||||
SegList(const SegList<T>&);
|
|
||||||
SegList& operator=(const SegList<T>&);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -201,10 +201,9 @@ createBtRequestGroup(const std::string& metaInfoUri,
|
||||||
if(adjustAnnounceUri) {
|
if(adjustAnnounceUri) {
|
||||||
bittorrent::adjustAnnounceUri(bittorrent::getTorrentAttrs(dctx), option);
|
bittorrent::adjustAnnounceUri(bittorrent::getTorrentAttrs(dctx), option);
|
||||||
}
|
}
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments(option->get(PREF_SELECT_FILE));
|
||||||
util::parseIntSegments(sgl, option->get(PREF_SELECT_FILE));
|
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
dctx->setFileFilter(sgl);
|
dctx->setFileFilter(std::move(sgl));
|
||||||
std::istringstream indexOutIn(option->get(PREF_INDEX_OUT));
|
std::istringstream indexOutIn(option->get(PREF_INDEX_OUT));
|
||||||
auto indexPaths = util::createIndexPaths(indexOutIn);
|
auto indexPaths = util::createIndexPaths(indexOutIn);
|
||||||
for(const auto& i : indexPaths) {
|
for(const auto& i : indexPaths) {
|
||||||
|
|
|
@ -584,8 +584,9 @@ bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseIntSegments(SegList<int>& sgl, const std::string& src)
|
SegList<int> parseIntSegments(const std::string& src)
|
||||||
{
|
{
|
||||||
|
SegList<int> sgl;
|
||||||
for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;) {
|
for(std::string::const_iterator i = src.begin(), eoi = src.end(); i != eoi;) {
|
||||||
std::string::const_iterator j = std::find(i, eoi, ',');
|
std::string::const_iterator j = std::find(i, eoi, ',');
|
||||||
if(j == i) {
|
if(j == i) {
|
||||||
|
@ -616,6 +617,7 @@ void parseIntSegments(SegList<int>& sgl, const std::string& src)
|
||||||
}
|
}
|
||||||
i = j+1;
|
i = j+1;
|
||||||
}
|
}
|
||||||
|
return sgl;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
|
@ -277,7 +277,7 @@ bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base = 10);
|
||||||
|
|
||||||
bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10);
|
bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10);
|
||||||
|
|
||||||
void parseIntSegments(SegList<int>& sgl, const std::string& src);
|
SegList<int> parseIntSegments(const std::string& src);
|
||||||
|
|
||||||
// Parses string which specifies the range of piece index for higher
|
// Parses string which specifies the range of piece index for higher
|
||||||
// priority and appends those indexes into result. The input string
|
// priority and appends those indexes into result. The input string
|
||||||
|
|
|
@ -652,20 +652,16 @@ void BittorrentHelperTest::testSetFileFilter_single()
|
||||||
load(A2_TEST_DIR"/single.torrent", dctx, option_);
|
load(A2_TEST_DIR"/single.torrent", dctx, option_);
|
||||||
|
|
||||||
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
||||||
SegList<int> sgl;
|
|
||||||
dctx->setFileFilter(sgl);
|
dctx->setFileFilter(SegList<int>());
|
||||||
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
||||||
|
|
||||||
sgl.clear();
|
dctx->setFileFilter(util::parseIntSegments("1,2"));
|
||||||
sgl.add(1, 2);
|
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
||||||
|
|
||||||
// For single file torrent, file is always selected whatever range
|
// For single file torrent, file is always selected whatever range
|
||||||
// is passed.
|
// is passed.
|
||||||
sgl.clear();
|
dctx->setFileFilter(util::parseIntSegments("2,3"));
|
||||||
sgl.add(2, 3);
|
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
CPPUNIT_ASSERT(dctx->getFirstFileEntry()->isRequested());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,25 +673,19 @@ void BittorrentHelperTest::testSetFileFilter_multi()
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
||||||
|
|
||||||
SegList<int> sgl;
|
dctx->setFileFilter(SegList<int>());
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
||||||
|
|
||||||
sgl.add(2, 3);
|
dctx->setFileFilter(util::parseIntSegments("2,3"));
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
|
CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
||||||
|
|
||||||
sgl.clear();
|
dctx->setFileFilter(util::parseIntSegments("3,4"));
|
||||||
sgl.add(3, 4);
|
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
|
CPPUNIT_ASSERT(!dctx->getFileEntries()[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(!dctx->getFileEntries()[1]->isRequested());
|
CPPUNIT_ASSERT(!dctx->getFileEntries()[1]->isRequested());
|
||||||
|
|
||||||
sgl.clear();
|
dctx->setFileFilter(util::parseIntSegments("1,2"));
|
||||||
util::parseIntSegments(sgl, "1,2");
|
|
||||||
dctx->setFileFilter(sgl);
|
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
CPPUNIT_ASSERT(dctx->getFileEntries()[1]->isRequested());
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,10 +83,9 @@ void DownloadContextTest::testSetFileFilter()
|
||||||
files.push_back(std::shared_ptr<FileEntry>(new FileEntry("file", 1, i)));
|
files.push_back(std::shared_ptr<FileEntry>(new FileEntry("file", 1, i)));
|
||||||
}
|
}
|
||||||
ctx.setFileEntries(files.begin(), files.end());
|
ctx.setFileEntries(files.begin(), files.end());
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("6-8,2-4");
|
||||||
util::parseIntSegments(sgl, "6-8,2-4");
|
|
||||||
sgl.normalize();
|
sgl.normalize();
|
||||||
ctx.setFileFilter(sgl);
|
ctx.setFileFilter(std::move(sgl));
|
||||||
const std::vector<std::shared_ptr<FileEntry> >& res = ctx.getFileEntries();
|
const std::vector<std::shared_ptr<FileEntry> >& res = ctx.getFileEntries();
|
||||||
CPPUNIT_ASSERT(!res[0]->isRequested());
|
CPPUNIT_ASSERT(!res[0]->isRequested());
|
||||||
CPPUNIT_ASSERT(res[1]->isRequested());
|
CPPUNIT_ASSERT(res[1]->isRequested());
|
||||||
|
|
|
@ -1669,70 +1669,65 @@ void UtilTest::testConvertBitfield()
|
||||||
|
|
||||||
void UtilTest::testParseIntSegments()
|
void UtilTest::testParseIntSegments()
|
||||||
{
|
{
|
||||||
SegList<int> sgl;
|
{
|
||||||
util::parseIntSegments(sgl, "1,3-8,10");
|
auto sgl = util::parseIntSegments("1,3-8,10");
|
||||||
|
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(1, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(1, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(3, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(3, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(4, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(4, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(5, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(5, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(6, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(6, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(7, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(7, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(8, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(8, sgl.next());
|
||||||
CPPUNIT_ASSERT(sgl.hasNext());
|
CPPUNIT_ASSERT(sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(10, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(10, sgl.next());
|
||||||
CPPUNIT_ASSERT(!sgl.hasNext());
|
CPPUNIT_ASSERT(!sgl.hasNext());
|
||||||
CPPUNIT_ASSERT_EQUAL(0, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(0, sgl.next());
|
||||||
|
}
|
||||||
sgl.clear();
|
{
|
||||||
util::parseIntSegments(sgl, ",,,1,,,3,,,");
|
auto sgl = util::parseIntSegments(",,,1,,,3,,,");
|
||||||
CPPUNIT_ASSERT_EQUAL(1, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(1, sgl.next());
|
||||||
CPPUNIT_ASSERT_EQUAL(3, sgl.next());
|
CPPUNIT_ASSERT_EQUAL(3, sgl.next());
|
||||||
CPPUNIT_ASSERT(!sgl.hasNext());
|
CPPUNIT_ASSERT(!sgl.hasNext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtilTest::testParseIntSegments_invalidRange()
|
void UtilTest::testParseIntSegments_invalidRange()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("-1");
|
||||||
util::parseIntSegments(sgl, "-1");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("1-");
|
||||||
util::parseIntSegments(sgl, "1-");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("2147483648");
|
||||||
util::parseIntSegments(sgl, "2147483648");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("2147483647-2147483648");
|
||||||
util::parseIntSegments(sgl, "2147483647-2147483648");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("1-2x");
|
||||||
util::parseIntSegments(sgl, "1-2x");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SegList<int> sgl;
|
auto sgl = util::parseIntSegments("3x-4");
|
||||||
util::parseIntSegments(sgl, "3x-4");
|
|
||||||
CPPUNIT_FAIL("exception must be thrown.");
|
CPPUNIT_FAIL("exception must be thrown.");
|
||||||
} catch(Exception& e) {
|
} catch(Exception& e) {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue