Skip to content

Commit

Permalink
'bdldd::BlobUtilHexDumper' API improvements. DRQS 175544483 (#4787)
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Sokolov authored and GitHub Enterprise committed Jul 31, 2024
1 parent a316c26 commit ef3e9ab
Show file tree
Hide file tree
Showing 3 changed files with 778 additions and 28 deletions.
77 changes: 66 additions & 11 deletions groups/bdl/bdlbb/bdlbb_blobutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
BSLS_IDENT_RCSID(bdlbb_blobutil_cpp, "$Id$ $CSID$")

#include <bdlb_print.h>

#include <bslma_allocator.h>
#include <bslma_deallocatorproctor.h>
#include <bslma_default.h>

#include <bsls_assert.h>
#include <bsls_platform.h>
#include <bsls_types.h>

#include <bsl_algorithm.h>
Expand Down Expand Up @@ -50,6 +53,36 @@ void copyFromPlace(char *dstBuffer,
} while (copied < length);
}

bsl::ostream& asciiDumpFromBufferStart(bsl::ostream& stream,
const bdlbb::Blob& source,
int bufferIndex,
int numBytes)
// Output to the specified 'stream' the specified 'numBytes' of data from
// the specified 'source' starting from the blob buffer having the
// specified 'bufferIndex' and return a reference to the modifiable
// 'stream'. The behavior is undefined unless '0 <= bufferIndex',
// '0 <= numBytes', and the incrementing 'bufferIndex' does not reach the
// number of data buffers.
{
BSLS_ASSERT(0 <= bufferIndex);
BSLS_ASSERT(0 <= numBytes);
while (0 < numBytes) {
BSLS_ASSERT(source.numDataBuffers() > bufferIndex);
const bdlbb::BlobBuffer& buffer = source.buffer(bufferIndex);

if (0 != buffer.size()) {
int bytesToWrite = numBytes < buffer.size() ? numBytes
: buffer.size();

stream.write(buffer.data(), bytesToWrite);
numBytes -= bytesToWrite;
}
++bufferIndex;
}

return stream;
}

} // close unnamed namespace

