1 /*
2 * Copyright (c) 2022 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 "hilog_module.h"
17 #include "hilog_wrapper.h"
18 #include "securec.h"
19
20 namespace OHOS {
21 namespace ACELite {
22 namespace {
23 #define DEFAULT_LOG_TYPE LOG_TYPE_MIN
24 // log content prefix:"%c %05X/%s: " %05X->domain %s->tag
25 static const int32_t DOMAIN_LEN = 5;
26 static const int32_t FIX_LEN = 5;
27 static const int32_t MIN_DOMAIN = 0x0;
28 static const int32_t MAX_DOMAIN = 0xFFFF;
29 static const int32_t MAX_TAG = 32;
30 static const int32_t MAX_FORMAT = 1024;
31 static const int32_t MIN_NUMBER = 3;
32 static const int32_t MAX_NUMBER = 16;
33 static const int32_t PUBLIC_LEN = 6;
34 static const int32_t PRIVATE_LEN = 7;
35 static const int32_t PROPERTY_POS = 2;
36 static const char PRIV_STR[10] = "<private>";
37 static const int32_t FIRST = 0;
38 static const int32_t SECOND = 1;
39 static const int32_t THIRD = 2;
40 static const int32_t FOURTH = 3;
41 static const int32_t FIFTH = 4;
42 }
43
ParseLogContent(const HilogString * formatStr,const HilogVector * params,HilogString * logContent)44 void HilogModule::ParseLogContent(const HilogString *formatStr, const HilogVector *params, HilogString *logContent)
45 {
46 if (formatStr == nullptr || params == nullptr || logContent == nullptr) {
47 return;
48 }
49 size_t size = HilogVector::Size(params);
50 if (size == 0) {
51 HilogString::Puts(HilogString::Get(formatStr), logContent);
52 return;
53 }
54 char *format = HilogString::Get(formatStr);
55 if (format == nullptr) {
56 return;
57 }
58 size_t len = HilogString::Length(formatStr);
59 size_t pos = 0;
60 size_t count = 0;
61
62 for (; pos < len; ++pos) {
63 bool showPriv = true;
64 if (count > size) {
65 break;
66 }
67 if (format[pos] != '%') {
68 HilogString::Putc(format[pos], logContent);
69 continue;
70 }
71
72 if (((pos + PUBLIC_LEN + PROPERTY_POS) < len) &&
73 (strncmp(format + pos + PROPERTY_POS, "public", PUBLIC_LEN) == 0)) {
74 pos += (PUBLIC_LEN + PROPERTY_POS);
75 showPriv = false;
76 } else if (((pos + PRIVATE_LEN + PROPERTY_POS) < len) &&
77 (strncmp(format + pos + PROPERTY_POS, "private", PRIVATE_LEN) == 0)) {
78 pos += (PRIVATE_LEN + PROPERTY_POS);
79 }
80
81 if (pos + 1 >= len) {
82 break;
83 }
84 AddLogContentOutParams outParams = {
85 .pos = &pos,
86 .count = &count,
87 .logContent = logContent,
88 };
89 AddLogContent(format, params, showPriv, &outParams);
90 }
91 if (pos < len) {
92 HilogString::Puts(format + pos, logContent, len - pos);
93 }
94 return;
95 }
96
AddLogContent(const char * format,const HilogVector * params,bool showPriv,const AddLogContentOutParams * outParams)97 void HilogModule::AddLogContent(const char *format, const HilogVector *params, bool showPriv,
98 const AddLogContentOutParams *outParams)
99 {
100 if (format == nullptr || outParams == nullptr || params == nullptr || outParams->pos == nullptr ||
101 outParams->count == nullptr || outParams->logContent == nullptr) {
102 return;
103 }
104 if ((*(outParams->pos) + 1) >= strlen(format)) {
105 return;
106 }
107
108 switch (format[*(outParams->pos) + 1]) {
109 case 'i':
110 case 'd':
111 if (HilogVector::GetType(params, *(outParams->count)) == INT_TYPE) {
112 HilogString::Puts(
113 showPriv ? PRIV_STR : HilogVector::GetStr(params, *(outParams->count)), outParams->logContent);
114 }
115 (*(outParams->count))++;
116 ++(*(outParams->pos));
117 break;
118 case 's':
119 if (HilogVector::GetType(params, *(outParams->count)) == STRING_TYPE) {
120 HilogString::Puts(
121 showPriv ? PRIV_STR : HilogVector::GetStr(params, *(outParams->count)), outParams->logContent);
122 }
123 (*(outParams->count))++;
124 ++(*(outParams->pos));
125 break;
126 case 'O':
127 case 'o':
128 if (HilogVector::GetType(params, *(outParams->count)) == OBJECT_TYPE) {
129 HilogString::Puts(
130 showPriv ? PRIV_STR : HilogVector::GetStr(params, *(outParams->count)), outParams->logContent);
131 }
132 (*(outParams->count))++;
133 ++(*(outParams->pos));
134 break;
135 case '%':
136 HilogString::Putc(format[*(outParams->pos)], outParams->logContent);
137 ++(*(outParams->pos));
138 break;
139 default:
140 HilogString::Putc(format[*(outParams->pos)], outParams->logContent);
141 break;
142 }
143 }
144
Debug(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)145 JSIValue HilogModule::Debug(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
146 {
147 return HilogModule::HilogImpl(thisVal, args, argsNum, LogLevel::LOG_DEBUG);
148 }
149
Info(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)150 JSIValue HilogModule::Info(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
151 {
152 return HilogModule::HilogImpl(thisVal, args, argsNum, LogLevel::LOG_INFO);
153 }
154
Error(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)155 JSIValue HilogModule::Error(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
156 {
157 return HilogModule::HilogImpl(thisVal, args, argsNum, LogLevel::LOG_ERROR);
158 }
159
Warn(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)160 JSIValue HilogModule::Warn(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
161 {
162 return HilogModule::HilogImpl(thisVal, args, argsNum, LogLevel::LOG_WARN);
163 }
164
Fatal(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)165 JSIValue HilogModule::Fatal(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
166 {
167 return HilogModule::HilogImpl(thisVal, args, argsNum, LogLevel::LOG_FATAL);
168 }
169
HiLogIsLoggable(int32_t domain,const char * tag,LogLevel level)170 bool HiLogIsLoggable(int32_t domain, const char *tag, LogLevel level)
171 {
172 if ((level < LOG_DEBUG) || (level > LOG_FATAL) || tag == nullptr ||
173 domain > MAX_DOMAIN || domain < MIN_DOMAIN) {
174 return false;
175 }
176 return true;
177 }
178
IsLoggable(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum)179 JSIValue HilogModule::IsLoggable(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum)
180 {
181 if ((args == nullptr) || (argsNum < MIN_NUMBER) || JSI::ValueIsUndefined(args[FIRST]) ||
182 JSI::ValueIsUndefined(args[SECOND]) || JSI::ValueIsUndefined(args[THIRD])) {
183 HILOG_HILOGE("IsLoggable: args is invalid.");
184 return JSI::CreateBoolean(false);
185 }
186 if (JSI::ValueIsNull(args[FIRST]) || JSI::ValueIsNull(args[SECOND]) ||
187 JSI::ValueIsNull(args[THIRD])) {
188 HILOG_HILOGE("IsLoggable: args type is null.");
189 return JSI::CreateBoolean(false);
190 }
191 if (!JSI::ValueIsNumber(args[FIRST]) || !JSI::ValueIsString(args[SECOND]) ||
192 !JSI::ValueIsNumber(args[THIRD])) {
193 HILOG_HILOGE("IsLoggable: args type is invalid.");
194 return JSI::CreateBoolean(false);
195 }
196
197 int32_t domain = static_cast<int32_t>(JSI::ValueToNumber(args[FIRST]));
198 if (domain > MAX_DOMAIN || domain < MIN_DOMAIN) {
199 HILOG_HILOGE("IsLoggable: domain is invalid.");
200 return JSI::CreateBoolean(false);
201 }
202 char *tag = JSI::ValueToString(args[SECOND]);
203 if (tag == nullptr || strlen(tag) > MAX_TAG) {
204 HILOG_HILOGE("IsLoggable: tag is null or tag > %{public}d.", MAX_TAG);
205 return JSI::CreateBoolean(false);
206 }
207 int32_t level = static_cast<int32_t>(JSI::ValueToNumber(args[THIRD]));
208 if (level > LOG_FATAL || level < LOG_DEBUG) {
209 HILOG_HILOGE("IsLoggable:level is error.");
210 JSI::ReleaseString(tag);
211 return JSI::CreateBoolean(false);
212 }
213 bool res = HiLogIsLoggable(domain, tag, static_cast<LogLevel>(level));
214 JSI::ReleaseString(tag);
215 return JSI::CreateBoolean(res);
216 }
217
ParseNapiValue(const JSIValue thisVal,const JSIValue * element,HilogVector * params)218 void HilogModule::ParseNapiValue(const JSIValue thisVal, const JSIValue *element, HilogVector *params)
219 {
220 if (element == nullptr || params == nullptr) {
221 HILOG_HILOGE("ParseNapiValue: element or params is nullptr.");
222 return;
223 }
224 if (JSI::ValueIsNumber(element[0])) {
225 char *value = JSI::JSIValueToString(element[0]);
226 HilogVector::Push(params, value, INT_TYPE);
227 JSI::ReleaseString(value);
228 } else if (JSI::ValueIsString(element[0])) {
229 char *value = JSI::ValueToString(element[0]);
230 HilogVector::Push(params, value, STRING_TYPE);
231 JSI::ReleaseString(value);
232 } else if (JSI::ValueIsObject(element[0])) {
233 char *value = JSI::JSIValueToString(element[0]);
234 HilogVector::Push(params, value, OBJECT_TYPE);
235 JSI::ReleaseString(value);
236 } else {
237 HILOG_HILOGE("ParseNapiValue: type mismatch.");
238 }
239 return;
240 }
241
HilogImpl(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum,int level)242 JSIValue HilogModule::HilogImpl(const JSIValue thisVal, const JSIValue *args, uint8_t argsNum, int level)
243 {
244 JSIValue undefValue = JSI::CreateUndefined();
245 if ((args == nullptr) || (argsNum < MIN_NUMBER) || (argsNum > MAX_NUMBER) ||
246 JSI::ValueIsUndefined(args[FIRST]) || JSI::ValueIsUndefined(args[SECOND]) ||
247 JSI::ValueIsUndefined(args[THIRD]) || JSI::ValueIsNull(args[FIRST]) ||
248 JSI::ValueIsNull(args[SECOND]) || JSI::ValueIsNull(args[THIRD])) {
249 HILOG_HILOGE("HilogImpl: args is invalid.");
250 return undefValue;
251 }
252
253 int32_t domain = static_cast<int32_t>(JSI::ValueToNumber(args[FIRST]));
254 if (domain > MAX_DOMAIN || domain < MIN_DOMAIN) {
255 HILOG_HILOGE("HilogImpl: domain is invalid.");
256 return undefValue;
257 }
258 char *tag = JSI::ValueToString(args[SECOND]);
259 if (tag == nullptr || strlen(tag) > MAX_TAG) {
260 HILOG_HILOGE("HilogImpl: tag is null or tag > %{public}d.", MAX_TAG);
261 return undefValue;
262 }
263 char *fmtString = JSI::ValueToString(args[THIRD]);
264 if (fmtString == nullptr || strlen(fmtString) > MAX_FORMAT) {
265 HILOG_HILOGE("HilogImpl: fmtString is null or fmtString > %{public}d.", MAX_FORMAT);
266 JSI::ReleaseString(tag);
267 return undefValue;
268 }
269
270 HilogVector params;
271 bool result = HilogImplParseValue(thisVal, args, argsNum, ¶ms);
272 if (!result) {
273 JSI::ReleaseString(fmtString);
274 JSI::ReleaseString(tag);
275 return undefValue;
276 }
277 HilogString fmtStringBuffer;
278 HilogString logContent;
279 HilogString::Puts(fmtString, &fmtStringBuffer);
280 ParseLogContent(&fmtStringBuffer, ¶ms, &logContent);
281 if ((HilogString::Length(&logContent) + DOMAIN_LEN + FIX_LEN) + strlen(tag) > (MAX_FORMAT - 1)) {
282 HILOG_HILOGE("HilogImpl: log length > %{public}d.", MAX_FORMAT - DOMAIN_LEN - FIX_LEN - strlen(tag) - 1);
283 JSI::ReleaseString(fmtString);
284 JSI::ReleaseString(tag);
285 return undefValue;
286 }
287 HiLogPrint(DEFAULT_LOG_TYPE, static_cast<LogLevel>(level), domain, tag, HilogString::Get(&logContent), "");
288 JSI::ReleaseString(fmtString);
289 JSI::ReleaseString(tag);
290 return undefValue;
291 }
292
HilogImplParseValue(const JSIValue thisVal,const JSIValue * args,uint8_t argsNum,HilogVector * params)293 bool HilogModule::HilogImplParseValue(
294 const JSIValue thisVal, const JSIValue *args, uint8_t argsNum, HilogVector *params)
295 {
296 if (params == nullptr || args == nullptr) {
297 return false;
298 }
299 if (argsNum > MIN_NUMBER && !JSI::ValueIsUndefined(args[FOURTH]) && !JSI::ValueIsNull(args[FOURTH])) {
300 if (!JSI::ValueIsArray(args[FOURTH])) {
301 for (size_t i = MIN_NUMBER; i < argsNum; i++) {
302 ParseNapiValue(thisVal, &args[i], params);
303 }
304 } else {
305 if (argsNum != MIN_NUMBER + 1) {
306 HILOG_HILOGE("HilogImplParseValue: args mismatch.");
307 return false;
308 }
309 for (uint32_t i = 0; i < JSI::GetArrayLength(args[FOURTH]); i++) {
310 JSIValue element = JSI::GetPropertyByIndex(args[FOURTH], i);
311 ParseNapiValue(thisVal, &element, params);
312 }
313 }
314 }
315 return true;
316 }
317
InitLogLevelType(JSIValue target)318 void InitLogLevelType(JSIValue target)
319 {
320 JSIValue logLevel = JSI::CreateObject();
321 JSI::SetNumberProperty(logLevel, "DEBUG", LogLevel::LOG_DEBUG);
322 JSI::SetNumberProperty(logLevel, "INFO", LogLevel::LOG_INFO);
323 JSI::SetNumberProperty(logLevel, "WARN", LogLevel::LOG_WARN);
324 JSI::SetNumberProperty(logLevel, "ERROR", LogLevel::LOG_ERROR);
325 JSI::SetNumberProperty(logLevel, "FATAL", LogLevel::LOG_FATAL);
326 JSI::SetNamedProperty(target, "LogLevel", logLevel);
327 }
328
InitHilogModule(JSIValue exports)329 void InitHilogModule(JSIValue exports)
330 {
331 HILOG_HILOGI("InitHilogModule start");
332
333 InitLogLevelType(exports);
334 JSI::SetModuleAPI(exports, "debug", HilogModule::Debug);
335 JSI::SetModuleAPI(exports, "info", HilogModule::Info);
336 JSI::SetModuleAPI(exports, "error", HilogModule::Error);
337 JSI::SetModuleAPI(exports, "warn", HilogModule::Warn);
338 JSI::SetModuleAPI(exports, "fatal", HilogModule::Fatal);
339 JSI::SetModuleAPI(exports, "isLoggable", HilogModule::IsLoggable);
340
341 HILOG_HILOGI("InitHilogModule end");
342 }
343 } // ACELite
344 } // OHOS