* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INPUT_METHOD_SERIALIZABLE_H
#define INPUT_METHOD_SERIALIZABLE_H
#include <string>
#include <unordered_set>
#include "cJSON.h"
#include "global.h"
namespace OHOS {
namespace MiscServices {
#ifndef GET_NAME
#define GET_NAME(value) #value
#endif
struct Serializable {
public:
virtual ~Serializable(){};
bool Unmarshall(const std::string &content);
bool Marshall(std::string &content) const;
virtual bool Unmarshal(cJSON *node)
{
return false;
}
virtual bool Marshal(cJSON *node) const
{
return false;
}
static bool GetValue(cJSON *node, const std::string &name, std::string &value);
static bool GetValue(cJSON *node, const std::string &name, int32_t &value);
static bool GetValue(cJSON *node, const std::string &name, uint32_t &value);
static bool GetValue(cJSON *node, const std::string &name, bool &value);
static bool GetValue(cJSON *node, const std::string &name, Serializable &value);
static bool GetValue(cJSON *node, const std::string &name, std::vector<std::vector<std::string>> &values);
template<typename T>
static bool GetKeys(cJSON *nodes, std::vector<std::string> &keys, const std::function<bool(T)> &filter = nullptr)
{
if (nodes == nullptr) {
IMSA_HILOGE("nodes nullptr");
return false;
}
cJSON *child = nodes->child;
bool result = true;
while (child != nullptr) {
std::string nodeKey = child->string;
T value;
bool ret = GetValue(child, "", value);
if (ret && (filter == nullptr || filter(value))) {
keys.push_back(nodeKey);
}
result = result && ret;
child = child->next;
}
return result;
}
template<typename T>
static bool GetValues(cJSON *nodes, std::vector<T> &values, const std::function<bool(T)> &filter = nullptr)
{
if (nodes == nullptr) {
IMSA_HILOGE("nodes nullptr");
return false;
}
cJSON *child = nodes->child;
bool result = true;
while (child != nullptr) {
std::string nodeKey = child->string;
T value;
bool ret = GetValue(child, "", value);
if (ret && (filter == nullptr || filter(value))) {
values.push_back(value);
}
result = result && ret;
child = child->next;
}
return result;
}
template<typename T>
static bool GetValue(cJSON *node, const std::string &name, std::vector<T> &values, int32_t maxNum = 0)
{
auto subNode = GetSubNode(node, name);
if (!cJSON_IsArray(subNode)) {
IMSA_HILOGE("not array");
return false;
}
auto size = cJSON_GetArraySize(subNode);
IMSA_HILOGD("size:%{public}d, maxNum:%{public}d", size, maxNum);
if (maxNum > 0 && size > maxNum) {
size = maxNum;
}
values.resize(size);
bool ret = true;
for (int32_t i = 0; i < size; i++) {
auto item = cJSON_GetArrayItem(subNode, i);
if (item == NULL) {
return false;
}
ret = GetValue(item, "", values[i]) && ret;
}
return ret;
}
template<typename T>
static bool GetValue(cJSON *node, const std::string &name, std::unordered_set<T> &values, int32_t maxNum = 0)
{
auto subNode = GetSubNode(node, name);
if (!cJSON_IsArray(subNode)) {
IMSA_HILOGE("not array");
return false;
}
auto size = cJSON_GetArraySize(subNode);
IMSA_HILOGD("size:%{public}d, maxNum:%{public}d", size, maxNum);
if (maxNum > 0 && size > maxNum) {
size = maxNum;
}
bool result = true;
for (int32_t i = 0; i < size; i++) {
auto item = cJSON_GetArrayItem(subNode, i);
if (item == NULL) {
return false;
}
T value;
bool ret = GetValue(item, "", value);
if (ret && !values.count(value)) {
values.insert(value);
}
result = ret && result;
}
return result;
}
static bool SetValue(cJSON *node, const std::string &name, const std::string &value);
static bool SetValue(cJSON *node, const std::string &name, const int32_t &value);
static bool SetValue(cJSON *node, const std::string &name, const bool &value);
static bool SetValue(cJSON *node, const std::string &name, const Serializable &value);
static bool SetValue(cJSON *node, const std::string &name, const std::vector<std::vector<std::string>> &values);
static bool SetValue(cJSON *node, const std::string &name, const std::vector<std::string> &values);
template<typename T> static bool SetValue(cJSON *node, const std::string &name, const std::vector<T> &values)
{
auto array = cJSON_CreateArray();
for (const auto &value : values) {
auto *item = cJSON_CreateObject();
auto ret = value.Marshal(item);
if (!ret || !cJSON_AddItemToArray(array, item)) {
cJSON_Delete(item);
}
}
auto ret = cJSON_AddItemToObject(node, name.c_str(), array);
if (!ret) {
cJSON_Delete(array);
}
return ret;
}
static cJSON *GetSubNode(cJSON *node, const std::string &name);
};
}
}
#endif