Use std::unique_ptr instead of array_ptr

pull/103/head
Tatsuhiro Tsujikawa 2013-07-03 23:23:22 +09:00
parent df0034f1cd
commit 7e6db8d801
11 changed files with 81 additions and 150 deletions

View File

@ -214,16 +214,13 @@ void BtPieceMessage::send()
void BtPieceMessage::pushPieceData(int64_t offset, int32_t length) const void BtPieceMessage::pushPieceData(int64_t offset, int32_t length) const
{ {
assert(length <= 16*1024); assert(length <= 16*1024);
array_ptr<unsigned char> buf auto buf = make_unique<unsigned char[]>(length+MESSAGE_HEADER_LENGTH);
(new unsigned char[length+MESSAGE_HEADER_LENGTH]); createMessageHeader(buf.get());
createMessageHeader(buf);
ssize_t r; ssize_t r;
r = getPieceStorage()->getDiskAdaptor()->readData(buf+MESSAGE_HEADER_LENGTH, r = getPieceStorage()->getDiskAdaptor()->readData
length, offset); (buf.get()+MESSAGE_HEADER_LENGTH, length, offset);
if(r == length) { if(r == length) {
unsigned char* dbuf = buf; getPeerConnection()->pushBytes(buf.release(), length+MESSAGE_HEADER_LENGTH,
buf.reset(0);
getPeerConnection()->pushBytes(dbuf, length+MESSAGE_HEADER_LENGTH,
make_unique<PieceSendUpdate> make_unique<PieceSendUpdate>
(getPeer(), MESSAGE_HEADER_LENGTH)); (getPeer(), MESSAGE_HEADER_LENGTH));
// To avoid upload rate overflow, we update the length here at // To avoid upload rate overflow, we update the length here at

View File

@ -242,18 +242,17 @@ void DefaultBtProgressInfoFile::load()
throw DL_ABORT_EX(fmt("Invalid info hash length: %d", infoHashLength)); throw DL_ABORT_EX(fmt("Invalid info hash length: %d", infoHashLength));
} }
if(infoHashLength > 0) { if(infoHashLength > 0) {
array_ptr<unsigned char> savedInfoHash(new unsigned char[infoHashLength]); auto savedInfoHash = make_unique<unsigned char[]>((size_t)infoHashLength);
READ_CHECK(fp, static_cast<unsigned char*>(savedInfoHash), READ_CHECK(fp, savedInfoHash.get(), infoHashLength);
infoHashLength);
#ifdef ENABLE_BITTORRENT #ifdef ENABLE_BITTORRENT
if(infoHashCheckEnabled) { if(infoHashCheckEnabled) {
const unsigned char* infoHash = bittorrent::getInfoHash(dctx_); const unsigned char* infoHash = bittorrent::getInfoHash(dctx_);
if(infoHashLength != INFO_HASH_LENGTH || if(infoHashLength != INFO_HASH_LENGTH ||
memcmp(savedInfoHash, infoHash, INFO_HASH_LENGTH) != 0) { memcmp(savedInfoHash.get(), infoHash, INFO_HASH_LENGTH) != 0) {
throw DL_ABORT_EX throw DL_ABORT_EX
(fmt("info hash mismatch. expected: %s, actual: %s", (fmt("info hash mismatch. expected: %s, actual: %s",
util::toHex(infoHash, INFO_HASH_LENGTH).c_str(), util::toHex(infoHash, INFO_HASH_LENGTH).c_str(),
util::toHex(savedInfoHash, infoHashLength).c_str() util::toHex(savedInfoHash.get(), infoHashLength).c_str()
)); ));
} }
} }
@ -302,11 +301,10 @@ void DefaultBtProgressInfoFile::load()
bitfieldLength)); bitfieldLength));
} }
array_ptr<unsigned char> savedBitfield(new unsigned char[bitfieldLength]); auto savedBitfield = make_unique<unsigned char[]>((size_t)bitfieldLength);
READ_CHECK(fp, static_cast<unsigned char*>(savedBitfield), READ_CHECK(fp, savedBitfield.get(), bitfieldLength);
bitfieldLength);
if(pieceLength == static_cast<uint32_t>(dctx_->getPieceLength())) { if(pieceLength == static_cast<uint32_t>(dctx_->getPieceLength())) {
pieceStorage_->setBitfield(savedBitfield, bitfieldLength); pieceStorage_->setBitfield(savedBitfield.get(), bitfieldLength);
uint32_t numInFlightPiece; uint32_t numInFlightPiece;
READ_CHECK(fp, &numInFlightPiece, sizeof(numInFlightPiece)); READ_CHECK(fp, &numInFlightPiece, sizeof(numInFlightPiece));
@ -345,11 +343,10 @@ void DefaultBtProgressInfoFile::load()
static_cast<unsigned long>(piece->getBitfieldLength()), static_cast<unsigned long>(piece->getBitfieldLength()),
bitfieldLength)); bitfieldLength));
} }
array_ptr<unsigned char> pieceBitfield auto pieceBitfield = make_unique<unsigned char[]>
(new unsigned char[bitfieldLength]); ((size_t)bitfieldLength);
READ_CHECK(fp, static_cast<unsigned char*>(pieceBitfield), READ_CHECK(fp, pieceBitfield.get(), bitfieldLength);
bitfieldLength); piece->setBitfield(pieceBitfield.get(), bitfieldLength);
piece->setBitfield(pieceBitfield, bitfieldLength);
#ifdef ENABLE_MESSAGE_DIGEST #ifdef ENABLE_MESSAGE_DIGEST
@ -367,7 +364,7 @@ void DefaultBtProgressInfoFile::load()
numInFlightPiece = ntohl(numInFlightPiece); numInFlightPiece = ntohl(numInFlightPiece);
} }
BitfieldMan src(pieceLength, totalLength); BitfieldMan src(pieceLength, totalLength);
src.setBitfield(savedBitfield, bitfieldLength); src.setBitfield(savedBitfield.get(), bitfieldLength);
if((src.getCompletedLength() || numInFlightPiece) && if((src.getCompletedLength() || numInFlightPiece) &&
!option_->getAsBool(PREF_ALLOW_PIECE_LENGTH_CHANGE)) { !option_->getAsBool(PREF_ALLOW_PIECE_LENGTH_CHANGE)) {
throw DOWNLOAD_FAILURE_EXCEPTION2 throw DOWNLOAD_FAILURE_EXCEPTION2

View File

@ -197,9 +197,9 @@ DefaultBtRequestFactory::createRequestMessagesOnEndGame(size_t max)
itr != eoi && requests.size() < max; ++itr) { itr != eoi && requests.size() < max; ++itr) {
auto& piece = *itr; auto& piece = *itr;
const size_t mislen = piece->getBitfieldLength(); const size_t mislen = piece->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]); auto misbitfield = make_unique<unsigned char[]>(mislen);
piece->getAllMissingBlockIndexes(misbitfield, mislen); piece->getAllMissingBlockIndexes(misbitfield.get(), mislen);
auto missingBlockIndexes = std::vector<size_t>{}; auto missingBlockIndexes = std::vector<size_t>{};
size_t blockIndex = 0; size_t blockIndex = 0;

