]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/MacOSX/DarwinLog/LogFilterRegex.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / MacOSX / DarwinLog / LogFilterRegex.cpp
1 //===-- LogFilterRegex.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "LogFilterRegex.h"
11
12 #include "DNBLog.h"
13 #include "LogMessage.h"
14
15 //----------------------------------------------------------------------
16 // Enable enhanced mode if it is available. This allows for things like
17 // \d for digit, \s for space, and many more, but it isn't available
18 // everywhere.
19 //----------------------------------------------------------------------
20 #if defined(REG_ENHANCED)
21 #define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED)
22 #else
23 #define DEFAULT_COMPILE_FLAGS (REG_EXTENDED)
24 #endif
25
26 LogFilterRegex::LogFilterRegex(bool match_accepts, FilterTarget filter_target,
27                                const std::string &regex)
28     : LogFilter(match_accepts), m_filter_target(filter_target),
29       m_regex_text(regex), m_regex(), m_is_valid(false), m_error_text() {
30   // Clear it.
31   memset(&m_regex, 0, sizeof(m_regex));
32
33   // Compile it.
34   if (!regex.empty()) {
35     auto comp_err = ::regcomp(&m_regex, regex.c_str(), DEFAULT_COMPILE_FLAGS);
36     m_is_valid = (comp_err == 0);
37     if (!m_is_valid) {
38       char buffer[256];
39       buffer[0] = '\0';
40       ::regerror(comp_err, &m_regex, buffer, sizeof(buffer));
41       m_error_text = buffer;
42     }
43   }
44 }
45
46 LogFilterRegex::~LogFilterRegex() {
47   if (m_is_valid) {
48     // Free the regex internals.
49     regfree(&m_regex);
50   }
51 }
52
53 bool LogFilterRegex::DoesMatch(const LogMessage &message) const {
54   switch (m_filter_target) {
55   case eFilterTargetActivity:
56     // Empty fields never match a condition.
57     if (!message.HasActivity())
58       return false;
59     return ::regexec(&m_regex, message.GetActivity(), 0, nullptr, 0) == 0;
60   case eFilterTargetActivityChain:
61     // Empty fields never match a condition.
62     if (!message.HasActivity())
63       return false;
64     return ::regexec(&m_regex, message.GetActivityChain().c_str(), 0, nullptr,
65                      0) == 0;
66   case eFilterTargetCategory:
67     // Empty fields never match a condition.
68     if (!message.HasCategory())
69       return false;
70     return ::regexec(&m_regex, message.GetCategory(), 0, nullptr, 0) == 0;
71   case eFilterTargetMessage: {
72     const char *message_text = message.GetMessage();
73     if (!message_text) {
74       DNBLogThreadedIf(LOG_DARWIN_LOG,
75                        "LogFilterRegex: regex "
76                        "\"%s\" no match due to nullptr message.",
77                        m_regex_text.c_str());
78       return false;
79     }
80
81     bool match = ::regexec(&m_regex, message_text, 0, nullptr, 0) == 0;
82     DNBLogThreadedIf(LOG_DARWIN_LOG, "LogFilterRegex: regex "
83                                      "\"%s\" %s message \"%s\".",
84                      m_regex_text.c_str(), match ? "matches" : "does not match",
85                      message_text);
86     return match;
87   }
88   case eFilterTargetSubsystem:
89     // Empty fields never match a condition.
90     if (!message.HasSubsystem())
91       return false;
92     return ::regexec(&m_regex, message.GetSubsystem(), 0, nullptr, 0) == 0;
93   default:
94     // We don't know this type.
95     return false;
96   }
97 }