1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _ANDROID_DIAGNOSTICS_H 18 #define _ANDROID_DIAGNOSTICS_H 19 20 // on some systems ERROR is defined as 0 so android::base::ERROR becomes android::base::0 21 // which doesn't compile. We undef it here to avoid that and because we don't ever need that def. 22 #undef ERROR 23 24 #include <sstream> 25 #include <string> 26 27 #include "Source.h" 28 #include "android-base/logging.h" 29 #include "android-base/macros.h" 30 #include "androidfw/StringPiece.h" 31 32 namespace android { 33 34 struct DiagMessageActual { 35 Source source; 36 std::string message; 37 }; 38 39 struct DiagMessage { 40 public: 41 DiagMessage() = default; 42 DiagMessageDiagMessage43 explicit DiagMessage(android::StringPiece src) : source_(src) { 44 } 45 DiagMessageDiagMessage46 explicit DiagMessage(const Source& src) : source_(src) { 47 } 48 DiagMessageDiagMessage49 explicit DiagMessage(size_t line) : source_(Source().WithLine(line)) { 50 } 51 52 template <typename T> 53 DiagMessage& operator<<(const T& value) { 54 message_ << value; 55 return *this; 56 } 57 BuildDiagMessage58 DiagMessageActual Build() const { 59 return DiagMessageActual{source_, message_.str()}; 60 } 61 62 private: 63 Source source_; 64 std::stringstream message_; 65 }; 66 67 template <> 68 inline DiagMessage& DiagMessage::operator<<(const ::std::u16string& value) { 69 message_ << value; 70 return *this; 71 } 72 73 struct IDiagnostics { 74 virtual ~IDiagnostics() = default; 75 76 enum class Level { Note, Warn, Error }; 77 78 virtual void Log(Level level, DiagMessageActual& actualMsg) = 0; 79 ErrorIDiagnostics80 virtual void Error(const DiagMessage& message) { 81 DiagMessageActual actual = message.Build(); 82 Log(Level::Error, actual); 83 } 84 WarnIDiagnostics85 virtual void Warn(const DiagMessage& message) { 86 DiagMessageActual actual = message.Build(); 87 Log(Level::Warn, actual); 88 } 89 NoteIDiagnostics90 virtual void Note(const DiagMessage& message) { 91 DiagMessageActual actual = message.Build(); 92 Log(Level::Note, actual); 93 } 94 SetVerboseIDiagnostics95 virtual void SetVerbose(bool val) { 96 verbose_ = val; 97 } 98 IsVerboseIDiagnostics99 virtual bool IsVerbose() { 100 return verbose_; 101 } 102 103 private: 104 bool verbose_ = false; 105 }; 106 107 class SourcePathDiagnostics : public IDiagnostics { 108 public: SourcePathDiagnostics(const Source & src,IDiagnostics * diag)109 SourcePathDiagnostics(const Source& src, IDiagnostics* diag) : source_(src), diag_(diag) { 110 } 111 Log(Level level,DiagMessageActual & actual_msg)112 void Log(Level level, DiagMessageActual& actual_msg) override { 113 actual_msg.source.path = source_.path; 114 diag_->Log(level, actual_msg); 115 if (level == Level::Error) { 116 error = true; 117 } 118 } 119 HadError()120 bool HadError() { 121 return error; 122 } 123 SetVerbose(bool val)124 void SetVerbose(bool val) override { 125 diag_->SetVerbose(val); 126 } 127 IsVerbose()128 bool IsVerbose() override { 129 return diag_->IsVerbose(); 130 } 131 132 private: 133 Source source_; 134 IDiagnostics* diag_; 135 bool error = false; 136 137 DISALLOW_COPY_AND_ASSIGN(SourcePathDiagnostics); 138 }; 139 140 class NoOpDiagnostics : public IDiagnostics { 141 public: 142 NoOpDiagnostics() = default; 143 Log(Level level,DiagMessageActual & actual_msg)144 void Log(Level level, DiagMessageActual& actual_msg) override { 145 (void)level; 146 (void)actual_msg; 147 } 148 149 DISALLOW_COPY_AND_ASSIGN(NoOpDiagnostics); 150 }; 151 152 class AndroidLogDiagnostics : public IDiagnostics { 153 public: 154 AndroidLogDiagnostics() = default; 155 Log(Level level,DiagMessageActual & actual_msg)156 void Log(Level level, DiagMessageActual& actual_msg) override { 157 android::base::LogSeverity severity; 158 switch (level) { 159 case Level::Error: 160 severity = android::base::ERROR; 161 break; 162 163 case Level::Warn: 164 severity = android::base::WARNING; 165 break; 166 167 case Level::Note: 168 severity = android::base::INFO; 169 break; 170 } 171 if (!actual_msg.source.path.empty()) { 172 LOG(severity) << actual_msg.source << ": " + actual_msg.message; 173 } else { 174 LOG(severity) << actual_msg.message; 175 } 176 } 177 178 DISALLOW_COPY_AND_ASSIGN(AndroidLogDiagnostics); 179 }; 180 181 182 } // namespace android 183 184 #endif /* _ANDROID_DIAGNOSTICS_H */ 185