1 // Copyright 2014 The Android Open Source Project 2 // 3 // This software is licensed under the terms of the GNU General Public 4 // License version 2, as published by the Free Software Foundation, and 5 // may be copied, distributed, and modified under those terms. 6 // 7 // This program is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 // GNU General Public License for more details. 11 12 #define __STDC_LIMIT_MACROS 13 #include "android/base/Log.h" 14 15 #include <limits.h> 16 #include <stdint.h> 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 21 namespace android { 22 namespace base { 23 24 namespace { 25 26 // The current log output. 27 testing::LogOutput* gLogOutput = NULL; 28 29 bool gDcheckLevel = false; 30 31 // Convert a severity level into a string. 32 const char* severityLevelToString(LogSeverity severity) { 33 const char* kSeverityStrings[] = { 34 "INFO", "WARNING", "ERROR", "FATAL", 35 }; 36 if (severity >= 0 && severity < LOG_NUM_SEVERITIES) 37 return kSeverityStrings[severity]; 38 return "UNKNOWN"; 39 } 40 41 // Default log output function 42 void defaultLogMessage(const LogParams& params, 43 const char* message, 44 size_t messageLen) { 45 fprintf(stderr, 46 "%s:%s:%d:%.*s\n", 47 severityLevelToString(params.severity), 48 params.file, 49 params.lineno, 50 int(messageLen), 51 message); 52 // Note: by default, stderr is non buffered, but the program might 53 // have altered this setting, so always flush explicitly to ensure 54 // that the log is displayed as soon as possible. This avoids log 55 // messages being lost when a crash happens, and makes debugging 56 // easier. On the other hand, it means lots of logging will impact 57 // performance. 58 fflush(stderr); 59 60 if (params.severity >= LOG_FATAL) 61 exit(1); 62 } 63 64 void logMessage(const LogParams& params, 65 const char* message, 66 size_t messageLen) { 67 if (gLogOutput) { 68 gLogOutput->logMessage(params, message, messageLen); 69 } else { 70 defaultLogMessage(params, message, messageLen); 71 } 72 } 73 74 } // namespace 75 76 // DCHECK level. 77 78 bool dcheckIsEnabled() { 79 return gDcheckLevel; 80 } 81 82 bool setDcheckLevel(bool enabled) { 83 bool ret = gDcheckLevel; 84 gDcheckLevel = enabled; 85 return ret; 86 } 87 88 // LogSeverity 89 90 LogSeverity getMinLogLevel() { 91 return 0; 92 } 93 94 // LogString 95 96 LogString::LogString(const char* fmt, ...) : mString(NULL) { 97 size_t capacity = 100; 98 char* message = reinterpret_cast<char*>(::malloc(capacity)); 99 for (;;) { 100 va_list args; 101 va_start(args, fmt); 102 int ret = vsnprintf(message, capacity, fmt, args); 103 va_end(args); 104 if (ret >= 0 && size_t(ret) < capacity) 105 break; 106 capacity *= 2; 107 } 108 mString = message; 109 } 110 111 LogString::~LogString() { 112 ::free(mString); 113 } 114 115 // LogStream 116 117 LogStream::LogStream(const char* file, int lineno, LogSeverity severity) : 118 mParams(file, lineno, severity), 119 mString(NULL), 120 mSize(0), 121 mCapacity(0) {} 122 123 LogStream::~LogStream() { 124 mSize = 0; 125 mCapacity = 0; 126 ::free(mString); 127 } 128 129 LogStream& LogStream::operator<<(char ch) { 130 if (ch >= 32 && ch < 127) { 131 append(&ch, 1U); 132 } else { 133 char temp[5]; 134 snprintf(temp, sizeof temp, "\\x%02x", ch); 135 append(temp, 4U); 136 } 137 return *this; 138 } 139 140 LogStream& LogStream::operator<<(const void* ptr) { 141 char temp[20]; 142 int ret = snprintf(temp, sizeof temp, "%p", ptr); 143 append(temp, static_cast<size_t>(ret)); 144 return *this; 145 } 146 147 LogStream& LogStream::operator<<(int v) { 148 char temp[20]; 149 int ret = snprintf(temp, sizeof temp, "%d", v); 150 append(temp, static_cast<size_t>(ret)); 151 return *this; 152 } 153 154 LogStream& LogStream::operator<<(unsigned v) { 155 char temp[20]; 156 int ret = snprintf(temp, sizeof temp, "%u", v); 157 append(temp, static_cast<size_t>(ret)); 158 return *this; 159 } 160 161 LogStream& LogStream::operator<<(long v) { 162 char temp[20]; 163 int ret = snprintf(temp, sizeof temp, "%ld", v); 164 append(temp, static_cast<size_t>(ret)); 165 return *this; 166 } 167 168 LogStream& LogStream::operator<<(unsigned long v) { 169 char temp[20]; 170 int ret = snprintf(temp, sizeof temp, "%lu", v); 171 append(temp, static_cast<size_t>(ret)); 172 return *this; 173 } 174 175 LogStream& LogStream::operator<<(long long v) { 176 char temp[20]; 177 int ret = snprintf(temp, sizeof temp, "%lld", v); 178 append(temp, static_cast<size_t>(ret)); 179 return *this; 180 } 181 182 LogStream& LogStream::operator<<(unsigned long long v) { 183 char temp[20]; 184 int ret = snprintf(temp, sizeof temp, "%llu", v); 185 append(temp, static_cast<size_t>(ret)); 186 return *this; 187 } 188 189 void LogStream::append(const char* str) { 190 if (str && str[0]) 191 append(str, strlen(str)); 192 } 193 194 void LogStream::append(const char* str, size_t len) { 195 if (!len || len > INT32_MAX) 196 return; 197 198 size_t newSize = mSize + len; 199 if (newSize > mCapacity) { 200 size_t newCapacity = mCapacity; 201 while (newCapacity < newSize) 202 newCapacity += (newCapacity >> 2) + 32; 203 mString = reinterpret_cast<char*>( 204 ::realloc(mString, newCapacity + 1)); 205 mCapacity = newCapacity; 206 } 207 ::memcpy(mString + mSize, str, len); 208 mSize += len; 209 mString[mSize] = '\0'; 210 } 211 212 // LogMessage 213 214 LogMessage::LogMessage(const char* file, int line, LogSeverity severity) : 215 mStream(new LogStream(file, line, severity)) {} 216 217 LogMessage::~LogMessage() { 218 logMessage(mStream->params(), 219 mStream->string(), 220 mStream->size()); 221 delete mStream; 222 } 223 224 // ErrnoLogMessage 225 226 ErrnoLogMessage::ErrnoLogMessage(const char* file, 227 int line, 228 LogSeverity severity, 229 int errnoCode) : 230 mStream(NULL), mErrno(errnoCode) { 231 mStream = new LogStream(file, line, severity); 232 } 233 234 ErrnoLogMessage::~ErrnoLogMessage() { 235 (*mStream) << "Error message: " << strerror(mErrno); 236 logMessage(mStream->params(), 237 mStream->string(), 238 mStream->size()); 239 delete mStream; 240 // Restore the errno. 241 errno = mErrno; 242 } 243 244 // LogOutput 245 246 namespace testing { 247 248 // static 249 LogOutput* LogOutput::setNewOutput(LogOutput* newOutput) { 250 LogOutput* ret = gLogOutput; 251 gLogOutput = newOutput; 252 return ret; 253 } 254 255 } // namespace testing 256 257 } // naemspace base 258 } // namespace android