1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci 16fb299fa2Sopenharmony_ci#ifndef JSON_VISITOR_H 17fb299fa2Sopenharmony_ci#define JSON_VISITOR_H 18fb299fa2Sopenharmony_ci 19fb299fa2Sopenharmony_ci#include <type_traits> 20fb299fa2Sopenharmony_ci 21fb299fa2Sopenharmony_ci#include "json_node.h" 22fb299fa2Sopenharmony_ci#include "log/log.h" 23fb299fa2Sopenharmony_ci 24fb299fa2Sopenharmony_cinamespace Updater { 25fb299fa2Sopenharmony_citemplate<typename T> struct Traits; 26fb299fa2Sopenharmony_cienum Action { SETVAL, PRINTVAL }; 27fb299fa2Sopenharmony_cinamespace Detail { 28fb299fa2Sopenharmony_citemplate<typename Traits> 29fb299fa2Sopenharmony_ciconstexpr bool CheckTrait() 30fb299fa2Sopenharmony_ci{ 31fb299fa2Sopenharmony_ci bool res = true; 32fb299fa2Sopenharmony_ci for (int i = 0; i < Traits::COUNT; ++i) { 33fb299fa2Sopenharmony_ci res = res && Traits::MEMBER_KEY[i] != nullptr && std::string_view("") != Traits::MEMBER_KEY[i]; 34fb299fa2Sopenharmony_ci } 35fb299fa2Sopenharmony_ci return res; 36fb299fa2Sopenharmony_ci}; 37fb299fa2Sopenharmony_ci 38fb299fa2Sopenharmony_citemplate<Action action> 39fb299fa2Sopenharmony_cistruct MemberVisitor; 40fb299fa2Sopenharmony_ci 41fb299fa2Sopenharmony_citemplate<typename T, std::size_t idx> 42fb299fa2Sopenharmony_ciusing memberType = std::remove_reference_t<decltype(Traits<T>::template Get<idx>(std::declval<T&>()))>; 43fb299fa2Sopenharmony_ci 44fb299fa2Sopenharmony_citemplate<Action action> 45fb299fa2Sopenharmony_cistruct StructVisitor { 46fb299fa2Sopenharmony_ci template<typename T, std::size_t F, std::size_t... R> 47fb299fa2Sopenharmony_ci static bool VisitStruct(const JsonNode &node, const JsonNode &defaultNode, T &t, std::index_sequence<F, R...>) 48fb299fa2Sopenharmony_ci { 49fb299fa2Sopenharmony_ci static_assert(CheckTrait<Traits<T>>(), "Trait member key invalid, please check"); 50fb299fa2Sopenharmony_ci constexpr auto key = Traits<T>::MEMBER_KEY[F]; 51fb299fa2Sopenharmony_ci auto &FthMember = Traits<T>::template Get<F>(t); 52fb299fa2Sopenharmony_ci if (!MemberVisitor<action>::template VisitMember<memberType<T, F>>( 53fb299fa2Sopenharmony_ci node[key], defaultNode[key], FthMember, key)) { 54fb299fa2Sopenharmony_ci return false; 55fb299fa2Sopenharmony_ci } 56fb299fa2Sopenharmony_ci 57fb299fa2Sopenharmony_ci if constexpr (sizeof...(R) == 0) { 58fb299fa2Sopenharmony_ci return true; 59fb299fa2Sopenharmony_ci } else { // don't remove else, otherwise can't compile 60fb299fa2Sopenharmony_ci return VisitStruct(node, defaultNode, t, std::index_sequence<R...> {}); 61fb299fa2Sopenharmony_ci } 62fb299fa2Sopenharmony_ci } 63fb299fa2Sopenharmony_ci}; 64fb299fa2Sopenharmony_ci 65fb299fa2Sopenharmony_citemplate<> 66fb299fa2Sopenharmony_cistruct MemberVisitor<SETVAL> { 67fb299fa2Sopenharmony_ci // visit string, int, bool 68fb299fa2Sopenharmony_ci template<typename T, std::enable_if_t<Detail::G_IS_BASE_TYPE<T>, bool> = true> 69fb299fa2Sopenharmony_ci static bool VisitMember(const JsonNode &node, const JsonNode &defaultNode, T &obj, const char *key) 70fb299fa2Sopenharmony_ci { 71fb299fa2Sopenharmony_ci auto r = node.As<T>(); 72fb299fa2Sopenharmony_ci auto defaultR = defaultNode.As<T>(); 73fb299fa2Sopenharmony_ci if (!r.has_value() && !defaultR.has_value()) { 74fb299fa2Sopenharmony_ci LOG(ERROR) << key << " has not both default and non-default value!!!"; 75fb299fa2Sopenharmony_ci return false; 76fb299fa2Sopenharmony_ci } 77fb299fa2Sopenharmony_ci if (r) { 78fb299fa2Sopenharmony_ci obj = *r; 79fb299fa2Sopenharmony_ci return true; 80fb299fa2Sopenharmony_ci } 81fb299fa2Sopenharmony_ci if (defaultR) { 82fb299fa2Sopenharmony_ci obj = *defaultR; 83fb299fa2Sopenharmony_ci return true; 84fb299fa2Sopenharmony_ci } 85fb299fa2Sopenharmony_ci return false; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci // visit vector, T is std::vector<T::value_type> 88fb299fa2Sopenharmony_ci template<typename T, std::enable_if_t<Detail::G_IS_VECTOR<T>, bool> = true> 89fb299fa2Sopenharmony_ci static auto VisitMember(const JsonNode &node, const JsonNode &defaultNode, T &obj, const char *key) 90fb299fa2Sopenharmony_ci { 91fb299fa2Sopenharmony_ci if ((node.Type() != NodeType::UNKNOWN && node.Type() != NodeType::NUL && node.Type() != NodeType::ARRAY) || 92fb299fa2Sopenharmony_ci (defaultNode.Type() != NodeType::UNKNOWN && defaultNode.Type() != NodeType::NUL && 93fb299fa2Sopenharmony_ci defaultNode.Type() != NodeType::ARRAY)) { 94fb299fa2Sopenharmony_ci LOG(ERROR) << "Node type not matched with " << key; 95fb299fa2Sopenharmony_ci return false; 96fb299fa2Sopenharmony_ci } 97fb299fa2Sopenharmony_ci typename T::value_type ele {}; 98fb299fa2Sopenharmony_ci for (auto &subNode : node) { 99fb299fa2Sopenharmony_ci ele = {}; 100fb299fa2Sopenharmony_ci if (!VisitMember(subNode, {}, ele, "")) { 101fb299fa2Sopenharmony_ci return false; 102fb299fa2Sopenharmony_ci } 103fb299fa2Sopenharmony_ci obj.push_back(std::move(ele)); 104fb299fa2Sopenharmony_ci } 105fb299fa2Sopenharmony_ci for (auto &subNode : defaultNode) { 106fb299fa2Sopenharmony_ci ele = {}; 107fb299fa2Sopenharmony_ci // using subNode to contruct an element of i-th type of T 108fb299fa2Sopenharmony_ci if (!VisitMember(subNode, {}, ele, "")) { 109fb299fa2Sopenharmony_ci return false; 110fb299fa2Sopenharmony_ci } 111fb299fa2Sopenharmony_ci obj.push_back(std::move(ele)); 112fb299fa2Sopenharmony_ci } 113fb299fa2Sopenharmony_ci return true; 114fb299fa2Sopenharmony_ci } 115fb299fa2Sopenharmony_ci // visit struct 116fb299fa2Sopenharmony_ci template<typename T, std::enable_if_t<std::is_integral_v<decltype(Traits<T>::COUNT)>, bool> = true> 117fb299fa2Sopenharmony_ci static bool VisitMember(const JsonNode &node, const JsonNode &defaultNode, T &obj, const char *key) 118fb299fa2Sopenharmony_ci { 119fb299fa2Sopenharmony_ci return StructVisitor<SETVAL>::VisitStruct(node, defaultNode, obj, 120fb299fa2Sopenharmony_ci std::make_index_sequence<Traits<T>::COUNT> {}); 121fb299fa2Sopenharmony_ci } 122fb299fa2Sopenharmony_ci}; 123fb299fa2Sopenharmony_ci} // namespace Detail 124fb299fa2Sopenharmony_ci 125fb299fa2Sopenharmony_citemplate<Action act, typename T, std::enable_if_t<Detail::G_IS_VECTOR<T>, bool> = true> 126fb299fa2Sopenharmony_cibool Visit(const JsonNode &node, T &obj) 127fb299fa2Sopenharmony_ci{ 128fb299fa2Sopenharmony_ci static_assert(act == SETVAL, "only for setting stl vector without default node"); 129fb299fa2Sopenharmony_ci return Detail::MemberVisitor<act>::VisitMember(node, {}, obj, ""); 130fb299fa2Sopenharmony_ci} 131fb299fa2Sopenharmony_ci 132fb299fa2Sopenharmony_citemplate<Action act, typename T, std::enable_if_t<Detail::G_IS_NUM<decltype(Traits<T>::COUNT)>, bool> = true> 133fb299fa2Sopenharmony_cibool Visit(const JsonNode &node, const JsonNode &defaultNode, T &obj) 134fb299fa2Sopenharmony_ci{ 135fb299fa2Sopenharmony_ci static_assert(act == SETVAL, 136fb299fa2Sopenharmony_ci "Only for setting member of struct with default node!"); 137fb299fa2Sopenharmony_ci return Detail::StructVisitor<act>::VisitStruct(node, defaultNode, obj, 138fb299fa2Sopenharmony_ci std::make_index_sequence<Traits<T>::COUNT> {}); 139fb299fa2Sopenharmony_ci} 140fb299fa2Sopenharmony_ci 141fb299fa2Sopenharmony_citemplate<Action act, typename T, std::enable_if_t<Detail::G_IS_NUM<decltype(Traits<T>::COUNT)>, bool> = true> 142fb299fa2Sopenharmony_cibool Visit(const JsonNode &node, T &obj) 143fb299fa2Sopenharmony_ci{ 144fb299fa2Sopenharmony_ci static_assert(act == SETVAL, 145fb299fa2Sopenharmony_ci "Only for setting member of struct without default node!"); 146fb299fa2Sopenharmony_ci return Detail::StructVisitor<act>::VisitStruct(node, {}, obj, 147fb299fa2Sopenharmony_ci std::make_index_sequence<Traits<T>::COUNT> {}); 148fb299fa2Sopenharmony_ci} 149fb299fa2Sopenharmony_ci} // namespace Updater 150fb299fa2Sopenharmony_ci 151fb299fa2Sopenharmony_ci#endif 152