diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp index 261fe8fb5..4384fc8a3 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.cpp @@ -28,75 +28,86 @@ namespace m_bmqstoragetool { // ============================= CompositeSequenceNumber::CompositeSequenceNumber() -: d_leaseId(0) -, d_seqNumber(0) -, d_isSet(false) +: d_compositeSequenceNumber(0, 0) { // NOTHING } CompositeSequenceNumber::CompositeSequenceNumber( - const unsigned int leaseId, - const bsls::Types::Uint64 sequenceNumber) -: d_leaseId(leaseId) -, d_seqNumber(sequenceNumber) + unsigned int leaseId, + bsls::Types::Uint64 sequenceNumber) +: d_compositeSequenceNumber(leaseId, sequenceNumber) { - BSLS_ASSERT(d_leaseId > 0 && d_seqNumber > 0); - d_isSet = d_leaseId > 0 && d_seqNumber > 0; + // NOTHING } CompositeSequenceNumber& -CompositeSequenceNumber::fromString(bsl::ostream& errorDescription, +CompositeSequenceNumber::fromString(bool* success, + bsl::ostream& errorDescription, const bsl::string& seqNumString) { - d_isSet = false; - - if (seqNumString.empty()) { - errorDescription << "Invalid input: empty string."; - return *this; // RETURN - } - - // Find the position of the separator - const size_t separatorPos = seqNumString.find('-'); - if (separatorPos == bsl::string::npos) { - errorDescription << "Invalid format: no '-' separator found."; - return *this; // RETURN - } + // PRECONDITION + BSLS_ASSERT(success); - // Extract parts - const bsl::string firstPart = seqNumString.substr(0, separatorPos); - const bsl::string secondPart = seqNumString.substr(separatorPos + 1); + do { + if (seqNumString.empty()) { + errorDescription << "Invalid input: empty string."; + break; // BREAK + } - // Convert parts to numbers - try { - size_t posFirst, posSecond; + // Find the position of the separator + const size_t separatorPos = seqNumString.find('-'); + if (separatorPos == bsl::string::npos) { + errorDescription << "Invalid format: no '-' separator found."; + break; // BREAK + } - unsigned long uLong = bsl::stoul(firstPart, &posFirst); - d_seqNumber = bsl::stoul(secondPart, &posSecond); + // Extract parts + const bsl::string firstPart = seqNumString.substr(0, separatorPos); + const bsl::string secondPart = seqNumString.substr(separatorPos + 1); + + // Convert parts to numbers + size_t posFirst, posSecond; + unsigned long uLong; + bsls::Types::Uint64 seqNumber; + try { + uLong = bsl::stoul(firstPart, &posFirst); + seqNumber = bsl::stoul(secondPart, &posSecond); + } + catch (const bsl::invalid_argument& e) { + errorDescription + << "Invalid input: non-numeric values encountered."; + break; // BREAK + } + catch (const bsl::out_of_range& e) { + errorDescription << "Invalid input: number out of range."; + break; // BREAK + } if (posFirst != firstPart.size() || posSecond != secondPart.size()) { - throw bsl::invalid_argument(""); // THROW + errorDescription + << "Invalid input: non-numeric values encountered."; + break; // BREAK } - d_leaseId = static_cast(uLong); - if (uLong != d_leaseId) { - throw bsl::out_of_range(""); // THROW + unsigned int leaseId = static_cast(uLong); + if (uLong != leaseId) { + errorDescription << "Invalid input: number out of range."; + break; // BREAK } - if (d_leaseId == 0 || d_seqNumber == 0) { + if (leaseId == 0 || seqNumber == 0) { errorDescription << "Invalid input: zero values encountered."; - return *this; // RETURN + break; // BREAK } - d_isSet = true; - } - catch (const bsl::invalid_argument& e) { - errorDescription << "Invalid input: non-numeric values encountered."; - } - catch (const bsl::out_of_range& e) { - errorDescription << "Invalid input: number out of range."; - } + d_compositeSequenceNumber = bsl::make_pair(leaseId, seqNumber); + *success = true; + return *this; // RETURN + } while (false); + + *success = false; return *this; } @@ -110,13 +121,8 @@ bsl::ostream& CompositeSequenceNumber::print(bsl::ostream& stream, bdlb::Print::indent(stream, level, spacesPerLevel); - if (isSet()) { - stream << "leaseId: " << leaseId() - << ", sequenceNumber: " << sequenceNumber(); - } - else { - stream << "** UNSET **"; - } + stream << "leaseId: " << leaseId() + << ", sequenceNumber: " << sequenceNumber(); if (spacesPerLevel >= 0) { stream << '\n'; diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h index a8c5da817..9f1d481db 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.h @@ -44,48 +44,47 @@ namespace m_bmqstoragetool { class CompositeSequenceNumber { private: - // DATA - unsigned int d_leaseId; - // Primary Lease Id - bsls::Types::Uint64 d_seqNumber; - // Sequence Number - bool d_isSet; - // Set to `true` if the value of this object is set + // PRIVATE DATA + + /// Pair of primary lease Id and sequence number + bsl::pair d_compositeSequenceNumber; public: // CREATORS - /// Create an un-initialized CompositeSequenceNumber. Note that - /// `isSet()` would return false. + /// Create CompositeSequenceNumber with zero initialized values. CompositeSequenceNumber(); /// Create CompositeSequenceNumber from the specified `leaseId` and /// `sequenceNumber` - CompositeSequenceNumber(const unsigned int leaseId, - const bsls::Types::Uint64 sequenceNumber); + CompositeSequenceNumber(unsigned int leaseId, + bsls::Types::Uint64 sequenceNumber); // MANIPULATORS /// Initialize this CompositeSequenceNumber from the specified /// `seqNumString` representation in format `-`. /// Return a reference offering modifiable access to this object. If - /// convertion is successfull, `isSet()` would return `true`. Otherwise, - /// `isSet()` would return `false` and specified `errorDescription` is + /// convertion is successfull, `success` value is set to `true`. Otherwise, + /// `success` value is set to `false` and specified `errorDescription` is /// filled with error description. - CompositeSequenceNumber& fromString(bsl::ostream& errorDescription, + CompositeSequenceNumber& fromString(bool* success, + bsl::ostream& errorDescription, const bsl::string& seqNumString); // ACCESSORS - /// Return `true` if the value of this object is not set. - bool isSet() const; - - /// Return Primary Lease Id value. + /// Return primary Lease Id value. unsigned int leaseId() const; - /// Return Sequence Number value. + /// Return sequence number value. bsls::Types::Uint64 sequenceNumber() const; + /// Return the const reference to composite sequence number as a pair of + /// primary lease Id and sequence number. + const bsl::pair& + compositeSequenceNumber() const; + /// Write the value of this object to the specified output `stream` in a /// human-readable format, and return a reference to `stream`. /// Optionally specify an initial indentation `level`. If `level` is @@ -139,19 +138,20 @@ bool operator<=(const CompositeSequenceNumber& lhs, // ACCESSORS -inline bool CompositeSequenceNumber::isSet() const +inline unsigned int CompositeSequenceNumber::leaseId() const { - return d_isSet; + return d_compositeSequenceNumber.first; } -inline unsigned int CompositeSequenceNumber::leaseId() const +inline bsls::Types::Uint64 CompositeSequenceNumber::sequenceNumber() const { - return d_leaseId; + return d_compositeSequenceNumber.second; } -inline bsls::Types::Uint64 CompositeSequenceNumber::sequenceNumber() const +inline const bsl::pair& +CompositeSequenceNumber::compositeSequenceNumber() const { - return d_seqNumber; + return d_compositeSequenceNumber; } } // close package namespace @@ -166,9 +166,6 @@ inline bsl::ostream& m_bmqstoragetool::operator<<( bsl::ostream& stream, const m_bmqstoragetool::CompositeSequenceNumber& rhs) { - // PRECONDITIONS - BSLS_ASSERT(rhs.isSet()); - return rhs.print(stream, 0, -1); } @@ -176,41 +173,21 @@ inline bool m_bmqstoragetool::operator==( const m_bmqstoragetool::CompositeSequenceNumber& lhs, const m_bmqstoragetool::CompositeSequenceNumber& rhs) { - // PRECONDITIONS - BSLS_ASSERT(lhs.isSet() && rhs.isSet()); - - return (lhs.leaseId() == rhs.leaseId() && - lhs.sequenceNumber() == rhs.sequenceNumber()); + return lhs.compositeSequenceNumber() == rhs.compositeSequenceNumber(); } inline bool m_bmqstoragetool::operator<( const m_bmqstoragetool::CompositeSequenceNumber& lhs, const m_bmqstoragetool::CompositeSequenceNumber& rhs) { - // PRECONDITIONS - BSLS_ASSERT(lhs.isSet() && rhs.isSet()); - - // Check leaseId first - if (lhs.leaseId() < rhs.leaseId()) { - return true; // RETURN - } - else if (lhs.leaseId() == rhs.leaseId()) { - if (lhs.sequenceNumber() < rhs.sequenceNumber()) { - return true; // RETURN - } - } - - return false; + return lhs.compositeSequenceNumber() < rhs.compositeSequenceNumber(); } inline bool m_bmqstoragetool::operator<=( const m_bmqstoragetool::CompositeSequenceNumber& lhs, const m_bmqstoragetool::CompositeSequenceNumber& rhs) { - // PRECONDITIONS - BSLS_ASSERT(lhs.isSet() && rhs.isSet()); - - return (lhs < rhs || lhs == rhs); + return lhs.compositeSequenceNumber() <= rhs.compositeSequenceNumber(); } } // close enterprise namespace diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp index 779386935..7cad6e6a8 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_compositesequencenumber.t.cpp @@ -46,12 +46,12 @@ static void test1_breathingTest() { CompositeSequenceNumber compositeSeqNum; - BMQTST_ASSERT(!compositeSeqNum.isSet()); + BMQTST_ASSERT(compositeSeqNum.leaseId() == 0); + BMQTST_ASSERT(compositeSeqNum.sequenceNumber() == 0); } { CompositeSequenceNumber compositeSeqNum(1, 2); - BMQTST_ASSERT(compositeSeqNum.isSet()); BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 1ul); BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 2ul); } @@ -73,6 +73,8 @@ static void test2_fromStringTest() bmqu::MemOutStream errorDescription(bmqtst::TestHelperUtil::allocator()); + bool success = false; + // Valid string { CompositeSequenceNumber compositeSeqNum; @@ -80,8 +82,8 @@ static void test2_fromStringTest() bsl::string inputString("123-456", bmqtst::TestHelperUtil::allocator()); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT(compositeSeqNum.isSet()); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT(success); BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 123u); BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); BMQTST_ASSERT(errorDescription.str().empty()); @@ -94,8 +96,8 @@ static void test2_fromStringTest() bsl::string inputString("00123-000456", bmqtst::TestHelperUtil::allocator()); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT(compositeSeqNum.isSet()); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT(success); BMQTST_ASSERT_EQ(compositeSeqNum.leaseId(), 123u); BMQTST_ASSERT_EQ(compositeSeqNum.sequenceNumber(), 456u); BMQTST_ASSERT(errorDescription.str().empty()); @@ -107,8 +109,8 @@ static void test2_fromStringTest() bsl::string inputString("", bmqtst::TestHelperUtil::allocator()); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: empty string."); @@ -121,8 +123,8 @@ static void test2_fromStringTest() bsl::string inputString("123456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); @@ -136,8 +138,8 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid format: no '-' separator found."); @@ -151,8 +153,8 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); @@ -166,8 +168,8 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: non-numeric values encountered."); @@ -180,8 +182,8 @@ static void test2_fromStringTest() bsl::string inputString("0-456", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); @@ -194,8 +196,8 @@ static void test2_fromStringTest() bsl::string inputString("123-0", bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: zero values encountered."); @@ -210,8 +212,8 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); @@ -226,8 +228,8 @@ static void test2_fromStringTest() bmqtst::TestHelperUtil::allocator()); errorDescription.reset(); - compositeSeqNum.fromString(errorDescription, inputString); - BMQTST_ASSERT_EQ(compositeSeqNum.isSet(), false); + compositeSeqNum.fromString(&success, errorDescription, inputString); + BMQTST_ASSERT_EQ(success, false); BMQTST_ASSERT(!errorDescription.str().empty()); BMQTST_ASSERT_EQ(errorDescription.str(), "Invalid input: number out of range."); diff --git a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp index 4029fac12..05292143f 100644 --- a/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp +++ b/src/applications/bmqstoragetool/m_bmqstoragetool_parameters.cpp @@ -174,21 +174,23 @@ bool CommandLineArguments::validate(bsl::string* error, if (!d_seqNumLt.empty() || !d_seqNumGt.empty()) { bmqu::MemOutStream errorDescr(allocator); CompositeSequenceNumber seqNumLt, seqNumGt; + bool successLt = false; if (!d_seqNumLt.empty()) { - seqNumLt.fromString(errorDescr, d_seqNumLt); - if (!seqNumLt.isSet()) { + seqNumLt.fromString(&successLt, errorDescr, d_seqNumLt); + if (!successLt) { ss << "--seqnum-lt: " << errorDescr.str() << "\n"; errorDescr.reset(); } } + bool successGt = false; if (!d_seqNumGt.empty()) { - seqNumGt.fromString(errorDescr, d_seqNumGt); - if (!seqNumGt.isSet()) { + seqNumGt.fromString(&successGt, errorDescr, d_seqNumGt); + if (!successGt) { ss << "--seqnum-gt: " << errorDescr.str() << "\n"; } } - if (seqNumLt.isSet() && seqNumGt.isSet()) { + if (successLt && successGt) { if (seqNumLt <= seqNumGt) { ss << "Invalid sequence number range specified\n"; } @@ -239,12 +241,13 @@ bool CommandLineArguments::validate(bsl::string* error, } if (!d_seqNum.empty()) { CompositeSequenceNumber seqNum; + bool success = false; bmqu::MemOutStream errorDescr(allocator); for (bsl::vector::const_iterator cit = d_seqNum.begin(); cit != d_seqNum.end(); ++cit) { - seqNum.fromString(errorDescr, *cit); - if (!seqNum.isSet()) { + seqNum.fromString(&success, errorDescr, *cit); + if (!success) { ss << "--seqnum: " << errorDescr.str() << "\n"; errorDescr.reset(); } @@ -413,15 +416,20 @@ Parameters::Parameters(const CommandLineArguments& arguments, } else if (!arguments.d_seqNumLt.empty() || !arguments.d_seqNumGt.empty()) { bmqu::MemOutStream errorDescr(allocator); + bool success = false; if (!arguments.d_seqNumLt.empty()) { d_range.d_seqNumLt = CompositeSequenceNumber().fromString( + &success, errorDescr, arguments.d_seqNumLt); + BSLS_ASSERT(success); } if (!arguments.d_seqNumGt.empty()) { d_range.d_seqNumGt = CompositeSequenceNumber().fromString( + &success, errorDescr, arguments.d_seqNumGt); + BSLS_ASSERT(success); } } @@ -429,11 +437,12 @@ Parameters::Parameters(const CommandLineArguments& arguments, if (!arguments.d_seqNum.empty()) { CompositeSequenceNumber seqNum; bmqu::MemOutStream errorDescr(allocator); + bool success = false; for (bsl::vector::const_iterator cit = arguments.d_seqNum.begin(); cit != arguments.d_seqNum.end(); ++cit) { - seqNum.fromString(errorDescr, *cit); + seqNum.fromString(&success, errorDescr, *cit); d_seqNum.push_back(seqNum); } }