Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 37 additions & 61 deletions src/groups/bmq/bmqp/bmqp_messageproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,108 +259,84 @@ bool MessageProperties::streamInPropertyValue(const Property& p) const
BSLS_ASSERT_SAFE(p.d_value.isUnset());
BSLS_ASSERT_SAFE(p.d_offset);

bmqu::BlobPosition position;
int rc = bmqu::BlobUtil::findOffsetSafe(&position, *d_blob_p, p.d_offset);
BSLS_ASSERT_SAFE(rc == 0);
bmqu::BlobSection section;
const int rc = bmqu::BlobUtil::findBlobSectionSafe(&section,
*d_blob_p,
bmqu::BlobPosition(),
p.d_offset,
p.d_length);
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(0 != rc)) {
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
return false; // RETURN
}

switch (p.d_type) {
case bmqt::PropertyType::e_BOOL: {
char value;
rc = bmqu::BlobUtil::readNBytes(&value,
*d_blob_p,
position,
sizeof(value));

section.readTo(&value, *d_blob_p, sizeof(char));
p.d_value = value == 1 ? true : false;
break;
}
case bmqt::PropertyType::e_CHAR: {
char value;
rc = bmqu::BlobUtil::readNBytes(&value,
*d_blob_p,
position,
sizeof(value));

section.readTo(&value, *d_blob_p, sizeof(char));
p.d_value = value;
break;
}
case bmqt::PropertyType::e_SHORT: {
bdlb::BigEndianInt16 nboValue;
rc = bmqu::BlobUtil::readNBytes(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
position,
sizeof(nboValue));

section.readTo(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
sizeof(bdlb::BigEndianInt16));
p.d_value = static_cast<short>(nboValue);
break;
}
case bmqt::PropertyType::e_INT32: {
bdlb::BigEndianInt32 nboValue;
rc = bmqu::BlobUtil::readNBytes(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
position,
sizeof(nboValue));

section.readTo(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
sizeof(bdlb::BigEndianInt32));
p.d_value = static_cast<int>(nboValue);
break;
}
case bmqt::PropertyType::e_INT64: {
bdlb::BigEndianInt64 nboValue;
rc = bmqu::BlobUtil::readNBytes(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
position,
sizeof(nboValue));

section.readTo(reinterpret_cast<char*>(&nboValue),
*d_blob_p,
sizeof(bdlb::BigEndianInt64));
p.d_value = static_cast<bsls::Types::Int64>(nboValue);
break;
}

case bmqt::PropertyType::e_STRING: {
// Try to avoid copying the string. 'd_blop' already keeps a copy.
bmqu::BlobPosition end;
const int ret =
bmqu::BlobUtil::findOffset(&end, *d_blob_p, position, p.d_length);
bool doCopy = true;
if (ret == 0) {
// Do not align
if (bmqu::BlobUtil::isDataContinuous(position, end)) {
// Section is good
char* start = d_blob_p->buffer(position.buffer()).data() +
position.byte();

p.d_value = bsl::string_view(start, p.d_length);
doCopy = false;
}
if (section.isDataContinuous()) {
// Shallow copy
const bmqu::BlobPosition& start = section.start();
char* data = d_blob_p->buffer(start.buffer()).data() +
start.byte();
p.d_value = bsl::string_view(data, p.d_length);
}
if (doCopy) {
bsl::string value(p.d_length, ' ', d_allocator_p);
rc = bmqu::BlobUtil::readNBytes(&value[0],
*d_blob_p,
position,
p.d_length);
p.d_value = value;
else {
bsl::string copy(p.d_length, ' ', d_allocator_p);
section.readTo(copy.data(), *d_blob_p, p.d_length);
p.d_value = bslmf::MovableRefUtil::move(copy);
}

break;
}
case bmqt::PropertyType::e_BINARY: {
bsl::vector<char> value(p.d_length, d_allocator_p);
rc = bmqu::BlobUtil::readNBytes(&value[0],
*d_blob_p,
position,
p.d_length);

p.d_value = value;
bsl::vector<char> copy(p.d_length, d_allocator_p);
section.readTo(copy.data(), *d_blob_p, p.d_length);
p.d_value = bslmf::MovableRefUtil::move(copy);
break;
}
case bmqt::PropertyType::e_UNDEFINED:
case bmqt::PropertyType::e_UNDEFINED: BSLA_FALLTHROUGH;
default:
BSLS_ASSERT_OPT(0 && "Invalid data type for property value.");
rc = -1;
break; // BREAK
return false;
}

return rc == 0;
return true;
}

// CREATORS
Expand Down
85 changes: 69 additions & 16 deletions src/groups/bmq/bmqu/bmqu_blob.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

// BDE
#include <bdlbb_blob.h>
#include <bsl_cstring.h> // for bsl::memcpy
#include <bsl_iostream.h>

namespace BloombergLP {
Expand Down Expand Up @@ -141,6 +142,14 @@
/// Return the end position of the section.
const BlobPosition& end() const;

/// @brief Check if the data segment pointed at by this object
/// is continous (placed in the same blob buffer).
/// @return true if the segment is continuous, false otherwise.
/// NOTE: this function doesn't check if blob positions are valid.
bool isDataContinuous() const;

void readTo(char* buf, const bdlbb::Blob& blob, size_t numBytes) const;

/// Write the string representation of this object to the specified
/// output `stream`, and return a reference to `stream`. Optionally
/// specify an initial indentation `level`, whose absolute value is
Expand Down Expand Up @@ -208,22 +217,19 @@
const BlobPosition& start,
int offset);

static int findBlobSectionSafe(BlobSection* section,
const bdlbb::Blob& blob,
const BlobPosition& start,
int offset,
int length);

/// Return `true` if the specified `section` is a valid section of the
/// specified `blob`, and `false` otherwise. A section is valid if
/// `section.start() < section.end()` and both the start and the end
/// are valid positions in the blob.
static bool isValidSection(const bdlbb::Blob& blob,
const BlobSection& section);

/// @brief Check if the data segment defined by `start` and `end`
/// positions is continous (placed in the same blob buffer).
/// @param start the start position in a blob
/// @param end the end position in a blob
/// @return true if the segment is continuous, false otherwise.
/// NOTE: this function doesn't check if blob positions are valid.
static bool isDataContinuous(const bmqu::BlobPosition& start,
const bmqu::BlobPosition& end);

/// Find the distance from the specified `section`s `start()` to the
/// `section`s `end()` in the specified `blob` and return it in the
/// specified `size`. Return `0` on success or a negative value if the
Expand Down Expand Up @@ -553,6 +559,29 @@
return d_end;
}

