blob: e038c61a83e7a424f2af1a6045989a2ba20b8700 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include "log_level.h"
#include "macros.h"
// This file contains shared implementations for writing string logs between the legacy backend and
// the host backend
namespace syslog_backend {
struct MsgHeader {
syslog::LogSeverity severity;
char* offset;
LogBuffer* buffer;
bool first_tag;
char* user_tag;
bool has_msg;
size_t RemainingSpace() {
auto end = (reinterpret_cast<const char*>(this) + sizeof(LogBuffer));
auto avail = static_cast<size_t>(end - offset - 1);
return avail;
}
void WriteChar(const char value) {
if (!RemainingSpace()) {
FlushRecord(buffer);
offset = reinterpret_cast<char*>(buffer->data);
WriteString("CONTINUATION: ");
}
assert((offset + 1) < (reinterpret_cast<const char*>(this) + sizeof(LogBuffer)));
*offset = value;
offset++;
}
void WriteString(const char* c_str) {
size_t total_chars = strlen(c_str);
size_t written_chars = 0;
while (written_chars < total_chars) {
size_t written = WriteStringInternal(c_str + written_chars);
written_chars += written;
if (written_chars < total_chars) {
FlushAndReset();
WriteStringInternal("CONTINUATION: ");
}
}
}
void FlushAndReset() {
FlushRecord(buffer);
offset = reinterpret_cast<char*>(buffer->data);
}
// Writes a string to the buffer and returns the
// number of bytes written. Returns 0 only if
// the length of the string is 0, or if we're
// exactly at the end of the buffer and need a reset.
size_t WriteStringInternal(const char* c_str) {
size_t len = strlen(c_str);
auto remaining = RemainingSpace();
if (len > remaining) {
len = remaining;
}
assert((offset + len) < (reinterpret_cast<const char*>(this) + sizeof(LogBuffer)));
memcpy(offset, c_str, len);
offset += len;
return len;
}
void Init(LogBuffer* buffer, syslog::LogSeverity severity) {
this->severity = severity;
user_tag = nullptr;
offset = reinterpret_cast<char*>(buffer->data);
first_tag = true;
has_msg = false;
}
static MsgHeader* CreatePtr(LogBuffer* buffer) {
return reinterpret_cast<MsgHeader*>(&buffer->record_state);
}
};
#ifndef __Fuchsia__
const std::string GetNameForLogSeverity(syslog::LogSeverity severity);
#endif
static_assert(sizeof(MsgHeader) <= sizeof(LogBuffer::record_state));
void WritePreamble(LogBuffer* buffer);
} // namespace syslog_backend