1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef LOG_H
17 #define LOG_H
18 
19 #include <array>
20 #include <utility>
21 #include <string_view>
22 #include <cinttypes>
23 #include <cstdio>
24 #include <hilog/log_c.h>
25 
26 template<size_t N>
CountPercent(const char (& str)[N])27 constexpr auto CountPercent(const char(&str)[N])
28 {
29     uint32_t cntOfPercentSign = 0;
30     std::array<bool, N> isPercentSign{};
31     for (size_t i = 0; i < N; i++) {
32         if (str[i] == '%') {
33             cntOfPercentSign++;
34             isPercentSign[i] = true;
35         } else {
36             isPercentSign[i] = false;
37         }
38     }
39     for (size_t i = 1; i < N; i++) {
40         if (isPercentSign[i - 1] && isPercentSign[i]) {
41             cntOfPercentSign -= 2; // 2 is length of %%
42             isPercentSign[i - 1] = false;
43             isPercentSign[i] = false;
44         }
45     }
46     return std::make_pair(cntOfPercentSign, isPercentSign);
47 }
48 
49 template<uint32_t cntOfPercentSign, size_t N>
AddPublic(const char (& str)[N],const std::array<bool,N> & isPercentSign)50 constexpr auto AddPublic(const char(&str)[N], const std::array<bool, N> &isPercentSign)
51 {
52     constexpr std::string_view pub = "{public}";
53     std::array<char, N + cntOfPercentSign * pub.size()> newStr{};
54     for (size_t i = 0, j = 0; i < N; i++, j++) {
55         newStr[j] = str[i];
56         if (isPercentSign[i]) {
57             for (size_t k = 0; k < pub.size(); k++) {
58                 newStr[j + 1 + k] = pub[k];
59             }
60             j += pub.size();
61         }
62     }
63     return newStr;
64 }
65 
66 inline constexpr unsigned int HCODEC_DOMAIN = 0xD002B32;
67 inline constexpr const char* HCODEC_TAG = "HCODEC";
68 #ifdef HILOG_FMTID
69 #define RE_FORMAT(level, s, ...) do { \
70     constexpr auto pair = CountPercent(s); \
71     constexpr HILOG_FMT_IN_SECTION static auto newStr = AddPublic<pair.first>(s, pair.second); \
72     (void)HiLogPrintDictNew(LOG_CORE, level, HCODEC_DOMAIN, HCODEC_TAG, \
73           HILOG_UUID, HILOG_FMT_OFFSET(newStr.data()), newStr.data(), ##__VA_ARGS__); \
74 } while (0)
75 #else
76 #define RE_FORMAT(level, s, ...) do { \
77     constexpr auto pair = CountPercent(s); \
78     constexpr auto newStr = AddPublic<pair.first>(s, pair.second); \
79     (void)HiLogPrint(LOG_CORE, level, HCODEC_DOMAIN, HCODEC_TAG, newStr.data(), ##__VA_ARGS__); \
80 } while (0)
81 #endif
82 
StrLevel(LogLevel level)83 inline constexpr const char* StrLevel(LogLevel level)
84 {
85     switch (level) {
86         case LOG_ERROR:
87             return "E";
88         case LOG_WARN:
89             return "W";
90         case LOG_INFO:
91             return "I";
92         case LOG_DEBUG:
93             return "D";
94         default:
95             return "";
96     }
97 }
98 
99 #define PLOGI(...) RE_FORMAT(LOG_INFO, __VA_ARGS__)
100 
101 #define LOG(level, s, ...) RE_FORMAT(level, "[%s %d] " s, __FUNCTION__, __LINE__, ##__VA_ARGS__)
102 #define LOGE(...) LOG(LOG_ERROR, __VA_ARGS__)
103 #define LOGW(...) LOG(LOG_WARN, __VA_ARGS__)
104 #define LOGI(...) LOG(LOG_INFO, __VA_ARGS__)
105 #define LOGD(...) LOG(LOG_DEBUG, __VA_ARGS__)
106 
107 // for test
108 #define TLOG(level, s, ...) do { \
109     RE_FORMAT(level, "[%s %d] " s, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
110     printf("%s: [%s %d] " s "\n", StrLevel(level), __FUNCTION__, __LINE__, ##__VA_ARGS__); \
111 } while (0)
112 #define TLOGE(...) TLOG(LOG_ERROR, __VA_ARGS__)
113 #define TLOGW(...) TLOG(LOG_WARN, __VA_ARGS__)
114 #define TLOGI(...) TLOG(LOG_INFO, __VA_ARGS__)
115 #define TLOGD(...) TLOG(LOG_DEBUG, __VA_ARGS__)
116 
117 // for HCodec
118 #define HLOG(level, s, ...) RE_FORMAT(level, "%s[%s][%s %d] " s, \
119     compUniqueStr_.c_str(), currState_->GetName().c_str(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
120 #define HLOGE(...) HLOG(LOG_ERROR, __VA_ARGS__)
121 #define HLOGW(...) HLOG(LOG_WARN, __VA_ARGS__)
122 #define HLOGI(...) HLOG(LOG_INFO, __VA_ARGS__)
123 #define HLOGD(...) HLOG(LOG_DEBUG, __VA_ARGS__)
124 
125 // for HCodec inner state
126 #define SLOG(level, s, ...) RE_FORMAT(level, "%s[%s][%s %d] " s, \
127     codec_->compUniqueStr_.c_str(), stateName_.c_str(), __FUNCTION__, __LINE__, ##__VA_ARGS__)
128 #define SLOGE(...) SLOG(LOG_ERROR, __VA_ARGS__)
129 #define SLOGW(...) SLOG(LOG_WARN, __VA_ARGS__)
130 #define SLOGI(...) SLOG(LOG_INFO, __VA_ARGS__)
131 #define SLOGD(...) SLOG(LOG_DEBUG, __VA_ARGS__)
132 
133 #define IF_TRUE_RETURN_VAL(cond, val)  \
134     do {                               \
135         if (cond) {                    \
136             return val;                \
137         }                              \
138     } while (0)
139 #define IF_TRUE_RETURN_VAL_WITH_MSG(cond, val, msg, ...) \
140     do {                                        \
141         if (cond) {                             \
142             LOGE(msg, ##__VA_ARGS__);           \
143             return val;                         \
144         }                                       \
145     } while (0)
146 #define IF_TRUE_RETURN_VOID(cond)  \
147     do {                                \
148         if (cond) {                     \
149             return;                     \
150         }                               \
151     } while (0)
152 #define IF_TRUE_RETURN_VOID_WITH_MSG(cond, msg, ...)     \
153     do {                                        \
154         if (cond) {                             \
155             LOGE(msg, ##__VA_ARGS__);           \
156             return;                             \
157         }                                       \
158     } while (0)
159 
160 #endif