|  | /* | 
|  | * Copyright 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed 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. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #pragma clang diagnostic push | 
|  | #pragma clang diagnostic ignored "-Weverything" | 
|  | #include <fmt/format.h> | 
|  | #include <log/log.h> | 
|  | #pragma clang diagnostic pop | 
|  |  | 
|  | #include <type_traits> | 
|  |  | 
|  | namespace android { | 
|  | namespace gfx { | 
|  |  | 
|  | /* SafeLog is a mix-in that can be used to easily add typesafe logging using fmtlib to any class. | 
|  | * To use it, inherit from it using CRTP and implement the getLogTag method. | 
|  | * | 
|  | * For example: | 
|  | * | 
|  | * class Frobnicator : private SafeLog<Frobnicator> { | 
|  | *     friend class SafeLog<Frobnicator>;  // Allows getLogTag to be private | 
|  | * | 
|  | *   public: | 
|  | *     void frobnicate(int32_t i); | 
|  | * | 
|  | *   private: | 
|  | *     // SafeLog does member access on the object calling alog*, so this tag can theoretically vary | 
|  | *     // by instance unless getLogTag is made static | 
|  | *     const char* getLogTag() { return "Frobnicator"; } | 
|  | * }; | 
|  | * | 
|  | * void Frobnicator::frobnicate(int32_t i) { | 
|  | *     // Logs something like "04-16 21:35:46.811  3513  3513 I Frobnicator: frobnicating 42" | 
|  | *     alogi("frobnicating {}", i); | 
|  | * } | 
|  | * | 
|  | * See http://fmtlib.net for more information on the formatting API. | 
|  | */ | 
|  |  | 
|  | template <typename T> | 
|  | class SafeLog { | 
|  | protected: | 
|  | template <typename... Args> | 
|  | #if LOG_NDEBUG | 
|  | void alogv(Args&&... /*unused*/) const { | 
|  | } | 
|  | #else | 
|  | void alogv(Args&&... args) const { | 
|  | alog<ANDROID_LOG_VERBOSE>(std::forward<Args>(args)...); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | template <typename... Args> | 
|  | void alogd(Args&&... args) const { | 
|  | alog<ANDROID_LOG_DEBUG>(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | template <typename... Args> | 
|  | void alogi(Args&&... args) const { | 
|  | alog<ANDROID_LOG_INFO>(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | template <typename... Args> | 
|  | void alogw(Args&&... args) const { | 
|  | alog<ANDROID_LOG_WARN>(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | template <typename... Args> | 
|  | void aloge(Args&&... args) const { | 
|  | alog<ANDROID_LOG_ERROR>(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | private: | 
|  | // Suppresses clang-tidy check cppcoreguidelines-pro-bounds-array-to-pointer-decay | 
|  | template <size_t strlen, typename... Args> | 
|  | void write(fmt::MemoryWriter* writer, const char (&str)[strlen], Args&&... args) const { | 
|  | writer->write(static_cast<const char*>(str), std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | template <int priority, typename... Args> | 
|  | void alog(Args&&... args) const { | 
|  | static_assert(std::is_base_of<SafeLog<T>, T>::value, "Can't convert to SafeLog pointer"); | 
|  | fmt::MemoryWriter writer; | 
|  | write(&writer, std::forward<Args>(args)...); | 
|  | auto derivedThis = static_cast<const T*>(this); | 
|  | android_writeLog(priority, derivedThis->getLogTag(), writer.c_str()); | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace gfx | 
|  | }  // namespace android |