148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci#ifndef HIPERF_UTILITIES_H_
1648f512ceSopenharmony_ci#define HIPERF_UTILITIES_H_
1748f512ceSopenharmony_ci
1848f512ceSopenharmony_ci// for security function
1948f512ceSopenharmony_ci#include <securec.h>
2048f512ceSopenharmony_ci#include <algorithm>
2148f512ceSopenharmony_ci#include <cctype>
2248f512ceSopenharmony_ci#include <cinttypes>
2348f512ceSopenharmony_ci#include <cstdio>
2448f512ceSopenharmony_ci#include <fstream>
2548f512ceSopenharmony_ci#include <iomanip>
2648f512ceSopenharmony_ci#include <iostream>
2748f512ceSopenharmony_ci#include <sstream>
2848f512ceSopenharmony_ci#include <string>
2948f512ceSopenharmony_ci#include <vector>
3048f512ceSopenharmony_ci#include <set>
3148f512ceSopenharmony_ci
3248f512ceSopenharmony_ci#include <dirent.h>
3348f512ceSopenharmony_ci#include <fcntl.h>
3448f512ceSopenharmony_ci#include <file_ex.h>
3548f512ceSopenharmony_ci#include <stddef.h>
3648f512ceSopenharmony_ci#include <sys/stat.h>
3748f512ceSopenharmony_ci#include <unique_fd.h>
3848f512ceSopenharmony_ci#include <unistd.h>
3948f512ceSopenharmony_ci#if !is_mingw
4048f512ceSopenharmony_ci#include <gtest/gtest_prod.h>
4148f512ceSopenharmony_ci#include <sys/syscall.h>
4248f512ceSopenharmony_ci#endif
4348f512ceSopenharmony_ci#include <linux/types.h>
4448f512ceSopenharmony_ci#include "debug_logger.h"
4548f512ceSopenharmony_ci#include "noncopyable.h"
4648f512ceSopenharmony_ci
4748f512ceSopenharmony_ci// data and value
4848f512ceSopenharmony_ci/*
4948f512ceSopenharmony_cilong long always 64 only in ILP64, int is 64 otherwise int is always 32
5048f512ceSopenharmony_ci*/
5148f512ceSopenharmony_ciusing s8 = __s8;
5248f512ceSopenharmony_ciusing u8 = __u8;
5348f512ceSopenharmony_ciusing s16 = __s16;
5448f512ceSopenharmony_ciusing u16 = __u16;
5548f512ceSopenharmony_ciusing s32 = __s32;
5648f512ceSopenharmony_ciusing u32 = __u32;
5748f512ceSopenharmony_ciusing s64 = __s64;
5848f512ceSopenharmony_ciusing u64 = __u64;
5948f512ceSopenharmony_ci
6048f512ceSopenharmony_ciconstexpr const int NUMBER_FORMAT_HEX_BASE = 16;
6148f512ceSopenharmony_ciconstexpr const int BYTE_PRINT_WIDTH = 2;
6248f512ceSopenharmony_ciconstexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8;
6348f512ceSopenharmony_ciconstexpr const int BITS_OF_BYTE = 8;
6448f512ceSopenharmony_ciconstexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE;
6548f512ceSopenharmony_ciconstexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE;
6648f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE = 100;
6748f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_NUM_LEN = 5;      // 100.00
6848f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00
6948f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_LEN = 6;          // 100.00%
7048f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_DIFF_LEN = 7;     // +100.00%
7148f512ceSopenharmony_ciconstexpr const int THOUSANDS = 1000;
7248f512ceSopenharmony_ciconstexpr const int HUNDREDS = 100;
7348f512ceSopenharmony_ciconstexpr const int DEFAULT_STRING_BUF_SIZE = 4096;
7448f512ceSopenharmony_ciconstexpr const int FIVE_THOUSANDS = 5000;
7548f512ceSopenharmony_ciconstexpr const int DATA_MAX_SIZE = 1001;
7648f512ceSopenharmony_ciconstexpr const int LITTLE_MEMORY_SIZE = 1;
7748f512ceSopenharmony_ciconstexpr const int MULTIPLE_SIZE = 1024;
7848f512ceSopenharmony_ciconstexpr const uint16_t CHECK_FREQUENCY = 100; //
7948f512ceSopenharmony_ciconstexpr const uint8_t CHECK_TIMEOUT = 30;
8048f512ceSopenharmony_ciconstexpr const int INDENT_TWO = 2;
8148f512ceSopenharmony_ciconstexpr const float ALMOST_ZERO = 0.001;
8248f512ceSopenharmony_ci#if !is_mingw
8348f512ceSopenharmony_ci#ifndef O_BINARY
8448f512ceSopenharmony_ci#define O_BINARY 0
8548f512ceSopenharmony_ci#endif
8648f512ceSopenharmony_ci#endif
8748f512ceSopenharmony_ci
8848f512ceSopenharmony_ciconstexpr const double MS_DURATION =
8948f512ceSopenharmony_ci    static_cast<double>(std::chrono::milliseconds::duration::period::den);
9048f512ceSopenharmony_ci
9148f512ceSopenharmony_ciconstexpr uint64_t KILO = 1024;
9248f512ceSopenharmony_ci
9348f512ceSopenharmony_cinamespace OHOS {
9448f512ceSopenharmony_cinamespace Developtools {
9548f512ceSopenharmony_cinamespace HiPerf {
9648f512ceSopenharmony_cistd::string CanonicalizeSpecPath(const char* src);
9748f512ceSopenharmony_ciconst std::string EMPTY_STRING = "";
9848f512ceSopenharmony_ciconst ssize_t ERRINFOLEN = 512;
9948f512ceSopenharmony_ciconst std::set<int> ALLOW_UIDS = {1201};
10048f512ceSopenharmony_ci
10148f512ceSopenharmony_ciconst std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines";
10248f512ceSopenharmony_cistatic FILE *g_outputDump = nullptr;
10348f512ceSopenharmony_ciconst uint64_t waitAppRunCheckTimeOut = 20;
10448f512ceSopenharmony_ci
10548f512ceSopenharmony_cistruct ThreadInfos {
10648f512ceSopenharmony_ci    pid_t tid;
10748f512ceSopenharmony_ci    pid_t pid;
10848f512ceSopenharmony_ci};
10948f512ceSopenharmony_ci// string function
11048f512ceSopenharmony_ciclass MemoryHold {
11148f512ceSopenharmony_cipublic:
11248f512ceSopenharmony_ci    ~MemoryHold()
11348f512ceSopenharmony_ci    {
11448f512ceSopenharmony_ci        Clean();
11548f512ceSopenharmony_ci    }
11648f512ceSopenharmony_ci    // only use in UT
11748f512ceSopenharmony_ci    void Clean()
11848f512ceSopenharmony_ci    {
11948f512ceSopenharmony_ci        for (auto &p : holder_) {
12048f512ceSopenharmony_ci            delete[] p;
12148f512ceSopenharmony_ci        }
12248f512ceSopenharmony_ci        holder_.clear();
12348f512ceSopenharmony_ci    }
12448f512ceSopenharmony_ci    static MemoryHold &Get()
12548f512ceSopenharmony_ci    {
12648f512ceSopenharmony_ci        static MemoryHold instance;
12748f512ceSopenharmony_ci        return instance;
12848f512ceSopenharmony_ci    }
12948f512ceSopenharmony_ci
13048f512ceSopenharmony_ciprivate:
13148f512ceSopenharmony_ci    std::vector<char *> holder_;
13248f512ceSopenharmony_ci};
13348f512ceSopenharmony_ci
13448f512ceSopenharmony_cistd::string StringReplace(std::string source, const std::string &from, const std::string &to);
13548f512ceSopenharmony_ci
13648f512ceSopenharmony_citemplate<class T>
13748f512ceSopenharmony_cistd::string VectorToString(const std::vector<T> &items)
13848f512ceSopenharmony_ci{
13948f512ceSopenharmony_ci    if constexpr (std::is_same<T, std::vector<std::string>>::value) {
14048f512ceSopenharmony_ci        std::vector<std::string> stringItems;
14148f512ceSopenharmony_ci        for (auto item : items) {
14248f512ceSopenharmony_ci            stringItems.push_back("[" + VectorToString(item) + "]");
14348f512ceSopenharmony_ci        }
14448f512ceSopenharmony_ci        return VectorToString(stringItems);
14548f512ceSopenharmony_ci    } else {
14648f512ceSopenharmony_ci        std::string itemsString;
14748f512ceSopenharmony_ci        const std::string split = ",";
14848f512ceSopenharmony_ci        for (auto item : items) {
14948f512ceSopenharmony_ci            if (!itemsString.empty())
15048f512ceSopenharmony_ci                itemsString.append(split);
15148f512ceSopenharmony_ci            if constexpr (std::is_same<T, std::string>::value) {
15248f512ceSopenharmony_ci                itemsString.append(item);
15348f512ceSopenharmony_ci            } else {
15448f512ceSopenharmony_ci                itemsString.append(std::to_string(item));
15548f512ceSopenharmony_ci            }
15648f512ceSopenharmony_ci        }
15748f512ceSopenharmony_ci        if (itemsString.empty())
15848f512ceSopenharmony_ci            itemsString.append("<empty>");
15948f512ceSopenharmony_ci        return itemsString;
16048f512ceSopenharmony_ci    }
16148f512ceSopenharmony_ci}
16248f512ceSopenharmony_ci
16348f512ceSopenharmony_cistd::string BufferToHexString(const std::vector<unsigned char> &vec);
16448f512ceSopenharmony_cistd::string BufferToHexString(const unsigned char buf[], size_t size);
16548f512ceSopenharmony_civoid HexDump(const void *buf, size_t size, size_t max_size = 0);
16648f512ceSopenharmony_ci
16748f512ceSopenharmony_cistd::string &StringTrim(std::string &s);
16848f512ceSopenharmony_ci
16948f512ceSopenharmony_cistd::vector<std::string> StringSplit(std::string source, const std::string &split = ",");
17048f512ceSopenharmony_ci
17148f512ceSopenharmony_cisize_t SubStringCount(const std::string &source, const std::string &sub);
17248f512ceSopenharmony_ci
17348f512ceSopenharmony_cibool StringStartsWith(const std::string &string, const std::string &with);
17448f512ceSopenharmony_ci
17548f512ceSopenharmony_cibool StringEndsWith(const std::string &string, const std::string &with);
17648f512ceSopenharmony_ci
17748f512ceSopenharmony_cibool IsSameCommand(const std::string &cmdLine, const std::string &cmdName);
17848f512ceSopenharmony_ci
17948f512ceSopenharmony_cistd::vector<pid_t> GetSubthreadIDs(const pid_t pid);
18048f512ceSopenharmony_ci
18148f512ceSopenharmony_cibool IsDigits(const std::string &str);
18248f512ceSopenharmony_ci
18348f512ceSopenharmony_cibool IsHexDigits(const std::string &str);
18448f512ceSopenharmony_ci
18548f512ceSopenharmony_ciconstexpr const int COMPRESS_READ_BUF_SIZE = 4096;
18648f512ceSopenharmony_ci// compress specified dataFile into gzip file
18748f512ceSopenharmony_cibool CompressFile(const std::string &dataFile, const std::string &destFile);
18848f512ceSopenharmony_ci// uncompress specified gzip file into dataFile
18948f512ceSopenharmony_cibool UncompressFile(const std::string &gzipFile, const std::string &dataFile);
19048f512ceSopenharmony_ci
19148f512ceSopenharmony_citemplate<typename... VA>
19248f512ceSopenharmony_cistd::string StringPrintf(const char *stringFormat, VA... args)
19348f512ceSopenharmony_ci{
19448f512ceSopenharmony_ci    // check howmany bytes we need
19548f512ceSopenharmony_ci    char bytes[DEFAULT_STRING_BUF_SIZE];
19648f512ceSopenharmony_ci    bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0';
19748f512ceSopenharmony_ci
19848f512ceSopenharmony_ci    if (stringFormat == nullptr) {
19948f512ceSopenharmony_ci        return EMPTY_STRING;
20048f512ceSopenharmony_ci    }
20148f512ceSopenharmony_ci
20248f512ceSopenharmony_ci    // print it to bytes
20348f512ceSopenharmony_ci    if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat,
20448f512ceSopenharmony_ci                   args...) < 0) {
20548f512ceSopenharmony_ci        return EMPTY_STRING;
20648f512ceSopenharmony_ci    }
20748f512ceSopenharmony_ci
20848f512ceSopenharmony_ci    // make a string return
20948f512ceSopenharmony_ci    return std::string(bytes);
21048f512ceSopenharmony_ci}
21148f512ceSopenharmony_ci
21248f512ceSopenharmony_ci// path check
21348f512ceSopenharmony_cistd::vector<std::string> GetEntriesInDir(const std::string &basePath);
21448f512ceSopenharmony_ci
21548f512ceSopenharmony_cistd::vector<std::string> GetSubDirs(const std::string &basePath);
21648f512ceSopenharmony_cistd::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map);
21748f512ceSopenharmony_ci
21848f512ceSopenharmony_cibool IsDir(const std::string &path);
21948f512ceSopenharmony_ci
22048f512ceSopenharmony_cibool IsPath(const std::string &fileName);
22148f512ceSopenharmony_ci
22248f512ceSopenharmony_cibool LittleMemory();
22348f512ceSopenharmony_ci
22448f512ceSopenharmony_ci#if defined(is_mingw) && is_mingw
22548f512ceSopenharmony_ciconst char PATH_SEPARATOR = '\\';
22648f512ceSopenharmony_ci#else
22748f512ceSopenharmony_ciconst char PATH_SEPARATOR = '/';
22848f512ceSopenharmony_ci#endif
22948f512ceSopenharmony_ciconst std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR);
23048f512ceSopenharmony_ci
23148f512ceSopenharmony_cistd::string PlatformPathConvert(const std::string &path);
23248f512ceSopenharmony_ci
23348f512ceSopenharmony_ci// attribute
23448f512ceSopenharmony_ci#define PACKED __attribute__((packed))
23548f512ceSopenharmony_ci
23648f512ceSopenharmony_ci// data align
23748f512ceSopenharmony_ci
23848f512ceSopenharmony_ci// some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu
23948f512ceSopenharmony_ci#define HIPERF_BUF_ALIGN alignas(64)
24048f512ceSopenharmony_ci
24148f512ceSopenharmony_ci#define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1)))
24248f512ceSopenharmony_ci
24348f512ceSopenharmony_ciuint32_t RoundUp(uint32_t x, const int align);
24448f512ceSopenharmony_ci
24548f512ceSopenharmony_ci// data convert function
24648f512ceSopenharmony_citemplate<class T>
24748f512ceSopenharmony_cistd::string ToHex(const T &source, int size = sizeof(T), bool prefix = false)
24848f512ceSopenharmony_ci{
24948f512ceSopenharmony_ci    std::stringstream ss;
25048f512ceSopenharmony_ci    if (prefix) {
25148f512ceSopenharmony_ci        ss << "0x";
25248f512ceSopenharmony_ci    }
25348f512ceSopenharmony_ci    ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source;
25448f512ceSopenharmony_ci    return ss.str();
25548f512ceSopenharmony_ci}
25648f512ceSopenharmony_ci
25748f512ceSopenharmony_ci// data move and copy
25848f512ceSopenharmony_citemplate<class S, class T>
25948f512ceSopenharmony_cisize_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0)
26048f512ceSopenharmony_ci{
26148f512ceSopenharmony_ci    if (size == 0) {
26248f512ceSopenharmony_ci        size = sizeof(T);
26348f512ceSopenharmony_ci    }
26448f512ceSopenharmony_ci    if (memcpy_s(dest, size, buffer, size) != EOK) {
26548f512ceSopenharmony_ci        return size;
26648f512ceSopenharmony_ci    }
26748f512ceSopenharmony_ci    buffer = buffer + size;
26848f512ceSopenharmony_ci    return size;
26948f512ceSopenharmony_ci}
27048f512ceSopenharmony_ci
27148f512ceSopenharmony_ci// file read write
27248f512ceSopenharmony_cibool ReadIntFromProcFile(const std::string &path, int &value);
27348f512ceSopenharmony_cibool WriteIntToProcFile(const std::string &path, int value);
27448f512ceSopenharmony_cistd::string ReadFileToString(const std::string &fileName);
27548f512ceSopenharmony_cibool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0);
27648f512ceSopenharmony_cibool WriteStringToFile(const std::string &fileName, const std::string &value);
27748f512ceSopenharmony_ci
27848f512ceSopenharmony_ci// stdout
27948f512ceSopenharmony_ciclass StdoutRecord {
28048f512ceSopenharmony_cipublic:
28148f512ceSopenharmony_ci    ~StdoutRecord()
28248f512ceSopenharmony_ci    {
28348f512ceSopenharmony_ci        Stop(); // stdout need restore
28448f512ceSopenharmony_ci    }
28548f512ceSopenharmony_ci    StdoutRecord(const std::string &tempFile = EMPTY_STRING,
28648f512ceSopenharmony_ci                 const std::string &mode = EMPTY_STRING);
28748f512ceSopenharmony_ci
28848f512ceSopenharmony_ci    bool Start();
28948f512ceSopenharmony_ci    std::string Stop();
29048f512ceSopenharmony_ci
29148f512ceSopenharmony_ciprivate:
29248f512ceSopenharmony_ci    OHOS::UniqueFd stdoutFile_;       // back and restore stdout
29348f512ceSopenharmony_ci    std::FILE *recordFile_ = nullptr; // save the output
29448f512ceSopenharmony_ci    bool stop_ = true;
29548f512ceSopenharmony_ci    std::string content_ = EMPTY_STRING;
29648f512ceSopenharmony_ci};
29748f512ceSopenharmony_ci
29848f512ceSopenharmony_ci// misc
29948f512ceSopenharmony_citemplate<class T>
30048f512ceSopenharmony_cifloat Percentage(const T &a, const T &b)
30148f512ceSopenharmony_ci{
30248f512ceSopenharmony_ci    if (b == 0) {
30348f512ceSopenharmony_ci        return 0;
30448f512ceSopenharmony_ci    }
30548f512ceSopenharmony_ci    return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE;
30648f512ceSopenharmony_ci}
30748f512ceSopenharmony_ci
30848f512ceSopenharmony_cibool IsRoot();
30948f512ceSopenharmony_cibool IsBeta();
31048f512ceSopenharmony_cibool IsAllowProfilingUid();
31148f512ceSopenharmony_cibool IsHiviewCall();
31248f512ceSopenharmony_cibool PowerOfTwo(uint64_t n);
31348f512ceSopenharmony_ci
31448f512ceSopenharmony_ciconst std::string HMKERNEL = "HongMeng";
31548f512ceSopenharmony_ci
31648f512ceSopenharmony_ci#define PRINT_INDENT(indent, format, ...)                                                          \
31748f512ceSopenharmony_ci    if (indent >= 0) {                                                                             \
31848f512ceSopenharmony_ci        if (g_outputDump == nullptr) {                                                             \
31948f512ceSopenharmony_ci            printf("%*s" format, (indent)*2, "", ##__VA_ARGS__);                                   \
32048f512ceSopenharmony_ci        } else {                                                                                   \
32148f512ceSopenharmony_ci            fprintf(g_outputDump, "%*s" format, (indent)*2, "", ##__VA_ARGS__);                    \
32248f512ceSopenharmony_ci        }                                                                                          \
32348f512ceSopenharmony_ci    } else {                                                                                       \
32448f512ceSopenharmony_ci        HLOGV("%s" format, "", ##__VA_ARGS__);                                                     \
32548f512ceSopenharmony_ci    }
32648f512ceSopenharmony_ci
32748f512ceSopenharmony_ci#ifndef MMAP_FAILED
32848f512ceSopenharmony_ci#define MMAP_FAILED reinterpret_cast<void *>(-1)
32948f512ceSopenharmony_ci#endif
33048f512ceSopenharmony_ci#ifndef MAP_FAILED
33148f512ceSopenharmony_ci#define MAP_FAILED MMAP_FAILED
33248f512ceSopenharmony_ci#endif
33348f512ceSopenharmony_cipid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs,
33448f512ceSopenharmony_ci                       const uint64_t waitAppTimeOut);
33548f512ceSopenharmony_cibool IsRestarted(const std::string &appPackage);
33648f512ceSopenharmony_civoid CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage);
33748f512ceSopenharmony_cibool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs);
33848f512ceSopenharmony_cibool IsExistDebugByApp(const std::string& bundleName);
33948f512ceSopenharmony_cibool IsExistDebugByPid(const std::vector<pid_t> &pids);
34048f512ceSopenharmony_cibool IsDebugableApp(const std::string& bundleName);
34148f512ceSopenharmony_cibool IsSupportNonDebuggableApp();
34248f512ceSopenharmony_ciconst std::string GetUserType();
34348f512ceSopenharmony_cibool GetDeveloperMode();
34448f512ceSopenharmony_cibool IsArkJsFile(const std::string& filepath);
34548f512ceSopenharmony_cistd::string GetProcessName(int pid);
34648f512ceSopenharmony_cibool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize);
34748f512ceSopenharmony_cibool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname);
34848f512ceSopenharmony_cibool IsApplicationEncryped(const int pid);
34948f512ceSopenharmony_ci
35048f512ceSopenharmony_citemplate <typename Func>
35148f512ceSopenharmony_ciclass ScopeGuard {
35248f512ceSopenharmony_cipublic:
35348f512ceSopenharmony_ci    explicit ScopeGuard(Func&& fn)
35448f512ceSopenharmony_ci        : fn_(fn) {}
35548f512ceSopenharmony_ci    ~ScopeGuard()
35648f512ceSopenharmony_ci    {
35748f512ceSopenharmony_ci        fn_();
35848f512ceSopenharmony_ci    }
35948f512ceSopenharmony_ciprivate:
36048f512ceSopenharmony_ci    Func fn_;
36148f512ceSopenharmony_ci};
36248f512ceSopenharmony_ci
36348f512ceSopenharmony_cistruct ScopeGuardOnExit {};
36448f512ceSopenharmony_citemplate <typename Func>
36548f512ceSopenharmony_cistatic inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn)
36648f512ceSopenharmony_ci{
36748f512ceSopenharmony_ci    return ScopeGuard<Func>(std::forward<Func>(fn));
36848f512ceSopenharmony_ci}
36948f512ceSopenharmony_ci
37048f512ceSopenharmony_ci#define ON_SCOPE_EXIT \
37148f512ceSopenharmony_ci        auto __onGuardExit__ = ScopeGuardOnExit{} + [&]
37248f512ceSopenharmony_ci} // namespace HiPerf
37348f512ceSopenharmony_ci} // namespace Developtools
37448f512ceSopenharmony_ci} // namespace OHOS
37548f512ceSopenharmony_ci#endif // HIPERF_UTILITIES_H_
376