1 /*
2  * Copyright (c) 2024 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 NATIVE_CONVERT_JSON_H
17 #define NATIVE_CONVERT_JSON_H
18 
19 #include "ecmascript/log_wrapper.h"
20 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
21 #include "third_party/cJSON/cJSON.h"
22 
23 namespace native {
24 using namespace panda::ecmascript::pgo;
25 class JsonConverter {
26 public:
ConvertStr(const std::vector<ProfileType::StringMap>& data) const27     cJSON* ConvertStr(const std::vector<ProfileType::StringMap>& data) const
28     {
29         return HandleMapVector(data);
30     }
31 
Convert(const std::vector<ProfileType::jModuleType>& data) const32     cJSON* Convert(const std::vector<ProfileType::jModuleType>& data) const
33     {
34         cJSON* jsonArray = cJSON_CreateArray();
35         if (jsonArray == nullptr) {
36             return nullptr;
37         }
38         for (const auto& complexMap : data) {
39             cJSON* jsonObject = cJSON_CreateObject();
40             if (jsonObject == nullptr) {
41                 return nullptr;
42             }
43             for (const auto& [key, value] : complexMap) {
44                 cJSON* jsonValue = HandleVariant(value);
45                 if (jsonValue == nullptr) {
46                     return nullptr;
47                 }
48                 cJSON_AddItemToObject(jsonObject, key.c_str(), jsonValue);
49             }
50             cJSON_AddItemToArray(jsonArray, jsonObject);
51         }
52         return jsonArray;
53     }
54 
55 private:
HandleVariant(const std::variant<std::string, std::vector<ProfileType::VariantMap>>& value) const56     cJSON* HandleVariant(const std::variant<std::string, std::vector<ProfileType::VariantMap>>& value) const
57     {
58         if (std::holds_alternative<std::string>(value)) {
59             return cJSON_CreateString(std::get<std::string>(value).c_str());
60         } else if (std::holds_alternative<std::vector<ProfileType::VariantMap>>(value)) {
61             return HandleVariantMap(std::get<std::vector<ProfileType::VariantMap>>(value));
62         }
63         return nullptr;
64     }
65 
HandleVariantMap(const std::vector<ProfileType::VariantMap>& vaMap) const66     cJSON* HandleVariantMap(const std::vector<ProfileType::VariantMap>& vaMap) const
67     {
68         cJSON* jsonArray = cJSON_CreateArray();
69         if (jsonArray == nullptr) {
70             return nullptr;
71         }
72         for (const auto& nestedItem : vaMap) {
73             cJSON* mapObject = cJSON_CreateObject();
74             if (mapObject == nullptr) {
75                 return nullptr;
76             }
77             for (const auto& [key, value] : nestedItem) {
78                 cJSON* jsonValue = HandleVariantNext(value);
79                 if (jsonValue == nullptr) {
80                     return nullptr;
81                 }
82                 cJSON_AddItemToObject(mapObject, key.c_str(), jsonValue);
83             }
84             cJSON_AddItemToArray(jsonArray, mapObject);
85         }
86         return jsonArray;
87     }
88 
HandleVariantNext(const std::variant<std::string, ProfileType::VariantVector>& value) const89     cJSON* HandleVariantNext(const std::variant<std::string, ProfileType::VariantVector>& value) const
90     {
91         if (std::holds_alternative<std::string>(value)) {
92             return cJSON_CreateString(std::get<std::string>(value).c_str());
93         } else if (std::holds_alternative<ProfileType::VariantVector>(value)) {
94             return HandleVariantVector(std::get<ProfileType::VariantVector>(value));
95         }
96         return nullptr;
97     }
98 
HandleVariantVector(const ProfileType::VariantVector& vec) const99     cJSON* HandleVariantVector(const ProfileType::VariantVector& vec) const
100     {
101         cJSON* jsonArray = cJSON_CreateArray();
102         if (jsonArray == nullptr) {
103             return nullptr;
104         }
105         for (const auto& nestedItem : vec) {
106             if (std::holds_alternative<ProfileType::StringMap>(nestedItem)) {
107                 cJSON* mapObject = HandleStringMap(std::get<ProfileType::StringMap>(nestedItem));
108                 cJSON_AddItemToArray(jsonArray, mapObject);
109             } else if (std::holds_alternative<ProfileType::MapVector>(nestedItem)) {
110                 cJSON* innerInnerArray = HandleNestedMapVector(std::get<ProfileType::MapVector>(nestedItem));
111                 cJSON_AddItemToArray(jsonArray, innerInnerArray);
112             } else if (std::holds_alternative<std::vector<ProfileType::StringMap>>(nestedItem)) {
113                 cJSON* arrayOfMaps = HandleMapVector(std::get<std::vector<ProfileType::StringMap>>(nestedItem));
114                 cJSON_AddItemToArray(jsonArray, arrayOfMaps);
115             }
116         }
117         return jsonArray;
118     }
119 
HandleStringMap(const ProfileType::StringMap& stringMap) const120     cJSON* HandleStringMap(const ProfileType::StringMap& stringMap) const
121     {
122         cJSON* mapObject = cJSON_CreateObject();
123         if (mapObject == nullptr) {
124             return nullptr;
125         }
126         for (const auto& [mapKey, mapValue] : stringMap) {
127             cJSON_AddStringToObject(mapObject, mapKey.c_str(), mapValue.c_str());
128         }
129         return mapObject;
130     }
131 
HandleMapVector(const std::vector<ProfileType::StringMap>& vecMap) const132     cJSON* HandleMapVector(const std::vector<ProfileType::StringMap>& vecMap) const
133     {
134         cJSON* arrayOfMaps = cJSON_CreateArray();
135         if (arrayOfMaps == nullptr) {
136             return nullptr;
137         }
138         for (const auto& stringMap : vecMap) {
139             cJSON* mapObject = HandleStringMap(stringMap);
140             if (mapObject == nullptr) {
141                 return nullptr;
142             }
143             cJSON_AddItemToArray(arrayOfMaps, mapObject);
144         }
145         return arrayOfMaps;
146     }
147 
HandleNestedMapVector(const ProfileType::MapVector& vecVec) const148     cJSON* HandleNestedMapVector(const ProfileType::MapVector& vecVec) const
149     {
150         cJSON* innerInnerArray = cJSON_CreateArray();
151         if (innerInnerArray == nullptr) {
152             return nullptr;
153         }
154         for (const auto& vec1 : vecVec) {
155             cJSON* innerArray = cJSON_CreateArray();
156             if (innerArray == nullptr) {
157                 return nullptr;
158             }
159             for (const auto& stringMap : vec1) {
160                 cJSON* mapObject = HandleStringMap(stringMap);
161                 if (mapObject == nullptr) {
162                     return nullptr;
163                 }
164                 cJSON_AddItemToArray(innerArray, mapObject);
165             }
166             cJSON_AddItemToArray(innerInnerArray, innerArray);
167         }
168         return innerInnerArray;
169     }
170 };
171 } // namespace native
172 #endif // NATIVE_CONVERT_JSON_H
173