View File

@ -185,12 +185,12 @@ void DefaultPieceStorage::getMissingPiece
cuid_t cuid) cuid_t cuid)
{ {
const size_t mislen = bitfieldMan_->getBitfieldLength(); const size_t mislen = bitfieldMan_->getBitfieldLength();
array_ptr<unsigned char> misbitfield(new unsigned char[mislen]); auto misbitfield = make_unique<unsigned char[]>(mislen);
size_t blocks = bitfieldMan_->countBlock(); size_t blocks = bitfieldMan_->countBlock();
size_t misBlock = 0; size_t misBlock = 0;
if(isEndGame()) { if(isEndGame()) {
bool r = bitfieldMan_->getAllMissingIndexes bool r = bitfieldMan_->getAllMissingIndexes
(misbitfield, mislen, bitfield, length); (misbitfield.get(), mislen, bitfield, length);
if(!r) { if(!r) {
return; return;
} }
@ -214,15 +214,15 @@ void DefaultPieceStorage::getMissingPiece
} }
} else { } else {
bool r = bitfieldMan_->getAllMissingUnusedIndexes bool r = bitfieldMan_->getAllMissingUnusedIndexes
(misbitfield, mislen, bitfield, length); (misbitfield.get(), mislen, bitfield, length);
if(!r) { if(!r) {
return; return;
} }
while(misBlock < minMissingBlocks) { while(misBlock < minMissingBlocks) {
size_t index; size_t index;
if(pieceSelector_->select(index, misbitfield, blocks)) { if(pieceSelector_->select(index, misbitfield.get(), blocks)) {
pieces.push_back(checkOutPiece(index, cuid)); pieces.push_back(checkOutPiece(index, cuid));
bitfield::flipBit(misbitfield, blocks, index); bitfield::flipBit(misbitfield.get(), blocks, index);
misBlock += pieces.back()->countMissingBlock(); misBlock += pieces.back()->countMissingBlock();
} else { } else {
break; break;

View File

@ -128,15 +128,13 @@ void MSEHandshake::sendPublicKey()
{ {
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending public key.", A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending public key.",
cuid_)); cuid_));
unsigned char* buf = new unsigned char[KEY_LENGTH+MAX_PAD_LENGTH]; auto buf = make_unique<unsigned char[]>(KEY_LENGTH+MAX_PAD_LENGTH);
array_ptr<unsigned char> bufp(buf); dh_->getPublicKey(buf.get(), KEY_LENGTH);
dh_->getPublicKey(buf, KEY_LENGTH);
size_t padLength = size_t padLength =
SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1); SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
dh_->generateNonce(buf+KEY_LENGTH, padLength); dh_->generateNonce(buf.get()+KEY_LENGTH, padLength);
socketBuffer_.pushBytes(buf, KEY_LENGTH+padLength); socketBuffer_.pushBytes(buf.release(), KEY_LENGTH+padLength);
bufp.reset(0);
} }
void MSEHandshake::read() void MSEHandshake::read()
@ -271,23 +269,23 @@ void MSEHandshake::sendInitiatorStep2()
{ {
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending negotiation step2.", cuid_)); A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Sending negotiation step2.", cuid_));
// Assuming no exception // Assuming no exception
unsigned char* md = new unsigned char[20]; auto md = make_unique<unsigned char[]>((size_t)20);
createReq1Hash(md); createReq1Hash(md.get());
socketBuffer_.pushBytes(md, 20); socketBuffer_.pushBytes(md.release(), 20);
// Assuming no exception // Assuming no exception
md = new unsigned char[20]; md = make_unique<unsigned char[]>((size_t)20);
createReq23Hash(md, infoHash_); createReq23Hash(md.get(), infoHash_);
socketBuffer_.pushBytes(md, 20); socketBuffer_.pushBytes(md.release(), 20);
// buffer is filled in this order: // buffer is filled in this order:
// VC(VC_LENGTH bytes), // VC(VC_LENGTH bytes),
// crypto_provide(CRYPTO_BITFIELD_LENGTH bytes), // crypto_provide(CRYPTO_BITFIELD_LENGTH bytes),
// len(padC)(2 bytes), // len(padC)(2 bytes),
// padC(len(padC) bytes <= MAX_PAD_LENGTH), // padC(len(padC) bytes <= MAX_PAD_LENGTH),
// len(IA)(2 bytes) // len(IA)(2 bytes)
unsigned char* buffer = new unsigned char auto buffer = make_unique<unsigned char[]>(40+VC_LENGTH+
[40+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH+2]; CRYPTO_BITFIELD_LENGTH+2+
array_ptr<unsigned char> bufp(buffer); MAX_PAD_LENGTH+2);
unsigned char* ptr = buffer; unsigned char* ptr = buffer.get();
// VC // VC
memcpy(ptr, VC, sizeof(VC)); memcpy(ptr, VC, sizeof(VC));
ptr += sizeof(VC); ptr += sizeof(VC);
@ -317,8 +315,8 @@ void MSEHandshake::sendInitiatorStep2()
memcpy(ptr, &iaLengthBE, sizeof(iaLengthBE)); memcpy(ptr, &iaLengthBE, sizeof(iaLengthBE));
} }
ptr += 2; ptr += 2;
encryptAndSendData(buffer, ptr-buffer); size_t buflen = ptr-buffer.get();
bufp.reset(0); encryptAndSendData(buffer.release(), buflen);
} }
// This function reads exactly until the end of VC marker is reached. // This function reads exactly until the end of VC marker is reached.
@ -522,10 +520,10 @@ void MSEHandshake::sendReceiverStep2()
// cryptoSelect(CRYPTO_BITFIELD_LENGTH bytes), // cryptoSelect(CRYPTO_BITFIELD_LENGTH bytes),
// len(padD)(2bytes), // len(padD)(2bytes),
// padD(len(padD)bytes <= MAX_PAD_LENGTH) // padD(len(padD)bytes <= MAX_PAD_LENGTH)
unsigned char* buffer = new unsigned char auto buffer = make_unique<unsigned char[]>(VC_LENGTH+
[VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2+MAX_PAD_LENGTH]; CRYPTO_BITFIELD_LENGTH+2+
array_ptr<unsigned char> bufp(buffer); MAX_PAD_LENGTH);
unsigned char* ptr = buffer; unsigned char* ptr = buffer.get();
// VC // VC
memcpy(ptr, VC, sizeof(VC)); memcpy(ptr, VC, sizeof(VC));
ptr += sizeof(VC); ptr += sizeof(VC);
@ -542,8 +540,8 @@ void MSEHandshake::sendReceiverStep2()
// padD, all zeroed // padD, all zeroed
memset(ptr, 0, padDLength); memset(ptr, 0, padDLength);
ptr += padDLength; ptr += padDLength;
encryptAndSendData(buffer, ptr-buffer); size_t buflen = ptr - buffer.get();
bufp.reset(0); encryptAndSendData(buffer.release(), buflen);
} }
uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf, const char* padName) uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf, const char* padName)

