blob: 268b7211e8afef4eb9be8afe51d9dba07ce1ce1e [file] [log] [blame]
// Copyright 2022 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#pragma once
#include <cstring>
#include <streambuf>
#include "client/annotation.h"
namespace android {
namespace crashreport {
using crashpad::Annotation;
// A streambuffer that writes to an crashpad annotation, use your favorite
// std::stream that ends up in a minidump!
//
// AnnotationStreambuf should be declared with static storage duration!
//
// For example:
//
// AnnotationStreambuf<4096> mLogBuf{"my_label"};
// std::ostream log(&mLogBuf);
// log << "Some useful info when you crash later on.";
template <Annotation::ValueSizeType MaxSize>
class AnnotationStreambuf : public crashpad::Annotation, public std::streambuf {
public:
AnnotationStreambuf(const AnnotationStreambuf&) = delete;
AnnotationStreambuf& operator=(const AnnotationStreambuf&) = delete;
// Name of the annotation.. This is how it will show up in a minidump.
explicit AnnotationStreambuf(const char name[])
: Annotation(Type::kString, name, mBuffer), mBuffer() {
setp(mBuffer, mBuffer + MaxSize);
}
// Mainly for testing.
int sync() override {
setg(mBuffer, mBuffer, mBuffer + (pptr() - pbase()));
return 0;
}
protected:
std::streamsize xsputn(const char* s, std::streamsize n) override {
std::streamsize available = epptr() - pptr();
std::streamsize to_copy = std::min(n, available);
if (available <= 0) {
return traits_type::eof(); // No space left in the buffer
}
std::memcpy(pptr(), s, static_cast<std::size_t>(to_copy));
pbump(static_cast<int>(to_copy));
SetSize(pptr() - pbase());
return to_copy;
};
int_type overflow(int_type ch) override { return traits_type::eof(); }
int_type underflow() override {
return gptr() == egptr() ? traits_type::eof() : *gptr();
}
private:
char mBuffer[MaxSize];
};
// A stream buffer that can hold 8kb of annotation data.
using DefaultAnnotationStreambuf = AnnotationStreambuf<8192>;
} // namespace crashreport
} // namespace android