namespace bdlbb {
Expand Down Expand Up @@ -549,22 +582,44 @@ char *BlobUtil::getContiguousDataBuffer(Blob *blob,

bsl::ostream& BlobUtil::asciiDump(bsl::ostream& stream, const Blob& source)
{
int numBytes = source.length();
return asciiDumpFromBufferStart(stream, source, 0, source.length());
}

for (int numBytesRemaining = numBytes, i = 0; 0 < numBytesRemaining; ++i) {
BSLS_ASSERT(i < source.numBuffers());
bsl::ostream& BlobUtil::asciiDump(bsl::ostream& stream,
const Blob& source,
int offset,
int length)
{
BSLS_ASSERT(0 <= offset);
BSLS_ASSERT(0 <= length);
BSLS_ASSERT(length <= source.length());
BSLS_ASSERT(offset <= source.length() - length);

if (0 == source.length() || 0 == length) {
return stream; // RETURN
}

const BlobBuffer& buffer = source.buffer(i);
bsl::pair<int, int> place = findBufferIndexAndOffset(source, offset);
int bufferIndex = place.first;
int offsetInThisBuffer = place.second;

int bytesToWrite = numBytesRemaining < buffer.size()
? numBytesRemaining
: buffer.size();
// Stream data from the buffer pointed by the offset.

stream.write(buffer.data(), bytesToWrite);
numBytesRemaining -= bytesToWrite;
}
int numBytesLeft = length;
const BlobBuffer& offsetBuffer = source.buffer(bufferIndex);
int bytesToWrite = bsl::min(
numBytesLeft,
offsetBuffer.size() - offsetInThisBuffer);

return stream;
stream.write(offsetBuffer.data() + offsetInThisBuffer, bytesToWrite);
numBytesLeft -= bytesToWrite;

// Stream remaining data.

return asciiDumpFromBufferStart(stream,
source,
bufferIndex + 1,
numBytesLeft);
}

bsl::ostream& BlobUtil::hexDump(bsl::ostream& stream,
Expand Down
123 changes: 106 additions & 17 deletions groups/bdl/bdlbb/bdlbb_blobutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,17 @@ struct BlobUtil {
// Write to the specified 'stream' an ascii dump of the specified
// 'source', and return a reference to the modifiable 'stream'.

static bsl::ostream& asciiDump(bsl::ostream& stream,
const Blob& source,
int offset,
int length);
// Write to the specified 'stream' an ascii dump of the specified
// 'length' bytes of the specified 'source' starting at the specified
// 'offset', and return a reference to the modifiable 'stream'. The
// behavior is undefined unless '0 <= offset', '0 <= length',
// 'length <= source.length()' and
// 'offset <= source.length() - length'.

static bsl::ostream& hexDump(bsl::ostream& stream, const Blob& source);
// Write to the specified 'stream' a hexdump of the specified 'source',
// and return a reference to the modifiable 'stream'.
Expand All @@ -223,7 +234,10 @@ struct BlobUtil {
int length);
// Write to the specified 'stream' a hexdump of the specified 'length'
// bytes of the specified 'source' starting at the specified 'offset',
// and return a reference to the modifiable 'stream'.
// and return a reference to the modifiable 'stream'. The behavior is
// undefined unless '0 <= offset', '0 <= length',
// 'length <= source.length()' and
// 'offset <= source.length() - length'.

static void padToAlignment(Blob *dest,
int alignment,
Expand Down Expand Up @@ -392,17 +406,39 @@ struct BlobUtilAsciiDumper {
// 'ball' logs.

// DATA
const Blob *d_blob_p;
const Blob *d_blob_p; // data to be dumped (held, not owned)
int d_offset; // desired offset
int d_length; // desired number of bytes to be dumped

// CREATORS
explicit BlobUtilAsciiDumper(const Blob *blob);
// Create an ascii dumper for the specified 'blob'.
// Create an ascii dumper for the specified 'blob' that dumps the
// entire 'blob' to the output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilAsciiDumper&)' for details.

BlobUtilAsciiDumper(const Blob *blob, int length);
// Create an ascii dumper for the specified 'blob' that ascii dumps the
// first 'min(length, blob->length())' bytes of the 'blob' to the
// output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilAsciiDumper&)' for details.
// The behavior is undefined unless '0 <= length'.

BlobUtilAsciiDumper(const Blob *blob, int offset, int length);
// Create a hex dumper for the specified 'blob' that ascii dumps the
// bytes of the 'blob' starting with the 'min(offset, blob->length())'
// byte and until 'min(offset + length, blob->length())' byte to the
// output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilAsciiDumper&)' for details.
// The behavior is undefined unless '0 <= offset && 0 <= length'.
};

// FREE OPERATORS
bsl::ostream& operator<<(bsl::ostream& stream, const BlobUtilAsciiDumper& rhs);
// Ascii-dump the blob referenced by the specified 'rhs' to the specified
// 'stream', and return a reference to the modifiable 'stream'.
// Ascii-dump to the specified 'stream' the bytes of the blob referenced
// by the specified 'rhs' starting with the
// 'min(rhs.d_offset, rhs.d_blob_p->length())' byte and until
// 'min(rhs.d_offset + rhs.d_length, rhs.d_blob_p->length())' byte, and
// return a reference to the modifiable 'stream'.

// ========================
// struct BlobUtilHexDumper
Expand All @@ -414,23 +450,39 @@ struct BlobUtilHexDumper {
// 'ball' logs.

// DATA
const Blob *d_blob_p;
int d_offset;
int d_length;
const Blob *d_blob_p; // data to be dumped (held, not owned)
int d_offset; // desired offset
int d_length; // desired number of bytes to be dumped

// CREATORS
explicit BlobUtilHexDumper(const Blob *blob);
// Create a hex dumper for the specified 'blob'.
// Create a hex dumper for the specified 'blob' that hex dumps the
// entire 'blob' to the output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilHexDumper&)' for details.

BlobUtilHexDumper(const Blob *blob, int length);
// Create a hex dumper for the specified 'blob' that hex dumps the
// first 'min(length, blob->length())' bytes of the 'blob' to the
// output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilHexDumper&)' for details.
// The behavior is undefined unless '0 <= length'.

BlobUtilHexDumper(const Blob *blob, int offset, int length);
// Create a hex dumper for the specified 'blob' that dumps the
// specified 'length' bytes starting at the specified 'offset'.
// Create a hex dumper for the specified 'blob' that hex dumps the
// bytes of the 'blob' starting with the 'min(offset, blob->length())'
// byte and until 'min(offset + length, blob->length())' byte to the
// output stream when passed to 'operator<<'. See
// 'operator<<(bsl::ostream&, const BlobUtilHexDumper&)' for details.
// The behavior is undefined unless '0 <= offset && 0 <= length'.
};

// FREE OPERATORS
bsl::ostream& operator<<(bsl::ostream& stream, const BlobUtilHexDumper& rhs);
// Hex-dump the blob referenced by the specified 'rhs' to the specified
// 'stream', and return a reference to the modifiable 'stream'.
// Hex-dump to the specified 'stream' the bytes of the blob referenced by
// the specified 'rhs' starting with the
// 'min(rhs.d_offset, rhs.d_blob_p->length())' byte and until
// 'min(rhs.d_offset + rhs.d_length, rhs.d_blob_p->length())' byte, and
// return a reference to the modifiable 'stream'.

// ============================================================================
// INLINE DEFINITIONS
Expand Down Expand Up @@ -758,7 +810,30 @@ int BlobUtil::prependDataBufferIfValid(Blob *dest,
inline
BlobUtilAsciiDumper::BlobUtilAsciiDumper(const Blob *blob)
: d_blob_p(blob)
, d_offset(0)
, d_length(blob->length())
{
}

inline
BlobUtilAsciiDumper::BlobUtilAsciiDumper(const Blob *blob, int length)
: d_blob_p(blob)
, d_offset(0)
, d_length(length)
{
BSLS_ASSERT(0 <= length);
}

inline
BlobUtilAsciiDumper::BlobUtilAsciiDumper(const Blob *blob,
int offset,
int length)
: d_blob_p(blob)
, d_offset(offset)
, d_length(length)
{
BSLS_ASSERT(0 <= offset);
BSLS_ASSERT(0 <= length);
}
} // close package namespace

Expand All @@ -767,7 +842,9 @@ inline
bsl::ostream& bdlbb::operator<<(bsl::ostream& stream,
const BlobUtilAsciiDumper& rhs)
{
return BlobUtil::asciiDump(stream, *rhs.d_blob_p);
int offset = bsl::min(rhs.d_offset, rhs.d_blob_p->length());
int length = bsl::min(rhs.d_length, rhs.d_blob_p->length() - offset);
return BlobUtil::asciiDump(stream, *rhs.d_blob_p, offset, length);
}

namespace bdlbb {
Expand All @@ -785,12 +862,23 @@ BlobUtilHexDumper::BlobUtilHexDumper(const Blob *blob)
{
}

inline
BlobUtilHexDumper::BlobUtilHexDumper(const Blob *blob, int length)
: d_blob_p(blob)
, d_offset(0)
, d_length(length)
{
BSLS_ASSERT(0 <= length);
}

inline
BlobUtilHexDumper::BlobUtilHexDumper(const Blob *blob, int offset, int length)
: d_blob_p(blob)
, d_offset(offset)
, d_length((bsl::min)(length, blob->length() - offset))
, d_length(length)
{
BSLS_ASSERT(0 <= offset);
BSLS_ASSERT(0 <= length);
}
} // close package namespace

Expand All @@ -799,8 +887,9 @@ inline
bsl::ostream& bdlbb::operator<<(bsl::ostream& stream,
const BlobUtilHexDumper& rhs)
{
return BlobUtil::hexDump(
stream, *rhs.d_blob_p, rhs.d_offset, rhs.d_length);
int offset = bsl::min(rhs.d_offset, rhs.d_blob_p->length());
int length = bsl::min(rhs.d_length, rhs.d_blob_p->length() - offset);
return BlobUtil::hexDump(stream, *rhs.d_blob_p, offset, length);
}

} // close enterprise namespace
Expand Down
Loading

0 comments on commit ef3e9ab

Please sign in to comment.