View File

@ -186,10 +186,9 @@ void MessageDigest::digest(unsigned char* md)
std::string MessageDigest::digest() std::string MessageDigest::digest()
{ {
size_t length = pImpl_->getDigestLength(); size_t length = pImpl_->getDigestLength();
array_ptr<unsigned char> buf(new unsigned char[length]); auto buf = make_unique<unsigned char[]>(length);
pImpl_->digest(buf); pImpl_->digest(buf.get());
std::string hd(&buf[0], &buf[length]); return std::string(&buf[0], &buf[length]);
return hd;
} }
} // namespace aria2 } // namespace aria2

View File

@ -152,11 +152,11 @@ void OptionParser::parseArg
size_t numPublicOption = countPublicOption(handlers_.begin(), size_t numPublicOption = countPublicOption(handlers_.begin(),
handlers_.end()); handlers_.end());
int lopt; int lopt;
array_ptr<struct option> longOpts(new struct option[numPublicOption+1]); auto longOpts = make_unique<struct option[]>(numPublicOption+1);
putOptions(longOpts, &lopt, handlers_.begin(), handlers_.end()); putOptions(longOpts.get(), &lopt, handlers_.begin(), handlers_.end());
std::string optstring = createOptstring(handlers_.begin(), handlers_.end()); std::string optstring = createOptstring(handlers_.begin(), handlers_.end());
while(1) { while(1) {
int c = getopt_long(argc, argv, optstring.c_str(), longOpts, 0); int c = getopt_long(argc, argv, optstring.c_str(), longOpts.get(), 0);
if(c == -1) { if(c == -1) {
break; break;
} }

View File

@ -186,6 +186,12 @@ std::unique_ptr<T> make_unique(U&&... u)
return std::unique_ptr<T>(new T(std::forward<U>(u)...)); return std::unique_ptr<T>(new T(std::forward<U>(u)...));
} }
template<typename T>
std::unique_ptr<T> make_unique(size_t size)
{
return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]());
}
} // namespace aria2 } // namespace aria2
#endif // D_A2_FUNCTIONAL_H #endif // D_A2_FUNCTIONAL_H

