| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include "log_defines.h" |
| #include <string> |
| #include <array> |
| |
| #ifdef __ANDROID__ |
| #include <android/log.h> |
| #include "base/log_defines.h" |
| #endif |
| |
| #include "core/manager/weex_core_manager.h" |
| |
| weex::base::LogImplement* weex::base::LogImplement::g_instance = nullptr; |
| |
| namespace WeexCore { |
| struct LogFlattenHelper { |
| LogFlattenHelper() : mLargeBuf() {} |
| LogFlattenHelper(const char *fmt, va_list args) : LogFlattenHelper() { |
| set(fmt, args); |
| } |
| ~LogFlattenHelper() { |
| if (mLargeBuf) |
| free(mLargeBuf); |
| } |
| |
| const char *str() const { return mLargeBuf ? mLargeBuf : mSmallBuf.data(); } |
| LogFlattenHelper &set(const char *fmt, va_list args); |
| |
| private: |
| LogFlattenHelper(const LogFlattenHelper &) = delete; |
| void operator=(const LogFlattenHelper &) = delete; |
| |
| std::array<char, 4096> mSmallBuf; |
| char *mLargeBuf; |
| }; |
| |
| LogFlattenHelper &LogFlattenHelper::set(const char *fmt, va_list args) { |
| va_list argsCopy; |
| va_copy(argsCopy, args); |
| int len = 1 + vsnprintf(nullptr, 0, fmt, argsCopy); |
| va_end(argsCopy); |
| if (len <= 1) { |
| mSmallBuf[0] = 0; |
| return *this; |
| } |
| if (len > (int) mSmallBuf.size()) |
| mLargeBuf = static_cast<char *>(malloc(len)); |
| int rv; |
| if (mLargeBuf) { |
| rv = vsnprintf(mLargeBuf, len, fmt, args); |
| } else { |
| rv = vsnprintf(mSmallBuf.data(), mSmallBuf.size(), fmt, args); |
| } |
| (void) rv; |
| return *this; |
| } |
| |
| void PrintLog(LogLevel level, |
| const char *tag, |
| const char *file, |
| unsigned long line, |
| const char *fmt, |
| ...) { |
| va_list args; |
| va_start(args, fmt); |
| LogFlattenHelper log(fmt, args); |
| va_end(args); |
| |
| bool succeed = weex::base::LogImplement::getLog()->log(level, tag, file, line, log.str()); |
| if (!succeed) { |
| // Log to console by default |
| #ifdef __ANDROID__ |
| bool debugMode = weex::base::LogImplement::getLog()->debugMode(); |
| switch (level) { |
| case LogLevel::Error: |
| __android_log_print(ANDROID_LOG_ERROR, |
| tag, |
| "%s:%lu, %s", |
| file, |
| line, |
| log.str()); |
| break; |
| case LogLevel::Warn: |
| if (debugMode) { |
| __android_log_print(ANDROID_LOG_WARN, |
| tag, |
| "%s:%lu, %s", |
| file, |
| line, |
| log.str()); |
| } |
| break; |
| case LogLevel::Info: |
| if (debugMode) { |
| __android_log_print(ANDROID_LOG_INFO, |
| tag, |
| "%s:%lu, %s", |
| file, |
| line, |
| log.str()); |
| } |
| break; |
| case LogLevel::Debug: |
| if (debugMode) { |
| __android_log_print(ANDROID_LOG_DEBUG, |
| tag, |
| "%s:%lu, %s", |
| file, |
| line, |
| log.str()); |
| } |
| break; |
| default:break; |
| } |
| #elif __APPLE__ |
| switch (level) { |
| case LogLevel::Error: |
| printf("<%s:Error|%s:%lu> %s\n", tag, file, line, log.str()); |
| break; |
| case LogLevel::Warn: |
| printf("<%s:Warn|%s:%lu> %s\n", tag, file, line, log.str()); |
| break; |
| case LogLevel::Info: |
| printf("<%s:Info|%s:%lu> %s\n", tag, file, line, log.str()); |
| break; |
| case LogLevel::Debug: |
| printf("<%s:Debug|%s:%lu> %s\n", tag, file, line, log.str()); |
| break; |
| default: |
| break; |
| } |
| #endif |
| } |
| } |
| |
| } |