1/*
2 * Copyright (c) 2021-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 ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
17#define ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
18
19#include <fstream>
20#include <limits.h>
21#include <sstream>
22
23#include "ecmascript/dfx/hprof/file_stream.h"
24#include "ecmascript/mem/c_containers.h"
25#include "ecmascript/mem/c_string.h"
26
27#include "securec.h"
28
29namespace panda::ecmascript {
30using fstream = std::fstream;
31using stringstream = std::stringstream;
32
33class HeapSnapshot;
34class TraceNode;
35
36class StreamWriter {
37public:
38    explicit StreamWriter(Stream *stream)
39        : stream_(stream), chunkSize_(stream->GetSize()), chunk_(chunkSize_), current_(0)
40    {
41    }
42
43    void WriteString(const CString &str)
44    {
45        auto len = str.size();
46        ASSERT(len <= static_cast<size_t>(INT_MAX));
47        if (len == 0) {
48            return;
49        }
50        const char *cur = str.c_str();
51        const char *end = cur + len;
52        while (cur < end) {
53            int dstSize = chunkSize_ - current_;
54            int writeSize = std::min(static_cast<int>(end - cur), dstSize);
55            ASSERT(writeSize > 0);
56            if (memcpy_s(chunk_.data() + current_, dstSize, cur, writeSize) != EOK) {
57                LOG_FULL(FATAL) << "memcpy_s failed";
58            }
59            cur += writeSize;
60            current_ += writeSize;
61            MaybeWriteChunk();
62        }
63    }
64
65    void WriteChar(char c)
66    {
67        ASSERT(c != '\0');
68        ASSERT(current_ < chunkSize_);
69        chunk_[current_++] = c;
70        MaybeWriteChunk();
71    }
72
73    void WriteNumber(uint64_t num)
74    {
75        WriteString(ToCString(num));
76    }
77
78    void End()
79    {
80        if (current_ > 0) {
81            WriteChunk();
82        }
83        stream_->EndOfStream();
84    }
85
86private:
87    void MaybeWriteChunk()
88    {
89        ASSERT(current_ <= chunkSize_);
90        if (current_ == chunkSize_) {
91            WriteChunk();
92        }
93    }
94
95    void WriteChunk()
96    {
97        stream_->WriteChunk(chunk_.data(), current_);
98        current_ = 0;
99    }
100
101    Stream *stream_ {nullptr};
102    int chunkSize_ {0};
103    CVector<char> chunk_;
104    int current_ {0};
105};
106
107class HeapSnapshotJSONSerializer {
108public:
109    explicit HeapSnapshotJSONSerializer() = default;
110    ~HeapSnapshotJSONSerializer() = default;
111    NO_MOVE_SEMANTIC(HeapSnapshotJSONSerializer);
112    NO_COPY_SEMANTIC(HeapSnapshotJSONSerializer);
113    static bool Serialize(HeapSnapshot *snapshot, Stream *stream);
114    static void DumpStringTable(HeapSnapshot *snapshot, Stream *stream);
115
116private:
117    static constexpr char ASCII_US = 31;
118    static constexpr char ASCII_DEL = 127;
119    static constexpr uint8_t UTF8_MAX_BYTES = 4;
120
121private:
122    static void SerializeSnapshotHeader(HeapSnapshot *snapshot, StreamWriter *writer);
123    static void SerializeNodes(HeapSnapshot *snapshot, StreamWriter *writer);
124    static void SerializeEdges(HeapSnapshot *snapshot, StreamWriter *writer);
125    static void SerializeTraceFunctionInfo(HeapSnapshot *snapshot, StreamWriter *writer);
126    static void SerializeTraceTree(HeapSnapshot *snapshot, StreamWriter *writer);
127    static void SerializeTraceNode(TraceNode *node, StreamWriter *writer);
128    static void SerializeSamples(HeapSnapshot *snapshot, StreamWriter *writer);
129    static void SerializeLocations(StreamWriter *writer);
130    static void SerializeStringTable(HeapSnapshot *snapshot, StreamWriter *writer);
131    static void SerializeString(CString *str, StreamWriter *writer);
132    static void SerializeUnicodeChar(uint32_t unicodeChar, StreamWriter *writer);
133    static void SerializerSnapshotClosure(StreamWriter *writer);
134};
135}  // namespace panda::ecmascript
136#endif  // ECMASCRIPT_DFX_HPROF_HEAP_SNAPSHOT_SERIALIZER_H
137