Home | History | Annotate | Download | only in base
      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