1/*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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#include "print_event_parser.h"
16#include "animation_filter.h"
17#include "clock_filter_ex.h"
18#include "frame_filter.h"
19#include "measure_filter.h"
20#include "stat_filter.h"
21#include "string_to_numerical.h"
22#include <cinttypes>
23namespace SysTuning {
24namespace TraceStreamer {
25const uint8_t POINT_LENGTH = 1;
26const uint8_t MAX_POINT_LENGTH = 2;
27PrintEventParser::PrintEventParser(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
28    : EventParserBase(dataCache, filter)
29{
30    rsOnDoCompositionEvent_ = traceDataCache_->GetDataIndex(rsOnDoCompositionStr_);
31    eventToFrameFunctionMap_ = {
32        {recvievVsync_, bind(&PrintEventParser::ReciveVsync, this, std::placeholders::_1, std::placeholders::_2,
33                             std::placeholders::_3)},
34        {rsOnDoCompositionEvent_, bind(&PrintEventParser::RSReciveOnDoComposition, this, std::placeholders::_1,
35                                       std::placeholders::_2, std::placeholders::_3)},
36        {onVsyncEvent_, bind(&PrintEventParser::OnVsyncEvent, this, std::placeholders::_1, std::placeholders::_2,
37                             std::placeholders::_3)},
38        {marshRwTransactionData_, bind(&PrintEventParser::OnRwTransaction, this, std::placeholders::_1,
39                                       std::placeholders::_2, std::placeholders::_3)},
40        {rsMainThreadProcessCmd_, bind(&PrintEventParser::OnMainThreadProcessCmd, this, std::placeholders::_1,
41                                       std::placeholders::_2, std::placeholders::_3)}};
42}
43
44bool PrintEventParser::ParsePrintEvent(const std::string &comm,
45                                       uint64_t ts,
46                                       uint32_t pid,
47                                       std::string_view event,
48                                       const BytraceLine &line)
49{
50    streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
51    TracePoint point;
52    if (GetTracePoint(event, point) != PARSE_SUCCESS) {
53        streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
54        return false;
55    }
56    if (point.tgid_) {
57        // tgid use 'B|' after with 'TGID', the '(TGID)' maybe wrong, eg: xxx-21675 ( 1264) ...: print: B|21675|...
58        const_cast<BytraceLine &>(line).tgid = point.tgid_;
59        streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
60    }
61    switch (point.phase_) {
62        case 'B': {
63            ParseBeginEvent(comm, ts, pid, point, line);
64            break;
65        }
66        case 'E': {
67            ParseEndEvent(ts, pid, point);
68            break;
69        }
70        case 'S': {
71            ParseStartEvent(comm, ts, pid, point, line);
72            break;
73        }
74        case 'F': {
75            ParseFinishEvent(ts, pid, point, line);
76            break;
77        }
78        case 'C': {
79            ParseCreateEvent(ts, point);
80            break;
81        }
82        case 'G': {
83            ParseGEvent(ts, pid, point);
84            break;
85        }
86        case 'H': {
87            ParseHEvent(ts, point);
88            break;
89        }
90        default:
91            TS_LOGD("point missing!");
92            return false;
93    }
94    return true;
95}
96void PrintEventParser::ParseBeginEvent(const std::string &comm,
97                                       uint64_t ts,
98                                       uint32_t pid,
99                                       TracePoint &point,
100                                       const BytraceLine &line)
101{
102    uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
103                                                              traceDataCache_->GetDataIndex(point.name_));
104    if (index != INVALID_UINT32) {
105        // add distributed data
106        traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_,
107                                                                    point.parentSpanId_, point.flag_);
108        if (pid == point.tgid_) {
109            if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) {
110                return;
111            }
112        }
113        bool isDiscontinued = false;
114        if (traceDataCache_->TaskPoolTraceEnabled()) {
115            isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index);
116        }
117        if (traceDataCache_->AnimationTraceEnabled() && !isDiscontinued) {
118            (void)HandleAnimationBeginEvent(point, index, line);
119        }
120    } else {
121        streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
122    }
123}
124void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint &point)
125{
126    uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
127    if (pid == point.tgid_) {
128        HandleFrameSliceEndEvent(ts, point.tgid_, pid, index);
129    }
130    if (traceDataCache_->AnimationTraceEnabled()) {
131        streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index);
132    }
133}
134void PrintEventParser::ParseStartEvent(const std::string &comm,
135                                       uint64_t ts,
136                                       uint32_t pid,
137                                       const TracePoint &point,
138                                       const BytraceLine &line)
139{
140    auto cookie = static_cast<int64_t>(point.value_);
141    auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
142                                                               traceDataCache_->GetDataIndex(point.name_));
143    if (point.name_ == onFrameQueeuStartEvent_ && index != INVALID_UINT64) {
144        OnFrameQueueStart(ts, index, point.tgid_);
145    } else if (traceDataCache_->AnimationTraceEnabled() && index != INVALID_UINT64 &&
146               (base::EndWith(comm, onAnimationProcEvent_) ||
147                base::EndWith(comm, newOnAnimationProcEvent_))) { // the comm is taskName
148        streamFilters_->animationFilter_->StartAnimationEvent(line, point, index);
149    }
150}
151void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePoint &point, const BytraceLine &line)
152{
153    auto cookie = static_cast<int64_t>(point.value_);
154    auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
155                                                                traceDataCache_->GetDataIndex(point.name_));
156    HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index);
157    if (traceDataCache_->AnimationTraceEnabled()) {
158        streamFilters_->animationFilter_->FinishAnimationEvent(line, index);
159    }
160}
161void PrintEventParser::ParseCreateEvent(uint64_t ts, const TracePoint &point)
162{
163    DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
164    uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
165    if (internalPid != INVALID_ID) {
166        streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, internalPid, nameIndex, ts,
167                                                             point.value_);
168        streamFilters_->processFilter_->AddProcessMemory(internalPid);
169    } else {
170        streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
171    }
172}
173void PrintEventParser::ParseGEvent(uint64_t ts, uint32_t pid, TracePoint &point)
174{
175    auto cookie = static_cast<int64_t>(point.value_);
176    streamFilters_->sliceFilter_->StartGEvent(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
177}
178void PrintEventParser::ParseHEvent(uint64_t ts, const TracePoint &point)
179{
180    auto cookie = static_cast<int64_t>(point.value_);
181    streamFilters_->sliceFilter_->FinishHEvent(ts, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
182}
183bool PrintEventParser::HandleAnimationBeginEvent(const TracePoint &point, size_t callStackRow, const BytraceLine &line)
184{
185    if (!streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line)) {
186        return streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackRow);
187    }
188    return true;
189}
190void PrintEventParser::SetTraceType(TraceFileType traceType)
191{
192    traceType_ = traceType;
193}
194void PrintEventParser::SetTraceClockId(BuiltinClocks clock)
195{
196    if (clock != clock_) {
197        clock_ = clock;
198    }
199}
200void PrintEventParser::Finish()
201{
202    eventToFrameFunctionMap_.clear();
203    frameCallIds_.clear();
204    vsyncSliceMap_.clear();
205    streamFilters_->animationFilter_->Clear();
206    streamFilters_->frameFilter_->Clear();
207}
208ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const
209{
210    if (pointStr.size() == 0) {
211        TS_LOGD("get trace point data size is 0!");
212        return PARSE_ERROR;
213    }
214
215    std::string clockSyncSts = "trace_event_clock_sync";
216    if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) {
217        TS_LOGD("skip trace point :%s!", clockSyncSts.c_str());
218        return PARSE_ERROR;
219    }
220
221    if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 &&
222        pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0 && pointStr.find_first_of('G') != 0 &&
223        pointStr.find_first_of('H') != 0) {
224        TS_LOGD("trace point not supported : [%c] !", pointStr[0]);
225        return PARSE_ERROR;
226    }
227
228    if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) {
229        TS_LOGD("point string size error!");
230        return PARSE_ERROR;
231    }
232
233    if (pointStr.size() >= MAX_POINT_LENGTH) {
234        if ((pointStr[1] != '|') && (pointStr[1] != '\n')) {
235            TS_LOGD("not support data formart!");
236            return PARSE_ERROR;
237        }
238    }
239
240    return PARSE_SUCCESS;
241}
242
243std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const
244{
245    size_t index = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
246
247    size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0);
248    std::string_view name = std::string_view(pointStr.data() + index, length);
249    // remove space at the end
250    name = std::string_view(name.data(), name.find_last_not_of(" ") + 1);
251    return name;
252}
253
254ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
255{
256    outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength);
257    if (outPoint.name_.empty()) {
258        TS_LOGD("point name is empty!");
259        return PARSE_ERROR;
260    }
261    // Distributed data:
262    // <...>-357 (-------) .... 174330.287420: tracing_mark_write:
263    // B|1298|H:[8b00e96b2,2,1]#C##napi::NativeAsyncWork::QueueWithQos
264    std::smatch matcheLine;
265    bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher_);
266    if (matched) {
267        size_t index = 0;
268        outPoint.chainId_ = matcheLine[++index].str();
269        outPoint.spanId_ = matcheLine[++index].str();
270        outPoint.parentSpanId_ = matcheLine[++index].str();
271        outPoint.flag_ = matcheLine[++index].str();
272    } else {
273        auto space = outPoint.name_.find(' ');
274        if (space != std::string::npos) {
275            outPoint.funcPrefix_ = outPoint.name_.substr(0, space);
276            outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.funcPrefix_);
277            outPoint.funcArgs_ = outPoint.name_.substr(space + 1);
278        } else {
279            outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.name_);
280        }
281    }
282    return PARSE_SUCCESS;
283}
284
285bool PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName,
286                                                  size_t callStackRow,
287                                                  std::string &args,
288                                                  const BytraceLine &line)
289{
290    auto it = eventToFrameFunctionMap_.find(eventName);
291    if (it != eventToFrameFunctionMap_.end()) {
292        it->second(callStackRow, args, line);
293        return true;
294    } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), rsOnDoCompositionStr_)) {
295        RSReciveOnDoComposition(callStackRow, args, line);
296        return true;
297    }
298    return false;
299}
300bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string &args, const BytraceLine &line)
301{
302    streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_RECEIVED);
303    // args is like "dataCount:24bytes now:211306766162 expectedEnd:211323423844 vsyncId:3179"
304    std::sregex_iterator it(args.begin(), args.end(), recvVsyncPattern_);
305    std::sregex_iterator end;
306    uint64_t now = INVALID_UINT64;
307    uint64_t expectEnd = INVALID_UINT64;
308    uint32_t vsyncId = INVALID_UINT32;
309    while (it != end) {
310        std::smatch match = *it;
311        std::string key = match.str(1);
312        std::string value = match.str(2);
313        if (key == "now") {
314            now = base::StrToInt<uint64_t>(value).value();
315        } else if (key == "expectedEnd") {
316            expectEnd = base::StrToInt<uint64_t>(value).value();
317        } else if (key == "vsyncId") {
318            vsyncId = base::StrToInt<uint64_t>(value).value();
319        }
320        ++it;
321    }
322    if (convertVsyncTs_ && traceType_ == TRACE_FILETYPE_H_TRACE) {
323        if (now != INVALID_UINT64) {
324            now = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, now);
325        }
326        if (expectEnd != INVALID_UINT64) {
327            expectEnd = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_MONOTONIC, expectEnd);
328        }
329    }
330    streamFilters_->frameFilter_->BeginVsyncEvent(line, now, expectEnd, vsyncId, callStackRow);
331    auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
332    if (vsyncSliceMap_.count(iTid)) {
333        vsyncSliceMap_[iTid].push_back(callStackRow);
334    } else {
335        vsyncSliceMap_[iTid] = {callStackRow};
336    }
337    return true;
338}
339bool PrintEventParser::OnVsyncEvent(size_t callStackRow, std::string &args, const BytraceLine &line)
340{
341    Unused(args);
342    auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
343    if (!vsyncSliceMap_.count(iTid)) {
344        return false;
345    }
346    // when there are mutiple nested OnVsyncEvent,only handle the OnvsyncEvent of the next layer under ReceiveVsync
347    if (vsyncSliceMap_[iTid].size() >= maxVsyncEventSize_) {
348        return false;
349    }
350    vsyncSliceMap_[iTid].push_back(callStackRow);
351    return true;
352}
353bool PrintEventParser::RSReciveOnDoComposition(size_t callStackRow, std::string &args, const BytraceLine &line)
354{
355    streamFilters_->statFilter_->IncreaseStat(TRACE_ON_DO_COMPOSITION, STAT_EVENT_RECEIVED);
356    auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
357    (void)streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(line.ts, iTid);
358    return true;
359}
360bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, const BytraceLine &line)
361{
362    // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1
363    std::smatch match;
364    if (std::regex_search(args, match, transFlagPattern_)) {
365        std::string flag2 = match.str(2);
366        auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
367        return streamFilters_->frameFilter_->BeginRSTransactionData(line.ts, iTid,
368                                                                    base::StrToInt<uint32_t>(flag2).value());
369    }
370    return true;
371}
372bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string &args, const BytraceLine &line)
373{
374    std::sregex_iterator it(args.begin(), args.end(), mainProcessCmdPattern_);
375    std::sregex_iterator end;
376    std::vector<FrameFilter::FrameMap> frames;
377    while (it != end) {
378        std::smatch match = *it;
379        std::string value1 = match.str(1);
380        std::string value2 = match.str(2);
381        frames.push_back({streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(value1).value()),
382                          base::StrToInt<uint32_t>(value2).value()});
383        ++it;
384    }
385    auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
386    return streamFilters_->frameFilter_->BeginProcessCommandUni(line.ts, iTid, frames, callStackRow);
387}
388bool PrintEventParser::OnFrameQueueStart(uint64_t ts, size_t callStackRow, uint64_t pid)
389{
390    streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_RECEIVED);
391    auto iTid = streamFilters_->processFilter_->GetInternalTid(pid);
392    if (streamFilters_->frameFilter_->StartFrameQueue(ts, iTid)) {
393        frameCallIds_.push_back(callStackRow);
394    }
395    return true;
396}
397void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
398{
399    // it can be frame or slice
400    auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
401    if (vsyncSliceMap_.count(iTid)) {
402        auto pos = std::find(vsyncSliceMap_[iTid].begin(), vsyncSliceMap_[iTid].end(), callStackRow);
403        if (pos != vsyncSliceMap_[iTid].end()) {
404            if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) {
405                streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH);
406            }
407            vsyncSliceMap_[iTid].erase(pos);
408        }
409    }
410    return;
411}
412
413void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
414{
415    // it can be frame or slice
416    auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
417    auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow);
418    if (pos != frameCallIds_.end()) {
419        TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid);
420        if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) {
421            streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH);
422            TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid);
423        }
424        frameCallIds_.erase(pos);
425    }
426    return;
427}
428ParseResult PrintEventParser::HandlerE(void)
429{
430    return PARSE_SUCCESS;
431}
432
433size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
434{
435    size_t namelength = 0;
436    for (size_t i = nameIndex; i < pointStr.size(); i++) {
437        if (pointStr[i] == ' ') {
438            namelength = i - nameIndex;
439        }
440        if (pointStr[i] == '|') {
441            namelength = i - nameIndex;
442            break;
443        }
444    }
445    return namelength;
446}
447
448size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
449{
450    size_t valuePipe = pointStr.find('|', valueIndex);
451    size_t valueLen = pointStr.size() - valueIndex;
452    if (valuePipe != std::string_view::npos) {
453        valueLen = valuePipe - valueIndex;
454    }
455
456    if (valueLen == 0) {
457        return 0;
458    }
459
460    if (pointStr[valueIndex + valueLen - POINT_LENGTH] == '\n') {
461        valueLen--;
462    }
463
464    return valueLen;
465}
466
467ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
468{
469    // point name
470    size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
471    size_t namelength = GetNameLength(pointStr, nameIndex);
472    if (namelength == 0) {
473        TS_LOGD("point name length is error!");
474        return PARSE_ERROR;
475    }
476    outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
477
478    // point value
479    size_t valueIndex = nameIndex + namelength + POINT_LENGTH;
480    size_t valueLen = GetValueLength(pointStr, valueIndex);
481    if (valueLen == 0) {
482        TS_LOGD("point value length is error!");
483        return PARSE_ERROR;
484    }
485
486    std::string valueStr(pointStr.data() + valueIndex, valueLen);
487    if (!base::StrToInt<int64_t>(valueStr).has_value()) {
488        TS_LOGD("point value is error!");
489        return PARSE_ERROR;
490    }
491    outPoint.value_ = base::StrToInt<int64_t>(valueStr).value();
492
493    size_t valuePipe = pointStr.find('|', valueIndex);
494    if (valuePipe != std::string_view::npos) {
495        size_t groupLen = pointStr.size() - valuePipe - POINT_LENGTH;
496        if (groupLen == 0) {
497            return PARSE_ERROR;
498        }
499
500        if (pointStr[pointStr.size() - POINT_LENGTH] == '\n') {
501            groupLen--;
502        }
503
504        outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
505    }
506
507    return PARSE_SUCCESS;
508}
509
510size_t PrintEventParser::GetGHNameLength(std::string_view pointStr, size_t nameIndex)
511{
512    size_t endPos = pointStr.find('|', nameIndex);
513    if (endPos == std::string_view::npos) {
514        return 0;
515    }
516    size_t nextEndPos = pointStr.find('|', endPos + 1);
517    if (nextEndPos == std::string_view::npos) {
518        return 0;
519    }
520    return nextEndPos - nameIndex;
521}
522ParseResult PrintEventParser::HandlerGH(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
523{
524    size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
525    size_t nameLength = GetGHNameLength(pointStr, nameIndex);
526    if (nameLength == 0) {
527        TS_LOGD("point name length is error!");
528        return PARSE_ERROR;
529    }
530    outPoint.name_ = std::string_view(pointStr.data() + nameIndex, nameLength);
531    size_t valueIndex = nameIndex + nameLength + POINT_LENGTH;
532    size_t valueLen = GetValueLength(pointStr, valueIndex);
533    if (valueLen == 0) {
534        TS_LOGD("point value length is error!");
535        return PARSE_ERROR;
536    }
537    if (!base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).has_value()) {
538        TS_LOGD("point value is error!");
539        return PARSE_ERROR;
540    }
541    outPoint.value_ = base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).value();
542    return PARSE_SUCCESS;
543}
544
545ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint &outPoint) const
546{
547    if (CheckTracePoint(pointStr) != PARSE_SUCCESS) {
548        return PARSE_ERROR;
549    }
550
551    size_t tGidlength = 0;
552    // we may get wrong format data like tracing_mark_write: E
553    // while the format data must be E|call-tid
554    // please use a regular-format to get all the data
555    outPoint.phase_ = pointStr.front();
556    outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
557
558    ParseResult ret = PARSE_ERROR;
559    switch (outPoint.phase_) {
560        case 'B': {
561            ret = HandlerB(pointStr, outPoint, tGidlength);
562            break;
563        }
564        case 'E': {
565            ret = HandlerE();
566            break;
567        }
568        case 'S':
569        case 'F':
570        case 'C': {
571            ret = HandlerCSF(pointStr, outPoint, tGidlength);
572            break;
573        }
574        case 'G':
575        case 'H': {
576            ret = HandlerGH(pointStr, outPoint, tGidlength);
577            break;
578        }
579        default:
580            return PARSE_ERROR;
581    }
582    return ret;
583}
584
585uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t &length) const
586{
587    for (size_t i = MAX_POINT_LENGTH; i < pointStr.size(); i++) {
588        if (pointStr[i] == '|' || pointStr[i] == '\n') {
589            break;
590        }
591
592        if (pointStr[i] < '0' || pointStr[i] > '9') {
593            return PARSE_ERROR;
594        }
595
596        length++;
597    }
598
599    std::string str(pointStr.data() + MAX_POINT_LENGTH, length);
600    return base::StrToInt<uint32_t>(str).value_or(0);
601}
602} // namespace TraceStreamer
603} // namespace SysTuning
604