Skip to content

Commit 48933b9

Browse files
committed
curl: use unique_ptr to clean resources
No need to manually handle this. Allows defaulting the destructor and removes special member functions. Signed-off-by: Rosen Penev <[email protected]>
1 parent f771caa commit 48933b9

File tree

1 file changed

+34
-46
lines changed

1 file changed

+34
-46
lines changed

src/basicio.cpp

Lines changed: 34 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,10 +1484,8 @@ class CurlIo::CurlImpl : public Impl {
14841484
public:
14851485
//! Constructor
14861486
CurlImpl(const std::string& url, size_t blockSize);
1487-
//! Destructor. Cleans up the curl pointer and releases all managed memory.
1488-
~CurlImpl() override;
14891487

1490-
CURL* curl_; //!< libcurl pointer
1488+
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl_; //!< libcurl pointer
14911489

14921490
// METHODS
14931491
/*!
@@ -1521,18 +1519,12 @@ class CurlIo::CurlImpl : public Impl {
15211519
*/
15221520
void writeRemote(const byte* data, size_t size, size_t from, size_t to) override;
15231521

1524-
// NOT IMPLEMENTED
1525-
CurlImpl(const CurlImpl&) = delete; //!< Copy constructor
1526-
CurlImpl& operator=(const CurlImpl&) = delete; //!< Assignment
15271522
private:
15281523
long timeout_; //!< The number of seconds to wait while trying to connect.
15291524
};
15301525

1531-
CurlIo::CurlImpl::CurlImpl(const std::string& url, size_t blockSize) : Impl(url, blockSize), curl_(curl_easy_init()) {
1532-
if (!curl_) {
1533-
throw Error(ErrorCode::kerErrorMessage, "Unable to init libcurl.");
1534-
}
1535-
1526+
CurlIo::CurlImpl::CurlImpl(const std::string& url, size_t blockSize) :
1527+
Impl(url, blockSize), curl_(curl_easy_init(), curl_easy_cleanup) {
15361528
// The default block size for FTP is much larger than other protocols
15371529
// the reason is that getDataByRange() in FTP always creates the new connection,
15381530
// so we need the large block size to reduce the overhead of creating the connection.
@@ -1548,54 +1540,54 @@ CurlIo::CurlImpl::CurlImpl(const std::string& url, size_t blockSize) : Impl(url,
15481540
}
15491541

15501542
int64_t CurlIo::CurlImpl::getFileLength() {
1551-
curl_easy_reset(curl_); // reset all options
1552-
curl_easy_setopt(curl_, CURLOPT_URL, path_.c_str());
1553-
curl_easy_setopt(curl_, CURLOPT_NOBODY, 1); // HEAD
1554-
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, curlWriter);
1555-
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
1556-
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
1557-
curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, timeout_);
1558-
// curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1); // debugging mode
1543+
curl_easy_reset(curl_.get()); // reset all options
1544+
curl_easy_setopt(curl_.get(), CURLOPT_URL, path_.c_str());
1545+
curl_easy_setopt(curl_.get(), CURLOPT_NOBODY, 1); // HEAD
1546+
curl_easy_setopt(curl_.get(), CURLOPT_WRITEFUNCTION, curlWriter);
1547+
curl_easy_setopt(curl_.get(), CURLOPT_SSL_VERIFYPEER, 0L);
1548+
curl_easy_setopt(curl_.get(), CURLOPT_SSL_VERIFYHOST, 0L);
1549+
curl_easy_setopt(curl_.get(), CURLOPT_CONNECTTIMEOUT, timeout_);
1550+
// curl_easy_setopt(curl_.get(), CURLOPT_VERBOSE, 1); // debugging mode
15591551

15601552
/* Perform the request, res will get the return code */
1561-
if (auto res = curl_easy_perform(curl_); res != CURLE_OK) { // error happened
1553+
if (auto res = curl_easy_perform(curl_.get()); res != CURLE_OK) { // error happened
15621554
throw Error(ErrorCode::kerErrorMessage, curl_easy_strerror(res));
15631555
}
15641556
// get status
15651557
int serverCode;
1566-
curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &serverCode); // get code
1558+
curl_easy_getinfo(curl_.get(), CURLINFO_RESPONSE_CODE, &serverCode); // get code
15671559
if (serverCode >= 400 || serverCode < 0) {
15681560
throw Error(ErrorCode::kerFileOpenFailed, "http", serverCode, path_);
15691561
}
15701562
// get length
15711563
curl_off_t temp;
1572-
curl_easy_getinfo(curl_, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &temp); // return -1 if unknown
1564+
curl_easy_getinfo(curl_.get(), CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &temp); // return -1 if unknown
15731565
return temp;
15741566
}
15751567

