• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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