diff --git a/logcat_entry.cpp b/logcat_entry.cpp index 969f160..0d88c0d 100644 --- a/logcat_entry.cpp +++ b/logcat_entry.cpp @@ -1,11 +1,13 @@ #include +#include #include #include #include "logcat_entry.h" #include "pcre2_wrapper.h" -const Pcre2Regex LogcatEntryRegex("^\\s*(\\d+)(?:\\.\\d+)?(?:\\s+([\\w\\d._-]+))?\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+(.+?)\\s*:\\s(.*)$"); +static const Pcre2Regex LogcatEntryRegex("^\\s*(\\d+)(?:\\.\\d+)?(?:\\s+([\\w\\d._-]+))?\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s+(.+?)\\s*:\\s(.*)$"); +static const Pcre2Regex BufferRegex("^--------- (?:beginning of|switch to) (\\w+)$"); Priority priority_from(char c) { switch (c) { @@ -99,3 +101,29 @@ std::optional try_parse_logcat_entry(char* buf, size_t length, Buff }; return std::move(logcat_entry); } + +static bool substr_equal(const char* lhs_str, size_t lhs_length, const char* rhs_str) { + return lhs_length == strlen(rhs_str) && memcmp(lhs_str, rhs_str, lhs_length * sizeof(char)) == 0; +} + +std::optional try_parse_buffer(char* buf, size_t length) { + regmatch_t matches[2]; + matches[0].rm_so = 0; + matches[0].rm_eo = static_cast(length); + if (static_cast(matches[0].rm_eo) != length) { + throw std::range_error("Buffer line too long for int"); + } + + if (!BufferRegex.match(buf, sizeof(matches) / sizeof(regmatch_t), matches, REG_STARTEND)) { + return std::nullopt; + } + + const char* buffer_str = &buf[matches[1].rm_so]; + size_t buffer_length = static_cast(matches[1].rm_eo - matches[1].rm_so); + if (substr_equal(buffer_str, buffer_length, "main")) return Buffer::Main; + if (substr_equal(buffer_str, buffer_length, "system")) return Buffer::System; + if (substr_equal(buffer_str, buffer_length, "radio")) return Buffer::Radio; + if (substr_equal(buffer_str, buffer_length, "events")) return Buffer::Events; + if (substr_equal(buffer_str, buffer_length, "crash")) return Buffer::Crash; + return Buffer::Unknown; +} diff --git a/logcat_entry.h b/logcat_entry.h index 2ac9afb..f0ed008 100644 --- a/logcat_entry.h +++ b/logcat_entry.h @@ -37,3 +37,4 @@ Priority priority_from(char c); const char* priority_to(Priority priority); const char* buffer_to(Buffer buffer); std::optional try_parse_logcat_entry(char* buf, size_t length, Buffer buffer); +std::optional try_parse_buffer(char* buf, size_t length); diff --git a/logcat_thread.cpp b/logcat_thread.cpp index 6c21648..427fd96 100644 --- a/logcat_thread.cpp +++ b/logcat_thread.cpp @@ -162,7 +162,7 @@ void LogcatThread::_handle_line(char* buf, size_t length, bool is_stdout) { std::optional logcat_entry; try { - logcat_entry = try_parse_logcat_entry(buf, length, Buffer::Unknown); + logcat_entry = try_parse_logcat_entry(buf, length, this->_current_buffer); } catch (const std::exception& e) { std::string log_entry = format_log(std::string("Failed to parse logcat entry: ") + e.what()); printf("%s\n", log_entry.c_str()); @@ -172,7 +172,18 @@ void LogcatThread::_handle_line(char* buf, size_t length, bool is_stdout) { this->atomic_ring_buffer.put_and_increment_write(std::move(*logcat_entry)); return; } - // TODO handle buffers + std::optional new_buffer; + try { + new_buffer = try_parse_buffer(buf, length); + } catch (const std::exception& e) { + std::string log_entry = format_log(std::string("Failed to parse buffer line: ") + e.what()); + printf("%s\n", log_entry.c_str()); + this->atomic_ring_buffer.put_and_increment_write(std::move(log_entry)); + } + if (new_buffer) { + this->_current_buffer = *new_buffer; + return; + } std::string log_entry = format_log(std::string("Cannot parse logcat stdout: ") + std::string(buf, length)); printf("%s\n", log_entry.c_str()); diff --git a/logcat_thread.h b/logcat_thread.h index 69dcfbb..5411304 100644 --- a/logcat_thread.h +++ b/logcat_thread.h @@ -38,6 +38,7 @@ private: size_t _stdout_buf_used = 0; char _stderr_buf[NEWLINE_BUF_SIZE]; size_t _stderr_buf_used = 0; + Buffer _current_buffer = Buffer::Unknown; std::stop_source _stop_source; std::thread _thread; };