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#include "update_log.h"
17
18namespace OHOS {
19namespace UpdateEngine {
20UpdateLogLevel UpdateLog::level_ = UpdateLogLevel::UPDATE_INFO;
21constexpr int32_t COUNT_ONE = 1;
22constexpr int32_t LONG_LOG_LEN = 900;
23
24bool UpdateLog::JudgeLevel(const UpdateLogLevel &level)
25{
26    const UpdateLogLevel &curLevel = GetLogLevel();
27    if (level <= curLevel) {
28        return true;
29    }
30    return true;
31}
32
33void UpdateLog::SetLogLevel(const UpdateLogLevel &level)
34{
35    level_ = level;
36}
37
38const UpdateLogLevel &UpdateLog::GetLogLevel()
39{
40    return level_;
41}
42
43std::string UpdateLog::GetBriefFileName(const std::string &file)
44{
45    auto pos = file.find_last_of("/");
46    if (pos != std::string::npos) {
47        return file.substr(pos + 1);
48    }
49    pos = file.find_last_of("\\");
50    if (pos != std::string::npos) {
51        return file.substr(pos + 1);
52    }
53    return file;
54}
55
56void UpdateLog::PrintLongLog(const uint32_t subModuleTag, const UpdateLogContent &logContent)
57{
58    std::string fmtLabel = GetFmtLabel(logContent.log);
59    std::pair<std::string, std::string> splitLogPair = SplitLogByFmtLabel(logContent.log, fmtLabel);
60
61    PrintLog(subModuleTag, logContent.BuildWithFmtAndArgs(PUBLIC_FMT_LABEL, splitLogPair.first));     // log前缀不做打印控制
62    PrintLog(subModuleTag, logContent.BuildWithFmtAndArgs(fmtLabel, logContent.args));                // args采用fmt进行控制
63    PrintLog(subModuleTag, logContent.BuildWithFmtAndArgs(PUBLIC_FMT_LABEL, splitLogPair.second));    // log后缀不做打印控制
64}
65
66void UpdateLog::PrintLog(const uint32_t subModuleTag, const UpdateLogContent &logContent)
67{
68    int32_t printPos = 0;
69    int32_t len = static_cast<int32_t>(logContent.args.length());
70    while (printPos < len) {
71        int32_t printLen = std::min(len - printPos, LONG_LOG_LEN);
72        PrintSingleLine(subModuleTag, logContent.BuildWithArgs(logContent.args.substr(printPos, printLen)));
73        printPos += printLen;
74    }
75}
76
77void UpdateLog::PrintSingleLine(const uint32_t subModuleTag, const UpdateLogContent &logContent)
78{
79    // BASE_PRINT_LOG的第三个参数是hilog方法名,即hilogMethod
80    std::string fmtLabel = GetFmtLabel(logContent.log);
81    switch (logContent.level) {
82        case UpdateLogLevel::UPDATE_DEBUG:
83            LONG_PRINT_HILOG(LOG_DEBUG, subModuleTag, logContent.log,
84                UpdateLog::GetBriefFileName(logContent.fileName).c_str(), logContent.line, logContent.args.c_str());
85            break;
86        case UpdateLogLevel::UPDATE_INFO:
87            LONG_PRINT_HILOG(LOG_INFO, subModuleTag, logContent.log,
88                UpdateLog::GetBriefFileName(logContent.fileName).c_str(), logContent.line, logContent.args.c_str());
89            break;
90        case UpdateLogLevel::UPDATE_ERROR:
91            LONG_PRINT_HILOG(LOG_ERROR, subModuleTag, logContent.log,
92                UpdateLog::GetBriefFileName(logContent.fileName).c_str(), logContent.line, logContent.args.c_str());
93            break;
94        default:
95            break;
96    }
97}
98
99std::pair<std::string, std::string> UpdateLog::SplitLogByFmtLabel(const std::string &log, const std::string &fmtLabel)
100{
101    if (fmtLabel.empty()) {
102        // 如果log中没有%{public|private}s,则把log全部内容作为前缀字符串,后缀字符串为空
103        return std::make_pair(log, "");
104    }
105    return std::make_pair(log.substr(0, log.find(fmtLabel, 0)), log.substr(log.find(fmtLabel, 0) +
106        fmtLabel.length()));
107}
108
109std::string UpdateLog::GetFmtLabel(const std::string &log)
110{
111    if (FindSubStrCount(log, DEFAULT_LABEL) != COUNT_ONE) {
112        // 如果log中%字符出现次数不为一个,说明log格式有误,返回空的fmtLabel
113        return "";
114    }
115    if (FindSubStrCount(log, DEFAULT_FMT_LABEL) == COUNT_ONE) {
116        return DEFAULT_FMT_LABEL;
117    }
118    if (FindSubStrCount(log, PRIVATE_FMT_LABEL) == COUNT_ONE) {
119        return PRIVATE_FMT_LABEL;
120    }
121    if (FindSubStrCount(log, PUBLIC_FMT_LABEL) == COUNT_ONE) {
122        return PUBLIC_FMT_LABEL;
123    }
124    return "";
125}
126
127int32_t UpdateLog::FindSubStrCount(const std::string &str, const std::string &subStr)
128{
129    int32_t count = 0;
130    for (size_t pos = 0; (pos = str.find(subStr, pos)) != std::string::npos; pos++) {
131        count++;
132    }
133    return count;
134}
135} // namespace UpdateEngine
136} // namespace OHOS
137