15761568
void CurlIo::CurlImpl::getDataByRange(size_t lowBlock, size_t highBlock, std::string& response) {
1577-
curl_easy_reset(curl_); // reset all options
1578-
curl_easy_setopt(curl_, CURLOPT_URL, path_.c_str());
1579-
curl_easy_setopt(curl_, CURLOPT_NOPROGRESS, 1L); // no progress meter please
1580-
curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, curlWriter);
1581-
curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &response);
1582-
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
1583-
curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, timeout_);
1584-
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L);
1569+
curl_easy_reset(curl_.get()); // reset all options
1570+
curl_easy_setopt(curl_.get(), CURLOPT_URL, path_.c_str());
1571+
curl_easy_setopt(curl_.get(), CURLOPT_NOPROGRESS, 1L); // no progress meter please
1572+
curl_easy_setopt(curl_.get(), CURLOPT_WRITEFUNCTION, curlWriter);
1573+
curl_easy_setopt(curl_.get(), CURLOPT_WRITEDATA, &response);
1574+
curl_easy_setopt(curl_.get(), CURLOPT_SSL_VERIFYPEER, 0L);
1575+
curl_easy_setopt(curl_.get(), CURLOPT_CONNECTTIMEOUT, timeout_);
1576+
curl_easy_setopt(curl_.get(), CURLOPT_SSL_VERIFYHOST, 0L);
15851577

1586-
// curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1); // debugging mode
1578+
// curl_easy_setopt(curl_.get(), CURLOPT_VERBOSE, 1); // debugging mode
15871579

15881580
if (lowBlock != std::numeric_limits<size_t>::max() && highBlock != std::numeric_limits<size_t>::max()) {
15891581
auto range = stringFormat("{}-{}", lowBlock * blockSize_, (highBlock + 1) * (blockSize_ - 1));
1590-
curl_easy_setopt(curl_, CURLOPT_RANGE, range.c_str());
1582+
curl_easy_setopt(curl_.get(), CURLOPT_RANGE, range.c_str());
15911583
}
15921584

15931585
/* Perform the request, res will get the return code */
1594-
if (auto res = curl_easy_perform(curl_); res != CURLE_OK) {
1586+
if (auto res = curl_easy_perform(curl_.get()); res != CURLE_OK) {
15951587
throw Error(ErrorCode::kerErrorMessage, curl_easy_strerror(res));
15961588
}
15971589
int serverCode;
1598-
curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &serverCode); // get code
1590+
curl_easy_getinfo(curl_.get(), CURLINFO_RESPONSE_CODE, &serverCode); // get code
15991591
if (serverCode >= 400 || serverCode < 0) {
16001592
throw Error(ErrorCode::kerFileOpenFailed, "http", serverCode, path_);
16011593
}
@@ -1618,11 +1610,11 @@ void CurlIo::CurlImpl::writeRemote(const byte* data, size_t size, size_t from, s
16181610
scriptPath = hostInfo.Protocol + "://" + hostInfo.Host + scriptPath;
16191611
}
16201612

1621-
curl_easy_reset(curl_); // reset all options
1622-
curl_easy_setopt(curl_, CURLOPT_NOPROGRESS, 1L); // no progress meter please
1623-
// curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1); // debugging mode
1624-
curl_easy_setopt(curl_, CURLOPT_URL, scriptPath.c_str());
1625-
curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L);
1613+
curl_easy_reset(curl_.get()); // reset all options
1614+
curl_easy_setopt(curl_.get(), CURLOPT_NOPROGRESS, 1L); // no progress meter please
1615+
// curl_easy_setopt(curl_.get(), CURLOPT_VERBOSE, 1); // debugging mode
1616+
curl_easy_setopt(curl_.get(), CURLOPT_URL, scriptPath.c_str());
1617+
curl_easy_setopt(curl_.get(), CURLOPT_SSL_VERIFYPEER, 0L);
16261618

16271619
// encode base64
16281620
size_t encodeLength = (((size + 2) / 3) * 4) + 1;
@@ -1632,22 +1624,18 @@ void CurlIo::CurlImpl::writeRemote(const byte* data, size_t size, size_t from, s
16321624
const std::string urlencodeData = urlencode(encodeData.get());
16331625
auto postData = stringFormat("path={}&from={}&to={}&data={}", hostInfo.Path, from, to, urlencodeData);
16341626

1635-
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, postData.c_str());
1627+
curl_easy_setopt(curl_.get(), CURLOPT_POSTFIELDS, postData.c_str());
16361628
// Perform the request, res will get the return code.
1637-
if (auto res = curl_easy_perform(curl_); res != CURLE_OK) {
1629+
if (auto res = curl_easy_perform(curl_.get()); res != CURLE_OK) {
16381630
throw Error(ErrorCode::kerErrorMessage, curl_easy_strerror(res));
16391631
}
16401632
int serverCode;
1641-
curl_easy_getinfo(curl_, CURLINFO_RESPONSE_CODE, &serverCode);
1633+
curl_easy_getinfo(curl_.get(), CURLINFO_RESPONSE_CODE, &serverCode);
16421634
if (serverCode >= 400 || serverCode < 0) {
16431635
throw Error(ErrorCode::kerFileOpenFailed, "http", serverCode, path_);
16441636
}
16451637
}
16461638

1647-
CurlIo::CurlImpl::~CurlImpl() {
1648-
curl_easy_cleanup(curl_);
1649-
}
1650-
16511639
size_t CurlIo::write(const byte* data, size_t wcount) {
16521640
if (p_->protocol_ == pHttp || p_->protocol_ == pHttps) {
16531641
return RemoteIo::write(data, wcount);

0 commit comments

Comments
 (0)