SBuf&
SBuf::assign(const char *S, size_type n)
{
+ const Locker blobKeeper(this, S);
debugs(24, 6, id << " from c-string, n=" << n << ")");
clear();
return append(S, n); //bounds checked in append()
SBuf&
SBuf::append(const SBuf &S)
{
+ const Locker blobKeeper(this, S.buf());
return lowAppend(S.buf(), S.length());
}
SBuf &
SBuf::append(const char * S, size_type Ssize)
{
+ const Locker blobKeeper(this, S);
if (S == NULL)
return *this;
if (Ssize == SBuf::npos)
SBuf&
SBuf::Printf(const char *fmt, ...)
{
+ // with printf() the fmt or an arg might be a dangerous char*
+ // NP: cant rely on vappendf() Locker because of clear()
+ const Locker blobKeeper(this, buf());
+
va_list args;
va_start(args, fmt);
clear();
SBuf&
SBuf::vappendf(const char *fmt, va_list vargs)
{
+ // with (v)appendf() the fmt or an arg might be a dangerous char*
+ const Locker blobKeeper(this, buf());
+
Must(fmt != NULL);
int sz = 0;
//reserve twice the format-string size, it's a likely heuristic
int
SBuf::scanf(const char *format, ...)
{
+ // with the format or an arg might be a dangerous char*
+ // that gets invalidated by c_str()
+ const Locker blobKeeper(this, buf());
+
va_list arg;
int rv;
++stats.scanf;
// TODO: possibly implement a replace() call
private:
+ /**
+ * Keeps SBuf's MemBlob alive in a blob-destroying context where
+ * a seemingly unrelated memory pointer may belong to the same blob.
+ * For [an extreme] example, consider: a.append(a).
+ * Compared to an SBuf temporary, this class is optimized to
+ * preserve blobs only if needed and to reduce debugging noise.
+ */
+ class Locker
+ {
+ public:
+ Locker(SBuf *parent, const char *otherBuffer) {
+ // lock if otherBuffer intersects the parents buffer area
+ const MemBlob *blob = parent->store_.getRaw();
+ if (blob->mem <= otherBuffer && otherBuffer < (blob->mem + blob->capacity))
+ locket = blob;
+ }
+ private:
+ MemBlob::Pointer locket;
+ };
+ friend class Locker;
+
MemBlob::Pointer store_; ///< memory block, possibly shared with other SBufs
size_type off_; ///< our content start offset from the beginning of shared store_
size_type len_; ///< number of our content bytes in shared store_