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.
severityLevelToString(LogSeverity severity)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
defaultLogMessage(const LogParams & params,const char * message,size_t messageLen)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
logMessage(const LogParams & params,const char * message,size_t messageLen)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
dcheckIsEnabled()78 bool dcheckIsEnabled() {
79 return gDcheckLevel;
80 }
81
setDcheckLevel(bool enabled)82 bool setDcheckLevel(bool enabled) {
83 bool ret = gDcheckLevel;
84 gDcheckLevel = enabled;
85 return ret;
86 }
87
88 // LogSeverity
89
getMinLogLevel()90 LogSeverity getMinLogLevel() {
91 return 0;
92 }
93
94 // LogString
95
LogString(const char * fmt,...)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
~LogString()111 LogString::~LogString() {
112 ::free(mString);
113 }
114
115 // LogStream
116
LogStream(const char * file,int lineno,LogSeverity severity)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
~LogStream()123 LogStream::~LogStream() {
124 mSize = 0;
125 mCapacity = 0;
126 ::free(mString);
127 }
128
operator <<(char ch)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
operator <<(const void * ptr)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
operator <<(int v)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
operator <<(unsigned v)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
operator <<(long v)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
operator <<(unsigned long v)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
operator <<(long long v)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
operator <<(unsigned long long v)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
append(const char * str)189 void LogStream::append(const char* str) {
190 if (str && str[0])
191 append(str, strlen(str));
192 }
193
append(const char * str,size_t len)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
LogMessage(const char * file,int line,LogSeverity severity)214 LogMessage::LogMessage(const char* file, int line, LogSeverity severity) :
215 mStream(new LogStream(file, line, severity)) {}
216
~LogMessage()217 LogMessage::~LogMessage() {
218 logMessage(mStream->params(),
219 mStream->string(),
220 mStream->size());
221 delete mStream;
222 }
223
224 // ErrnoLogMessage
225
ErrnoLogMessage(const char * file,int line,LogSeverity severity,int errnoCode)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
~ErrnoLogMessage()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
setNewOutput(LogOutput * newOutput)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