/** * Copyright (C) 2015-2018 * All rights reserved. * * AUTHOR(S) * E-mail: "fuwangqini" niukey@qq.com * 2017.5.13 fixed one bug by "lindawei" <672496008@qq.com> * * VERSION * Sat 08 Oct 2016 09:07:14 PM CST */ #pragma once #include #include "acl_cpp/acl_cpp_define.hpp" #include "acl_cpp/stdlib/string.hpp" #include "acl_cpp/stdlib/json.hpp" #include "acl_cpp/stdlib/string.hpp" namespace acl { ///////////////////////////////////type_traits//////////////////////////////// struct true_type { static const bool value = true; }; struct false_type { static const bool value = false; }; template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; template struct remove_volatile { typedef T type; }; template struct remove_volatile { typedef T type; }; template struct remove_cv { typedef typename remove_const ::type>::type type; }; //remove_pointer template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; template struct enable_if { }; template struct enable_if { typedef T type; }; //_Is_number template struct _Is_number : false_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; #if 0 template<> struct _Is_number : true_type { }; template<> struct _Is_number : true_type { }; #endif template struct is_number : _Is_number::type> { }; //string template struct _Is_string : false_type { }; template<> struct _Is_string : true_type { }; template<> struct _Is_string : true_type { }; template struct is_string : _Is_string::type> { }; //double template struct _Is_double : false_type { }; template<> struct _Is_double : true_type { }; template<> struct _Is_double : true_type { }; template<> struct _Is_double : true_type { }; template struct is_double : _Is_double::type> { }; //char ptr. c string in cpp template struct _Is_char_ptr : false_type { }; template<> struct _Is_char_ptr : true_type { }; template struct is_char_ptr :_Is_char_ptr::type> { }; template struct _Is_bool : false_type { }; template<> struct _Is_bool : true_type { }; template struct is_bool : _Is_bool::type> { }; template struct _Is_object :false_type { }; template<> struct _Is_object : true_type { }; template struct is_object : _Is_object< !is_string::value && !is_double::value && !is_number::value && !is_bool::value && !is_char_ptr::value> { }; template static inline bool check_nullptr(T&) { return false; } template static inline bool check_nullptr(T *t) { if (t == NULL) return true; return false; } //acl::string ,std::string template typename enable_if::value, const char *>::type static inline get_value(const T &value) { return value.c_str(); } template typename enable_if::value, const char *>::type static inline get_value(const T *value) { return value->c_str(); } //char *,const char * static inline const char *get_value(const char *value) { return value; } //bool static inline bool get_value(const bool value) { return value; } static inline bool get_value(const bool* value) { return *value; } //number template typename enable_if::value, T>::type static inline get_value(const T t) { return t; } // number pointor -> number // eg: int * -> int . template typename enable_if::value, T>::type static inline get_value(const T *t) { return *t; } template typename enable_if::value, T>::type static inline get_value(const T &t) { return t; } template typename enable_if::value, T>::type static inline get_value(const T *t) { return *t; } // obj template typename enable_if::value, void>::type static inline add_item(acl::json &json, acl::json_node &node, const T &obj) { if(check_nullptr(obj)) node.add_array_null(); else node.add_child(gson(json, obj)); } // number template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T value) { node.add_array_number(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T *value) { if (check_nullptr(value)) node.add_array_null(); else node.add_array_number(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T value) { node.add_array_double(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T* value) { if(check_nullptr(value)) node.add_array_null(); else node.add_array_double(get_value(value)); } //bool template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T *value) { if (check_nullptr(value)) node.add_array_null(); else node.add_array_bool(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T value) { node.add_array_bool(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T value) { node.add_array_text(get_value(value)); } template typename enable_if::value, void>::type static inline add_item(acl::json &, acl::json_node &node, T *value) { if (check_nullptr(value)) node.add_array_null(); else node.add_array_text(get_value(value)); } static inline void add_item(acl::json &, acl::json_node &node, char *value) { if (check_nullptr(value)) node.add_array_null(); else node.add_array_text(value); } //define list -->json template static inline acl::json_node &gson(acl::json &json, const std::list &objects) { acl::json_node &node = json.create_array(); for (typename std::list::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { add_item(json, node, *itr); } return node; } template static inline acl::json_node &gson(acl::json &json, const std::list *objects) { return gson(json, *objects); } //define vector -->json template static inline acl::json_node &gson(acl::json &json, const std::vector &objects) { acl::json_node &node = json.create_array(); for (typename std::vector::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { add_item(json, node, *itr); } return node; } template static inline acl::json_node &gson(acl::json &json, const std::vector *objects) { return gson(json, *objects); } //define set -->json template static inline acl::json_node &gson(acl::json &json, const std::set &objects) { acl::json_node &node = json.create_array(); for (typename std::set::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { add_item(json, node, *itr); } return node; } template static inline acl::json_node &gson(acl::json &json, const std::set *objects) { return gson(json, *objects); } //define number map template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map &objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_number(tag, get_value(itr->second))); } return node; } //define number map template typename enable_if< is_number::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map *objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects->begin(); itr != objects->end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_number(tag, get_value(itr->second))); } return node; } //define floating map template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map &objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_double(tag, get_value(itr->second))); } return node; } template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map *objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects->begin(); itr != objects->end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_double(tag, get_value(itr->second))); } return node; } //define bool map template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map &objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_bool(tag, itr->second)); } return node; } template typename enable_if::value || is_char_ptr::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map & objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_text(tag, get_value(itr->second))); } return node; } template typename enable_if::value || is_char_ptr::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map & objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else node.add_child(json.create_node() .add_text(tag, get_value(itr->second))); } return node; } template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map &objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else { acl::json_node &item = gson(json, itr->second); node.add_child(json.create_node() .add_child(tag, item)); } } return node; } template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map *objects) { return gson(json, *objects); } template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map &objects) { acl::json_node &node = json.create_array(); for (typename std::map::const_iterator itr = objects.begin(); itr != objects.end(); ++itr) { const char *tag = get_value(itr->first); if (check_nullptr(itr->second)) node.add_child(json.create_node().add_null(tag)); else { acl::json_node &item = gson(json, itr->second); node.add_child(json.create_node() .add_child(tag, item)); } } return node; } template typename enable_if::value, acl::json_node &>::type static inline gson(acl::json &json, const std::map *objects) { return gson(json, *objects); } ////////////////////////////////////////////////////////////////////////////// template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T **obj); template static inline void del(T **obj) { delete *obj; *obj = NULL; } template static inline void del(T *obj) { (void) obj; } //bool static inline std::pair gson(acl::json_node &node, bool *obj) { if (node.is_bool() == false) return std::make_pair(false, "get bool failed"); *obj = *node.get_bool(); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, bool **obj) { *obj = NULL; if (node.is_bool() == false) return std::make_pair(false, "get bool failed"); *obj = new bool; **obj = *node.get_bool(); return std::make_pair(true, ""); } //double template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T *obj) { if (node.is_double() == false) return std::make_pair(false, "get double failed"); *obj = static_cast(*node.get_double()); return std::make_pair(true, ""); } template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T **obj) { *obj = NULL; if (node.is_double() == false) return std::make_pair(false, "get double failed");; *obj = new T; **obj = static_cast(*node.get_double()); return std::make_pair(true, ""); } //intergral template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T *obj) { if (node.is_number() == false) return std::make_pair(false, "get number failed"); *obj = static_cast(*node.get_int64()); return std::make_pair(true, ""); } template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T **obj) { *obj = NULL; if (node.is_number() == false) return std::make_pair(false, "get number failed");; *obj = new T; **obj = static_cast(*node.get_int64()); return std::make_pair(true, ""); } //string static inline std::pair gson(acl::json_node &node, char **obj) { *obj = NULL; if (node.is_string() == false) return std::make_pair(false, "get char * string failed"); int len = (int) strlen(node.get_string()); *obj = new char[len + 1]; memcpy(*obj, node.get_string(), len); (*obj)[len] = 0; return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, acl::string &obj) { if (node.is_string() == false) return std::make_pair(false, "get string failed"); obj.clear(); obj.append(node.get_string()); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, acl::string *obj) { if (node.is_string() == false) return std::make_pair(false, "get string failed"); obj->clear(); obj->append(node.get_string()); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, acl::string **obj) { *obj = NULL; if (node.is_string() == false) return std::make_pair(false, "get string failed"); *obj = new acl::string; (*obj)->append(node.get_string()); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, std::string &obj) { if (node.is_string() == false) return std::make_pair(false, "get string failed"); obj.clear(); obj.append(node.get_string()); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, std::string *obj) { if (node.is_string() == false) return std::make_pair(false, "get string failed"); obj->clear(); obj->append(node.get_string()); return std::make_pair(true, ""); } static inline std::pair gson(acl::json_node &node, std::string **obj) { *obj = NULL; if (node.is_string() == false) return std::make_pair(false, "get string failed"); *obj = new std::string; (*obj)->append(node.get_string()); return std::make_pair(true, ""); } template std::pair static inline gson(acl::json_node &node, std::set *objs); template std::pair static inline gson(acl::json_node &node, std::set *objs); template static inline std::pair gson(acl::json_node &node, std::list *objs); template static inline std::pair gson(acl::json_node &node, std::list *objs); template std::pair static inline gson(acl::json_node &node, std::vector *objs); template std::pair static inline gson(acl::json_node &node, std::vector *objs); // list template static inline std::pair gson(acl::json_node &node, std::list *objs) { std::pair result; acl::json_node *itr = node.first_child(); while (itr) { // for avoiding object's member pointor copy, the obj can be // put in list first, when error happened just only erase it. // ---lindawei T obj; objs->push_back(obj); typename std::list::iterator it = objs->end(); --it; result = gson(*itr, *it); if (!result.first) { break; } itr = node.next_child(); } if (!result.first) objs->clear(); return result; } // list template static inline std::pair gson(acl::json_node &node, std::list *objs) { std::pair result(false, "null"); acl::json_node *itr = node.first_child(); while (itr) { // for avoiding object's member pointor copy // ---lindawei T* obj = NULL; result = gson(*itr, &obj); if (!result.first) { break; } acl_assert(obj); objs->push_back(obj); itr = node.next_child(); } if (!result.first) { for (typename std::list::iterator it = objs->begin(); it != objs->end(); it++) { del(&(*it)); } objs->clear(); } return result; } // vector template std::pair static inline gson(acl::json_node &node, std::vector *objs) { std::pair result(false," null"); acl::json_node *itr = node.first_child(); while (itr) { // for avoiding object's member pointor copy // ---lindawei T obj; objs->push_back(obj); typename std::vector::iterator it = objs->end(); --it; result = gson(*itr, &(*it)); if (!result.first) { break; } itr = node.next_child(); } if (!result.first) objs->clear(); return result; } // vector template std::pair static inline gson(acl::json_node &node, std::vector *objs) { std::pair result(false, ""); acl::json_node *itr = node.first_child(); while (itr) { T* obj = new T; objs->push_back(obj); typename std::vector::iterator it = objs->end(); --it; result = gson(*itr, &(*it)); if (!result.first) { break; } itr = node.next_child(); } if (!result.first) { for (typename std::vector::iterator it = objs->begin(); it != objs->end(); it++) { delete *it; } objs->clear(); } return result; } //set template std::pair static inline gson(acl::json_node &node, std::set *objs) { std::pair result(false," null"); acl::json_node *itr = node.first_child(); while (itr) { T obj; result = gson(*itr, &obj); objs->insert(obj); if (!result.first) { break; } itr = node.next_child(); } //clear objs; if (!result.first) { objs->clear(); } return result; } template static inline std::pair gson(acl::json_node &node, std::set *objs) { std::pair result(false, " null"); acl::json_node *itr = node.first_child(); while (itr) { T *obj = new T; result = gson(*itr, obj); objs->insert(obj); if (!result.first) { break; } itr = node.next_child(); } if (!result.first) { for (typename std::set::iterator it = objs->begin(); it != objs->end(); ++it) { //delete T delete *it; } objs->clear(); } return result; } template typename enable_if::value, std::pair >::type static inline gson(acl::json_node &node, T **obj) { *obj = new T(); std::pair result = gson(node, *obj); if (result.first == false) { delete *obj; *obj = NULL; } return result; } ///////////////////////////////////////////map//////////////////////////////// // int map template typename enable_if< is_string::value|| is_bool::value|| is_number::value|| is_double::value|| is_char_ptr::value, std::pair >::type static inline expand(acl::json_node &node, std::map *objs) { std::pair result(false, " null"); acl::json_node *itr = node.first_child(); while (itr) { T obj; result = gson(*itr, &obj); if (!result.first) break; objs->insert(std::make_pair(K(itr->tag_name()), obj)); itr = node.next_child(); } if (!result.first) { for (typename std::map::iterator it = objs->begin(); it != objs->end(); ++it) { del(&it->second); } objs->clear(); } return result; } template typename enable_if ::value , std::pair > ::type static inline expand(acl::json_node &node, std::map *objs) { std::pair result(false, "null"); acl::json_node *itr = node.first_child(); while (itr && itr->get_obj()) { T obj; result = gson(*(itr->get_obj()), &obj); if (!result.first) break; objs->insert(std::make_pair(K(itr->tag_name()), obj)); itr = node.next_child(); } if (!result.first) { for (typename std::map::iterator itr2 = objs->begin(); itr2 != objs->end(); ++itr2) { del(&itr2->second); } objs->clear(); } return result; } // map template std::pair static inline gson(acl::json_node &node, std::map *objs) { std::pair result(false," null"); acl::json_node *itr = node.first_child(); while (itr) { result = expand(*itr, objs); if (result.first == false) { break; } itr = node.next_child(); } return result; } template typename enable_if< is_string::value|| is_bool::value|| is_number::value|| is_double::value|| is_char_ptr::value, std::pair >::type static inline expand(acl::json_node &node, std::map *objs) { std::pair result(false, " null"); acl::json_node *itr = node.first_child(); while (itr) { T* obj = new T; //insert to objs first. // if gson failed .delete obj from objs objs->insert(std::make_pair(K(itr->tag_name()), obj)); result = gson(*itr, obj); if (!result.first) break; itr = node.next_child(); } if (!result.first) { for (typename std::map::iterator it = objs->begin(); it != objs->end(); ++it) { del(&it->second); } objs->clear(); } return result; } template typename enable_if ::value , std::pair > ::type static inline expand(acl::json_node &node, std::map *objs) { std::pair result; acl::json_node *itr = node.first_child(); while (itr && itr->get_obj()) { T* obj = new T; //insert to objs first. // if gson failed .delete obj from objs objs->insert(std::make_pair(K(itr->tag_name()), obj)); result = gson(*(itr->get_obj()), obj); if (!result.first) break; itr = node.next_child(); } if (!result.first) { for (typename std::map::iterator itr2 = objs->begin(); itr2 != objs->end(); ++itr2) { del(&itr2->second); } objs->clear(); } return result; } // map template std::pair static inline gson(acl::json_node &node, std::map *objs) { std::pair result; acl::json_node *itr = node.first_child(); std::string error_string; while (itr) { result = expand(*itr, objs); if (result.first == false) error_string.append(result.second); itr = node.next_child(); } return std::make_pair(!!!objs->empty(), error_string); } } // namespace acl