inline bool BlobSection::isDataContinuous() const
{
return (d_start.buffer() == d_end.buffer() ||
(d_start.buffer() + 1 == d_end.buffer() && d_end.byte() == 0));
}

inline void
BlobSection::readTo(char* buf, const bdlbb::Blob& blob, size_t numBytes) const
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(buf);

if (isDataContinuous()) {
bsl::memcpy(buf,
blob.buffer(d_start.buffer()).data() + d_start.byte(),
numBytes);
}
else {
// Rare path
bmqu::BlobUtil::readNBytes(buf, blob, d_start, numBytes);

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build Prometheus plugin [ubuntu]

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / UT [c++] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 all.t

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]

Check warning on line 581 in src/groups/bmq/bmqu/bmqu_blob.h

View workflow job for this annotation

GitHub Actions / Build [ubuntu] / Build [ubuntu] e2b5a704775cbcbb8421626414d886726d283f66 bmqbrkr bmqtool bmqstoragetool all.it

conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘int’ may change value [-Wconversion]
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int BlobUtil::readUpToNBytes(char*               buf,
                             const bdlbb::Blob&  blob,
                             const BlobPosition& start,
                             int                 length)
{
    if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValidPos(blob, start))) {
        BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
        return -1;  // RETURN
    }

    if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(length == 0)) {
        BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
        return 0;  // RETURN
    }

    char*              outPosition = buf;
    const int          numBuffers  = blob.numDataBuffers();
    bmqu::BlobPosition cursor(start);

    while (length != 0 && (cursor.buffer() != numBuffers)) {
        const bdlbb::BlobBuffer& buffer   = blob.buffer(cursor.buffer());
        const int                buffSize = bufferSize(blob, cursor.buffer());

        const int toCopy = bsl::min(buffSize - cursor.byte(), length);
        bsl::memcpy(outPosition, buffer.data() + cursor.byte(), toCopy);

        outPosition += toCopy;
        length -= toCopy;

        cursor.setBuffer(cursor.buffer() + 1);
        cursor.setByte(0);
    }

    return static_cast<int>(outPosition - buf);
}

Short memcpy path should skip all these other operations


// ---------------
// struct BlobUtil
// ---------------
Expand Down Expand Up @@ -593,6 +622,37 @@
return findOffset(pos, blob, BlobPosition(), offset);
}

inline int BlobUtil::findBlobSectionSafe(BlobSection* section,
const bdlbb::Blob& blob,
const BlobPosition& start,
int offset,
int length)
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(section);

// Check if 'start' is a valid position in the blob.
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!isValidPos(blob, start))) {
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
return -1; // RETURN
}

if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(
0 != findOffset(&section->start(), blob, start, offset))) {
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
return -2; // RETURN
}

if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(
0 !=
findOffset(&section->end(), blob, section->start(), length))) {
BSLS_PERFORMANCEHINT_UNLIKELY_HINT;
return -2; // RETURN
}

return 0;
}

inline int BlobUtil::positionToOffsetSafe(int* offset,
const bdlbb::Blob& blob,
const BlobPosition& position)
Expand Down Expand Up @@ -640,13 +700,6 @@
copyFromBlob));
}

inline bool BlobUtil::isDataContinuous(const bmqu::BlobPosition& start,
const bmqu::BlobPosition& end)
{
return (start.buffer() == end.buffer() ||
(start.buffer() + 1 == end.buffer() && end.byte() == 0));
}

} // close package namespace

// FREE OPERATORS
Expand Down
Loading