View File

@ -53,45 +53,6 @@ char (&char_array_ref_fun(T (&)[0u]))[0u];
// To calculate size of array at compile time, we use macro here. // To calculate size of array at compile time, we use macro here.
#define A2_ARRAY_LEN(X) sizeof(char_array_ref_fun(X)) #define A2_ARRAY_LEN(X) sizeof(char_array_ref_fun(X))
template<typename T>
class array_ptr {
private:
T* array_;
// Copies are not allowed. Let's make them private.
array_ptr(const array_ptr& s);
array_ptr& operator=(const array_ptr& s);
template<typename S>
array_ptr& operator=(const array_ptr<S>& s);
public:
array_ptr():array_(0) {}
explicit array_ptr(T* array):array_(array) {}
~array_ptr()
{
delete [] array_;
}
operator T*()
{
return array_;
}
operator const T*() const
{
return array_;
}
void reset(T* array)
{
array_ = array;
}
};
template<typename T, size_t N> template<typename T, size_t N>
class array_wrapper { class array_wrapper {
private: private:

View File

@ -129,16 +129,15 @@ int wCharToAnsi(char* out, size_t outLength, const wchar_t* src)
std::wstring utf8ToWChar(const char* src) std::wstring utf8ToWChar(const char* src)
{ {
int len = utf8ToWChar(0, 0, src); int len = utf8ToWChar(0, 0, src);
if(len == 0) { if(len <= 0) {
abort(); abort();
} }
array_ptr<wchar_t> buf(new wchar_t[len]); auto buf = make_unique<wchar_t[]>((size_t)len);
len = utf8ToWChar(buf, len, src); len = utf8ToWChar(buf.get(), len, src);
if(len == 0) { if(len <= 0) {
abort(); abort();
} else { } else {
std::wstring dest(buf); return buf.get();
return dest;
} }
} }
@ -151,47 +150,45 @@ std::string utf8ToNative(const std::string& src)
{ {
std::wstring wsrc = utf8ToWChar(src); std::wstring wsrc = utf8ToWChar(src);
int len = wCharToAnsi(0, 0, wsrc.c_str()); int len = wCharToAnsi(0, 0, wsrc.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} }
array_ptr<char> buf(new char[len]); auto buf = make_unique<char[]>((size_t)len);
len = wCharToAnsi(buf, len, wsrc.c_str()); len = wCharToAnsi(buf.get(), len, wsrc.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} else { } else {
std::string dest(buf); return buf.get();
return dest;
} }
} }
std::string wCharToUtf8(const std::wstring& wsrc) std::string wCharToUtf8(const std::wstring& wsrc)
{ {
int len = wCharToUtf8(0, 0, wsrc.c_str()); int len = wCharToUtf8(0, 0, wsrc.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} }
array_ptr<char> buf(new char[len]); auto buf = make_unique<char[]>((size_t)len);
len = wCharToUtf8(buf, len, wsrc.c_str()); len = wCharToUtf8(buf.get(), len, wsrc.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} else { } else {
std::string dest(buf); return buf.get();
return dest;
} }
} }
std::string nativeToUtf8(const std::string& src) std::string nativeToUtf8(const std::string& src)
{ {
int len = ansiToWChar(0, 0, src.c_str()); int len = ansiToWChar(0, 0, src.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} }
array_ptr<wchar_t> buf(new wchar_t[len]); auto buf = make_unique<wchar_t[]>((size_t)len);
len = ansiToWChar(buf, len, src.c_str()); len = ansiToWChar(buf.get(), len, src.c_str());
if(len == 0) { if(len <= 0) {
abort(); abort();
} else { } else {
return wCharToUtf8(std::wstring(buf)); return wCharToUtf8(std::wstring(buf.get()));
} }
} }
#endif // __MINGW32__ #endif // __MINGW32__
@ -1770,12 +1767,12 @@ void executeHook
} }
int cmdlineLen = utf8ToWChar(0, 0, cmdline.c_str()); int cmdlineLen = utf8ToWChar(0, 0, cmdline.c_str());
assert(cmdlineLen > 0); assert(cmdlineLen > 0);
array_ptr<wchar_t> wcharCmdline(new wchar_t[cmdlineLen]); auto wcharCmdline = std::unique_ptr<wchar_t[]>(new wchar_t[cmdlineLen]);
cmdlineLen = utf8ToWChar(wcharCmdline, cmdlineLen, cmdline.c_str()); cmdlineLen = utf8ToWChar(wcharCmdline.get(), cmdlineLen, cmdline.c_str());
assert(cmdlineLen > 0); assert(cmdlineLen > 0);
A2_LOG_INFO(fmt("Executing user command: %s", cmdline.c_str())); A2_LOG_INFO(fmt("Executing user command: %s", cmdline.c_str()));
DWORD rc = CreateProcessW(batch ? utf8ToWChar(cmdexe).c_str() : NULL, DWORD rc = CreateProcessW(batch ? utf8ToWChar(cmdexe).c_str() : NULL,
wcharCmdline, wcharCmdline.get(),
NULL, NULL,
NULL, NULL,
true, true,

View File

@ -11,7 +11,6 @@ class array_funTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testArray_negate); CPPUNIT_TEST(testArray_negate);
CPPUNIT_TEST(testArray_and); CPPUNIT_TEST(testArray_and);
CPPUNIT_TEST(testArrayLength); CPPUNIT_TEST(testArrayLength);
CPPUNIT_TEST(testArrayPtr);
CPPUNIT_TEST(testArrayWrapper); CPPUNIT_TEST(testArrayWrapper);
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
@ -21,7 +20,6 @@ public:
void testArray_negate(); void testArray_negate();
void testArray_and(); void testArray_and();
void testArrayLength(); void testArrayLength();
void testArrayPtr();
void testArrayWrapper(); void testArrayWrapper();
struct X{ struct X{
@ -70,15 +68,6 @@ void array_funTest::testArrayLength()
// CPPUNIT_ASSERT_EQUAL((size_t)0, A2_ARRAY_LEN(zeroLengthArray)); // CPPUNIT_ASSERT_EQUAL((size_t)0, A2_ARRAY_LEN(zeroLengthArray));
} }
namespace {
// Check operator[] in const context.
void arrayPtrConst(const array_ptr<struct array_funTest::X>& ax)
{
CPPUNIT_ASSERT_EQUAL(100, ax[3].m);
CPPUNIT_ASSERT_EQUAL(99, ax[2].m);
}
} // namespace
namespace { namespace {
void arrayPtrCast(struct array_funTest::X* x) {} void arrayPtrCast(struct array_funTest::X* x) {}
} // namespace } // namespace
@ -87,19 +76,6 @@ namespace {
void arrayPtrConstCast(const struct array_funTest::X* x) {} void arrayPtrConstCast(const struct array_funTest::X* x) {}
} // namespace } // namespace
void array_funTest::testArrayPtr()
{
array_ptr<struct X> ax(new struct X[10]);
ax[3].m = 100;
ax[2].m = 99;
CPPUNIT_ASSERT_EQUAL(100, ax[3].m);
CPPUNIT_ASSERT_EQUAL(99, ax[2].m);
arrayPtrConst(ax);
arrayPtrCast(ax);
arrayPtrConstCast(ax);
}
namespace { namespace {
void arrayWrapperConst(const array_wrapper<int, 10>& array) void arrayWrapperConst(const array_wrapper<int, 10>& array)
{ {