Browse Source

#修改命名空间

zxs 3 months ago
parent
commit
c547869463

+ 43 - 41
robot/robotics/application.hpp

@@ -14,48 +14,50 @@
 #include "utils.hpp"
 #include "logger.hpp"
 
-namespace robotics::v3 {
-    class application_base {
-    public:
-        virtual void run() = 0;
-        virtual void stop() = 0;
-    };
-    template<typename _Type>
-    class application {
-    public:
-        static int run(int argc, char* argv[]) {
-            int result = -2;
-            if (argc <= 0) {
-                result = -1;
+namespace robotics {
+    namespace v3 {
+        class application_base {
+        public:
+            virtual void run() = 0;
+            virtual void stop() = 0;
+        };
+        template<typename _Type>
+        class application {
+        public:
+            static int run(int argc, char* argv[]) {
+                int result = -2;
+                if (argc <= 0) {
+                    result = -1;
+                }
+                else if (0 == strcmp(argv[argc - 1], "run")) {
+                    LOG_INSTALL;
+                    instance()->app_->run();
+                    std::this_thread::sleep_for(std::chrono::seconds(0xffffff));
+                    instance()->app_->stop();
+                    result = 0;
+                }
+                else if (0 == strcmp(argv[argc - 1], "debug") || 0 == strcmp(argv[argc - 1], "cmakedebug")) {
+                    SET_CONSOLE_UTF8;
+                    if (argc >= 3 && 0 == strcmp(argv[argc - 1], "cmakedebug")) {
+                        std::filesystem::current_path(argv[argc - 2]);
+                    }
+                    instance()->app_->run();
+                    getchar();
+                    instance()->app_->stop();
+                    result = 0;
+                }
+                return result;
             }
-            else if (0 == strcmp(argv[argc - 1], "run")) {
-                LOG_INSTALL;
-                instance()->app_->run();
-                std::this_thread::sleep_for(std::chrono::seconds(0xffffff));
-                instance()->app_->stop();
-                result = 0;
+        private:
+            application() {
+                app_ = std::make_shared<_Type>();
             }
-            else if (0 == strcmp(argv[argc - 1], "debug") || 0 == strcmp(argv[argc - 1], "cmakedebug")) {
-                SET_CONSOLE_UTF8;
-                if (argc >= 3 && 0 == strcmp(argv[argc - 1], "cmakedebug")) {
-                    std::filesystem::current_path(argv[argc - 2]);
-                }
-                instance()->app_->run();
-                getchar();
-                instance()->app_->stop();
-                result = 0;
+            static application* instance() {
+                static application g_application;
+                return &g_application;
             }
-            return result;
-        }
-    private:
-        application() {
-            app_ = std::make_shared<_Type>();
-        }
-        static application* instance() {
-            static application g_application;
-            return &g_application;
-        }
-    private:
-        std::shared_ptr<application_base> app_;
-    };
+        private:
+            std::shared_ptr<application_base> app_;
+        };
+    }
 }

+ 52 - 50
robot/robotics/config.hpp

@@ -13,57 +13,59 @@
 #include <boost/property_tree/ptree.hpp>
 #include <boost/property_tree/ini_parser.hpp>
 
-namespace robotics::v3 {
-    class config {
-    public:
-        /**
-         * @brief 读取配置文件
-         * @tparam 返回值类型
-         * @param 配置段名称
-         * @param 配置键名称
-         * @param 默认值
-         * @param 文件名称
-         * @return 返回值
-        */
-        template<typename _Ret>
-        static _Ret read(std::string const& section, std::string const& key, _Ret dc = _Ret(), std::string const& filename = "./config/config.ini") {
-            boost::property_tree::ptree pt;
-            try {
-                boost::property_tree::ini_parser::read_ini(filename, pt);
-                dc = pt.get<_Ret>(section + "." + key, dc);
-            }
-            catch (...) {}
-            return dc;
-        }
-        /**
-         * @brief 读取配置文件
-         * @param 配置段名称
-         * @param 配置键名称
-         * @param 默认值
-         * @param 文件名称
-         * @return 返回值
-        */
-        static std::string read(std::string const& section, std::string const& key, const char* dc = "", std::string const& filename = "./config/config.ini") {
-            return read<std::string>(section, key, dc, filename);
-        }
-        /**
-         * @brief 写配置文件
-         * @tparam 值类型
-         * @param 返回值类型
-         * @param 配置段名称
-         * @param 配置值
-         * @param 文件名称
-        */
-        template<typename _Value>
-        static void write(std::string const& section, std::string const& key, _Value const& value, std::string const& filename = "./config/config.ini") {
-            try {
+namespace robotics {
+    namespace v3 {
+        class config {
+        public:
+            /**
+             * @brief 读取配置文件
+             * @tparam 返回值类型
+             * @param 配置段名称
+             * @param 配置键名称
+             * @param 默认值
+             * @param 文件名称
+             * @return 返回值
+            */
+            template<typename _Ret>
+            static _Ret read(std::string const& section, std::string const& key, _Ret dc = _Ret(), std::string const& filename = "./config/config.ini") {
                 boost::property_tree::ptree pt;
-                boost::property_tree::ini_parser::read_ini(filename, pt);
-                pt.put(section + "." + key, boost::str(boost::format("%1%") % value));
-                boost::property_tree::ini_parser::write_ini(filename, pt);
+                try {
+                    boost::property_tree::ini_parser::read_ini(filename, pt);
+                    dc = pt.get<_Ret>(section + "." + key, dc);
+                }
+                catch (...) {}
+                return dc;
+            }
+            /**
+             * @brief 读取配置文件
+             * @param 配置段名称
+             * @param 配置键名称
+             * @param 默认值
+             * @param 文件名称
+             * @return 返回值
+            */
+            static std::string read(std::string const& section, std::string const& key, const char* dc = "", std::string const& filename = "./config/config.ini") {
+                return read<std::string>(section, key, dc, filename);
             }
-            catch (...) {
+            /**
+             * @brief 写配置文件
+             * @tparam 值类型
+             * @param 返回值类型
+             * @param 配置段名称
+             * @param 配置值
+             * @param 文件名称
+            */
+            template<typename _Value>
+            static void write(std::string const& section, std::string const& key, _Value const& value, std::string const& filename = "./config/config.ini") {
+                try {
+                    boost::property_tree::ptree pt;
+                    boost::property_tree::ini_parser::read_ini(filename, pt);
+                    pt.put(section + "." + key, boost::str(boost::format("%1%") % value));
+                    boost::property_tree::ini_parser::write_ini(filename, pt);
+                }
+                catch (...) {
+                }
             }
-        }
-    };
+        };
+    }
 }

+ 360 - 358
robot/robotics/datetime.hpp

@@ -14,396 +14,398 @@
 #include <time.h>
 #include <chrono>
 
-namespace robotics::v3 {
-	class datetime {
-	public:
-		/**
-		 * @brief 默认构造
-		 */
-		datetime() {}
-		/**
-		 * @brief 时间戳构造
-		 * @param time
-		 */
-		datetime(time_t time) {
-			time_stamp_ = time;
-		}
-		/**
-		 * @brief 时间日期字符串构造
-		 * @param time
-		 */
-		datetime(std::string const& time) {
-			time_stamp_ = from_datetime(time).time_stamp_;
-		}
-		/**
-		 * @brief 时间日期字符串构造
-		 * @param time
-		 */
-		datetime(char const* time) {
-			time_stamp_ = from_datetime(time).time_stamp_;
-		}
-		/**
-		 * @brief 转时间日期字符串
-		 */
-		operator std::string() {
-			return to_string();
-		}
-		/**
-		 * @brief 时间戳
-		 */
-		operator time_t() {
-			return time_stamp();
-		}
-		/**
-		 * @brief tm
-		 */
-		operator std::tm() const {
-			std::tm t_time;
-			time_t time_stamp = time_stamp_ / 1000;
+namespace robotics {
+	namespace v3 {
+		class datetime {
+		public:
+			/**
+			 * @brief 默认构造
+			 */
+			datetime() {}
+			/**
+			 * @brief 时间戳构造
+			 * @param time
+			 */
+			datetime(time_t time) {
+				time_stamp_ = time;
+			}
+			/**
+			 * @brief 时间日期字符串构造
+			 * @param time
+			 */
+			datetime(std::string const& time) {
+				time_stamp_ = from_datetime(time).time_stamp_;
+			}
+			/**
+			 * @brief 时间日期字符串构造
+			 * @param time
+			 */
+			datetime(char const* time) {
+				time_stamp_ = from_datetime(time).time_stamp_;
+			}
+			/**
+			 * @brief 转时间日期字符串
+			 */
+			operator std::string() {
+				return to_string();
+			}
+			/**
+			 * @brief 时间戳
+			 */
+			operator time_t() {
+				return time_stamp();
+			}
+			/**
+			 * @brief tm
+			 */
+			operator std::tm() const {
+				std::tm t_time;
+				time_t time_stamp = time_stamp_ / 1000;
 #ifdef WINDOWS_BUILD
-			::localtime_s(&t_time, &time_stamp);
+				::localtime_s(&t_time, &time_stamp);
 #elif LINUX_BUILD
-			::localtime_r(&time_stamp, &t_time);
+				::localtime_r(&time_stamp, &t_time);
 #endif
-			return t_time;
-		}
-		/**
-		 * @brief 时间戳
-		 * @return
-		 */
-		time_t time_stamp() const {
-			return time_stamp_;
-		}
-		/**
-		 * @brief 设置字符串输出格式
-		 * @param format
-		 */
-		void set_format(std::string const& format) {
-			format_ = format_;
-		}
-		/**
-		 * @brief 转字符串
-		 * @return
-		 */
-		std::string to_string() {
-			return to_string(format_);
-		}
-		/**
-		 * @brief 转字符串
-		 * @param format
-		 * @return
-		 */
-		std::string to_string(std::string const& format) {
-			std::string result = format;
-			std::tm t_time;
-			time_t time_stamp = time_stamp_;
-			int t_time_tm_msec = time_stamp % 1000;
-			time_stamp = time_stamp / 1000;
+				return t_time;
+			}
+			/**
+			 * @brief 时间戳
+			 * @return
+			 */
+			time_t time_stamp() const {
+				return time_stamp_;
+			}
+			/**
+			 * @brief 设置字符串输出格式
+			 * @param format
+			 */
+			void set_format(std::string const& format) {
+				format_ = format_;
+			}
+			/**
+			 * @brief 转字符串
+			 * @return
+			 */
+			std::string to_string() {
+				return to_string(format_);
+			}
+			/**
+			 * @brief 转字符串
+			 * @param format
+			 * @return
+			 */
+			std::string to_string(std::string const& format) {
+				std::string result = format;
+				std::tm t_time;
+				time_t time_stamp = time_stamp_;
+				int t_time_tm_msec = time_stamp % 1000;
+				time_stamp = time_stamp / 1000;
 #ifdef WINDOWS_BUILD
-			::localtime_s(&t_time, &time_stamp);
+				::localtime_s(&t_time, &time_stamp);
 #elif LINUX_BUILD
-			::localtime_r(&time_stamp, &t_time);
+				::localtime_r(&time_stamp, &t_time);
 #endif
-			//年
-			std::string year = std::to_string(t_time.tm_year + 1900);
-			{
-				size_t index = result.find("yyyy");
-				if (index != -1)
-					result.replace(index, 4, year);
-			}
-			//月
-			std::string mon = std::to_string(t_time.tm_mon + 1);
-			{
-				size_t index = result.find("MM");
-				if (index != -1)
+				//年
+				std::string year = std::to_string(t_time.tm_year + 1900);
 				{
-					result.replace(index, 2, mon.size() == 2 ? mon : "0" + mon);
-				}
-				else {
-					index = result.find("M");
+					size_t index = result.find("yyyy");
 					if (index != -1)
-						result.replace(index, 1, mon);
+						result.replace(index, 4, year);
 				}
-			}
-			//日
-			std::string day = std::to_string(t_time.tm_mday);
-			{
-				size_t index = result.find("dd");
-				if (index != -1)
+				//月
+				std::string mon = std::to_string(t_time.tm_mon + 1);
 				{
-					result.replace(index, 2, day.size() == 2 ? day : "0" + day);
-				}
-				else {
-					index = result.find("d");
+					size_t index = result.find("MM");
 					if (index != -1)
-						result.replace(index, 1, day);
+					{
+						result.replace(index, 2, mon.size() == 2 ? mon : "0" + mon);
+					}
+					else {
+						index = result.find("M");
+						if (index != -1)
+							result.replace(index, 1, mon);
+					}
 				}
-			}
-			//时
-			std::string hour = std::to_string(t_time.tm_hour);
-			{
-				size_t index = result.find("HH");
-				if (index != -1)
+				//日
+				std::string day = std::to_string(t_time.tm_mday);
 				{
-					result.replace(index, 2, hour.size() == 2 ? hour : "0" + hour);
-				}
-				else {
-					index = result.find("H");
+					size_t index = result.find("dd");
 					if (index != -1)
-						result.replace(index, 1, hour);
+					{
+						result.replace(index, 2, day.size() == 2 ? day : "0" + day);
+					}
+					else {
+						index = result.find("d");
+						if (index != -1)
+							result.replace(index, 1, day);
+					}
 				}
-			}
-			//分
-			std::string min = std::to_string(t_time.tm_min);
-			{
-				size_t index = result.find("mm");
-				if (index != -1)
+				//时
+				std::string hour = std::to_string(t_time.tm_hour);
 				{
-					result.replace(index, 2, min.size() == 2 ? min : "0" + min);
-				}
-				else {
-					index = result.find("m");
+					size_t index = result.find("HH");
 					if (index != -1)
-						result.replace(index, 1, min);
+					{
+						result.replace(index, 2, hour.size() == 2 ? hour : "0" + hour);
+					}
+					else {
+						index = result.find("H");
+						if (index != -1)
+							result.replace(index, 1, hour);
+					}
 				}
-			}
-			//秒
-			std::string sec = std::to_string(t_time.tm_sec);
-			{
-				size_t index = result.find("ss");
-				if (index != -1)
+				//分
+				std::string min = std::to_string(t_time.tm_min);
 				{
-					result.replace(index, 2, sec.size() == 2 ? sec : "0" + sec);
+					size_t index = result.find("mm");
+					if (index != -1)
+					{
+						result.replace(index, 2, min.size() == 2 ? min : "0" + min);
+					}
+					else {
+						index = result.find("m");
+						if (index != -1)
+							result.replace(index, 1, min);
+					}
 				}
-				else {
-					index = result.find("s");
+				//秒
+				std::string sec = std::to_string(t_time.tm_sec);
+				{
+					size_t index = result.find("ss");
 					if (index != -1)
-						result.replace(index, 1, sec);
+					{
+						result.replace(index, 2, sec.size() == 2 ? sec : "0" + sec);
+					}
+					else {
+						index = result.find("s");
+						if (index != -1)
+							result.replace(index, 1, sec);
+					}
 				}
-			}
-			//毫秒
-			std::string msec = std::to_string(t_time_tm_msec);
-			{
-				size_t index = result.find("fff");
-				if (index != -1)
+				//毫秒
+				std::string msec = std::to_string(t_time_tm_msec);
 				{
-					result.replace(index, 3, msec);
+					size_t index = result.find("fff");
+					if (index != -1)
+					{
+						result.replace(index, 3, msec);
+					}
 				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 加天
-		 * @param value
-		 * @return
-		 */
-		datetime& add_day(time_t value) {
-			add_hour(24 * value);
-			return *this;
-		}
-		/**
-		 * @brief 加小时
-		 * @param value
-		 * @return
-		 */
-		datetime& add_hour(time_t value) {
-			add_minute(60 * value);
-			return *this;
-		}
-		/**
-		 * @brief 加分钟
-		 * @param value
-		 * @return
-		 */
-		datetime& add_minute(time_t value) {
-			add_second(60 * value);
-			return *this;
-		}
-		/**
-		 * @brief 加秒
-		 * @param value
-		 * @return
-		 */
-		datetime& add_second(time_t value) {
-			add_millisecond(1000 * value);
-			return *this;
-		}
-		/**
-		 * @brief 加毫秒
-		 * @param value
-		 * @return
-		 */
-		datetime& add_millisecond(time_t value) {
-			time_stamp_ += value;
-			return *this;
-		}
-		/**
-		 * @brief 赋值
-		 * @param time
-		 * @return
-		 */
-		datetime& operator=(const std::string& time) {
-			time_stamp_ = from_datetime(time).time_stamp_;
-			return *this;
-		}
-		/**
-		 * @brief 赋值
-		 * @param time
-		 * @return
-		 */
-		datetime& operator=(const char* time) {
-			time_stamp_ = from_datetime(time).time_stamp_;
-			return *this;
-		}
-		/**
-		 * @brief 赋值
-		 * @param time
-		 * @return
-		 */
-		datetime& operator=(const time_t& time) {
-			time_stamp_ = time;
-			return *this;
-		}
-		/**
-		 * @brief 相减
-		 * @param value
-		 * @return
-		 */
-		time_t operator-(datetime const& value) const {
-			return time_stamp_ - value.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator>(datetime const& time) const {
-			return time_stamp_ > time.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator>=(datetime const& time) const {
-			return time_stamp_ >= time.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator<(datetime const& time) const {
-			return time_stamp_ < time.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator<=(datetime const& time) const {
-			return time_stamp_ <= time.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator==(datetime const& time) const {
-			return time_stamp_ == time.time_stamp_;
-		}
-		/**
-		 * @brief 比较
-		 * @param time
-		 * @return
-		 */
-		bool operator!=(datetime const& time) const {
-			return time_stamp_ != time.time_stamp_;
-		}
-		/**
-		 * @brief 字符串转时间日期
-		 * @param value
-		 * @return
-		 */
-		bool from_string(std::string const& value) {
-			time_stamp_ = from_datetime(value).time_stamp_;
-			return time_stamp_ != 0;
-		}
-		/**
-		 * @brief 字符串转时间日期
-		 * @param value
-		 * @return
-		 */
-		static datetime from_datetime(std::string const& value) {
-			datetime result;
-			std::string time = value;
-			for (size_t i = 0; i < time.size(); i++) {
-				if (time[i] == '/') {
-					time[i] = '-';
-				}
-				else if (time[i] == 'T') {
-					time[i] = ' ';
-				}
+			/**
+			 * @brief 加天
+			 * @param value
+			 * @return
+			 */
+			datetime& add_day(time_t value) {
+				add_hour(24 * value);
+				return *this;
+			}
+			/**
+			 * @brief 加小时
+			 * @param value
+			 * @return
+			 */
+			datetime& add_hour(time_t value) {
+				add_minute(60 * value);
+				return *this;
+			}
+			/**
+			 * @brief 加分钟
+			 * @param value
+			 * @return
+			 */
+			datetime& add_minute(time_t value) {
+				add_second(60 * value);
+				return *this;
+			}
+			/**
+			 * @brief 加秒
+			 * @param value
+			 * @return
+			 */
+			datetime& add_second(time_t value) {
+				add_millisecond(1000 * value);
+				return *this;
+			}
+			/**
+			 * @brief 加毫秒
+			 * @param value
+			 * @return
+			 */
+			datetime& add_millisecond(time_t value) {
+				time_stamp_ += value;
+				return *this;
+			}
+			/**
+			 * @brief 赋值
+			 * @param time
+			 * @return
+			 */
+			datetime& operator=(const std::string& time) {
+				time_stamp_ = from_datetime(time).time_stamp_;
+				return *this;
+			}
+			/**
+			 * @brief 赋值
+			 * @param time
+			 * @return
+			 */
+			datetime& operator=(const char* time) {
+				time_stamp_ = from_datetime(time).time_stamp_;
+				return *this;
+			}
+			/**
+			 * @brief 赋值
+			 * @param time
+			 * @return
+			 */
+			datetime& operator=(const time_t& time) {
+				time_stamp_ = time;
+				return *this;
+			}
+			/**
+			 * @brief 相减
+			 * @param value
+			 * @return
+			 */
+			time_t operator-(datetime const& value) const {
+				return time_stamp_ - value.time_stamp_;
+			}
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator>(datetime const& time) const {
+				return time_stamp_ > time.time_stamp_;
 			}
-			//日期
-			if (std::find(time.begin(), time.end(), ':') == time.end()) {
-				time += " 00:00:00";
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator>=(datetime const& time) const {
+				return time_stamp_ >= time.time_stamp_;
 			}
-			//时间
-			else if (std::find(time.begin(), time.end(), '-') == time.end()) {
-				time = "1970-01-02 " + time;
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator<(datetime const& time) const {
+				return time_stamp_ < time.time_stamp_;
 			}
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator<=(datetime const& time) const {
+				return time_stamp_ <= time.time_stamp_;
+			}
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator==(datetime const& time) const {
+				return time_stamp_ == time.time_stamp_;
+			}
+			/**
+			 * @brief 比较
+			 * @param time
+			 * @return
+			 */
+			bool operator!=(datetime const& time) const {
+				return time_stamp_ != time.time_stamp_;
+			}
+			/**
+			 * @brief 字符串转时间日期
+			 * @param value
+			 * @return
+			 */
+			bool from_string(std::string const& value) {
+				time_stamp_ = from_datetime(value).time_stamp_;
+				return time_stamp_ != 0;
+			}
+			/**
+			 * @brief 字符串转时间日期
+			 * @param value
+			 * @return
+			 */
+			static datetime from_datetime(std::string const& value) {
+				datetime result;
+				std::string time = value;
+				for (size_t i = 0; i < time.size(); i++) {
+					if (time[i] == '/') {
+						time[i] = '-';
+					}
+					else if (time[i] == 'T') {
+						time[i] = ' ';
+					}
+				}
+				//日期
+				if (std::find(time.begin(), time.end(), ':') == time.end()) {
+					time += " 00:00:00";
+				}
+				//时间
+				else if (std::find(time.begin(), time.end(), '-') == time.end()) {
+					time = "1970-01-02 " + time;
+				}
 
-			struct tm t_tm;
-			memset(&t_tm, 0, sizeof(t_tm));
-			int _ms = 0;
+				struct tm t_tm;
+				memset(&t_tm, 0, sizeof(t_tm));
+				int _ms = 0;
 #ifdef WINDOWS_BUILD
-			int result_count = sscanf_s(time.c_str(), "%d-%d-%d %d:%d:%d.%3d",
-				&(t_tm.tm_year),
-				&(t_tm.tm_mon),
-				&(t_tm.tm_mday),
-				&(t_tm.tm_hour),
-				&(t_tm.tm_min),
-				&(t_tm.tm_sec),
-				&_ms);
+				int result_count = sscanf_s(time.c_str(), "%d-%d-%d %d:%d:%d.%3d",
+					&(t_tm.tm_year),
+					&(t_tm.tm_mon),
+					&(t_tm.tm_mday),
+					&(t_tm.tm_hour),
+					&(t_tm.tm_min),
+					&(t_tm.tm_sec),
+					&_ms);
 #elif LINUX_BUILD
-			int result_count = sscanf(time.c_str(), "%d-%d-%d %d:%d:%d.%3d",
-				&(t_tm.tm_year),
-				&(t_tm.tm_mon),
-				&(t_tm.tm_mday),
-				&(t_tm.tm_hour),
-				&(t_tm.tm_min),
-				&(t_tm.tm_sec),
-				&_ms);
+				int result_count = sscanf(time.c_str(), "%d-%d-%d %d:%d:%d.%3d",
+					&(t_tm.tm_year),
+					&(t_tm.tm_mon),
+					&(t_tm.tm_mday),
+					&(t_tm.tm_hour),
+					&(t_tm.tm_min),
+					&(t_tm.tm_sec),
+					&_ms);
 #endif
-			if (result_count == 6 || result_count == 7 || result_count == 3) {
-				t_tm.tm_year -= 1900;
-				t_tm.tm_mon--;
-				result.time_stamp_ = mktime(&t_tm) * 1000 + _ms;
-				return result;
+				if (result_count == 6 || result_count == 7 || result_count == 3) {
+					t_tm.tm_year -= 1900;
+					t_tm.tm_mon--;
+					result.time_stamp_ = mktime(&t_tm) * 1000 + _ms;
+					return result;
+				}
+				else {
+					result.time_stamp_ = 0;
+					return result;
+				}
 			}
-			else {
-				result.time_stamp_ = 0;
-				return result;
+			/**
+			 * @brief 当前时间戳
+			 * @return
+			 */
+			static time_t current_time_stamp() {
+				return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch()).count();
+			}
+			/**
+			 * @brief 当前时间日期
+			 * @param format
+			 * @return
+			 */
+			static datetime current_datetime(std::string const& format = "yyyy-MM-dd HH:mm:ss.fff") {
+				return current_time_stamp();
 			}
-		}
-		/**
-		 * @brief 当前时间戳
-		 * @return
-		 */
-		static time_t current_time_stamp() {
-			return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch()).count();
-		}
-		/**
-		 * @brief 当前时间日期
-		 * @param format
-		 * @return
-		 */
-		static datetime current_datetime(std::string const& format = "yyyy-MM-dd HH:mm:ss.fff") {
-			return current_time_stamp();
-		}
-	private:
-		std::string format_ = "yyyy-MM-dd HH:mm:ss.fff";
-		time_t time_stamp_ = 0;
-	};
+		private:
+			std::string format_ = "yyyy-MM-dd HH:mm:ss.fff";
+			time_t time_stamp_ = 0;
+		};
+	}
 }

+ 136 - 134
robot/robotics/delegates.hpp

@@ -14,141 +14,143 @@
 #include <vector>
 #include <functional>
 
-namespace robotics::v3 {
-	template<typename... _Args>
-	class delegates {
-	public:
-		typedef std::function<void(_Args...)> _FnType;
-		/**
-		 * @brief 析构
-		 */
-		~delegates() {
-			clear();
-		}
-		/**
-		 * @brief 绑定
-		 * @param fn
-		 */
-		void bind(_FnType&& fn) {
-			handlers_.emplace_back(std::forward<_FnType>(fn));
-		}
-		/**
-		 * @brief 添加
-		 * @param fn
-		 */
-		void operator+=(_FnType&& fn) {
-			bind(std::forward<_FnType>(fn));
-		}
-		/**
-		 * @brief 绑定
-		 * @tparam _Fn
-		 * @tparam _Obj
-		 * @param fn
-		 * @param obj
-		 * @param id
-		 */
-		template<typename _Fn, typename _Obj>
-		void bind(_Fn&& fn, _Obj&& obj) {
-			bind(std::bind_front(std::forward<_Fn>(fn), std::forward<_Obj>(obj)));
-		}
-		/**
-		 * @brief 调用
-		 * @param ...args
-		 */
-		void operator()(_Args...args) {
-			for (auto& elem : handlers_) {
-				elem(args...);
+namespace robotics {
+	namespace v3 {
+		template<typename... _Args>
+		class delegates {
+		public:
+			typedef std::function<void(_Args...)> _FnType;
+			/**
+			 * @brief 析构
+			 */
+			~delegates() {
+				clear();
 			}
-		}
-		/**
-		 * @brief 清空
-		 */
-		void clear() {
-			handlers_.clear();
-		}
-		/**
-		 * @brief 数量
-		 * @return
-		 */
-		size_t size() {
-			return handlers_.size();
-		}
-		/**
-		 * @brief 是否是空
-		 * @return
-		 */
-		bool empty() {
-			return handlers_.empty();
-		}
-	private:
-		//委托列表
-		std::vector<_FnType> handlers_;
-	};
-	/**
-	 * @brief 委托
-	 * @tparam _Ret
-	 * @tparam ..._Args
-	 */
-	template<typename _Ret, typename... _Args>
-	class delegate {
-	public:
-		typedef std::function<_Ret(_Args...)> _FnType;
-		/**
-		 * @brief 析构
-		 */
-		~delegate() {
-			clear();
-		}
-		/**
-		 * @brief 
-		 * @param fn 
-		 */
-		void bind(_FnType&& fn) {
-			handler_ = std::forward<_FnType>(fn);
-		}
-		/**
-		 * @brief
-		 * @param fn
-		 */
-		void operator=(_FnType&& fn) {
-			bind(std::forward<_FnType>(fn));
-		}
-		/**
-		 * @brief 绑定
-		 * @tparam _Fn
-		 * @tparam _Obj
-		 * @param fn
-		 * @param obj
-		 */
-		template<typename _Fn, typename _Obj>
-		void bind(_Fn&& fn, _Obj&& obj) {
-			handler_ = std::bind_front(std::forward<_FnType>(fn), std::forward<_FnType>(obj));
-		}
-		/**
-		 * @brief 调用
-		 * @param ...args
-		 * @return
-		 */
-		_Ret operator()(_Args...args) {
-			if (handler_)
-				handler_(args...);
-			std::runtime_error("func nullptr");
-		}
-		/**
-		 * @brief 清空
-		 */
-		void clear() {
-			handler_ = nullptr;
-		}
+			/**
+			 * @brief 绑定
+			 * @param fn
+			 */
+			void bind(_FnType&& fn) {
+				handlers_.emplace_back(std::forward<_FnType>(fn));
+			}
+			/**
+			 * @brief 添加
+			 * @param fn
+			 */
+			void operator+=(_FnType&& fn) {
+				bind(std::forward<_FnType>(fn));
+			}
+			/**
+			 * @brief 绑定
+			 * @tparam _Fn
+			 * @tparam _Obj
+			 * @param fn
+			 * @param obj
+			 * @param id
+			 */
+			template<typename _Fn, typename _Obj>
+			void bind(_Fn&& fn, _Obj&& obj) {
+				bind(std::bind_front(std::forward<_Fn>(fn), std::forward<_Obj>(obj)));
+			}
+			/**
+			 * @brief 调用
+			 * @param ...args
+			 */
+			void operator()(_Args...args) {
+				for (auto& elem : handlers_) {
+					elem(args...);
+				}
+			}
+			/**
+			 * @brief 清空
+			 */
+			void clear() {
+				handlers_.clear();
+			}
+			/**
+			 * @brief 数量
+			 * @return
+			 */
+			size_t size() {
+				return handlers_.size();
+			}
+			/**
+			 * @brief 是否是空
+			 * @return
+			 */
+			bool empty() {
+				return handlers_.empty();
+			}
+		private:
+			//委托列表
+			std::vector<_FnType> handlers_;
+		};
 		/**
-		 * @brief 数量
-		 * @return
+		 * @brief 委托
+		 * @tparam _Ret
+		 * @tparam ..._Args
 		 */
-		int size() {
-			return handler_ == nullptr ? 0 : 1;
-		}
-	private:
-		//委托列表
-		_FnType handler_ = nullptr;
-	};
+		template<typename _Ret, typename... _Args>
+		class delegate {
+		public:
+			typedef std::function<_Ret(_Args...)> _FnType;
+			/**
+			 * @brief 析构
+			 */
+			~delegate() {
+				clear();
+			}
+			/**
+			 * @brief
+			 * @param fn
+			 */
+			void bind(_FnType&& fn) {
+				handler_ = std::forward<_FnType>(fn);
+			}
+			/**
+			 * @brief
+			 * @param fn
+			 */
+			void operator=(_FnType&& fn) {
+				bind(std::forward<_FnType>(fn));
+			}
+			/**
+			 * @brief 绑定
+			 * @tparam _Fn
+			 * @tparam _Obj
+			 * @param fn
+			 * @param obj
+			 */
+			template<typename _Fn, typename _Obj>
+			void bind(_Fn&& fn, _Obj&& obj) {
+				handler_ = std::bind_front(std::forward<_FnType>(fn), std::forward<_FnType>(obj));
+			}
+			/**
+			 * @brief 调用
+			 * @param ...args
+			 * @return
+			 */
+			_Ret operator()(_Args...args) {
+				if (handler_)
+					handler_(args...);
+				std::runtime_error("func nullptr");
+			}
+			/**
+			 * @brief 清空
+			 */
+			void clear() {
+				handler_ = nullptr;
+			}
+			/**
+			 * @brief 数量
+			 * @return
+			 */
+			int size() {
+				return handler_ == nullptr ? 0 : 1;
+			}
+		private:
+			//委托列表
+			_FnType handler_ = nullptr;
+		};
+	}
 }

+ 64 - 62
robot/robotics/dump.hpp

@@ -24,72 +24,74 @@
 #define DUMP_INSTALL robotics::v3::dump::install()
 #endif // DUMP_INSTALL
 
-namespace robotics::v3 {
-    class dump {
-    public:
-        /**
-         * @brief 安装dump
-         */
-        static void install() {
-            ::SetUnhandledExceptionFilter(dump::sys_exception_filter);
-            void* addr = (void*)GetProcAddress(LoadLibraryA("kernel32.dll"), "SetUnhandledExceptionFilter");
-            if (addr != NULL) {
-                unsigned char code[16];
-                int size = 0;
-                code[size++] = 0x33;
-                code[size++] = 0xC0;
-                code[size++] = 0xC2;
-                code[size++] = 0x04;
-                code[size++] = 0x00;
-                DWORD dwOldFlag, dwTempFlag;
-                VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
-                WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
-                VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
+namespace robotics {
+    namespace v3 {
+        class dump {
+        public:
+            /**
+             * @brief 安装dump
+             */
+            static void install() {
+                ::SetUnhandledExceptionFilter(dump::sys_exception_filter);
+                void* addr = (void*)GetProcAddress(LoadLibraryA("kernel32.dll"), "SetUnhandledExceptionFilter");
+                if (addr != NULL) {
+                    unsigned char code[16];
+                    int size = 0;
+                    code[size++] = 0x33;
+                    code[size++] = 0xC0;
+                    code[size++] = 0xC2;
+                    code[size++] = 0x04;
+                    code[size++] = 0x00;
+                    DWORD dwOldFlag, dwTempFlag;
+                    VirtualProtect(addr, size, PAGE_READWRITE, &dwOldFlag);
+                    WriteProcessMemory(GetCurrentProcess(), addr, code, size, NULL);
+                    VirtualProtect(addr, size, dwOldFlag, &dwTempFlag);
+                }
             }
-        }
-    private:
-        static long __stdcall sys_exception_filter(LPEXCEPTION_POINTERS lp_exception_info) {
-            if (IsDebuggerPresent()) {
-                return EXCEPTION_CONTINUE_SEARCH;
+        private:
+            static long __stdcall sys_exception_filter(LPEXCEPTION_POINTERS lp_exception_info) {
+                if (IsDebuggerPresent()) {
+                    return EXCEPTION_CONTINUE_SEARCH;
+                }
+                create_dump_file(get_dump_file_name(), lp_exception_info);
+                return EXCEPTION_EXECUTE_HANDLER;
             }
-            create_dump_file(get_dump_file_name(), lp_exception_info);
-            return EXCEPTION_EXECUTE_HANDLER;
-        }
-        static bool create_dump_file(std::string const& filename, PEXCEPTION_POINTERS p_except) {
-            MINIDUMP_EXCEPTION_INFORMATION exceptInfo;
-            exceptInfo.ExceptionPointers = p_except;
-            exceptInfo.ThreadId = GetCurrentThreadId();
-            exceptInfo.ClientPointers = TRUE;
+            static bool create_dump_file(std::string const& filename, PEXCEPTION_POINTERS p_except) {
+                MINIDUMP_EXCEPTION_INFORMATION exceptInfo;
+                exceptInfo.ExceptionPointers = p_except;
+                exceptInfo.ThreadId = GetCurrentThreadId();
+                exceptInfo.ClientPointers = TRUE;
 
-            HANDLE dumpFile = ::CreateFileA((LPCSTR)filename.c_str(), GENERIC_WRITE, 0, NULL,
-                CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-            if (dumpFile != INVALID_HANDLE_VALUE) {
-                MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, (MINIDUMP_TYPE)0x9b67, &exceptInfo, NULL, NULL);
-                CloseHandle(dumpFile);
-                LOG_INFO << "已生成DUMP文件(" << filename << ")";
-                ::Sleep(1000);
-                return true;
+                HANDLE dumpFile = ::CreateFileA((LPCSTR)filename.c_str(), GENERIC_WRITE, 0, NULL,
+                    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+                if (dumpFile != INVALID_HANDLE_VALUE) {
+                    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, (MINIDUMP_TYPE)0x9b67, &exceptInfo, NULL, NULL);
+                    CloseHandle(dumpFile);
+                    LOG_INFO << "已生成DUMP文件(" << filename << ")";
+                    ::Sleep(1000);
+                    return true;
+                }
+                else {
+                    LOG_ERROR << "DUMP文件创建失败(" << filename << ")错误代码:" << (int)::GetLastError();
+                    ::Sleep(1000);
+                    return false;
+                }
             }
-            else {
-                LOG_ERROR << "DUMP文件创建失败(" << filename << ")错误代码:" << (int)::GetLastError();
-                ::Sleep(1000);
-                return false;
+            static std::string get_dump_file_name() {
+                std::string currentTime = v3::datetime::current_datetime().to_string("yyyy_MM_dd_HH_mm_ss_fff");
+                char filename[512] = { 0 };
+                GetModuleFileNameA(NULL, filename, 512);
+                std::filesystem::path path = filename;
+                path /= "dump";
+                if (!std::filesystem::exists(path)) {
+                    std::filesystem::create_directory(path);
+                }
+                path /= currentTime + ".dmp";
+                return path.string();
             }
-        }
-        static std::string get_dump_file_name() {
-            std::string currentTime = v3::datetime::current_datetime().to_string("yyyy_MM_dd_HH_mm_ss_fff");
-            char filename[512] = { 0 };
-            GetModuleFileNameA(NULL, filename, 512);
-            std::filesystem::path path = filename;
-            path /= "dump";
-            if (!std::filesystem::exists(path)) {
-                std::filesystem::create_directory(path);
-            }
-            path /= currentTime + ".dmp";
-            return path.string();
-        }
-    protected:
-        dump() {}
-    };
+        protected:
+            dump() {}
+        };
+    }
 }
 #endif

+ 96 - 94
robot/robotics/event_trigger.hpp

@@ -12,102 +12,104 @@
 #include "delegates.hpp"
 #include "utils.hpp"
 
-namespace robotics::v3 {
-	template<typename ..._Args>
-	struct event_trigger {
-		event_trigger() {
-			start();
-		}
-		~event_trigger() {
-			stop();
-		}
-		/**
-		 * @brief 添加任务
-		 * @param sleep
-		 * @param ...args
-		 */
-		void add(time_t sleep, _Args const&...args) {
-			std::lock_guard<std::mutex> locker(mutex_);
-			task_list_.push_back(std::make_pair(std::make_tuple(args...), v3::utils::steady_time_stamp() + sleep));
-			cv_.notify_one();
-		}
-		/**
-		 * @brief 清空
-		 */
-		void clear() {
-			std::lock_guard<std::mutex> locker(mutex_);
-			task_list_.clear();
-		}
-		/**
-		 * @brief 
-		 * @param fn 
-		 */
-		void bind(std::function<void(_Args...)>&& fn) {
-			event.bind(std::move(fn));
-		}
-		/**
-		 * @brief 
-		 * @param fn 
-		 */
-		void operator+=(std::function<void(_Args...)>&& fn) {
-			bind(std::move(fn));
-		}
-		/**
-		 * @brief 
-		 * @tparam _Fn 
-		 * @tparam _Obj 
-		 * @param fn 
-		 * @param obj 
-		 */
-		template<typename _Fn, typename _Obj>
-		void bind(_Fn&& fn, _Obj&& obj) {
-			bind(std::bind_front(std::move(fn), std::move(obj)));
-		}
-		/**
-		 * @brief 事件
-		 */
-		delegates<_Args...> event;
-	private:
-		void start() {
-			std::thread th(&event_trigger::thread_work, this);
-			thread_ = std::move(th);
-		}
-		void stop() {
-			running_ = false;
-			cv_.notify_all();
-			if (thread_.joinable())
-				thread_.join();
-		}
-		void on_event(int time, _Args...args) {
-			event(args...);
-		}
-		void thread_work() {
-			running_ = true;
-			while (running_) {
-				{
-					std::unique_lock<std::mutex> lock(mutex_);
-					while (task_list_.empty() && running_)
-						cv_.wait(lock);
-					time_t current_time = v3::utils::steady_time_stamp();
-					for (int i = 0; i < task_list_.size(); ++i) {
-						if (task_list_[i].second <= current_time) {
-							std::apply([&](auto&&...args) {
-								on_event(current_time - task_list_[i].second, std::forward<decltype(args)>(args)...);
-								}, task_list_[i].first);
-							task_list_.erase(task_list_.begin() + i);
-							--i;
+namespace robotics {
+	namespace v3 {
+		template<typename ..._Args>
+		struct event_trigger {
+			event_trigger() {
+				start();
+			}
+			~event_trigger() {
+				stop();
+			}
+			/**
+			 * @brief 添加任务
+			 * @param sleep
+			 * @param ...args
+			 */
+			void add(time_t sleep, _Args const&...args) {
+				std::lock_guard<std::mutex> locker(mutex_);
+				task_list_.push_back(std::make_pair(std::make_tuple(args...), v3::utils::steady_time_stamp() + sleep));
+				cv_.notify_one();
+			}
+			/**
+			 * @brief 清空
+			 */
+			void clear() {
+				std::lock_guard<std::mutex> locker(mutex_);
+				task_list_.clear();
+			}
+			/**
+			 * @brief
+			 * @param fn
+			 */
+			void bind(std::function<void(_Args...)>&& fn) {
+				event.bind(std::move(fn));
+			}
+			/**
+			 * @brief
+			 * @param fn
+			 */
+			void operator+=(std::function<void(_Args...)>&& fn) {
+				bind(std::move(fn));
+			}
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam _Obj
+			 * @param fn
+			 * @param obj
+			 */
+			template<typename _Fn, typename _Obj>
+			void bind(_Fn&& fn, _Obj&& obj) {
+				bind(std::bind_front(std::move(fn), std::move(obj)));
+			}
+			/**
+			 * @brief 事件
+			 */
+			delegates<_Args...> event;
+		private:
+			void start() {
+				std::thread th(&event_trigger::thread_work, this);
+				thread_ = std::move(th);
+			}
+			void stop() {
+				running_ = false;
+				cv_.notify_all();
+				if (thread_.joinable())
+					thread_.join();
+			}
+			void on_event(int time, _Args...args) {
+				event(args...);
+			}
+			void thread_work() {
+				running_ = true;
+				while (running_) {
+					{
+						std::unique_lock<std::mutex> lock(mutex_);
+						while (task_list_.empty() && running_)
+							cv_.wait(lock);
+						time_t current_time = v3::utils::steady_time_stamp();
+						for (int i = 0; i < task_list_.size(); ++i) {
+							if (task_list_[i].second <= current_time) {
+								std::apply([&](auto&&...args) {
+									on_event(current_time - task_list_[i].second, std::forward<decltype(args)>(args)...);
+									}, task_list_[i].first);
+								task_list_.erase(task_list_.begin() + i);
+								--i;
+							}
 						}
 					}
+					std::this_thread::sleep_for(std::chrono::microseconds(1));
 				}
-				std::this_thread::sleep_for(std::chrono::microseconds(1));
+				running_ = false;
 			}
-			running_ = false;
-		}
-	private:
-		std::thread thread_;
-		bool running_ = false;
-		std::mutex mutex_;
-		std::condition_variable cv_;
-		std::vector<std::pair<std::tuple<_Args...>, time_t>> task_list_;
-	};
+		private:
+			std::thread thread_;
+			bool running_ = false;
+			std::mutex mutex_;
+			std::condition_variable cv_;
+			std::vector<std::pair<std::tuple<_Args...>, time_t>> task_list_;
+		};
+	}
 }

+ 37 - 35
robot/robotics/event_wait_for.hpp

@@ -15,39 +15,41 @@
 #include <any>
 #include <condition_variable>
 
-namespace robotics::v3 {
-	class event_wait_for {
-	public:
-		explicit event_wait_for() {
-		}
-		~event_wait_for() {
-			notify();
-		}
-		bool wait(std::uint32_t ms) {
-			std::unique_lock<std::mutex> lock(mutex_);
-			bool result = false;
-			cv_.wait_for(lock, std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::milliseconds(ms)), [this] {return notify_; });
-			result = notify_;
-			notify_ = false;
-			return result;
-		}
-		void notify() {
-			std::lock_guard<std::mutex> locker(mutex_);
-			notify_ = true;
-			cv_.notify_all();
-		}
-		template<typename _Type>
-		void set_custom_value(_Type const& value) {
-			user_data_ = value;
-		}
-		template<typename _Ret>
-		_Ret get_custom_value() {
-			return std::any_cast<_Ret>(user_data_);
-		}
-	private:
-		std::any							user_data_;
-		bool								notify_ = false;
-		std::mutex							mutex_;
-		std::condition_variable				cv_;
-	};
+namespace robotics {
+	namespace v3 {
+		class event_wait_for {
+		public:
+			explicit event_wait_for() {
+			}
+			~event_wait_for() {
+				notify();
+			}
+			bool wait(std::uint32_t ms) {
+				std::unique_lock<std::mutex> lock(mutex_);
+				bool result = false;
+				cv_.wait_for(lock, std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::milliseconds(ms)), [this] {return notify_; });
+				result = notify_;
+				notify_ = false;
+				return result;
+			}
+			void notify() {
+				std::lock_guard<std::mutex> locker(mutex_);
+				notify_ = true;
+				cv_.notify_all();
+			}
+			template<typename _Type>
+			void set_custom_value(_Type const& value) {
+				user_data_ = value;
+			}
+			template<typename _Ret>
+			_Ret get_custom_value() {
+				return std::any_cast<_Ret>(user_data_);
+			}
+		private:
+			std::any							user_data_;
+			bool								notify_ = false;
+			std::mutex							mutex_;
+			std::condition_variable				cv_;
+		};
+	}
 }

+ 49 - 47
robot/robotics/function_traits.hpp

@@ -13,65 +13,67 @@
 #include <functional>
 #include <tuple>
 
-namespace robotics::v3 {
-	template <typename _Type>
-	struct function_traits;
+namespace robotics {
+	namespace v3 {
+		template <typename _Type>
+		struct function_traits;
 
-	template<typename Ret, typename...Args>
-	struct function_traits<Ret(Args...)>
-	{
-	public:
-		enum { arity = sizeof...(Args) };
-		typedef Ret function_type(Args...);
-		typedef Ret return_type;
-		using stl_function_type = std::function<function_type>;
-		typedef Ret(*pointer)(Args...);
-		typedef std::tuple<Args...> param_type;
-		typedef std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...> param_remove_reference_and_const_type;
-
-		template<size_t I>
-		struct args
+		template<typename Ret, typename...Args>
+		struct function_traits<Ret(Args...)>
 		{
-			static_assert(I < arity, "index is out of range,index must less than sizeof Args");
-			using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
+		public:
+			enum { arity = sizeof...(Args) };
+			typedef Ret function_type(Args...);
+			typedef Ret return_type;
+			using stl_function_type = std::function<function_type>;
+			typedef Ret(*pointer)(Args...);
+			typedef std::tuple<Args...> param_type;
+			typedef std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...> param_remove_reference_and_const_type;
+
+			template<size_t I>
+			struct args
+			{
+				static_assert(I < arity, "index is out of range,index must less than sizeof Args");
+				using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
+			};
 		};
-	};
 
-	//
-	template<typename Ret, typename...Args>
-	struct function_traits<Ret(*)(Args...)> :function_traits<Ret(Args...)> {};
-	// std::function
-	template <typename Ret, typename... Args>
-	struct function_traits<std::function<Ret(Args...)>> :function_traits<Ret(Args...)> {};
+		//
+		template<typename Ret, typename...Args>
+		struct function_traits<Ret(*)(Args...)> :function_traits<Ret(Args...)> {};
+		// std::function
+		template <typename Ret, typename... Args>
+		struct function_traits<std::function<Ret(Args...)>> :function_traits<Ret(Args...)> {};
 #define FunctionTraits(...) \
 	template<typename ReturnType,typename ClassType,typename...Args>\
 	struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__>:\
 	function_traits<ReturnType(Args...)>{};
 
-	FunctionTraits()
-		FunctionTraits(const)
-		FunctionTraits(volatile)
-		FunctionTraits(const volatile)
+		FunctionTraits()
+			FunctionTraits(const)
+			FunctionTraits(volatile)
+			FunctionTraits(const volatile)
 
-		//
-		template<typename Callable>
-	struct function_traits :function_traits<decltype(&Callable::operator())> {};
+			//
+			template<typename Callable>
+		struct function_traits :function_traits<decltype(&Callable::operator())> {};
 
-	template<typename Function>
-	typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
-	{
-		return  static_cast<typename function_traits<Function>::stl_function_type> (lambda);
-	}
+		template<typename Function>
+		typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
+		{
+			return  static_cast<typename function_traits<Function>::stl_function_type> (lambda);
+		}
 
-	template<typename Function>
-	typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
-	{
-		return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
-	}
+		template<typename Function>
+		typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
+		{
+			return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
+		}
 
-	template<typename Function>
-	typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
-	{
-		return static_cast<typename function_traits<Function>::pointer>(lambda);
+		template<typename Function>
+		typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
+		{
+			return static_cast<typename function_traits<Function>::pointer>(lambda);
+		}
 	}
 }

+ 113 - 111
robot/robotics/http_client.hpp

@@ -11,122 +11,124 @@
 //asio2
 #include <asio2/asio2.hpp>
 
-namespace robotics::v3 {
-	class http_type{
-	public:
-		using HTTP  = asio2::http_client;
-		using HTTPS = asio2::https_client;
-	};
-	template<typename _HttpType, int _Count = 5>
-	class http_client {
-		typedef std::vector<std::pair<std::shared_ptr<_HttpType>, bool>> HttpClientType;
-		struct http_client_gc {
-			http_client_gc(std::shared_ptr<_HttpType>& client, std::mutex& mutex, HttpClientType& clients, std::condition_variable& cv) :
-				client_(client),
-				mutex_(mutex),
-				clients_(clients),
-				cv_(cv) {
-			}
-			~http_client_gc() {
-				std::lock_guard<std::mutex> locker(mutex_);
-				for (auto& it : clients_) {
-					if (it.first == client_) {
-						it.second = false;
-						break;
+namespace robotics {
+	namespace v3 {
+		class http_type {
+		public:
+			using HTTP = asio2::http_client;
+			using HTTPS = asio2::https_client;
+		};
+		template<typename _HttpType, int _Count = 5>
+		class http_client {
+			typedef std::vector<std::pair<std::shared_ptr<_HttpType>, bool>> HttpClientType;
+			struct http_client_gc {
+				http_client_gc(std::shared_ptr<_HttpType>& client, std::mutex& mutex, HttpClientType& clients, std::condition_variable& cv) :
+					client_(client),
+					mutex_(mutex),
+					clients_(clients),
+					cv_(cv) {
+				}
+				~http_client_gc() {
+					std::lock_guard<std::mutex> locker(mutex_);
+					for (auto& it : clients_) {
+						if (it.first == client_) {
+							it.second = false;
+							break;
+						}
 					}
+					cv_.notify_one();
 				}
-				cv_.notify_one();
+			private:
+				std::mutex& mutex_;
+				HttpClientType& clients_;
+				std::condition_variable& cv_;
+				std::shared_ptr<_HttpType>& client_;
+			};
+		public:
+			~http_client() {
+				stop();
 			}
-		private:
-			std::mutex&					mutex_;
-			HttpClientType&				clients_;
-			std::condition_variable&	cv_;
-			std::shared_ptr<_HttpType>& client_;
-		};
-	public:
-		~http_client() {
-			stop();
-		}
-		/**
-		 * @brief 请求
-		 * @param req 
-		 * @param timeout 
-		 * @return 
-		 */
-		http::web_response execute(http::web_request&& req, int timeout) {
-			std::shared_ptr<_HttpType> client = get_client(timeout);
-			if (!client)
-				throw std::runtime_error("Http pool error!");
-			http_client_gc gc(client, client_mutex_, clients_, cv_);
-			if (!client->is_started())
-				client->start(req.host(), req.port());
-			if (asio2::get_last_error())
-				throw std::runtime_error(asio2::get_last_error_msg().c_str());
-			auto result = client->call<http::web_response>(std::move(req), std::chrono::milliseconds(timeout));
-			if (asio2::get_last_error()) {
-				std::string err = asio2::get_last_error_msg();
-				client->stop();
-				throw std::runtime_error(err.c_str());
+			/**
+			 * @brief 请求
+			 * @param req
+			 * @param timeout
+			 * @return
+			 */
+			http::web_response execute(http::web_request&& req, int timeout) {
+				std::shared_ptr<_HttpType> client = get_client(timeout);
+				if (!client)
+					throw std::runtime_error("Http pool error!");
+				http_client_gc gc(client, client_mutex_, clients_, cv_);
+				if (!client->is_started())
+					client->start(req.host(), req.port());
+				if (asio2::get_last_error())
+					throw std::runtime_error(asio2::get_last_error_msg().c_str());
+				auto result = client->call<http::web_response>(std::move(req), std::chrono::milliseconds(timeout));
+				if (asio2::get_last_error()) {
+					std::string err = asio2::get_last_error_msg();
+					client->stop();
+					throw std::runtime_error(err.c_str());
+				}
+				return result;
+			}
+			/**
+			 * @brief 启动
+			 */
+			void start() {
+				run_ = true;
+			}
+			/**
+			 * @brief 停止
+			 */
+			void stop() {
+				run_ = false;
+				cv_.notify_all();
 			}
-			return result;
-		}
-		/**
-		 * @brief 启动
-		 */
-		void start() {
-			run_ = true;
-		}
-		/**
-		 * @brief 停止
-		 */
-		void stop() {
-			run_ = false;
-			cv_.notify_all();
-		}
-	private:
-		std::shared_ptr<_HttpType> get_client(int timeout) {
-			std::shared_ptr<_HttpType> result;
-			std::unique_lock<std::mutex> locker(client_mutex_);
-			cv_.wait(locker, [&]() {
-				if (!run_)
-					return true;
-				//判断有没有可用连接
-				for (auto& it : clients_) {
-					if (!it.second) {
-						it.second = true;
-						result = it.first;
+		private:
+			std::shared_ptr<_HttpType> get_client(int timeout) {
+				std::shared_ptr<_HttpType> result;
+				std::unique_lock<std::mutex> locker(client_mutex_);
+				cv_.wait(locker, [&]() {
+					if (!run_)
 						return true;
+					//判断有没有可用连接
+					for (auto& it : clients_) {
+						if (!it.second) {
+							it.second = true;
+							result = it.first;
+							return true;
+						}
 					}
-				}
-				//判断是否添加
-				if (clients_.size() < _Count) {
-					auto item = std::make_pair(std::make_shared<_HttpType>(), true);
-					clients_.push_back(item);
-					result = item.first;
-					return true;
-				}
-				return false; });
-			result->set_connect_timeout(std::chrono::milliseconds(timeout));
-			return result;
-		}
-	private:
-		bool					run_ = false;
-		std::mutex				client_mutex_;
-		HttpClientType			clients_;
-		std::condition_variable cv_;
-	};
-	/*
-	* http_client<asio2::http_client> request;
-	* https http判断 req.schema();
-	* http::web_request req = http::make_request("http://127.0.0.1:8888/BranchWeb/sortService");
-			req.method(http::verb::post);
-			req.set(http::field::content_type,"application/x-www-form-urlencoded");
-			req.body() = "data=123456&data_digest=987654321&msg_type=TEST_INFO&company_id=yjkj";
-			req.keep_alive(false);
-			auto response = request.execute(std::move(req),2000);
-			if (asio2::get_last_error())
-				throw std::exception(asio2::get_last_error_msg().c_str());
-			LOG_INFO << response.body().text();
-	*/
+					//判断是否添加
+					if (clients_.size() < _Count) {
+						auto item = std::make_pair(std::make_shared<_HttpType>(), true);
+						clients_.push_back(item);
+						result = item.first;
+						return true;
+					}
+					return false; });
+				result->set_connect_timeout(std::chrono::milliseconds(timeout));
+				return result;
+			}
+		private:
+			bool					run_ = false;
+			std::mutex				client_mutex_;
+			HttpClientType			clients_;
+			std::condition_variable cv_;
+		};
+		/*
+		* http_client<asio2::http_client> request;
+		* https http判断 req.schema();
+		* http::web_request req = http::make_request("http://127.0.0.1:8888/BranchWeb/sortService");
+				req.method(http::verb::post);
+				req.set(http::field::content_type,"application/x-www-form-urlencoded");
+				req.body() = "data=123456&data_digest=987654321&msg_type=TEST_INFO&company_id=yjkj";
+				req.keep_alive(false);
+				auto response = request.execute(std::move(req),2000);
+				if (asio2::get_last_error())
+					throw std::exception(asio2::get_last_error_msg().c_str());
+				LOG_INFO << response.body().text();
+		*/
+	}
 }
 

+ 78 - 76
robot/robotics/ioc_interface.hpp

@@ -16,82 +16,84 @@
 //robotics
 #include "utils.hpp"
 
-namespace robotics::v3 {
-	template<typename _Interface, typename ..._Args>
-	class ioc_interface {
-	public:
-		/**
-		 * @brief 注册
-		 * @tparam _Type
-		 * @param key
-		 * @return
-		 */
-		template<typename _Type>
-		bool register_type(std::string const& key) {
-			std::function<_Interface* (_Args...)> func = [](_Args&&...args) { return new _Type(std::forward<_Args>(args)...); };
-			if (map_.find(key) != map_.end())
-				return false;
-			map_[key] = func;
-			return true;
-		}
-		/**
-		 * @brief 注册
-		 * @param key
-		 * @param libpath
-		 * @param funcname
-		 * @return
-		 */
-		bool register_type(std::string const& key, std::string const& libpath, std::string const& funcname) {
-			if (map_.find(key) != map_.end())
-				return false;
-			boost::dll::shared_library lib;
-			try {
-				lib.load(libpath, boost::dll::load_mode::default_mode);
-				map_[key] = lib.get<_Interface * (_Args...)>(funcname);
+namespace robotics {
+	namespace v3 {
+		template<typename _Interface, typename ..._Args>
+		class ioc_interface {
+		public:
+			/**
+			 * @brief 注册
+			 * @tparam _Type
+			 * @param key
+			 * @return
+			 */
+			template<typename _Type>
+			bool register_type(std::string const& key) {
+				std::function<_Interface* (_Args...)> func = [](_Args&&...args) { return new _Type(std::forward<_Args>(args)...); };
+				if (map_.find(key) != map_.end())
+					return false;
+				map_[key] = func;
+				return true;
 			}
-			catch (std::exception const& ec) {
-				return false;
+			/**
+			 * @brief 注册
+			 * @param key
+			 * @param libpath
+			 * @param funcname
+			 * @return
+			 */
+			bool register_type(std::string const& key, std::string const& libpath, std::string const& funcname) {
+				if (map_.find(key) != map_.end())
+					return false;
+				boost::dll::shared_library lib;
+				try {
+					lib.load(libpath, boost::dll::load_mode::default_mode);
+					map_[key] = lib.get<_Interface * (_Args...)>(funcname);
+				}
+				catch (std::exception const& ec) {
+					return false;
+				}
+				libs_.push_back(std::move(lib));
+				return true;
 			}
-			libs_.push_back(std::move(lib));
-			return true;
-		}
-		/**
-		 * @brief 卸载
-		 * @param key
-		 * @return
-		 */
-		bool unregister_type(std::string const& key) {
-			if (map_.find(key) == map_.end())
-				return false;
-			map_.erase(key);
-			return true;
-		}
-		/**
-		 * @brief
-		 * @param key
-		 * @param ...args
-		 * @return
-		 */
-		_Interface* resolve(std::string const& key, _Args const&...args) {
-			if (map_.find(key) == map_.end())
-				return nullptr;
-			return map_[key](args...);
-		}
-		/**
-		 * @brief
-		 * @param key
-		 * @param ...args
-		 * @return
-		 */
-		std::shared_ptr<_Interface> resolve_shared(std::string const& key, _Args const&...args) {
-			if (map_.find(key) == map_.end())
-				return nullptr;
-			return std::shared_ptr<_Interface>(resolve(key, args...));
-		}
-	private:
-		//接口
-		std::vector<boost::dll::shared_library> libs_;
-		//容器
-		std::map<std::string, std::function<_Interface* (_Args...)>> map_;
-	};
+			/**
+			 * @brief 卸载
+			 * @param key
+			 * @return
+			 */
+			bool unregister_type(std::string const& key) {
+				if (map_.find(key) == map_.end())
+					return false;
+				map_.erase(key);
+				return true;
+			}
+			/**
+			 * @brief
+			 * @param key
+			 * @param ...args
+			 * @return
+			 */
+			_Interface* resolve(std::string const& key, _Args const&...args) {
+				if (map_.find(key) == map_.end())
+					return nullptr;
+				return map_[key](args...);
+			}
+			/**
+			 * @brief
+			 * @param key
+			 * @param ...args
+			 * @return
+			 */
+			std::shared_ptr<_Interface> resolve_shared(std::string const& key, _Args const&...args) {
+				if (map_.find(key) == map_.end())
+					return nullptr;
+				return std::shared_ptr<_Interface>(resolve(key, args...));
+			}
+		private:
+			//接口
+			std::vector<boost::dll::shared_library> libs_;
+			//容器
+			std::map<std::string, std::function<_Interface* (_Args...)>> map_;
+		};
+	}
 }

+ 433 - 431
robot/robotics/json.hpp

@@ -17,482 +17,484 @@
 //robotics
 #include "utils.hpp"
 
-namespace robotics::v3 {
-	template <typename, template <typename...> class>
-	struct is_specialization : std::false_type {};
-	template <template <typename...> class Template, typename... Args>
-	struct is_specialization<Template<Args...>, Template> : std::true_type {};
-	class json_convert;
-	class json_convert_impl {
-		friend class json_convert;
-		static void serialize(rttr::instance const& value, nlohmann::json& result) {
-			rttr::instance obj = value.get_type().get_raw_type().is_wrapper() ? value.get_wrapped_instance() : value;
-			auto properties = obj.get_derived_type().get_properties();
-			for (auto& property : properties) {
-				std::string prop_name;
-				rttr::variant no_json = property.get_metadata("NoJson");
-				rttr::variant prop_var_name = property.get_metadata("Json");
-				if (no_json.get_type() == rttr::type::get<bool>() && no_json.get_value<bool>()) {
-					continue;
-				}
-				if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-					prop_name = prop_var_name.get_value<std::string>();
-				}
-				else {
-					prop_name = std::string(property.get_name());
-				}
-				if (utils::rttr_type<int>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<int>();
-				}
-				else if (utils::rttr_type<bool>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<bool>();
-				}
-				else if (utils::rttr_type<double>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<double>();
-				}
-				else if (utils::rttr_type<float>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<float>();
-				}
-				else if (utils::rttr_type<std::int64_t>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::int64_t>();
-				}
-				else if (utils::rttr_type<datetime>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<datetime>().to_string();
-				}
-				else if (utils::rttr_type<std::string>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::string>();
-				}
-				//list
-				else if (utils::rttr_type<std::vector<int>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<int>>();
-				}
-				else if (utils::rttr_type<std::vector<bool>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<bool>>();
-				}
-				else if (utils::rttr_type<std::vector<double>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<double>>();
-				}
-				else if (utils::rttr_type<std::vector<float>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<float>>();
-				}
-				else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<std::int64_t>>();
-				}
-				else if (utils::rttr_type<std::vector<std::string>>(property.get_type())) {
-					result[prop_name] = property.get_value(obj).get_value<std::vector<std::string>>();
-				}
-				else if (utils::rttr_type<std::vector<datetime>>(property.get_type())) {
-					std::vector<std::string> datetime_list;
-					auto times = property.get_value(obj).get_value<std::vector<datetime>>();
-					for (auto& it : times) {
-						datetime_list.push_back(it.to_string());
+namespace robotics {
+	namespace v3 {
+		template <typename, template <typename...> class>
+		struct is_specialization : std::false_type {};
+		template <template <typename...> class Template, typename... Args>
+		struct is_specialization<Template<Args...>, Template> : std::true_type {};
+		class json_convert;
+		class json_convert_impl {
+			friend class json_convert;
+			static void serialize(rttr::instance const& value, nlohmann::json& result) {
+				rttr::instance obj = value.get_type().get_raw_type().is_wrapper() ? value.get_wrapped_instance() : value;
+				auto properties = obj.get_derived_type().get_properties();
+				for (auto& property : properties) {
+					std::string prop_name;
+					rttr::variant no_json = property.get_metadata("NoJson");
+					rttr::variant prop_var_name = property.get_metadata("Json");
+					if (no_json.get_type() == rttr::type::get<bool>() && no_json.get_value<bool>()) {
+						continue;
+					}
+					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+						prop_name = prop_var_name.get_value<std::string>();
+					}
+					else {
+						prop_name = std::string(property.get_name());
+					}
+					if (utils::rttr_type<int>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<int>();
+					}
+					else if (utils::rttr_type<bool>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<bool>();
+					}
+					else if (utils::rttr_type<double>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<double>();
+					}
+					else if (utils::rttr_type<float>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<float>();
+					}
+					else if (utils::rttr_type<std::int64_t>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::int64_t>();
+					}
+					else if (utils::rttr_type<datetime>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<datetime>().to_string();
+					}
+					else if (utils::rttr_type<std::string>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::string>();
+					}
+					//list
+					else if (utils::rttr_type<std::vector<int>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<int>>();
+					}
+					else if (utils::rttr_type<std::vector<bool>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<bool>>();
+					}
+					else if (utils::rttr_type<std::vector<double>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<double>>();
+					}
+					else if (utils::rttr_type<std::vector<float>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<float>>();
+					}
+					else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<std::int64_t>>();
+					}
+					else if (utils::rttr_type<std::vector<std::string>>(property.get_type())) {
+						result[prop_name] = property.get_value(obj).get_value<std::vector<std::string>>();
+					}
+					else if (utils::rttr_type<std::vector<datetime>>(property.get_type())) {
+						std::vector<std::string> datetime_list;
+						auto times = property.get_value(obj).get_value<std::vector<datetime>>();
+						for (auto& it : times) {
+							datetime_list.push_back(it.to_string());
+						}
+						result[prop_name] = datetime_list;
+					}
+					//嵌套结构体列表
+					else if (property.get_type().is_sequential_container()) {
+						result[prop_name] = nlohmann::json::array();
+						auto value_tmp = property.get_value(obj);
+						for (auto& it : value_tmp.create_sequential_view()) {
+							nlohmann::json child;
+							serialize(it.extract_wrapped_value(), child);
+							result[prop_name].push_back(child);
+						}
 					}
-					result[prop_name] = datetime_list;
-				}
-				//嵌套结构体列表
-				else if (property.get_type().is_sequential_container()) {
-					result[prop_name] = nlohmann::json::array();
-					auto value_tmp = property.get_value(obj);
-					for (auto& it : value_tmp.create_sequential_view()) {
-						nlohmann::json child;
-						serialize(it.extract_wrapped_value(), child);
-						result[prop_name].push_back(child);
+					//嵌套结构体
+					else if (property.get_type().is_class()) {
+						auto value_tmp = property.get_value(obj);
+						serialize(value_tmp, result[prop_name]);
 					}
 				}
-				//嵌套结构体
-				else if (property.get_type().is_class()) {
-					auto value_tmp = property.get_value(obj);
-					serialize(value_tmp, result[prop_name]);
-				}
 			}
-		}
-		static void deserialize(nlohmann::json const& value, rttr::instance result) {
-			auto properties = result.get_derived_type().get_properties();
-			for (auto& property : properties) {
-				std::string prop_name;
-				rttr::variant no_json = property.get_metadata("NoJson");
-				rttr::variant prop_var_name = property.get_metadata("Json");
-				if (no_json.get_type() == rttr::type::get<bool>() && no_json.get_value<bool>())
-					continue;
-				if (prop_var_name.get_type() == rttr::type::get<std::string>())
-					prop_name = prop_var_name.get_value<std::string>();
-				else
-					prop_name = std::string(property.get_name());
-				if (!value.contains(prop_name))
-					continue;
+			static void deserialize(nlohmann::json const& value, rttr::instance result) {
+				auto properties = result.get_derived_type().get_properties();
+				for (auto& property : properties) {
+					std::string prop_name;
+					rttr::variant no_json = property.get_metadata("NoJson");
+					rttr::variant prop_var_name = property.get_metadata("Json");
+					if (no_json.get_type() == rttr::type::get<bool>() && no_json.get_value<bool>())
+						continue;
+					if (prop_var_name.get_type() == rttr::type::get<std::string>())
+						prop_name = prop_var_name.get_value<std::string>();
+					else
+						prop_name = std::string(property.get_name());
+					if (!value.contains(prop_name))
+						continue;
 
-				if (utils::rttr_type<int>(property.get_type())) {
-					int value_tmp = 0;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = value[prop_name].get<int>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>() ? 1 : 0;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = int(value[prop_name].get<float>());
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = std::atoi(value[prop_name].get<std::string>().c_str());
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<bool>(property.get_type())) {
-					bool value_tmp = false;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = value[prop_name].get<int>() > 1;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = value[prop_name].get<float>() > 1;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = value[prop_name].get<std::string>() == "true" || value[prop_name].get<std::string>() == "True" || value[prop_name].get<std::string>() == "TRUE" || value[prop_name].get<std::string>() == "1";
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<double>(property.get_type())) {
-					double value_tmp = 0;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = value[prop_name].get<int>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>() ? 1 : 0;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = value[prop_name].get<float>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = std::atof(value[prop_name].get<std::string>().c_str());
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<float>(property.get_type())) {
-					float value_tmp = 0;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = value[prop_name].get<int>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>() ? 1 : 0;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = value[prop_name].get<float>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = std::atof(value[prop_name].get<std::string>().c_str());
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<std::int64_t>(property.get_type())) {
-					std::int64_t value_tmp = 0;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = value[prop_name].get<std::int64_t>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>() ? 1 : 0;
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = std::int64_t(value[prop_name].get<float>());
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = std::atoll(value[prop_name].get<std::string>().c_str());
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<datetime>(property.get_type())) {
-					datetime value_tmp;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = (time_t)value[prop_name].get<std::int64_t>();
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = time_t(value[prop_name].get<float>());
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = value[prop_name].get<std::string>();
-					}
-					property.set_value(result, value_tmp);
-				}
-				else if (utils::rttr_type<std::string>(property.get_type())) {
-					std::string value_tmp;
-					if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
-						value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
-						value_tmp = std::to_string(value[prop_name].get<std::int64_t>());
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
-						value_tmp = value[prop_name].get<bool>() ? "true" : "false";
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
-						value_tmp = std::to_string(value[prop_name].get<float>());
-					}
-					else if (value[prop_name].type() == nlohmann::json::value_t::string) {
-						value_tmp = value[prop_name].get<std::string>();
-					}
-					property.set_value(result, value_tmp);
-				}
-				//list
-				else if (utils::rttr_type<std::vector<int>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<int> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(it.get<int>());
+					if (utils::rttr_type<int>(property.get_type())) {
+						int value_tmp = 0;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = value[prop_name].get<int>();
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>() ? 1 : 0);
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>() ? 1 : 0;
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(int(it.get<float>()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = int(value[prop_name].get<float>());
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(std::atoi(it.get<std::string>().c_str()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = std::atoi(value[prop_name].get<std::string>().c_str());
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<bool>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<bool> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(it.get<int>() > 1);
+					else if (utils::rttr_type<bool>(property.get_type())) {
+						bool value_tmp = false;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = value[prop_name].get<int>() > 1;
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>());
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>();
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(it.get<float>() > 1);
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = value[prop_name].get<float>() > 1;
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(it.get<std::string>() == "true" || it.get<std::string>() == "True" || it.get<std::string>() == "TRUE" || it.get<std::string>() == "1");
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = value[prop_name].get<std::string>() == "true" || value[prop_name].get<std::string>() == "True" || value[prop_name].get<std::string>() == "TRUE" || value[prop_name].get<std::string>() == "1";
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<double>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<double> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(it.get<int>());
+					else if (utils::rttr_type<double>(property.get_type())) {
+						double value_tmp = 0;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = value[prop_name].get<int>();
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>() ? 1 : 0);
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>() ? 1 : 0;
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(it.get<float>());
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = value[prop_name].get<float>();
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(std::atof(it.get<std::string>().c_str()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = std::atof(value[prop_name].get<std::string>().c_str());
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<float>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<float> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(it.get<int>());
+					else if (utils::rttr_type<float>(property.get_type())) {
+						float value_tmp = 0;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = value[prop_name].get<int>();
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>() ? 1 : 0);
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>() ? 1 : 0;
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(it.get<float>());
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = value[prop_name].get<float>();
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(std::atof(it.get<std::string>().c_str()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = std::atof(value[prop_name].get<std::string>().c_str());
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<std::int64_t> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(it.get<std::int64_t>());
+					else if (utils::rttr_type<std::int64_t>(property.get_type())) {
+						std::int64_t value_tmp = 0;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = value[prop_name].get<std::int64_t>();
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>() ? 1 : 0);
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>() ? 1 : 0;
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(std::int64_t(it.get<float>()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = std::int64_t(value[prop_name].get<float>());
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(std::atoll(it.get<std::string>().c_str()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = std::atoll(value[prop_name].get<std::string>().c_str());
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<datetime>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<datetime> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back((time_t)it.get<std::int64_t>());
+					else if (utils::rttr_type<datetime>(property.get_type())) {
+						datetime value_tmp;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = (time_t)value[prop_name].get<std::int64_t>();
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(time_t(it.get<float>()));
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = time_t(value[prop_name].get<float>());
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(it.get<std::string>());
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = value[prop_name].get<std::string>();
 						}
+						property.set_value(result, value_tmp);
 					}
-					property.set_value(result, item_list);
-				}
-				else if (utils::rttr_type<std::vector<std::string>>(property.get_type()) &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					std::vector<std::string> item_list;
-					nlohmann::json item_value = value[prop_name];
-					for (auto& it : item_value) {
-						if (it.type() == nlohmann::json::value_t::number_integer ||
-							it.type() == nlohmann::json::value_t::number_unsigned) {
-							item_list.push_back(std::to_string(it.get<std::int64_t>()));
+					else if (utils::rttr_type<std::string>(property.get_type())) {
+						std::string value_tmp;
+						if (value[prop_name].type() == nlohmann::json::value_t::number_integer ||
+							value[prop_name].type() == nlohmann::json::value_t::number_unsigned) {
+							value_tmp = std::to_string(value[prop_name].get<std::int64_t>());
+						}
+						else if (value[prop_name].type() == nlohmann::json::value_t::boolean) {
+							value_tmp = value[prop_name].get<bool>() ? "true" : "false";
+						}
+						else if (value[prop_name].type() == nlohmann::json::value_t::number_float) {
+							value_tmp = std::to_string(value[prop_name].get<float>());
+						}
+						else if (value[prop_name].type() == nlohmann::json::value_t::string) {
+							value_tmp = value[prop_name].get<std::string>();
+						}
+						property.set_value(result, value_tmp);
+					}
+					//list
+					else if (utils::rttr_type<std::vector<int>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<int> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(it.get<int>());
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>() ? 1 : 0);
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(int(it.get<float>()));
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(std::atoi(it.get<std::string>().c_str()));
+							}
 						}
-						else if (it.type() == nlohmann::json::value_t::boolean) {
-							item_list.push_back(it.get<bool>() ? "true" : "false");
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<bool>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<bool> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(it.get<int>() > 1);
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>());
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(it.get<float>() > 1);
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(it.get<std::string>() == "true" || it.get<std::string>() == "True" || it.get<std::string>() == "TRUE" || it.get<std::string>() == "1");
+							}
 						}
-						else if (it.type() == nlohmann::json::value_t::number_float) {
-							item_list.push_back(std::to_string(it.get<float>()));
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<double>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<double> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(it.get<int>());
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>() ? 1 : 0);
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(it.get<float>());
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(std::atof(it.get<std::string>().c_str()));
+							}
 						}
-						else if (it.type() == nlohmann::json::value_t::string) {
-							item_list.push_back(it.get<std::string>());
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<float>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<float> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(it.get<int>());
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>() ? 1 : 0);
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(it.get<float>());
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(std::atof(it.get<std::string>().c_str()));
+							}
 						}
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<std::int64_t> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(it.get<std::int64_t>());
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>() ? 1 : 0);
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(std::int64_t(it.get<float>()));
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(std::atoll(it.get<std::string>().c_str()));
+							}
+						}
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<datetime>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<datetime> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back((time_t)it.get<std::int64_t>());
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(time_t(it.get<float>()));
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(it.get<std::string>());
+							}
+						}
+						property.set_value(result, item_list);
+					}
+					else if (utils::rttr_type<std::vector<std::string>>(property.get_type()) &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						std::vector<std::string> item_list;
+						nlohmann::json item_value = value[prop_name];
+						for (auto& it : item_value) {
+							if (it.type() == nlohmann::json::value_t::number_integer ||
+								it.type() == nlohmann::json::value_t::number_unsigned) {
+								item_list.push_back(std::to_string(it.get<std::int64_t>()));
+							}
+							else if (it.type() == nlohmann::json::value_t::boolean) {
+								item_list.push_back(it.get<bool>() ? "true" : "false");
+							}
+							else if (it.type() == nlohmann::json::value_t::number_float) {
+								item_list.push_back(std::to_string(it.get<float>()));
+							}
+							else if (it.type() == nlohmann::json::value_t::string) {
+								item_list.push_back(it.get<std::string>());
+							}
+						}
+						property.set_value(result, item_list);
+					}
+					//object
+					else if (property.get_type().is_sequential_container() &&
+						value[prop_name].type() == nlohmann::json::value_t::array) {
+						rttr::variant var = property.get_value(result);
+						auto view = var.create_sequential_view();
+						size_t size = value[prop_name].size();
+						view.set_size(size);
+						for (size_t i = 0; i < size; ++i) {
+							rttr::variant var_tmp = view.get_value(i).extract_wrapped_value();
+							deserialize(value[prop_name][i], var_tmp);
+							view.set_value(i, var_tmp);
+						}
+						property.set_value(result, var);
+					}
+					//objectlist
+					else if (property.get_type().is_class() &&
+						value[prop_name].type() == nlohmann::json::value_t::object) {
+						rttr::variant child = property.get_value(result);
+						deserialize(value[prop_name], child);
+						property.set_value(result, child);
 					}
-					property.set_value(result, item_list);
 				}
-				//object
-				else if (property.get_type().is_sequential_container() &&
-					value[prop_name].type() == nlohmann::json::value_t::array) {
-					rttr::variant var = property.get_value(result);
-					auto view = var.create_sequential_view();
-					size_t size = value[prop_name].size();
-					view.set_size(size);
-					for (size_t i = 0; i < size; ++i) {
-						rttr::variant var_tmp = view.get_value(i).extract_wrapped_value();
-						deserialize(value[prop_name][i], var_tmp);
-						view.set_value(i, var_tmp);
-					}
-					property.set_value(result, var);
+			}
+		};
+		class json_convert {
+		public:
+			/**
+			 * @brief 序列化
+			 * @tparam _Type
+			 * @param value
+			 * @param result
+			 */
+			template<typename _Type>
+			static void serialize(_Type const& value, nlohmann::json& result) {
+				json_convert_impl::serialize(value, result);
+			}
+			/**
+			 * @brief 反序列化
+			 * @tparam _Type
+			 * @param value
+			 * @param result
+			 */
+			template<typename _Type>
+			static void deserialize(nlohmann::json const& value, _Type& result) {
+				json_convert_impl::deserialize(value, result);
+			}
+			/**
+			 * @brief 反序列化
+			 * @tparam _Type
+			 * @param value
+			 * @param result
+			 */
+			static void deserialize(std::string const& value, rttr::variant& result) {
+				nlohmann::json json = nlohmann::json::parse(value);
+				json_convert_impl::deserialize(json, result);
+			}
+			/**
+			 * @brief 序列化
+			 * @tparam _Type
+			 * @param value
+			 * @return
+			 */
+			template<typename _Type>
+			static std::string serialize(_Type const& value) {
+				nlohmann::json result;
+				if constexpr (is_specialization<_Type, std::vector>::value) {
+					result = nlohmann::json::array();
+					for (auto& it : value) {
+						nlohmann::json result_item;
+						serialize(it, result_item);
+						result.push_back(result_item);
+					}
 				}
-				//objectlist
-				else if (property.get_type().is_class() &&
-					value[prop_name].type() == nlohmann::json::value_t::object) {
-					rttr::variant child = property.get_value(result);
-					deserialize(value[prop_name], child);
-					property.set_value(result, child);
+				else {
+					serialize(value, result);
 				}
+				return result.dump();
 			}
-		}
-	};
-	class json_convert {
-	public:
-		/**
-		 * @brief 序列化
-		 * @tparam _Type
-		 * @param value
-		 * @param result
-		 */
-		template<typename _Type>
-		static void serialize(_Type const& value, nlohmann::json& result) {
-			json_convert_impl::serialize(value, result);
-		}
-		/**
-		 * @brief 反序列化
-		 * @tparam _Type
-		 * @param value
-		 * @param result
-		 */
-		template<typename _Type>
-		static void deserialize(nlohmann::json const& value, _Type& result) {
-			json_convert_impl::deserialize(value, result);
-		}
-		/**
-		 * @brief 反序列化
-		 * @tparam _Type
-		 * @param value
-		 * @param result
-		 */
-		static void deserialize(std::string const& value, rttr::variant& result) {
-			nlohmann::json json = nlohmann::json::parse(value);
-			json_convert_impl::deserialize(json, result);
-		}
-		/**
-		 * @brief 序列化
-		 * @tparam _Type
-		 * @param value
-		 * @return
-		 */
-		template<typename _Type>
-		static std::string serialize(_Type const& value) {
-			nlohmann::json result;
-			if constexpr (is_specialization<_Type, std::vector>::value) {
-				result = nlohmann::json::array();
-				for (auto& it : value) {
-					nlohmann::json result_item;
-					serialize(it, result_item);
-					result.push_back(result_item);
+			/**
+			 * @brief 反序列化
+			 * @tparam _Type
+			 * @param value
+			 * @param result
+			 */
+			template<typename _Type>
+			static _Type deserialize(std::string const& value) {
+				_Type result;
+				nlohmann::json json = nlohmann::json::parse(value);
+				if constexpr (is_specialization<_Type, std::vector>::value) {
+					if (json.type() != nlohmann::json::value_t::array)
+						throw std::runtime_error("not array");
+					for (size_t i = 0; i < json.size(); ++i) {
+						typename _Type::value_type result_item;
+						deserialize(json[i], result_item);
+						result.push_back(result_item);
+					}
 				}
-			}
-			else {
-				serialize(value, result);
-			}
-			return result.dump();
-		}
-		/**
-		 * @brief 反序列化
-		 * @tparam _Type
-		 * @param value
-		 * @param result
-		 */
-		template<typename _Type>
-		static _Type deserialize(std::string const& value) {
-			_Type result;
-			nlohmann::json json = nlohmann::json::parse(value);
-			if constexpr (is_specialization<_Type, std::vector>::value) {
-				if (json.type() != nlohmann::json::value_t::array)
-					throw std::runtime_error("not array");
-				for (size_t i = 0; i < json.size(); ++i) {
-					typename _Type::value_type result_item;
-					deserialize(json[i], result_item);
-					result.push_back(result_item);
+				else {
+					deserialize(json, result);
 				}
+				return result;
 			}
-			else {
-				deserialize(json, result);
+			/**
+			 * @brief 反序列化
+			 * @tparam _Type
+			 * @param value
+			 * @param result
+			 */
+			template<typename _Type>
+			static void deserialize(std::string const& value, _Type& result) {
+				result = deserialize<_Type>(value);
 			}
-			return result;
-		}
-		/**
-		 * @brief 反序列化
-		 * @tparam _Type
-		 * @param value
-		 * @param result
-		 */
-		template<typename _Type>
-		static void deserialize(std::string const& value, _Type& result) {
-			result = deserialize<_Type>(value);
-		}
-	};
+		};
+	}
 }

File diff suppressed because it is too large
+ 928 - 897
robot/robotics/linq.hpp


+ 35 - 33
robot/robotics/logger_impl.h

@@ -17,43 +17,45 @@
 #include "text_stream.hpp"
 #include "config.hpp"
 
-namespace robotics::v3 {
+namespace robotics {
+	namespace v3 {
 #ifdef WINDOWS_BUILD
-	class LOGGER_IMPL logger_impl {
+		class LOGGER_IMPL logger_impl {
 #elif LINUX_BUILD
-	class logger_impl {
+		class logger_impl {
 #endif
-	public:
-		~logger_impl();
-		void write(int color, std::string const& type, std::string const& time, std::string const& file, std::string const& func, int line, std::thread::id thread_id, std::string const& text);
-		static logger_impl& instance();
-		static void install(std::string const& filename = "./config/config.ini");
-	private:
-		explicit logger_impl();
-		void backup(std::string const& filename);
-		void remove();
-	private:
-		int max_time_ = 30;
-		int max_size_ = 10;
-		std::set<std::string> save_;
-		asio::thread_pool thread_pool_;
-	};
+		public:
+			~logger_impl();
+			void write(int color, std::string const& type, std::string const& time, std::string const& file, std::string const& func, int line, std::thread::id thread_id, std::string const& text);
+			static logger_impl& instance();
+			static void install(std::string const& filename = "./config/config.ini");
+		private:
+			explicit logger_impl();
+			void backup(std::string const& filename);
+			void remove();
+		private:
+			int max_time_ = 30;
+			int max_size_ = 10;
+			std::set<std::string> save_;
+			asio::thread_pool thread_pool_;
+		};
 #ifdef WINDOWS_BUILD
-	class LOGGER_IMPL logger_stream {
+		class LOGGER_IMPL logger_stream {
 #elif LINUX_BUILD
-	class logger_stream {
+		class logger_stream {
 #endif
-	public:
-		explicit logger_stream(int color, std::string const& type, std::string const& time, std::string const& file, std::string const& func, int line, std::thread::id thread_id);
-		~logger_stream();
-		text_stream stream;
-	private:
-		std::string type_;
-		std::string time_;
-		std::string file_;
-		std::string func_;
-		int line_ = 0;
-		int color_ = 37;
-		std::thread::id thread_id_;
-	};
+		public:
+			explicit logger_stream(int color, std::string const& type, std::string const& time, std::string const& file, std::string const& func, int line, std::thread::id thread_id);
+			~logger_stream();
+			text_stream stream;
+		private:
+			std::string type_;
+			std::string time_;
+			std::string file_;
+			std::string func_;
+			int line_ = 0;
+			int color_ = 37;
+			std::thread::id thread_id_;
+		};
+	}
 }

+ 87 - 85
robot/robotics/message_bus.hpp

@@ -18,92 +18,94 @@
 //robotics
 #include "function_traits.hpp"
 
-namespace robotics::v3 {
-	class message_bus :boost::noncopyable {
-	public:
-		~message_bus() {
-			map_.clear();
-		}
-		/**
-		 * @brief 注册消息
-		 * @tparam _Fn
-		 * @param str_topic
-		 * @param f
-		 */
-		template<typename _Fn>
-		void bind(const std::string& str_topic, _Fn&& f) {
-			auto func = v3::to_function(std::forward<_Fn>(f));
-			add(str_topic, std::move(func));
-		}
-		/**
-		 * @brief 注册消息
-		 * @tparam _Fn
-		 * @tparam _Obj
-		 * @param str_topic
-		 * @param f
-		 * @param obj
-		 */
-		template<typename _Fn, typename _Obj>
-		void bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
-			auto func = v3::to_function(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj)));
-			add(str_topic, std::move(func));
-		}
-		/**
-		 * @brief 发送消息
-		 * @param str_topic
-		 */
-		void call(const std::string& str_topic) {
-			using function_type = std::function<void()>;
-			std::string str_msg_type = str_topic + typeid(function_type).name();
-			auto range = map_.equal_range(str_msg_type);
-			for (Iterater it = range.first; it != range.second; ++it) {
-				std::any_cast<function_type>(it->second)();
+namespace robotics {
+	namespace v3 {
+		class message_bus :boost::noncopyable {
+		public:
+			~message_bus() {
+				map_.clear();
 			}
-		}
-		/**
-		 * @brief 发送消息
-		 * @tparam ..._Args
-		 * @param str_topic
-		 * @param ...args
-		 */
-		template<typename... _Args>
-		void call(const std::string& str_topic, _Args ...args) {
-			using function_type = std::function<void(_Args...)>;
-			std::string str_msg_type = str_topic + typeid(function_type).name();
-			auto range = map_.equal_range(str_msg_type);
-			for (Iterater it = range.first; it != range.second; ++it) {
-				std::any_cast<function_type>(it->second)(args...);
+			/**
+			 * @brief 注册消息
+			 * @tparam _Fn
+			 * @param str_topic
+			 * @param f
+			 */
+			template<typename _Fn>
+			void bind(const std::string& str_topic, _Fn&& f) {
+				auto func = v3::to_function(std::forward<_Fn>(f));
+				add(str_topic, std::move(func));
 			}
-		}
-		/**
-		 * @brief 移除某个主题,需要主题和消息类型
-		 * @tparam ...Args
-		 * @param strTopic
-		 */
-		template<typename..._Args>
-		void remove(const std::string& str_topic) {
-			using function_type = std::function<void(_Args...)>;
-			std::string str_msg_type = str_topic + typeid(function_type).name();
-			auto range = map_.equal_range(str_msg_type);
-			while (range.first != range.second) {
-				range.first = map_.erase(range.first);
-				++range.first;
+			/**
+			 * @brief 注册消息
+			 * @tparam _Fn
+			 * @tparam _Obj
+			 * @param str_topic
+			 * @param f
+			 * @param obj
+			 */
+			template<typename _Fn, typename _Obj>
+			void bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
+				auto func = v3::to_function(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj)));
+				add(str_topic, std::move(func));
 			}
-		}
-	private:
-		/**
-		 * @brief 添加
-		 * @tparam _Fn
-		 * @param str_topic
-		 * @param f
-		 */
-		template<typename _Fn>
-		void add(const std::string& str_topic, _Fn&& f) {
-			std::string str_msg_type = str_topic + typeid(f).name();
-			map_.emplace(std::move(str_msg_type), std::forward<_Fn>(f));
-		}
-	private:
-		std::multimap<std::string, std::any> map_;
-		typedef std::multimap<std::string, std::any>::iterator Iterater;
-	};
+			/**
+			 * @brief 发送消息
+			 * @param str_topic
+			 */
+			void call(const std::string& str_topic) {
+				using function_type = std::function<void()>;
+				std::string str_msg_type = str_topic + typeid(function_type).name();
+				auto range = map_.equal_range(str_msg_type);
+				for (Iterater it = range.first; it != range.second; ++it) {
+					std::any_cast<function_type>(it->second)();
+				}
+			}
+			/**
+			 * @brief 发送消息
+			 * @tparam ..._Args
+			 * @param str_topic
+			 * @param ...args
+			 */
+			template<typename... _Args>
+			void call(const std::string& str_topic, _Args ...args) {
+				using function_type = std::function<void(_Args...)>;
+				std::string str_msg_type = str_topic + typeid(function_type).name();
+				auto range = map_.equal_range(str_msg_type);
+				for (Iterater it = range.first; it != range.second; ++it) {
+					std::any_cast<function_type>(it->second)(args...);
+				}
+			}
+			/**
+			 * @brief 移除某个主题,需要主题和消息类型
+			 * @tparam ...Args
+			 * @param strTopic
+			 */
+			template<typename..._Args>
+			void remove(const std::string& str_topic) {
+				using function_type = std::function<void(_Args...)>;
+				std::string str_msg_type = str_topic + typeid(function_type).name();
+				auto range = map_.equal_range(str_msg_type);
+				while (range.first != range.second) {
+					range.first = map_.erase(range.first);
+					++range.first;
+				}
+			}
+		private:
+			/**
+			 * @brief 添加
+			 * @tparam _Fn
+			 * @param str_topic
+			 * @param f
+			 */
+			template<typename _Fn>
+			void add(const std::string& str_topic, _Fn&& f) {
+				std::string str_msg_type = str_topic + typeid(f).name();
+				map_.emplace(std::move(str_msg_type), std::forward<_Fn>(f));
+			}
+		private:
+			std::multimap<std::string, std::any> map_;
+			typedef std::multimap<std::string, std::any>::iterator Iterater;
+		};
+	}
 }

File diff suppressed because it is too large
+ 950 - 945
robot/robotics/mvc.hpp


+ 806 - 803
robot/robotics/nexus_net_client.hpp

@@ -17,884 +17,887 @@
 #include <robotics/config.hpp>
 #include <robotics/timer.hpp>
 
-namespace robotics::v3 {
-    template<typename _Type>
-    class match_role {
-    public:
-        /**
-         * @brief 默认构造
-         */
-        explicit match_role() {}
-        /**
-         * @brief 构造
-         * @param session
-         */
-        explicit match_role(std::shared_ptr<_Type> const& session) :
-            session_(session) {
-        }
-        /**
-         * @brief 解包
-         * @tparam Iterator
-         * @param begin
-         * @param end
-         * @return
-         */
-        template <typename Iterator>
-        std::pair<Iterator, bool> operator()(Iterator begin, Iterator end) const {
-            Iterator p = begin;
-            while (p != end) {
-                //判断协议头
-                if (*p != 0x02) {
-                    asio2::error_code ec;
-                    session_->socket().close(ec);
-                    break;
-                }
-                //获取数据长度
-                size_t size = size_t(std::uint8_t(*(++p))) << 24;
-                size += size_t(std::uint8_t(*(++p))) << 16;
-                size += size_t(std::uint8_t(*(++p))) << 8;
-                size += size_t(std::uint8_t(*(++p))) << 0;
-
-                if (end - begin >= size) {
-                    if (*(begin + size - 1) == 0x03) {
-                        return std::pair(begin + size, true);
-                    }
-                    else {
+namespace robotics {
+    namespace v3 {
+        template<typename _Type>
+        class match_role {
+        public:
+            /**
+             * @brief 默认构造
+             */
+            explicit match_role() {}
+            /**
+             * @brief 构造
+             * @param session
+             */
+            explicit match_role(std::shared_ptr<_Type> const& session) :
+                session_(session) {
+            }
+            /**
+             * @brief 解包
+             * @tparam Iterator
+             * @param begin
+             * @param end
+             * @return
+             */
+            template <typename Iterator>
+            std::pair<Iterator, bool> operator()(Iterator begin, Iterator end) const {
+                Iterator p = begin;
+                while (p != end) {
+                    //判断协议头
+                    if (*p != 0x02) {
                         asio2::error_code ec;
                         session_->socket().close(ec);
+                        break;
+                    }
+                    //获取数据长度
+                    size_t size = size_t(std::uint8_t(*(++p))) << 24;
+                    size += size_t(std::uint8_t(*(++p))) << 16;
+                    size += size_t(std::uint8_t(*(++p))) << 8;
+                    size += size_t(std::uint8_t(*(++p))) << 0;
+
+                    if (end - begin >= size) {
+                        if (*(begin + size - 1) == 0x03) {
+                            return std::pair(begin + size, true);
+                        }
+                        else {
+                            asio2::error_code ec;
+                            session_->socket().close(ec);
+                        }
                     }
+                    break;
                 }
-                break;
+                return std::pair(begin, false);
             }
-            return std::pair(begin, false);
-        }
-        /**
-         * @brief 初始化
-         * @param session
-         */
-        void init(std::shared_ptr<asio2::tcp_session>& session) {
-            session_ = session;
-        }
-    private:
-        /**
-         * @brief 客户端
-         */
-        std::shared_ptr<_Type> session_;
-    };
+            /**
+             * @brief 初始化
+             * @param session
+             */
+            void init(std::shared_ptr<asio2::tcp_session>& session) {
+                session_ = session;
+            }
+        private:
+            /**
+             * @brief 客户端
+             */
+            std::shared_ptr<_Type> session_;
+        };
+    }
 }
 template<> struct asio::is_match_condition<robotics::v3::match_role<asio2::tcp_client>> : public  std::true_type {};
 template<> struct asio::is_match_condition<robotics::v3::match_role<asio2::tcp_session>> : public std::true_type {};
-namespace robotics::v3 {
-    /**
-     * @brief 消息类型
-     */
-    enum class nexus_net_msg_type_enum {
-        /**
-         * @brief 身份认证
-         */
-        AUTHENTICATE = 1,
-        /**
-         * @brief 身份认证响应
-        */
-        REPAUTHENTICATE,
-        /**
-         * @brief 订阅
-         */
-        SUBSCRIBE,
-        /**
-         * @brief 删除订阅
-         */
-        REMOVESUBSCRIBE,
-        /**
-         * @brief 发布
-         */
-        PUBLISHER,
-        /**
-         * @brief 发布响应
-         */
-        REPPUBLISHER,
-        /**
-         * @brief 心跳
-         */
-        HEARTBEAT,
+namespace robotics {
+    namespace v3 {
         /**
-         * @brief 详情
-         */
-        DETAILS,
-        /**
-         * @brief 详情响应
-         */
-        REPDETAILS
-    };
-    /**
-     * @brief 消息
-     */
-    class nexus_net_message {
-    public:
-        /**
-         * @brief 构造
-         */
-        nexus_net_message() {}
-        /**
-         * @brief 构造
-         * @param sv
-         */
-        nexus_net_message(std::string_view sv) {
-            set_data(sv);
-        }
-        /**
-         * @brief 构造
-         * @param data
-         */
-        nexus_net_message(std::vector<std::uint8_t>const& data) {
-            set_data(data);
-        }
-        /**
-         * @brief 设置
-         * @param sv
-         */
-        void set_data(std::string_view sv) {
-            set_data(std::vector<std::uint8_t>(sv.begin(), sv.end()));
-        }
-        /**
-         * @brief 设置
-         * @param data
+         * @brief 消息类型
          */
-        void set_data(std::vector<std::uint8_t>const& data) {
-            //消息类型
-            msg_type = data[5];
-            //消息ID
-            size_t size = data[6];
-            size_t begin = 7;
-            size_t end = begin + size;
-            msg_id.assign(data.begin() + begin, data.begin() + end);
-            //路由
-            size = data[end];
-            begin = end + 1;
-            end = begin + size;
-            route.assign(data.begin() + begin, data.begin() + end);
-            //路由列表
-            size = data[end] << 8;
-            size += data[++end];
-            begin = end + 1;
-            end = begin + size;
-            if (size > 0) {
-                std::string str_routes(data.begin() + begin, data.begin() + end);
-                routes = v3::utils::split(str_routes, 0x0d);
-            }
-            //参数
-            size = (data[end] << 24);
-            size += (data[++end] << 16);
-            size += (data[++end] << 8);
-            size += data[++end];
-            begin = end + 1;
-            end = begin + size;
-            args.add(std::vector<std::uint8_t>(data.begin() + begin, data.begin() + end));
-        }
+        enum class nexus_net_msg_type_enum {
+            /**
+             * @brief 身份认证
+             */
+            AUTHENTICATE = 1,
+            /**
+             * @brief 身份认证响应
+            */
+            REPAUTHENTICATE,
+            /**
+             * @brief 订阅
+             */
+            SUBSCRIBE,
+            /**
+             * @brief 删除订阅
+             */
+            REMOVESUBSCRIBE,
+            /**
+             * @brief 发布
+             */
+            PUBLISHER,
+            /**
+             * @brief 发布响应
+             */
+            REPPUBLISHER,
+            /**
+             * @brief 心跳
+             */
+            HEARTBEAT,
+            /**
+             * @brief 详情
+             */
+            DETAILS,
+            /**
+             * @brief 详情响应
+             */
+            REPDETAILS
+        };
         /**
-         * @brief 获取
-         * @return
+         * @brief 消息
          */
-        std::vector<std::uint8_t> get_data() {
-            std::vector<std::uint8_t> result;
-            //协议头
-            result.push_back(0x02);
-            //字节数量
-            result.push_back(0x00);
-            result.push_back(0x00);
-            result.push_back(0x00);
-            result.push_back(0x00);
-            //消息类型
-            result.push_back(msg_type);
-            //消息ID
-            result.push_back(msg_id.size());
-            result.insert(result.end(), msg_id.begin(), msg_id.end());
-            //路由
-            result.push_back(route.size());
-            result.insert(result.end(), route.begin(), route.end());
-            //路由列表
-            std::vector<std::uint8_t> vec_routes;
-            for (size_t i = 0; i < routes.size(); ++i) {
-                if (i + 1 == routes.size()) {
-                    vec_routes.insert(vec_routes.end(), routes[i].begin(), routes[i].end());
+        class nexus_net_message {
+        public:
+            /**
+             * @brief 构造
+             */
+            nexus_net_message() {}
+            /**
+             * @brief 构造
+             * @param sv
+             */
+            nexus_net_message(std::string_view sv) {
+                set_data(sv);
+            }
+            /**
+             * @brief 构造
+             * @param data
+             */
+            nexus_net_message(std::vector<std::uint8_t>const& data) {
+                set_data(data);
+            }
+            /**
+             * @brief 设置
+             * @param sv
+             */
+            void set_data(std::string_view sv) {
+                set_data(std::vector<std::uint8_t>(sv.begin(), sv.end()));
+            }
+            /**
+             * @brief 设置
+             * @param data
+             */
+            void set_data(std::vector<std::uint8_t>const& data) {
+                //消息类型
+                msg_type = data[5];
+                //消息ID
+                size_t size = data[6];
+                size_t begin = 7;
+                size_t end = begin + size;
+                msg_id.assign(data.begin() + begin, data.begin() + end);
+                //路由
+                size = data[end];
+                begin = end + 1;
+                end = begin + size;
+                route.assign(data.begin() + begin, data.begin() + end);
+                //路由列表
+                size = data[end] << 8;
+                size += data[++end];
+                begin = end + 1;
+                end = begin + size;
+                if (size > 0) {
+                    std::string str_routes(data.begin() + begin, data.begin() + end);
+                    routes = v3::utils::split(str_routes, 0x0d);
                 }
-                else {
-                    vec_routes.insert(vec_routes.end(), routes[i].begin(), routes[i].end());
-                    vec_routes.push_back(0x0d);
-                }
-            }
-            result.push_back(vec_routes.size() >> 8);
-            result.push_back(vec_routes.size() >> 0);
-            result.insert(result.end(), vec_routes.begin(), vec_routes.end());
-            //参数
-            std::vector<std::uint8_t> vec_args = args.data();
-            result.push_back(vec_args.size() >> 24);
-            result.push_back(vec_args.size() >> 16);
-            result.push_back(vec_args.size() >> 8);
-            result.push_back(vec_args.size() >> 0);
-            result.insert(result.end(), vec_args.begin(), vec_args.end());
-            //协议尾
-            result.push_back(0x03);
+                //参数
+                size = (data[end] << 24);
+                size += (data[++end] << 16);
+                size += (data[++end] << 8);
+                size += data[++end];
+                begin = end + 1;
+                end = begin + size;
+                args.add(std::vector<std::uint8_t>(data.begin() + begin, data.begin() + end));
+            }
+            /**
+             * @brief 获取
+             * @return
+             */
+            std::vector<std::uint8_t> get_data() {
+                std::vector<std::uint8_t> result;
+                //协议头
+                result.push_back(0x02);
+                //字节数量
+                result.push_back(0x00);
+                result.push_back(0x00);
+                result.push_back(0x00);
+                result.push_back(0x00);
+                //消息类型
+                result.push_back(msg_type);
+                //消息ID
+                result.push_back(msg_id.size());
+                result.insert(result.end(), msg_id.begin(), msg_id.end());
+                //路由
+                result.push_back(route.size());
+                result.insert(result.end(), route.begin(), route.end());
+                //路由列表
+                std::vector<std::uint8_t> vec_routes;
+                for (size_t i = 0; i < routes.size(); ++i) {
+                    if (i + 1 == routes.size()) {
+                        vec_routes.insert(vec_routes.end(), routes[i].begin(), routes[i].end());
+                    }
+                    else {
+                        vec_routes.insert(vec_routes.end(), routes[i].begin(), routes[i].end());
+                        vec_routes.push_back(0x0d);
+                    }
+                }
+                result.push_back(vec_routes.size() >> 8);
+                result.push_back(vec_routes.size() >> 0);
+                result.insert(result.end(), vec_routes.begin(), vec_routes.end());
+                //参数
+                std::vector<std::uint8_t> vec_args = args.data();
+                result.push_back(vec_args.size() >> 24);
+                result.push_back(vec_args.size() >> 16);
+                result.push_back(vec_args.size() >> 8);
+                result.push_back(vec_args.size() >> 0);
+                result.insert(result.end(), vec_args.begin(), vec_args.end());
+                //协议尾
+                result.push_back(0x03);
 
-            result[1] = (result.size() >> 24);
-            result[2] = (result.size() >> 16);
-            result[3] = (result.size() >> 8);
-            result[4] = (result.size() >> 0);
-            return result;
-        }
-    public:
-        /**
-         * @brief 消息类型
-         */
-        std::uint8_t msg_type = 0;
-        /**
-         * @brief 消息ID
-         */
-        std::string msg_id;
-        /**
-         * @brief 路由
-         */
-        std::string route;
-        /**
-         * @brief 路由列表
-         */
-        std::vector<std::string> routes;
-        /**
-         * @brief 参数
-         */
-        v3::archive::stream args;
-    };
-    /**
-     * @brief 日志类型
-     */
-    struct nexus_net_logger_config_info {
+                result[1] = (result.size() >> 24);
+                result[2] = (result.size() >> 16);
+                result[3] = (result.size() >> 8);
+                result[4] = (result.size() >> 0);
+                return result;
+            }
+        public:
+            /**
+             * @brief 消息类型
+             */
+            std::uint8_t msg_type = 0;
+            /**
+             * @brief 消息ID
+             */
+            std::string msg_id;
+            /**
+             * @brief 路由
+             */
+            std::string route;
+            /**
+             * @brief 路由列表
+             */
+            std::vector<std::string> routes;
+            /**
+             * @brief 参数
+             */
+            v3::archive::stream args;
+        };
         /**
          * @brief 日志类型
          */
-        int type = 0;
-        /**
-         * @brief 启用
-         */
-        bool enable = false;
-        /**
-         * @brief 备注
-         */
-        std::string remarks;
-    };
-    /**
-     * @brief 父节点配置
-     */
-    struct nexus_net_client_config_info {
-        /**
-         * @brief IP地址
-         */
-        std::string ip;
-        /**
-         * @brief 端口
-         */
-        int port = 0;
-        /**
-         * @brief 启用
-         */
-        bool enable = false;
-        /**
-         * @brief 备注
-         */
-        std::string remarks;
-    };
-    /**
-     * @brief 订阅配置
-     */
-    struct nexus_net_subscribe_config_info {
-        /**
-         * @brief KEY
-         */
-        std::string key;
-        /**
-         * @brief 路由
-         */
-        std::string route;
-        /**
-         * @brief 启用
-         */
-        bool enable = false;
-        /**
-         * @brief 备注
-         */
-        std::string remarks;
-    };
-    /**
-     * @brief 发布配置
-     */
-    struct nexus_net_publisher_config_info {
-        /**
-         * @brief KEY
-         */
-        std::string key;
-        /**
-         * @brief 节点
-         */
-        std::string route;
-        /**
-         * @brief 启用
-         */
-        bool enable = false;
-        /**
-         * @brief 备注
-         */
-        std::string remarks;
-    };
-    /**
-     * @brief 用户信息
-     */
-    struct nexus_net_user_config_info {
-        /**
-         * @brief 名称
-         */
-        std::string name;
+        struct nexus_net_logger_config_info {
+            /**
+             * @brief 日志类型
+             */
+            int type = 0;
+            /**
+             * @brief 启用
+             */
+            bool enable = false;
+            /**
+             * @brief 备注
+             */
+            std::string remarks;
+        };
         /**
-         * @brief 代码
+         * @brief 父节点配置
          */
-        std::string code;
+        struct nexus_net_client_config_info {
+            /**
+             * @brief IP地址
+             */
+            std::string ip;
+            /**
+             * @brief 端口
+             */
+            int port = 0;
+            /**
+             * @brief 启用
+             */
+            bool enable = false;
+            /**
+             * @brief 备注
+             */
+            std::string remarks;
+        };
         /**
-         * @brief 密码
+         * @brief 订阅配置
          */
-        std::string password;
+        struct nexus_net_subscribe_config_info {
+            /**
+             * @brief KEY
+             */
+            std::string key;
+            /**
+             * @brief 路由
+             */
+            std::string route;
+            /**
+             * @brief 启用
+             */
+            bool enable = false;
+            /**
+             * @brief 备注
+             */
+            std::string remarks;
+        };
         /**
-         * @brief 启用
+         * @brief 发布配置
          */
-        bool enable = false;
+        struct nexus_net_publisher_config_info {
+            /**
+             * @brief KEY
+             */
+            std::string key;
+            /**
+             * @brief 节点
+             */
+            std::string route;
+            /**
+             * @brief 启用
+             */
+            bool enable = false;
+            /**
+             * @brief 备注
+             */
+            std::string remarks;
+        };
         /**
-         * @brief 备注
+         * @brief 用户信息
          */
-        std::string remarks;
-    };
-    /**
-     * @brief 配置
-     */
-    struct nexus_net_config_info {
+        struct nexus_net_user_config_info {
+            /**
+             * @brief 名称
+             */
+            std::string name;
+            /**
+             * @brief 代码
+             */
+            std::string code;
+            /**
+             * @brief 密码
+             */
+            std::string password;
+            /**
+             * @brief 启用
+             */
+            bool enable = false;
+            /**
+             * @brief 备注
+             */
+            std::string remarks;
+        };
         /**
-         * @brief 身份
+         * @brief 配置
          */
-        nexus_net_user_config_info user;
+        struct nexus_net_config_info {
+            /**
+             * @brief 身份
+             */
+            nexus_net_user_config_info user;
+            /**
+             * @brief 日志
+             */
+            std::vector<nexus_net_logger_config_info> loggers;
+            /**
+             * @brief 客户端
+             */
+            nexus_net_client_config_info client;
+            /**
+             * @brief 订阅
+             */
+            std::map<std::string, nexus_net_subscribe_config_info> subscribes;
+            /**
+             * @brief 发布
+             */
+            std::map<std::string, nexus_net_publisher_config_info> publishers;
+        };
         /**
-         * @brief 日志
+         * @brief nexusnet配置
          */
-        std::vector<nexus_net_logger_config_info> loggers;
+        class nexus_net_config {
+        public:
+            static nexus_net_config_info& read() {
+                static std::shared_ptr<nexus_net_config_info> result;
+                static std::mutex mutex;
+                std::lock_guard<std::mutex> locker(mutex);
+                if (result)
+                    return *result;
+                result.reset(new nexus_net_config_info());
+                boost::property_tree::ptree root;
+                read_xml(v3::config::read<std::string>("NEXUS_NET", "PATH", "./config/nexus_net_config.xml"), root);
+                //身份信息
+                for (auto& it : root.get_child("root.user")) {
+                    if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
+                        continue;
+                    result->user.name = it.second.get<std::string>("<xmlattr>.name", "admin");
+                    result->user.code = it.second.get<std::string>("<xmlattr>.code", "admin");
+                    result->user.password = it.second.get<std::string>("<xmlattr>.password", "123456");
+                    result->user.enable = it.second.get<bool>("<xmlattr>.enable", true);
+                    result->user.remarks = it.second.get<std::string>("<xmlattr>.remarks", "身份信息");
+                    break;
+                }
+                //日志
+                for (auto& it : root.get_child("root.logger")) {
+                    if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
+                        continue;
+                    nexus_net_logger_config_info item;
+                    item.type = it.second.get<int>("<xmlattr>.type", 0);
+                    item.enable = it.second.get<bool>("<xmlattr>.enable", true);
+                    item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "日志");
+                    result->loggers.push_back(item);
+                }
+                //客户端
+                for (auto& it : root.get_child("root.client")) {
+                    if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
+                        continue;
+                    result->client.ip = it.second.get<std::string>("<xmlattr>.ip", "127.0.0.1");
+                    result->client.port = it.second.get<int>("<xmlattr>.port", 20001);
+                    result->client.enable = it.second.get<bool>("<xmlattr>.enable", false);
+                    result->client.remarks = it.second.get<std::string>("<xmlattr>.remarks", "客户");
+                    break;
+                }
+                //订阅
+                for (auto& it : root.get_child("root.subscribe")) {
+                    if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
+                        continue;
+                    nexus_net_subscribe_config_info item;
+                    item.key = it.second.get<std::string>("<xmlattr>.key", "");
+                    item.route = it.second.get<std::string>("<xmlattr>.route", "");
+                    item.enable = it.second.get<bool>("<xmlattr>.enable", false);
+                    item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "白名单");
+                    result->subscribes[item.key] = item;
+                }
+                //发布
+                for (auto& it : root.get_child("root.publisher")) {
+                    if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
+                        continue;
+                    nexus_net_publisher_config_info item;
+                    item.key = it.second.get<std::string>("<xmlattr>.key", "");
+                    item.route = it.second.get<std::string>("<xmlattr>.route", "");
+                    item.enable = it.second.get<bool>("<xmlattr>.enable", false);
+                    item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "白名单");
+                    result->publishers[item.key] = item;
+                }
+                return *result;
+            }
+            static void logger(bool success, bool is_out, nexus_net_message value) {
+                static std::map<std::uint8_t, std::string> g_msg_type = {
+                    {(std::uint8_t)nexus_net_msg_type_enum::AUTHENTICATE,     "身份认证"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::REPAUTHENTICATE,  "身份认证响应"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE,        "订阅"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::REMOVESUBSCRIBE,  "删除订阅"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::PUBLISHER,        "发布"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER,     "发布响应"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::HEARTBEAT,        "心跳"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::DETAILS,          "详情"},
+                    {(std::uint8_t)nexus_net_msg_type_enum::REPDETAILS,       "详情响应"}
+                };
+                auto config = read();
+                auto it = std::find_if(config.loggers.begin(), config.loggers.end(), [=](auto& it) {
+                    return it.type == value.msg_type && it.enable; });
+                if (it != config.loggers.end()) {
+                    if (success) {
+                        LOG_INFO << (is_out ? "接收成功" : "发送成功") << ",消息类型:" << g_msg_type[value.msg_type] << " 消息ID:" << value.msg_id << " 事件:" << value.route << " 路由:" << value.routes;
+                    }
+                    else {
+                        LOG_ERROR << (is_out ? "接收失败" : "发送失败") << ",消息类型:" << g_msg_type[value.msg_type] << " 消息ID:" << value.msg_id << " 事件:" << value.route << " 路由:" << value.routes;
+                    }
+                }
+            }
+        };
         /**
          * @brief 客户端
          */
-        nexus_net_client_config_info client;
-        /**
-         * @brief 订阅
-         */
-        std::map<std::string, nexus_net_subscribe_config_info> subscribes;
+        class nexus_net_tcp_client {
+        public:
+            nexus_net_tcp_client() :
+                client_(new asio2::tcp_client()) {
+                client_->bind_connect(&nexus_net_tcp_client::on_connect, this);
+                client_->bind_disconnect(&nexus_net_tcp_client::on_disconnect, this);
+                client_->bind_recv(&nexus_net_tcp_client::on_recv, this);
+            }
+            void start(std::string const& ip, int port) {
+                client_->async_start(ip, port, match_role<asio2::tcp_client>(client_));
+            }
+            void stop() {
+                client_->stop();
+            }
+            void send(nexus_net_message& data, std::function<void()> const& fn) {
+                client_->async_send(data.get_data(), fn);
+            }
+            v3::delegates<bool, std::string const&> connect_event;
+            v3::delegates<>                         disconnect_event;
+            v3::delegates<nexus_net_message const&> recv_event;
+        private:
+            void on_connect() {
+                connect_event(!asio2::get_last_error(), asio2::get_last_error_msg());
+            }
+            void on_disconnect() {
+                disconnect_event();
+            }
+            void on_recv(std::string_view sv) {
+                recv_event(nexus_net_message(sv));
+            }
+        private:
+            std::shared_ptr<asio2::tcp_client> client_;
+        };
         /**
-         * @brief 发布
+         * @brief 客户端
          */
-        std::map<std::string, nexus_net_publisher_config_info> publishers;
-    };
-    /**
-     * @brief nexusnet配置
-     */
-    class nexus_net_config {
-    public:
-        static nexus_net_config_info& read() {
-            static std::shared_ptr<nexus_net_config_info> result;
-            static std::mutex mutex;
-            std::lock_guard<std::mutex> locker(mutex);
-            if (result)
-                return *result;
-            result.reset(new nexus_net_config_info());
-            boost::property_tree::ptree root;
-            read_xml(v3::config::read<std::string>("NEXUS_NET", "PATH", "./config/nexus_net_config.xml"), root);
-            //身份信息
-            for (auto& it : root.get_child("root.user")) {
-                if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
-                    continue;
-                result->user.name = it.second.get<std::string>("<xmlattr>.name", "admin");
-                result->user.code = it.second.get<std::string>("<xmlattr>.code", "admin");
-                result->user.password = it.second.get<std::string>("<xmlattr>.password", "123456");
-                result->user.enable = it.second.get<bool>("<xmlattr>.enable", true);
-                result->user.remarks = it.second.get<std::string>("<xmlattr>.remarks", "身份信息");
-                break;
-            }
-            //日志
-            for (auto& it : root.get_child("root.logger")) {
-                if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
-                    continue;
-                nexus_net_logger_config_info item;
-                item.type = it.second.get<int>("<xmlattr>.type", 0);
-                item.enable = it.second.get<bool>("<xmlattr>.enable", true);
-                item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "日志");
-                result->loggers.push_back(item);
-            }
-            //客户端
-            for (auto& it : root.get_child("root.client")) {
-                if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
-                    continue;
-                result->client.ip = it.second.get<std::string>("<xmlattr>.ip", "127.0.0.1");
-                result->client.port = it.second.get<int>("<xmlattr>.port", 20001);
-                result->client.enable = it.second.get<bool>("<xmlattr>.enable", false);
-                result->client.remarks = it.second.get<std::string>("<xmlattr>.remarks", "客户");
-                break;
-            }
-            //订阅
-            for (auto& it : root.get_child("root.subscribe")) {
-                if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
-                    continue;
-                nexus_net_subscribe_config_info item;
-                item.key = it.second.get<std::string>("<xmlattr>.key", "");
-                item.route = it.second.get<std::string>("<xmlattr>.route", "");
-                item.enable = it.second.get<bool>("<xmlattr>.enable", false);
-                item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "白名单");
-                result->subscribes[item.key] = item;
-            }
-            //发布
-            for (auto& it : root.get_child("root.publisher")) {
-                if (it.first != "item" || !it.second.get<bool>("<xmlattr>.enable", false))
-                    continue;
-                nexus_net_publisher_config_info item;
-                item.key = it.second.get<std::string>("<xmlattr>.key", "");
-                item.route = it.second.get<std::string>("<xmlattr>.route", "");
-                item.enable = it.second.get<bool>("<xmlattr>.enable", false);
-                item.remarks = it.second.get<std::string>("<xmlattr>.remarks", "白名单");
-                result->publishers[item.key] = item;
-            }
-            return *result;
-        }
-        static void logger(bool success, bool is_out, nexus_net_message value) {
-            static std::map<std::uint8_t, std::string> g_msg_type = {
-                {(std::uint8_t)nexus_net_msg_type_enum::AUTHENTICATE,     "身份认证"},
-                {(std::uint8_t)nexus_net_msg_type_enum::REPAUTHENTICATE,  "身份认证响应"},
-                {(std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE,        "订阅"},
-                {(std::uint8_t)nexus_net_msg_type_enum::REMOVESUBSCRIBE,  "删除订阅"},
-                {(std::uint8_t)nexus_net_msg_type_enum::PUBLISHER,        "发布"},
-                {(std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER,     "发布响应"},
-                {(std::uint8_t)nexus_net_msg_type_enum::HEARTBEAT,        "心跳"},
-                {(std::uint8_t)nexus_net_msg_type_enum::DETAILS,          "详情"},
-                {(std::uint8_t)nexus_net_msg_type_enum::REPDETAILS,       "详情响应"}
+        class nexus_net_client : public v3::thread_pool<nexus_net_client> {
+        private:
+            class message_manage_gc;
+            /**
+             * @brief 消息管理
+             */
+            class message_manage {
+            private:
+                friend class message_manage_gc;
+                typedef std::map<std::string, std::pair<std::shared_ptr<v3::event_wait_for>, nexus_net_message>> message_list_type;
+            public:
+                /**
+                 * @brief 添加
+                 * @param msg_id
+                 * @return
+                 */
+                std::shared_ptr<v3::event_wait_for> add(std::string const& msg_id) {
+                    std::lock_guard<std::mutex> locker(mutex_);
+                    msg_list_[msg_id].first.reset(new v3::event_wait_for);
+                    return msg_list_[msg_id].first;
+                }
+                /**
+                 * @brief 获取数据
+                 * @param msg_id
+                 * @return
+                 */
+                nexus_net_message& get_data(std::string const& msg_id) {
+                    std::lock_guard<std::mutex> locker(mutex_);
+                    return msg_list_[msg_id].second;
+                }
+                /**
+                 * @brief 设置数据
+                 * @param msg_id
+                 * @param data
+                 */
+                void set_data(std::string const& msg_id, nexus_net_message const& data) {
+                    std::lock_guard<std::mutex> locker(mutex_);
+                    msg_list_[msg_id].second = data;
+                    msg_list_[msg_id].first->notify();
+                }
+                /**
+                 * @brief 查找数据
+                 * @param msg_id
+                 * @return
+                 */
+                bool find(std::string const& msg_id) {
+                    std::lock_guard<std::mutex> locker(mutex_);
+                    return msg_list_.find(msg_id) != msg_list_.end();
+                }
+                /**
+                 * @brief 移出
+                 * @param msg_id
+                 */
+                void remove(std::string const& msg_id) {
+                    std::lock_guard<std::mutex> locker(mutex_);
+                    msg_list_.erase(msg_id);
+                }
+            private:
+                message_list_type   msg_list_;
+                std::mutex          mutex_;
             };
-            auto config = read();
-            auto it = std::find_if(config.loggers.begin(), config.loggers.end(), [=](auto& it) {
-                return it.type == value.msg_type && it.enable; });
-            if (it != config.loggers.end()) {
-                if (success) {
-                    LOG_INFO << (is_out ? "接收成功" : "发送成功") << ",消息类型:" << g_msg_type[value.msg_type] << " 消息ID:" << value.msg_id << " 事件:" << value.route << " 路由:" << value.routes;
+            /**
+             * @brief 消息管理GC
+             */
+            class message_manage_gc {
+            public:
+                /**
+                 * @brief 构造
+                 * @param data
+                 * @param msg_id
+                 */
+                message_manage_gc(message_manage& data, std::string& msg_id) :
+                    message_list_(data),
+                    msg_id_(msg_id) {
+                    wait_ = message_list_.add(msg_id_);
                 }
-                else {
-                    LOG_ERROR << (is_out ? "接收失败" : "发送失败") << ",消息类型:" << g_msg_type[value.msg_type] << " 消息ID:" << value.msg_id << " 事件:" << value.route << " 路由:" << value.routes;
-                }
-            }
-        }
-    };
-    /**
-     * @brief 客户端
-     */
-    class nexus_net_tcp_client {
-    public:
-        nexus_net_tcp_client() :
-            client_(new asio2::tcp_client()) {
-            client_->bind_connect(&nexus_net_tcp_client::on_connect, this);
-            client_->bind_disconnect(&nexus_net_tcp_client::on_disconnect, this);
-            client_->bind_recv(&nexus_net_tcp_client::on_recv, this);
-        }
-        void start(std::string const& ip, int port) {
-            client_->async_start(ip, port, match_role<asio2::tcp_client>(client_));
-        }
-        void stop() {
-            client_->stop();
-        }
-        void send(nexus_net_message& data, std::function<void()> const& fn) {
-            client_->async_send(data.get_data(), fn);
-        }
-        v3::delegates<bool, std::string const&> connect_event;
-        v3::delegates<>                         disconnect_event;
-        v3::delegates<nexus_net_message const&> recv_event;
-    private:
-        void on_connect() {
-            connect_event(!asio2::get_last_error(), asio2::get_last_error_msg());
-        }
-        void on_disconnect() {
-            disconnect_event();
-        }
-        void on_recv(std::string_view sv) {
-            recv_event(nexus_net_message(sv));
-        }
-    private:
-        std::shared_ptr<asio2::tcp_client> client_;
-    };
-    /**
-     * @brief 客户端
-     */
-    class nexus_net_client : public v3::thread_pool<nexus_net_client> {
-    private:
-        class message_manage_gc;
-        /**
-         * @brief 消息管理
-         */
-        class message_manage {
-        private:
-            friend class message_manage_gc;
-            typedef std::map<std::string, std::pair<std::shared_ptr<v3::event_wait_for>, nexus_net_message>> message_list_type;
+                /**
+                 * @brief 析构
+                 */
+                ~message_manage_gc() {
+                    message_list_.remove(msg_id_);
+                }
+                //添加
+                bool loop(int millisecond) {
+                    return wait_->wait(millisecond);
+                }
+                /**
+                 * @brief 设置数据
+                 * @return
+                 */
+                nexus_net_message& get_data() {
+                    return message_list_.get_data(msg_id_);
+                }
+            private:
+                std::string& msg_id_;
+                message_manage& message_list_;
+                std::shared_ptr<v3::event_wait_for> wait_;
+            };
         public:
             /**
-             * @brief 添加
-             * @param msg_id
+             * @brief 单例
              * @return
              */
-            std::shared_ptr<v3::event_wait_for> add(std::string const& msg_id) {
-                std::lock_guard<std::mutex> locker(mutex_);
-                msg_list_[msg_id].first.reset(new v3::event_wait_for);
-                return msg_list_[msg_id].first;
+            static nexus_net_client* instance() {
+                static nexus_net_client g_nexus_net_client;
+                return &g_nexus_net_client;
             }
             /**
-             * @brief 获取数据
-             * @param msg_id
-             * @return
+             * @brief 析构
              */
-            nexus_net_message& get_data(std::string const& msg_id) {
-                std::lock_guard<std::mutex> locker(mutex_);
-                return msg_list_[msg_id].second;
+            ~nexus_net_client() {
+                stop();
             }
             /**
-             * @brief 设置数据
-             * @param msg_id
-             * @param data
+             * @brief 启动
+             */
+            void start() {
+                auto config = nexus_net_config::read();
+                if (config.client.enable) {
+                    client_.start(config.client.ip, config.client.port);
+                }
+            }
+            /**
+             * @brief 停止
+             */
+            void stop() {
+                client_.stop();
+            }
+            /**
+             * @brief 添加订阅
+             * @tparam _Fn
+             * @tparam _This
+             * @param key
+             * @param fn
+             * @param ths
+             * @return
              */
-            void set_data(std::string const& msg_id, nexus_net_message const& data) {
-                std::lock_guard<std::mutex> locker(mutex_);
-                msg_list_[msg_id].second = data;
-                msg_list_[msg_id].first->notify();
+            template<typename _Fn, typename _This>
+            bool subscribe(std::string const& key, _Fn&& fn, _This&& ths) {
+                if (nexus_net_config::read().subscribes.contains(key)) {
+                    functions_.bind(nexus_net_config::read().subscribes[key].route, std::forward<_Fn>(fn), std::forward<_This>(ths));
+                    nexus_net_message msg;
+                    msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE;
+                    msg.route = nexus_net_config::read().subscribes[key].route;
+                    subscribes_.push_back(msg);
+                    return true;
+                }
+                return false;
             }
             /**
-             * @brief 查找数据
-             * @param msg_id
+             * @brief 发布
+             * @tparam _Ret
+             * @tparam ..._Args
+             * @param key
+             * @param ...args
              * @return
              */
-            bool find(std::string const& msg_id) {
-                std::lock_guard<std::mutex> locker(mutex_);
-                return msg_list_.find(msg_id) != msg_list_.end();
+            template<typename _Ret, typename ..._Args>
+            _Ret publisher(std::string const& key, _Args&&...args) {
+                auto& config = nexus_net_config::read();
+                if (!config.publishers.contains(key))
+                    throw std::runtime_error("key不存在!");
+                nexus_net_message msg;
+                msg.route = config.publishers[key].route;
+                msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::PUBLISHER;
+                msg.args << std::make_tuple(std::forward<_Args>(args)...);
+                if constexpr (!std::is_same<void, _Ret>::value) {
+                    msg.msg_id = v3::utils::uuid();
+                    message_manage_gc gc(message_manage_, msg.msg_id);
+                    send(msg);
+                    if (!gc.loop(2000))
+                        throw std::runtime_error("请求超时");
+                    _Ret result;
+                    gc.get_data().args >> result;
+                    return result;
+                }
+                else {
+                    send(msg);
+                }
             }
             /**
-             * @brief 移出
-             * @param msg_id
+             * @brief 发布
+             * @tparam _Ret
+             * @tparam ..._Args
+             * @param timeout
+             * @param route
+             * @param ...args
+             * @return
              */
-            void remove(std::string const& msg_id) {
-                std::lock_guard<std::mutex> locker(mutex_);
-                msg_list_.erase(msg_id);
+            template<typename _Ret, typename ..._Args>
+            _Ret publisher(int timeout, std::string const& key, _Args&&...args) {
+                auto& config = nexus_net_config::read();
+                if (!config.publishers.contains(key))
+                    throw std::runtime_error("key不存在!");
+                nexus_net_message msg;
+                msg.route = config.publishers[key].route;
+                msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::PUBLISHER;
+                msg.args << std::make_tuple(std::forward<_Args>(args)...);
+                if constexpr (!std::is_same<void, _Ret>::value) {
+                    msg.msg_id = v3::utils::uuid();
+                    message_manage_gc gc(message_manage_, msg.msg_id);
+                    send(msg);
+                    if (!gc.loop(timeout))
+                        throw std::runtime_error("请求超时");
+                    _Ret result;
+                    gc.get_data().args >> result;
+                    return result;
+                }
+                else {
+                    send(msg);
+                }
             }
+            /**
+             * @brief 授权状态
+             */
+            v3::delegates<bool, std::string const&, std::string const&> authorized_event;
+            /**
+             * @brief 连接断开
+             */
+            v3::delegates<>                                             disconnect_event;
+            /**
+             * @brief 连接状态
+             */
+            v3::delegates<bool>                                         connect_event;
         private:
-            message_list_type   msg_list_;
-            std::mutex          mutex_;
-        };
-        /**
-         * @brief 消息管理GC
-         */
-        class message_manage_gc {
-        public:
             /**
              * @brief 构造
-             * @param data
-             * @param msg_id
              */
-            message_manage_gc(message_manage& data, std::string& msg_id) :
-                message_list_(data),
-                msg_id_(msg_id) {
-                wait_ = message_list_.add(msg_id_);
+            nexus_net_client() :
+                v3::thread_pool<nexus_net_client>(5) {
+                client_.connect_event.bind(&nexus_net_client::on_connect, this);
+                client_.disconnect_event.bind(&nexus_net_client::on_disconnect, this);
+                client_.recv_event.bind(&nexus_net_client::do_work_nexus_net_message, this);
+                timer_.timeout_event.bind(&nexus_net_client::on_timeout, this);
+                timer_.start(5000);
             }
             /**
-             * @brief 析构
+             * @brief 发送
+             * @param data
              */
-            ~message_manage_gc() {
-                message_list_.remove(msg_id_);
-            }
-            //添加
-            bool loop(int millisecond) {
-                return wait_->wait(millisecond);
+            void send(nexus_net_message data) {
+                if (data.msg_type != (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER) {
+                    auto config = nexus_net_config::read();
+                    data.routes.push_back(config.user.code);
+                    if (data.msg_type == (std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE) {
+                        data.route = fmt::format("{}/{}/{}", parent_code_, config.user.code, data.route);
+                    }
+                }
+                else if (data.msg_type == (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER && !data.routes.empty()) {
+                    data.routes.pop_back();
+                }
+                client_.send(data, [=]() {
+                    nexus_net_config::logger(!asio2::get_last_error(), false, data); });
             }
             /**
-             * @brief 设置数据
-             * @return
+             * @brief 身份认证
              */
-            nexus_net_message& get_data() {
-                return message_list_.get_data(msg_id_);
-            }
-        private:
-            std::string& msg_id_;
-            message_manage& message_list_;
-            std::shared_ptr<v3::event_wait_for> wait_;
-        };
-    public:
-        /**
-         * @brief 单例
-         * @return 
-         */
-        static nexus_net_client* instance() {
-            static nexus_net_client g_nexus_net_client;
-            return &g_nexus_net_client;
-        }
-        /**
-         * @brief 析构
-         */
-        ~nexus_net_client() {
-            stop();
-        }
-        /**
-         * @brief 启动
-         */
-        void start() {
-            auto config = nexus_net_config::read();
-            if (config.client.enable) {
-                client_.start(config.client.ip, config.client.port);
+            void authenticate() {
+                auto config = nexus_net_config::read();
+                if (config.user.enable) {
+                    nexus_net_message data;
+                    data.msg_type = (std::uint8_t)nexus_net_msg_type_enum::AUTHENTICATE;
+                    data.args << config.user.code << config.user.password << config.user.name << 1;
+                    send(data);
+                }
             }
-        }
-        /**
-         * @brief 停止
-         */
-        void stop() {
-            client_.stop();
-        }
-        /**
-         * @brief 添加订阅
-         * @tparam _Fn 
-         * @tparam _This 
-         * @param key 
-         * @param fn 
-         * @param ths 
-         * @return 
-         */
-        template<typename _Fn, typename _This>
-        bool subscribe(std::string const& key, _Fn&& fn, _This&& ths) {
-            if (nexus_net_config::read().subscribes.contains(key)) {
-                functions_.bind(nexus_net_config::read().subscribes[key].route, std::forward<_Fn>(fn), std::forward<_This>(ths));
+            /**
+             * @brief 心跳
+             */
+            void heartbeat() {
+                if (!is_heartbeat_)
+                    return;
                 nexus_net_message msg;
-                msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE;
-                msg.route = nexus_net_config::read().subscribes[key].route;
-                subscribes_.push_back(msg);
-                return true;
-            }
-            return false;
-        }
-        /**
-         * @brief 发布
-         * @tparam _Ret 
-         * @tparam ..._Args 
-         * @param key 
-         * @param ...args 
-         * @return 
-         */
-        template<typename _Ret, typename ..._Args>
-        _Ret publisher(std::string const& key, _Args&&...args) {
-            auto& config = nexus_net_config::read();
-            if(!config.publishers.contains(key))
-                throw std::runtime_error("key不存在!");
-            nexus_net_message msg;
-            msg.route = config.publishers[key].route;
-            msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::PUBLISHER;
-            msg.args << std::make_tuple(std::forward<_Args>(args)...);
-            if constexpr (!std::is_same<void, _Ret>::value) {
-                msg.msg_id = v3::utils::uuid();
-                message_manage_gc gc(message_manage_, msg.msg_id);
-                send(msg);
-                if (!gc.loop(2000))
-                    throw std::runtime_error("请求超时");
-                _Ret result;
-                gc.get_data().args >> result;
-                return result;
-            }
-            else {
+                msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::HEARTBEAT;
                 send(msg);
             }
-        }
-        /**
-         * @brief 发布
-         * @tparam _Ret 
-         * @tparam ..._Args 
-         * @param timeout 
-         * @param route 
-         * @param ...args 
-         * @return 
-         */
-        template<typename _Ret, typename ..._Args>
-        _Ret publisher(int timeout, std::string const& key, _Args&&...args) {
-            auto& config = nexus_net_config::read();
-            if (!config.publishers.contains(key))
-                throw std::runtime_error("key不存在!");
-            nexus_net_message msg;
-            msg.route = config.publishers[key].route;
-            msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::PUBLISHER;
-            msg.args << std::make_tuple(std::forward<_Args>(args)...);
-            if constexpr (!std::is_same<void, _Ret>::value) {
-                msg.msg_id = v3::utils::uuid();
-                message_manage_gc gc(message_manage_, msg.msg_id);
-                send(msg);
-                if (!gc.loop(timeout))
-                    throw std::runtime_error("请求超时");
-                _Ret result;
-                gc.get_data().args >> result;
-                return result;
+            /**
+             * @brief 订阅
+             */
+            void subscribe() {
+                for (auto& it : subscribes_) {
+                    send(it);
+                }
             }
-            else {
-                send(msg);
+        private:
+            void on_connect(bool success, std::string const& msg) {
+                if (success) {
+                    connect_event(true);
+                    authenticate();
+                }
+                else {
+                    connect_event(false);
+                }
             }
-        }
-        /**
-         * @brief 授权状态
-         */
-        v3::delegates<bool,std::string const&, std::string const&> authorized_event;
-        /**
-         * @brief 连接断开
-         */
-        v3::delegates<>                                             disconnect_event;
-        /**
-         * @brief 连接状态
-         */
-        v3::delegates<bool>                                         connect_event;
-    private:
-        /**
-         * @brief 构造
-         */
-        nexus_net_client() :
-            v3::thread_pool<nexus_net_client>(5) {
-            client_.connect_event.bind(&nexus_net_client::on_connect, this);
-            client_.disconnect_event.bind(&nexus_net_client::on_disconnect, this);
-            client_.recv_event.bind(&nexus_net_client::do_work_nexus_net_message, this);
-            timer_.timeout_event.bind(&nexus_net_client::on_timeout, this);
-            timer_.start(5000);
-        }
-        /**
-         * @brief 发送
-         * @param data 
-         */
-        void send(nexus_net_message data) {
-            if (data.msg_type != (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER) {
-                auto config = nexus_net_config::read();
-                data.routes.push_back(config.user.code);
-                if (data.msg_type == (std::uint8_t)nexus_net_msg_type_enum::SUBSCRIBE) {
-                    data.route = fmt::format("{}/{}/{}", parent_code_, config.user.code, data.route);
+            void on_disconnect() {
+                disconnect_event();
+                is_heartbeat_ = false;
+            }
+            void do_work_nexus_net_message(nexus_net_message data) {
+                nexus_net_config::logger(true, true, data);
+                try {
+                    switch ((nexus_net_msg_type_enum)data.msg_type) {
+                    case nexus_net_msg_type_enum::REPAUTHENTICATE:  on_authenticate(data);  break;
+                    case nexus_net_msg_type_enum::PUBLISHER:        on_publisher(data);     break;
+                    case nexus_net_msg_type_enum::REPPUBLISHER:     on_reppublisher(data);  break;
+                    }
+                }
+                catch (std::exception const& ec) {
+                    LOG_ERROR << ec;
                 }
             }
-            else if (data.msg_type == (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER && !data.routes.empty()) {
-                data.routes.pop_back();
+            void on_timeout() {
+                heartbeat();
             }
-            client_.send(data, [=]() {
-                nexus_net_config::logger(!asio2::get_last_error(), false, data); });
-        }
-        /**
-         * @brief 身份认证
-         */
-        void authenticate() {
-            auto config = nexus_net_config::read();
-            if (config.user.enable) {
-                nexus_net_message data;
-                data.msg_type = (std::uint8_t)nexus_net_msg_type_enum::AUTHENTICATE;
-                data.args << config.user.code << config.user.password << config.user.name << 1;
-                send(data);
-            }
-        }
-        /**
-         * @brief 心跳
-         */
-        void heartbeat() {
-            if (!is_heartbeat_)
-                return;
-            nexus_net_message msg;
-            msg.msg_type = (std::uint8_t)nexus_net_msg_type_enum::HEARTBEAT;
-            send(msg);
-        }
-        /**
-         * @brief 订阅
-         */
-        void subscribe() {
-            for (auto& it : subscribes_) {
-                send(it);
-            }
-        }
-    private:
-        void on_connect(bool success, std::string const& msg) {
-            if (success) {
-                connect_event(true);
-                authenticate();
-            }
-            else {
-                connect_event(false);
-            }
-        }
-        void on_disconnect() {
-            disconnect_event();
-            is_heartbeat_ = false;
-        }
-        void do_work_nexus_net_message(nexus_net_message data) {
-            nexus_net_config::logger(true, true, data);
-            try {
-                switch ((nexus_net_msg_type_enum)data.msg_type) {
-                case nexus_net_msg_type_enum::REPAUTHENTICATE:  on_authenticate(data);  break;
-                case nexus_net_msg_type_enum::PUBLISHER:        on_publisher(data);     break;
-                case nexus_net_msg_type_enum::REPPUBLISHER:     on_reppublisher(data);  break;
-                }
-            }
-            catch (std::exception const& ec) {
-                LOG_ERROR << ec;
-            }
-        }
-        void on_timeout() {
-            heartbeat();
-        }
-    private:
-        /**
-         * @brief 授权响应
-         * @param data
-         */
-        void on_authenticate(nexus_net_message data) {
-            try {
-                data.args >> is_heartbeat_ >> parent_code_ >> parent_name_;
-                if (is_heartbeat_) {
-                    authorized_event(true, parent_code_, parent_name_);
-                    subscribe();
+        private:
+            /**
+             * @brief 授权响应
+             * @param data
+             */
+            void on_authenticate(nexus_net_message data) {
+                try {
+                    data.args >> is_heartbeat_ >> parent_code_ >> parent_name_;
+                    if (is_heartbeat_) {
+                        authorized_event(true, parent_code_, parent_name_);
+                        subscribe();
+                    }
+                    else {
+                        authorized_event(false, "", "");
+                    }
                 }
-                else {
-                    authorized_event(false, "", "");
+                catch (std::exception const& ec) {
+                    LOG_ERROR << ec;
+                }
+            }
+            /**
+             * @brief 发布
+             * @param data
+             */
+            void on_publisher(nexus_net_message data) {
+                REGISTER_ASYNC_FUNC(on_publisher, data);
+                if (3 != std::count(data.route.begin(), data.route.end(), '/')) {
+                    return;
+                }
+                std::string key = data.route.substr(data.route.find('/', data.route.find('/') + 1) + 1);
+                data.args = functions_.invoke(key, data.args);
+                if (!data.args.empty()) {
+                    data.msg_type = (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER;
+                    send(data);
                 }
             }
-            catch (std::exception const& ec) {
-                LOG_ERROR << ec;
+            /**
+             * @brief 发布响应
+             * @param data
+             */
+            void on_reppublisher(nexus_net_message data) {
+                if (message_manage_.find(data.msg_id)) {
+                    message_manage_.set_data(data.msg_id, data);
+                }
             }
-        }
-        /**
-         * @brief 发布
-         * @param data
-         */
-        void on_publisher(nexus_net_message data) {
-            REGISTER_ASYNC_FUNC(on_publisher, data);
-            if (3 != std::count(data.route.begin(), data.route.end(), '/')) {
-                return;
-            }
-            std::string key = data.route.substr(data.route.find('/', data.route.find('/') + 1) + 1);
-            data.args = functions_.invoke(key, data.args);
-            if (!data.args.empty()) {
-                data.msg_type = (std::uint8_t)nexus_net_msg_type_enum::REPPUBLISHER;
-                send(data);
-            }
-        }
-        /**
-         * @brief 发布响应
-         * @param data
-         */
-        void on_reppublisher(nexus_net_message data) {
-            if (message_manage_.find(data.msg_id)) {
-                message_manage_.set_data(data.msg_id, data);
-            }
-        }
-    private:
-        v3::timer                                   timer_;
-        std::string                                 parent_code_;
-        std::string                                 parent_name_;
-        bool                                        is_heartbeat_ = false;
-        nexus_net_tcp_client                        client_;
-        message_manage                              message_manage_;
-        std::vector<nexus_net_message>              subscribes_;
-        v3::archive::function_manage<std::string>   functions_;
-    };
-
+        private:
+            v3::timer                                   timer_;
+            std::string                                 parent_code_;
+            std::string                                 parent_name_;
+            bool                                        is_heartbeat_ = false;
+            nexus_net_tcp_client                        client_;
+            message_manage                              message_manage_;
+            std::vector<nexus_net_message>              subscribes_;
+            v3::archive::function_manage<std::string>   functions_;
+        };
+    }
 }

+ 1166 - 1164
robot/robotics/orm.hpp

@@ -24,106 +24,249 @@
 #include "config.hpp"
 #include "utils.hpp"
 
-namespace robotics::v3 {
-	namespace orm {
-		using sql_result = cppdb::result;
+namespace robotics {
+	namespace v3 {
+		namespace orm {
+			using sql_result = cppdb::result;
 
-		using sql_connect = cppdb::ref_ptr<cppdb::backend::connection>;
+			using sql_connect = cppdb::ref_ptr<cppdb::backend::connection>;
 
-		class sql_connect_pool {
-		public:
-			explicit sql_connect_pool() = delete;
-			virtual ~sql_connect_pool() = delete;
-			/**
-			 * @brief 获取链接
-			 * @tparam _ConnectConfig
-			 * @return
-			 */
-			template<typename _ConnectConfig>
-			static sql_connect open() {
-				static cppdb::pool::pointer pointer_ =
-					cppdb::pool::create(_ConnectConfig());
-				return pointer_->open();
-			}
-			/**
-			 * @brief 获取链接
-			 * @param connct_string
-			 * @return
-			 */
-			static sql_connect open(std::string const& connct_string) {
-				static cppdb::pool::pointer pointer_ =
-					cppdb::pool::create(connct_string);
-				return pointer_->open();
-			}
-		};
+			class sql_connect_pool {
+			public:
+				explicit sql_connect_pool() = delete;
+				virtual ~sql_connect_pool() = delete;
+				/**
+				 * @brief 获取链接
+				 * @tparam _ConnectConfig
+				 * @return
+				 */
+				template<typename _ConnectConfig>
+				static sql_connect open() {
+					static cppdb::pool::pointer pointer_ =
+						cppdb::pool::create(_ConnectConfig());
+					return pointer_->open();
+				}
+				/**
+				 * @brief 获取链接
+				 * @param connct_string
+				 * @return
+				 */
+				static sql_connect open(std::string const& connct_string) {
+					static cppdb::pool::pointer pointer_ =
+						cppdb::pool::create(connct_string);
+					return pointer_->open();
+				}
+			};
 
-		class sql_record {
-		public:
-			explicit sql_record() = default;
-			sql_record(sql_result const& result) :
-				record_(result) {
-			}
-			template<typename _Table>
-			std::vector<_Table> value() {
-				std::vector<_Table> result;
-				rttr::type type = rttr::type::get<_Table>();
-				auto properties = type.get_properties();
-				while (record_.next()) {
-					_Table add_item;
-					for (auto& property : properties) {
-						std::string prop_name;
-						rttr::variant no_sql = property.get_metadata("NoSql");
-						rttr::variant prop_var_name = property.get_metadata("Sql");
-						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>())
-							continue;
-						if (prop_var_name.get_type() == rttr::type::get<std::string>())
-							prop_name = prop_var_name.get_value<std::string>();
-						else
-							prop_name = std::string(property.get_name());
-						int record_index = record_.find_column(prop_name);
+			class sql_record {
+			public:
+				explicit sql_record() = default;
+				sql_record(sql_result const& result) :
+					record_(result) {
+				}
+				template<typename _Table>
+				std::vector<_Table> value() {
+					std::vector<_Table> result;
+					rttr::type type = rttr::type::get<_Table>();
+					auto properties = type.get_properties();
+					while (record_.next()) {
+						_Table add_item;
+						for (auto& property : properties) {
+							std::string prop_name;
+							rttr::variant no_sql = property.get_metadata("NoSql");
+							rttr::variant prop_var_name = property.get_metadata("Sql");
+							if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>())
+								continue;
+							if (prop_var_name.get_type() == rttr::type::get<std::string>())
+								prop_name = prop_var_name.get_value<std::string>();
+							else
+								prop_name = std::string(property.get_name());
+							int record_index = record_.find_column(prop_name);
+							if (-1 == record_index)
+								continue;
+							if (utils::rttr_type<int>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<int>(record_index));
+								}
+							}
+							else if (utils::rttr_type<bool>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<int>(record_index) > 0);
+								}
+							}
+							else if (utils::rttr_type<double>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<double>(record_index));
+								}
+							}
+							else if (utils::rttr_type<long>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<long>(record_index));
+								}
+							}
+							else if (utils::rttr_type<float>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<double>(record_index));
+								}
+							}
+							else if (utils::rttr_type<std::int64_t>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<std::int64_t>(record_index));
+								}
+							}
+							else if (utils::rttr_type<std::string>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, record_.get<std::string>(record_index));
+								}
+							}
+							else if (utils::rttr_type<datetime>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									property.set_value(add_item, datetime(record_.get<std::string>(record_index)));
+								}
+							}
+							else if (utils::rttr_type<std::vector<int>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<int> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(std::atoi(it.c_str()));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<bool>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<bool> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										if (it == "1" || it == "true" || it == "True")
+											vec.push_back(true);
+										else
+											vec.push_back(false);
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<double>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<double> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(std::atof(it.c_str()));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<long>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<long> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(std::atol(it.c_str()));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<float>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<long> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(std::atof(it.c_str()));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<std::int64_t> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(std::atoll(it.c_str()));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<std::string>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<std::string> vec;
+									boost::split(vec, record_.get<std::string>(record_index), boost::is_any_of(","));
+									property.set_value(add_item, vec);
+								}
+							}
+							else if (utils::rttr_type<std::vector<datetime>>(property.get_type())) {
+								if (!record_.is_null(record_index)) {
+									std::vector<datetime> vec;
+									std::vector<std::string> split_value;
+									boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
+									for (auto& it : split_value) {
+										vec.push_back(datetime(it));
+									}
+									property.set_value(add_item, vec);
+								}
+							}
+						}
+						result.push_back(add_item);
+					}
+					return result;
+				}
+				sql_result record() {
+					return record_;
+				}
+				template<typename _Ret>
+				_Ret value(std::string const& field, _Ret const& df = _Ret()) {
+					_Ret result = df;
+					while (record_.next()) {
+						int record_index = record_.find_column(field);
 						if (-1 == record_index)
-							continue;
-						if (utils::rttr_type<int>(property.get_type())) {
+							break;
+						if constexpr (std::is_same<int, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<int>(record_index));
+								result = record_.get<int>(record_index);
 							}
 						}
-						else if (utils::rttr_type<bool>(property.get_type())) {
+						else if (std::is_same<bool, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<int>(record_index) > 0);
+								result = record_.get<int>(record_index) > 0;
 							}
 						}
-						else if (utils::rttr_type<double>(property.get_type())) {
+						else if constexpr (std::is_same<double, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<double>(record_index));
+								result = record_.get<double>(record_index);
 							}
 						}
-						else if (utils::rttr_type<long>(property.get_type())) {
+						else if constexpr (std::is_same<long, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<long>(record_index));
+								result = record_.get<long>(record_index);
 							}
 						}
-						else if (utils::rttr_type<float>(property.get_type())) {
+						else if constexpr (std::is_same<float, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<double>(record_index));
+								result = record_.get<double>(record_index);
 							}
 						}
-						else if (utils::rttr_type<std::int64_t>(property.get_type())) {
+						else if constexpr (std::is_same<std::int64_t, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<std::int64_t>(record_index));
+								result = record_.get<std::int64_t>(record_index);
 							}
 						}
-						else if (utils::rttr_type<std::string>(property.get_type())) {
+						else if constexpr (std::is_same<std::string, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, record_.get<std::string>(record_index));
+								result = record_.get<std::string>(record_index);
 							}
 						}
-						else if (utils::rttr_type<datetime>(property.get_type())) {
+						else if constexpr (std::is_same<datetime, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
-								property.set_value(add_item, datetime(record_.get<std::string>(record_index)));
+								result = datetime(record_.get<std::string>(record_index));
 							}
 						}
-						else if (utils::rttr_type<std::vector<int>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<int>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<int> vec;
 								std::vector<std::string> split_value;
@@ -131,10 +274,10 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(std::atoi(it.c_str()));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<bool>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<bool>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<bool> vec;
 								std::vector<std::string> split_value;
@@ -145,10 +288,10 @@ namespace robotics::v3 {
 									else
 										vec.push_back(false);
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<double>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<double>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<double> vec;
 								std::vector<std::string> split_value;
@@ -156,10 +299,10 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(std::atof(it.c_str()));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<long>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<long>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<long> vec;
 								std::vector<std::string> split_value;
@@ -167,10 +310,10 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(std::atol(it.c_str()));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<float>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<float>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<long> vec;
 								std::vector<std::string> split_value;
@@ -178,10 +321,10 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(std::atof(it.c_str()));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<std::int64_t>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<std::int64_t>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<std::int64_t> vec;
 								std::vector<std::string> split_value;
@@ -189,17 +332,17 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(std::atoll(it.c_str()));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<std::string>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<std::string>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<std::string> vec;
 								boost::split(vec, record_.get<std::string>(record_index), boost::is_any_of(","));
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
-						else if (utils::rttr_type<std::vector<datetime>>(property.get_type())) {
+						else if constexpr (std::is_same<std::vector<datetime>, _Ret>::value) {
 							if (!record_.is_null(record_index)) {
 								std::vector<datetime> vec;
 								std::vector<std::string> split_value;
@@ -207,1163 +350,1022 @@ namespace robotics::v3 {
 								for (auto& it : split_value) {
 									vec.push_back(datetime(it));
 								}
-								property.set_value(add_item, vec);
+								result = vec;
 							}
 						}
 					}
-					result.push_back(add_item);
+					return result;
 				}
-				return result;
-			}
-			sql_result record() {
-				return record_;
-			}
-			template<typename _Ret>
-			_Ret value(std::string const& field, _Ret const& df = _Ret()) {
-				_Ret result = df;
-				while (record_.next()) {
-					int record_index = record_.find_column(field);
-					if (-1 == record_index)
-						break;
-					if constexpr (std::is_same<int, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<int>(record_index);
-						}
+			private:
+				sql_result record_;
+			};
+
+			class sql_query {
+			public:
+				sql_query() = delete;
+				sql_query(cppdb::ref_ptr<cppdb::backend::connection> connect) :
+					session_(connect) {
+				}
+				cppdb::session& session() {
+					return session_;
+				}
+				operator cppdb::session& () {
+					return session();
+				}
+				template<typename _Ret, typename ..._Args>
+				_Ret execute(std::string const& sql, _Args &&...args) {
+					static_assert(std::is_same<_Ret, void>::value || std::is_same<_Ret, sql_result>::value, "type error,is type void or sql_result");
+					cppdb::statement stmt = session_ << sql;
+					if constexpr (sizeof...(_Args) > 0)
+						bind_param(stmt, std::forward<_Args>(args)...);
+
+					if constexpr (std::is_same<void, _Ret>::value) {
+						stmt.exec();
 					}
-					else if (std::is_same<bool, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<int>(record_index) > 0;
-						}
+					else {
+						return stmt.query();
 					}
-					else if constexpr (std::is_same<double, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<double>(record_index);
-						}
+				}
+				template<typename _Ret>
+				_Ret execute(std::string const& sql, std::vector<rttr::variant>& args) {
+					static_assert(std::is_same<_Ret, void>::value || std::is_same<_Ret, sql_result>::value, "type error,is type void or sql_result");
+					cppdb::statement stmt = session_ << sql;
+					bind_param(stmt, args);
+					if constexpr (std::is_same<void, _Ret>::value) {
+						stmt.exec();
 					}
-					else if constexpr (std::is_same<long, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<long>(record_index);
-						}
+					else {
+						return stmt.query();
 					}
-					else if constexpr (std::is_same<float, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<double>(record_index);
-						}
+				}
+				void begin_transaction() {
+					guard_.reset(new cppdb::transaction(session_));
+				}
+				void end_transaction() {
+					if (guard_) {
+						guard_->commit();
 					}
-					else if constexpr (std::is_same<std::int64_t, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<std::int64_t>(record_index);
-						}
+				}
+				void rollback_transaction() {
+					if (guard_) {
+						guard_->rollback();
 					}
-					else if constexpr (std::is_same<std::string, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = record_.get<std::string>(record_index);
+				}
+			private:
+				void bind_param(cppdb::statement& stmt, std::vector<rttr::variant>& args) {
+					for (auto& it : args) {
+						if (utils::rttr_type<int>(it.get_type())) {
+							stmt << it.get_value<int>();
 						}
-					}
-					else if constexpr (std::is_same<datetime, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							result = datetime(record_.get<std::string>(record_index));
+						else if (utils::rttr_type<bool>(it.get_type())) {
+							stmt << (it.get_value<bool>() == true ? 1 : 0);
 						}
-					}
-					else if constexpr (std::is_same<std::vector<int>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<int> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(std::atoi(it.c_str()));
-							}
-							result = vec;
+						else if (utils::rttr_type<double>(it.get_type())) {
+							stmt << it.get_value<double>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<bool>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<bool> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								if (it == "1" || it == "true" || it == "True")
-									vec.push_back(true);
-								else
-									vec.push_back(false);
-							}
-							result = vec;
+						else if (utils::rttr_type<long>(it.get_type())) {
+							stmt << it.get_value<long>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<double>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<double> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(std::atof(it.c_str()));
-							}
-							result = vec;
+						else if (utils::rttr_type<float>(it.get_type())) {
+							stmt << it.get_value<float>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<long>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<long> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(std::atol(it.c_str()));
-							}
-							result = vec;
+						else if (utils::rttr_type<std::int64_t>(it.get_type())) {
+							stmt << it.get_value<std::int64_t>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<float>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<long> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(std::atof(it.c_str()));
-							}
-							result = vec;
+						else if (utils::rttr_type<std::string>(it.get_type())) {
+							stmt << it.get_value<std::string>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<std::int64_t>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<std::int64_t> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(std::atoll(it.c_str()));
-							}
-							result = vec;
+						else if (utils::rttr_type<datetime>(it.get_type())) {
+							datetime time = it.get_value<datetime>();
+							stmt << (std::tm)time;
 						}
-					}
-					else if constexpr (std::is_same<std::vector<std::string>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<std::string> vec;
-							boost::split(vec, record_.get<std::string>(record_index), boost::is_any_of(","));
-							result = vec;
+						else if (utils::rttr_type<std::vector<int>>(it.get_type())) {
+							std::vector<int> source_value = it.get_value<std::vector<int>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](int item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
 						}
-					}
-					else if constexpr (std::is_same<std::vector<datetime>, _Ret>::value) {
-						if (!record_.is_null(record_index)) {
-							std::vector<datetime> vec;
-							std::vector<std::string> split_value;
-							boost::split(split_value, record_.get<std::string>(record_index), boost::is_any_of(","));
-							for (auto& it : split_value) {
-								vec.push_back(datetime(it));
+						else if (utils::rttr_type<std::vector<bool>>(it.get_type())) {
+							std::vector<bool> source_value = it.get_value<std::vector<bool>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](bool item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<double>>(it.get_type())) {
+							std::vector<double> source_value = it.get_value<std::vector<double>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](double item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<long>>(it.get_type())) {
+							std::vector<long> source_value = it.get_value<std::vector<long>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](long item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<float>>(it.get_type())) {
+							std::vector<float> source_value = it.get_value<std::vector<float>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](float item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<std::int64_t>>(it.get_type())) {
+							std::vector<std::int64_t> source_value = it.get_value<std::vector<std::int64_t>>();
+							std::vector<std::string> join_value;
+							join_value.reserve(source_value.size());
+							std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
+								[](std::int64_t item) { std::stringstream ss; ss << item; return ss.str(); });
+							it = boost::join(join_value, ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<std::string>>(it.get_type())) {
+							it = boost::join(it.get_value<std::vector<std::string>>(), ",");
+							stmt << it.get_value<std::string>();
+						}
+						else if (utils::rttr_type<std::vector<datetime>>(it.get_type())) {
+							std::vector<std::string> params;
+							std::vector<datetime> vec = it.get_value<std::vector<datetime>>();
+							for (auto& item : vec) {
+								params.push_back(item.to_string());
 							}
-							result = vec;
+							it = boost::join(params, ",");
+							stmt << it.get_value<std::string>();
 						}
 					}
 				}
-				return result;
-			}
-		private:
-			sql_result record_;
-		};
-
-		class sql_query {
-		public:
-			sql_query() = delete;
-			sql_query(cppdb::ref_ptr<cppdb::backend::connection> connect) :
-				session_(connect) {
-			}
-			cppdb::session& session() {
-				return session_;
-			}
-			operator cppdb::session& () {
-				return session();
-			}
-			template<typename _Ret, typename ..._Args>
-			_Ret execute(std::string const& sql, _Args &&...args) {
-				static_assert(std::is_same<_Ret, void>::value || std::is_same<_Ret, sql_result>::value, "type error,is type void or sql_result");
-				cppdb::statement stmt = session_ << sql;
-				if constexpr (sizeof...(_Args) > 0)
-					bind_param(stmt, std::forward<_Args>(args)...);
-
-				if constexpr (std::is_same<void, _Ret>::value) {
-					stmt.exec();
-				}
-				else {
-					return stmt.query();
-				}
-			}
-			template<typename _Ret>
-			_Ret execute(std::string const& sql, std::vector<rttr::variant>& args) {
-				static_assert(std::is_same<_Ret, void>::value || std::is_same<_Ret, sql_result>::value, "type error,is type void or sql_result");
-				cppdb::statement stmt = session_ << sql;
-				bind_param(stmt, args);
-				if constexpr (std::is_same<void, _Ret>::value) {
-					stmt.exec();
-				}
-				else {
-					return stmt.query();
+				template<typename _Type>
+				void bind_param(cppdb::statement& stmt, _Type&& value) {
+					stmt << value;
 				}
-			}
-			void begin_transaction() {
-				guard_.reset(new cppdb::transaction(session_));
-			}
-			void end_transaction() {
-				if (guard_) {
-					guard_->commit();
+				template<typename _Type, typename ..._Args>
+				void bind_param(cppdb::statement& stmt, _Type&& value, _Args &&...args) {
+					stmt << value;
+					bind_param(stmt, std::forward<_Args>(args)...);
 				}
-			}
-			void rollback_transaction() {
-				if (guard_) {
-					guard_->rollback();
+			private:
+				cppdb::session						session_;
+				std::shared_ptr<cppdb::transaction> guard_;
+			};
+
+			template<typename ..._Args>
+			struct sql_value {
+				explicit sql_value(std::string const& field, std::string const& value, std::string const& symbol) :
+					field_(field),
+					value_string_(value),
+					symbol_(symbol) {
 				}
-			}
-		private:
-			void bind_param(cppdb::statement& stmt, std::vector<rttr::variant>& args) {
-				for (auto& it : args) {
-					if (utils::rttr_type<int>(it.get_type())) {
-						stmt << it.get_value<int>();
-					}
-					else if (utils::rttr_type<bool>(it.get_type())) {
-						stmt << (it.get_value<bool>() == true ? 1 : 0);
-					}
-					else if (utils::rttr_type<double>(it.get_type())) {
-						stmt << it.get_value<double>();
-					}
-					else if (utils::rttr_type<long>(it.get_type())) {
-						stmt << it.get_value<long>();
-					}
-					else if (utils::rttr_type<float>(it.get_type())) {
-						stmt << it.get_value<float>();
-					}
-					else if (utils::rttr_type<std::int64_t>(it.get_type())) {
-						stmt << it.get_value<std::int64_t>();
-					}
-					else if (utils::rttr_type<std::string>(it.get_type())) {
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<datetime>(it.get_type())) {
-						datetime time = it.get_value<datetime>();
-						stmt << (std::tm)time;
-					}
-					else if (utils::rttr_type<std::vector<int>>(it.get_type())) {
-						std::vector<int> source_value = it.get_value<std::vector<int>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](int item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<bool>>(it.get_type())) {
-						std::vector<bool> source_value = it.get_value<std::vector<bool>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](bool item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<double>>(it.get_type())) {
-						std::vector<double> source_value = it.get_value<std::vector<double>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](double item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<long>>(it.get_type())) {
-						std::vector<long> source_value = it.get_value<std::vector<long>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](long item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<float>>(it.get_type())) {
-						std::vector<float> source_value = it.get_value<std::vector<float>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](float item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<std::int64_t>>(it.get_type())) {
-						std::vector<std::int64_t> source_value = it.get_value<std::vector<std::int64_t>>();
-						std::vector<std::string> join_value;
-						join_value.reserve(source_value.size());
-						std::transform(source_value.begin(), source_value.end(), std::back_inserter(join_value),
-							[](std::int64_t item) { std::stringstream ss; ss << item; return ss.str(); });
-						it = boost::join(join_value, ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<std::string>>(it.get_type())) {
-						it = boost::join(it.get_value<std::vector<std::string>>(), ",");
-						stmt << it.get_value<std::string>();
-					}
-					else if (utils::rttr_type<std::vector<datetime>>(it.get_type())) {
-						std::vector<std::string> params;
-						std::vector<datetime> vec = it.get_value<std::vector<datetime>>();
-						for (auto& item : vec) {
-							params.push_back(item.to_string());
-						}
-						it = boost::join(params, ",");
-						stmt << it.get_value<std::string>();
-					}
+				bool get_value(std::vector<std::string>& ret_sql, std::vector<rttr::variant>& ret_value) {
+					if (value_string_.empty())
+						return false;
+					std::vector<std::string> ret_sql_list;
+					utils::for_each(value_, [&](auto& it) {
+						ret_value.push_back(it);
+						ret_sql_list.push_back(field_ + "" + symbol_ + "?"); });
+					ret_sql.push_back("(" + boost::join(ret_sql_list, " or ") + ")");
+					return true;
 				}
-			}
-			template<typename _Type>
-			void bind_param(cppdb::statement& stmt, _Type&& value) {
-				stmt << value;
-			}
-			template<typename _Type, typename ..._Args>
-			void bind_param(cppdb::statement& stmt, _Type&& value, _Args &&...args) {
-				stmt << value;
-				bind_param(stmt, std::forward<_Args>(args)...);
-			}
-		private:
-			cppdb::session						session_;
-			std::shared_ptr<cppdb::transaction> guard_;
-		};
-
-		template<typename ..._Args>
-		struct sql_value {
-			explicit sql_value(std::string const& field, std::string const& value, std::string const& symbol) :
-				field_(field),
-				value_string_(value),
-				symbol_(symbol) {
-			}
-			bool get_value(std::vector<std::string>& ret_sql, std::vector<rttr::variant>& ret_value) {
-				if (value_string_.empty())
-					return false;
-				std::vector<std::string> ret_sql_list;
-				utils::for_each(value_, [&](auto& it) {
-					ret_value.push_back(it);
-					ret_sql_list.push_back(field_ + "" + symbol_ + "?"); });
-				ret_sql.push_back("(" + boost::join(ret_sql_list, " or ") + ")");
-				return true;
-			}
-			std::string				value_string_;
-			std::tuple<_Args...>	value_;
-			std::string				field_;
-			std::string				symbol_;
-		};
-
-		struct sql_bool : public sql_value<bool> {
-			sql_bool(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<bool>(field, value, symbol) {
-				value_ = std::make_tuple(value == "true");
-			}
-		};
-
-		struct sql_int : public sql_value<int> {
-			sql_int(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<int>(field, value, symbol) {
-				value_ = std::make_tuple(std::atoi(value.c_str()));
-			}
-		};
-
-		struct sql_int64 : public sql_value<std::int64_t> {
-			sql_int64(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<std::int64_t>(field, value, symbol) {
-				value_ = std::make_tuple(std::atoll(value.c_str()));
-			}
-		};
-
-		struct sql_long : public sql_value<long> {
-			sql_long(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<long>(field, value, symbol) {
-				value_ = std::make_tuple(std::atoll(value.c_str()));
-			}
-		};
+				std::string				value_string_;
+				std::tuple<_Args...>	value_;
+				std::string				field_;
+				std::string				symbol_;
+			};
 
-		struct sql_double : public sql_value<double> {
-			sql_double(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<double>(field, value, symbol) {
-				value_ = std::make_tuple(std::atof(value.c_str()));
-			}
-		};
+			struct sql_bool : public sql_value<bool> {
+				sql_bool(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<bool>(field, value, symbol) {
+					value_ = std::make_tuple(value == "true");
+				}
+			};
 
-		struct sql_float : public sql_value<float> {
-			sql_float(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<float>(field, value, symbol) {
-				value_ = std::make_tuple(std::atof(value.c_str()));
-			}
-		};
+			struct sql_int : public sql_value<int> {
+				sql_int(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<int>(field, value, symbol) {
+					value_ = std::make_tuple(std::atoi(value.c_str()));
+				}
+			};
 
-		struct sql_string : public sql_value<std::string> {
-			sql_string(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<std::string>(field, value, symbol) {
-				value_ = std::make_tuple(value);
-			}
-		};
+			struct sql_int64 : public sql_value<std::int64_t> {
+				sql_int64(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<std::int64_t>(field, value, symbol) {
+					value_ = std::make_tuple(std::atoll(value.c_str()));
+				}
+			};
 
-		struct sql_datetime : public sql_value<datetime> {
-			sql_datetime(std::string const& field, std::string const& value, std::string const& symbol = "=") :
-				sql_value<datetime>(field, value, symbol) {
-				value_ = std::make_tuple(datetime(value));
-			}
-		};
+			struct sql_long : public sql_value<long> {
+				sql_long(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<long>(field, value, symbol) {
+					value_ = std::make_tuple(std::atoll(value.c_str()));
+				}
+			};
 
-		struct sql_list : public sql_value<std::string, std::string, std::string, std::string> {
-			sql_list(std::string const& field, std::string const& value, std::string const& symbol = "like") :
-				sql_value<std::string, std::string, std::string, std::string>(field, value, symbol) {
-				value_ = std::make_tuple(
-					value_string_.empty() ? "" : value,
-					value_string_.empty() ? "" : value + ",%",
-					value_string_.empty() ? "" : "%," + value,
-					value_string_.empty() ? "" : "%," + value + ",%");
-				symbol_ = " like ";
-			}
-		};
+			struct sql_double : public sql_value<double> {
+				sql_double(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<double>(field, value, symbol) {
+					value_ = std::make_tuple(std::atof(value.c_str()));
+				}
+			};
 
-		template<typename _SqlConnectConfig>
-		class sql_context {
-			//不区分大小写查找器
-			struct __iequals {
-				__iequals(std::string const& value) :
-					value_(value) {
+			struct sql_float : public sql_value<float> {
+				sql_float(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<float>(field, value, symbol) {
+					value_ = std::make_tuple(std::atof(value.c_str()));
 				}
-				bool operator()(const std::string& a) {
-					return std::equal(a.begin(), a.end(), value_.begin(), value_.end(),
-						[](char a_ch, char b_ch) {
-							return tolower(a_ch) == tolower(b_ch);
-						});
+			};
+
+			struct sql_string : public sql_value<std::string> {
+				sql_string(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<std::string>(field, value, symbol) {
+					value_ = std::make_tuple(value);
 				}
-			private:
-				std::string value_;
 			};
-		public:
-			/**
-			 * @brief 创建数据库
-			 * @return
-			 */
-			static bool create_database() {
-				std::pair<std::string, std::map<std::string, std::string>> config;
-				std::string database_name;
-				{
-					std::string sql_connct_string = _SqlConnectConfig();
-					std::vector<std::string> config_list;
-					boost::split(config_list, sql_connct_string, boost::is_any_of(":"));
-					if (config_list.size() != 2)
-						return false;
-					config.first = config_list[0];
-					sql_connct_string = config_list[1];
-					boost::split(config_list, sql_connct_string, boost::is_any_of(";"));
-					for (auto& it : config_list) {
-						std::vector<std::string> tmp;
-						boost::split(tmp, it, boost::is_any_of("="));
-						if (tmp.size() == 2) {
-							config.second[tmp[0]] = tmp[1];
-						}
-					}
+
+			struct sql_datetime : public sql_value<datetime> {
+				sql_datetime(std::string const& field, std::string const& value, std::string const& symbol = "=") :
+					sql_value<datetime>(field, value, symbol) {
+					value_ = std::make_tuple(datetime(value));
 				}
-				for (auto& it : config.second) {
-					if (boost::algorithm::to_upper_copy(it.first) == "DATABASE") {
-						database_name = it.second;
-						break;
-					}
+			};
+
+			struct sql_list : public sql_value<std::string, std::string, std::string, std::string> {
+				sql_list(std::string const& field, std::string const& value, std::string const& symbol = "like") :
+					sql_value<std::string, std::string, std::string, std::string>(field, value, symbol) {
+					value_ = std::make_tuple(
+						value_string_.empty() ? "" : value,
+						value_string_.empty() ? "" : value + ",%",
+						value_string_.empty() ? "" : "%," + value,
+						value_string_.empty() ? "" : "%," + value + ",%");
+					symbol_ = " like ";
 				}
-				if (database_name.empty())
-					return false;
-				std::string connect_string = config.first + ":";
-				for (auto& it : config.second) {
-					if (boost::algorithm::to_upper_copy(it.first) == "DATABASE") {
-						connect_string += it.first + "=mysql;";
+			};
+
+			template<typename _SqlConnectConfig>
+			class sql_context {
+				//不区分大小写查找器
+				struct __iequals {
+					__iequals(std::string const& value) :
+						value_(value) {
 					}
-					else {
-						connect_string += it.first + "=" + it.second + ";";
+					bool operator()(const std::string& a) {
+						return std::equal(a.begin(), a.end(), value_.begin(), value_.end(),
+							[](char a_ch, char b_ch) {
+								return tolower(a_ch) == tolower(b_ch);
+							});
 					}
-				}
-				std::string sql = "CREATE DATABASE IF NOT EXISTS `" + database_name + "`;";
-				auto conn = sql_connect_pool::open(connect_string);
-				cppdb::session session(conn);
-				cppdb::statement stmt = session << sql;
-				stmt.exec();
-				return true;
-			}
-			/**
-			 * @brief 创建表
-			 * @tparam _Table
-			 */
-			template<typename _Table>
-			static void create_table() {
-				static std::map<rttr::type, std::string> property_list = {
-					{rttr::type::get<int						>(),"`%1%` int"							},
-					{rttr::type::get<std::int64_t				>(),"`%1%` bigint"						},
-					{rttr::type::get<float						>(),"`%1%` float"						},
-					{rttr::type::get<double						>(),"`%1%` double"						},
-					{rttr::type::get<long						>(),"`%1%` bigint"						},
-					{rttr::type::get<bool						>(),"`%1%` int(1) NOT NULL"				},
-					{rttr::type::get<std::string				>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<datetime					>(),"`%1%` datetime DEFAULT NULL"		},
-					{rttr::type::get<std::vector<int		>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<std::int64_t  >>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<float		>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<double		>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<long		>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<bool		>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<std::string>	>(),"`%1%` varchar(255) default NULL"	},
-					{rttr::type::get<std::vector<datetime	>	>(),"`%1%` varchar(255) default NULL"	}
+				private:
+					std::string value_;
 				};
-				std::string sql = "CREATE TABLE `%1%`(\n%2%)\n ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;";
-				rttr::type type = rttr::type::get<_Table>();
-				auto propertys = type.get_properties();
-				std::vector<std::string> fields;
-				for (auto& property : propertys) {
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					rttr::variant prop_key = property.get_metadata("SqlKey");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
-						continue;
+			public:
+				/**
+				 * @brief 创建数据库
+				 * @return
+				 */
+				static bool create_database() {
+					std::pair<std::string, std::map<std::string, std::string>> config;
+					std::string database_name;
+					{
+						std::string sql_connct_string = _SqlConnectConfig();
+						std::vector<std::string> config_list;
+						boost::split(config_list, sql_connct_string, boost::is_any_of(":"));
+						if (config_list.size() != 2)
+							return false;
+						config.first = config_list[0];
+						sql_connct_string = config_list[1];
+						boost::split(config_list, sql_connct_string, boost::is_any_of(";"));
+						for (auto& it : config_list) {
+							std::vector<std::string> tmp;
+							boost::split(tmp, it, boost::is_any_of("="));
+							if (tmp.size() == 2) {
+								config.second[tmp[0]] = tmp[1];
+							}
+						}
 					}
-					std::string prop_name;
-					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-						prop_name = prop_var_name.get_value<std::string>();
+					for (auto& it : config.second) {
+						if (boost::algorithm::to_upper_copy(it.first) == "DATABASE") {
+							database_name = it.second;
+							break;
+						}
 					}
-					else {
-						prop_name = std::string(property.get_name());
+					if (database_name.empty())
+						return false;
+					std::string connect_string = config.first + ":";
+					for (auto& it : config.second) {
+						if (boost::algorithm::to_upper_copy(it.first) == "DATABASE") {
+							connect_string += it.first + "=mysql;";
+						}
+						else {
+							connect_string += it.first + "=" + it.second + ";";
+						}
 					}
+					std::string sql = "CREATE DATABASE IF NOT EXISTS `" + database_name + "`;";
+					auto conn = sql_connect_pool::open(connect_string);
+					cppdb::session session(conn);
+					cppdb::statement stmt = session << sql;
+					stmt.exec();
+					return true;
+				}
+				/**
+				 * @brief 创建表
+				 * @tparam _Table
+				 */
+				template<typename _Table>
+				static void create_table() {
+					static std::map<rttr::type, std::string> property_list = {
+						{rttr::type::get<int						>(),"`%1%` int"							},
+						{rttr::type::get<std::int64_t				>(),"`%1%` bigint"						},
+						{rttr::type::get<float						>(),"`%1%` float"						},
+						{rttr::type::get<double						>(),"`%1%` double"						},
+						{rttr::type::get<long						>(),"`%1%` bigint"						},
+						{rttr::type::get<bool						>(),"`%1%` int(1) NOT NULL"				},
+						{rttr::type::get<std::string				>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<datetime					>(),"`%1%` datetime DEFAULT NULL"		},
+						{rttr::type::get<std::vector<int		>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<std::int64_t  >>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<float		>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<double		>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<long		>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<bool		>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<std::string>	>(),"`%1%` varchar(255) default NULL"	},
+						{rttr::type::get<std::vector<datetime	>	>(),"`%1%` varchar(255) default NULL"	}
+					};
+					std::string sql = "CREATE TABLE `%1%`(\n%2%)\n ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;";
+					rttr::type type = rttr::type::get<_Table>();
+					auto propertys = type.get_properties();
+					std::vector<std::string> fields;
+					for (auto& property : propertys) {
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						rttr::variant prop_key = property.get_metadata("SqlKey");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
+							continue;
+						}
+						std::string prop_name;
+						if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+							prop_name = prop_var_name.get_value<std::string>();
+						}
+						else {
+							prop_name = std::string(property.get_name());
+						}
 
-					if (boost::algorithm::to_upper_copy(prop_name) == "ID") {
-						fields.push_back(boost::str(boost::format("`%1%` bigint(20) NOT NULL AUTO_INCREMENT,\n PRIMARY KEY(`%1%`)") % prop_name));
-					}
-					else {
-						if (property_list.find(property.get_type()) != property_list.end()) {
-							fields.push_back(boost::str(boost::format(property_list[property.get_type()]) % prop_name));
-							if (prop_key.get_type() == rttr::type::get<bool>() && prop_key.get_value<bool>()) {
-								fields.push_back(boost::str(boost::format("KEY `%1%` USING BTREE (`%1%`),\n") % prop_name));
+						if (boost::algorithm::to_upper_copy(prop_name) == "ID") {
+							fields.push_back(boost::str(boost::format("`%1%` bigint(20) NOT NULL AUTO_INCREMENT,\n PRIMARY KEY(`%1%`)") % prop_name));
+						}
+						else {
+							if (property_list.find(property.get_type()) != property_list.end()) {
+								fields.push_back(boost::str(boost::format(property_list[property.get_type()]) % prop_name));
+								if (prop_key.get_type() == rttr::type::get<bool>() && prop_key.get_value<bool>()) {
+									fields.push_back(boost::str(boost::format("KEY `%1%` USING BTREE (`%1%`),\n") % prop_name));
+								}
 							}
 						}
 					}
+					sql = boost::str(boost::format(sql) % type.get_name() % boost::join(fields, ",\n"));
+					auto conn = sql_connect_pool::open<_SqlConnectConfig>();
+					cppdb::session session(conn);
+					cppdb::statement stmt = session << sql;
+					stmt.exec();
 				}
-				sql = boost::str(boost::format(sql) % type.get_name() % boost::join(fields, ",\n"));
-				auto conn = sql_connect_pool::open<_SqlConnectConfig>();
-				cppdb::session session(conn);
-				cppdb::statement stmt = session << sql;
-				stmt.exec();
-			}
-			/**
-			 * @brief 创建表
-			 * @tparam _Table
-			 * @return
-			 */
-			template<typename _Table>
-			static bool create_table_if_not_exists() {
-				rttr::type type = rttr::type::get<_Table>();
-				sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
-				sql_query query(conn);
-				sql_result result = query.execute<sql_result>("select count(0) as count from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME=?", std::string(type.get_name()));
-				while (result.next()) {
-					if (result.get<int>(0) == 0) {
-						create_table<_Table>();
-						return true;
+				/**
+				 * @brief 创建表
+				 * @tparam _Table
+				 * @return
+				 */
+				template<typename _Table>
+				static bool create_table_if_not_exists() {
+					rttr::type type = rttr::type::get<_Table>();
+					sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
+					sql_query query(conn);
+					sql_result result = query.execute<sql_result>("select count(0) as count from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME=?", std::string(type.get_name()));
+					while (result.next()) {
+						if (result.get<int>(0) == 0) {
+							create_table<_Table>();
+							return true;
+						}
 					}
+					return false;
 				}
-				return false;
-			}
-			/**
-			 * @brief 添加数据
-			 * @tparam _Table 结构体
-			 * @param value 值
-			 */
-			template<typename _Table>
-			static void insert(_Table const& value) {
-				rttr::type type = rttr::type::get<_Table>();
-				auto propertys = type.get_properties();
-				std::pair<std::vector<std::string>, std::vector<std::string>> fields;
-				std::vector<rttr::variant> params;
-				for (auto& property : propertys) {
-					std::string prop_name;
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
-						continue;
-					}
-					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-						prop_name = prop_var_name.get_value<std::string>();
-					}
-					else {
-						prop_name = std::string(property.get_name());
-					}
-					boost::algorithm::to_upper(prop_name);
-					if (prop_name == "ID") {
-						rttr::variant var_value = property.get_value(value);
-						if (var_value.get_value<int>() <= 0) {
+				/**
+				 * @brief 添加数据
+				 * @tparam _Table 结构体
+				 * @param value 值
+				 */
+				template<typename _Table>
+				static void insert(_Table const& value) {
+					rttr::type type = rttr::type::get<_Table>();
+					auto propertys = type.get_properties();
+					std::pair<std::vector<std::string>, std::vector<std::string>> fields;
+					std::vector<rttr::variant> params;
+					for (auto& property : propertys) {
+						std::string prop_name;
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
 							continue;
 						}
+						if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+							prop_name = prop_var_name.get_value<std::string>();
+						}
+						else {
+							prop_name = std::string(property.get_name());
+						}
+						boost::algorithm::to_upper(prop_name);
+						if (prop_name == "ID") {
+							rttr::variant var_value = property.get_value(value);
+							if (var_value.get_value<int>() <= 0) {
+								continue;
+							}
+						}
+						fields.first.push_back(prop_name);
+						fields.second.push_back("?");
+						params.push_back(property.get_value(value));
 					}
-					fields.first.push_back(prop_name);
-					fields.second.push_back("?");
-					params.push_back(property.get_value(value));
+					execute<void>(boost::str(boost::format("insert into `%1%`(%2%) values(%3%);") % type.get_name() % boost::join(fields.first, ",") % boost::join(fields.second, ",")), (std::vector<rttr::variant>&)params);
 				}
-				execute<void>(boost::str(boost::format("insert into `%1%`(%2%) values(%3%);") % type.get_name() % boost::join(fields.first, ",") % boost::join(fields.second, ",")), (std::vector<rttr::variant>&)params);
-			}
-			/**
-			 * @brief 添加数据
-			 * @tparam _Table 结构体
-			 * @param values 值
-			 */
-			template<typename _Table>
-			static void insert(std::vector<_Table> const& values) {
-				for (auto& it : values) {
-					insert(it);
-				}
-			}
-			/**
-			 * @brief 查询
-			 * @tparam _Table 结构体
-			 * @tparam ..._Args 参数列表
-			 * @param where 条件
-			 * @param ...args 参数
-			 * @return 返回值
-			 */
-			template<typename _Table, typename ..._Args>
-			static std::vector<_Table> select(std::string const& where, _Args &&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("select * from `%1%` where %2%;") % type.get_name() % where);
-				sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
-				return record.value<_Table>();
-			}
-			/**
-			 * @brief 查询
-			 * @tparam _Table 结构体
-			 * @return 返回值
-			 */
-			template<typename _Table>
-			static std::vector<_Table> select() {
-				return select<_Table>("1=?", 1);
-			}
-			/**
-			 * @brief 查询
-			 * @tparam _Table 结构体
-			 * @tparam ..._Args 参数列表
-			 * @param where 条件
-			 * @param ...args 参数
-			 * @return 返回值
-			 */
-			template<typename _Table, typename ..._Args>
-			static std::vector<std::shared_ptr<_Table>> select_ptr(std::string const& where, _Args &&...args) {
-				std::vector<std::shared_ptr<_Table>> result;
-				auto values = select<_Table>(where, std::forward<_Args>(args)...);
-				for (auto& it : values) {
-					result.push_back(std::make_shared<_Table>(it));
+				/**
+				 * @brief 添加数据
+				 * @tparam _Table 结构体
+				 * @param values 值
+				 */
+				template<typename _Table>
+				static void insert(std::vector<_Table> const& values) {
+					for (auto& it : values) {
+						insert(it);
+					}
 				}
-				return result;
-			}
-			/**
-			 * @brief 查询
-			 * @tparam _Table 结构体
-			 * @return 返回值
-			 */
-			template<typename _Table>
-			static std::vector<std::shared_ptr<_Table>> select_ptr() {
-				return select_ptr<_Table>("1=?", 1);
-			}
-			/**
-			 * @brief 分页查询
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param page
-			 * @param count
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Table, typename ..._Args>
-			static std::vector<_Table> select_page(int page, int count, std::string const& where, _Args &&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("select * from `%1%` where %2% limit %3%,%4%;") % type.get_name() % where % ((page - 1) * count) % count);
-				sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
-				return record.value<_Table>();
-			}
-			/**
-			 * @brief 查询数量
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Table, typename ..._Args>
-			static int select_page_count(std::string const& where, _Args &&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("select count(0) as count from `%1%` where %2% ;") % type.get_name() % where);
-				sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
-				return record.value<int>("count");
-			}
-			/**
-			 * @brief 分页查询数量
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Table, typename ..._Args>
-			static int select_web_page_count(_Args &&...args) {
-				std::vector<rttr::variant> sql_value;
-				std::vector<std::string>   sql_where;
-				if constexpr (sizeof...(_Args) > 0) {
-					auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
-					utils::for_each(tuple, [&](auto& it) {
-						it.get_value(sql_where, sql_value); });
+				/**
+				 * @brief 查询
+				 * @tparam _Table 结构体
+				 * @tparam ..._Args 参数列表
+				 * @param where 条件
+				 * @param ...args 参数
+				 * @return 返回值
+				 */
+				template<typename _Table, typename ..._Args>
+				static std::vector<_Table> select(std::string const& where, _Args &&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("select * from `%1%` where %2%;") % type.get_name() % where);
+					sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
+					return record.value<_Table>();
 				}
-				return  select_page_count<_Table, std::vector<rttr::variant>&>(boost::join(sql_where, " and "), sql_value);
-			}
-			/**
-			 * @brief sql_value分页查询
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param page
-			 * @param count
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Table, typename ..._Args>
-			static std::vector<_Table> select_web_page(int page, int count, _Args &&...args) {
-				std::vector<rttr::variant> sql_value;
-				std::vector<std::string>   sql_where;
-				if constexpr (sizeof...(_Args) > 0) {
-					auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
-					utils::for_each(tuple, [&](auto& it) {
-						it.get_value(sql_where, sql_value); });
+				/**
+				 * @brief 查询
+				 * @tparam _Table 结构体
+				 * @return 返回值
+				 */
+				template<typename _Table>
+				static std::vector<_Table> select() {
+					return select<_Table>("1=?", 1);
 				}
-				return  select_page<_Table, std::vector<rttr::variant>&>(page, count, boost::join(sql_where, " and "), sql_value);
-			}
-			/**
-			 * @brief 分页查询
-			 * @tparam _Table
-			 * @param page
-			 * @param count
-			 * @return
-			 */
-			template<typename _Table>
-			static std::vector<_Table> select_page(int page, int count) {
-				return select_page<_Table>(page, count, "1=?", 1);
-			}
-			/**
-			 * @brief 分页查询
-			 * @tparam _Table
-			 * @param page
-			 * @param count
-			 * @param where
-			 * @param args
-			 * @return
-			 */
-			template<typename _Table>
-			static std::vector<_Table> select_page(int page, int count, std::string const& where, std::vector<rttr::variant>& args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("select * from `%1%` where %2% limit %3%,%4%;") % type.get_name() % where % ((page - 1) * count) % count);
-				sql_record record = execute<sql_result>(sql, args);
-				return record.value<_Table>();
-			}
-			/**
-			 * @brief 查询最小值
-			 * @tparam _Ret 返回值类型
-			 * @tparam ..._Args 参数列表
-			 * @tparam _Table
-			 * @param field
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Ret, typename _Table, typename ..._Args>
-			static _Ret select_min(std::string const& field, std::string const& where, _Args&&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				sql_record record = execute<sql_result>(boost::str(boost::format("select min(`%1%`) as min from `%2%` where %3%;")
-					% field
-					% type.get_name()
-					% where), std::forward<_Args>(args)...);
-				return record.value<_Ret>("min");
-			}
-			/**
-			 * @brief 查询最大值
-			 * @tparam _Ret
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param field
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Ret, typename _Table, typename ..._Args>
-			static _Ret select_max(std::string const& field, std::string const& where, _Args&&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				sql_record record = execute<sql_result>(boost::str(boost::format("select max(`%1%`) as max from `%2%` where %3%;")
-					% field
-					% type.get_name()
-					% where), std::forward<_Args>(args)...);
-				return record.value<_Ret>("max");
-			}
-			/**
-			 * @brief 汇总
-			 * @tparam _Ret
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param field
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Ret, typename _Table, typename ..._Args>
-			static _Ret select_sum(std::string const& field, std::string const& where, _Args&&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				sql_record record = execute<sql_result>(boost::str(boost::format("select sum(`%1%`) as sum from `%2%` where %3%;")
-					% field
-					% type.get_name()
-					% where), std::forward<_Args>(args)...);
-				return record.value<_Ret>("sum");
-			}
-			/**
-			 * @brief 查询数量
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param field
-			 * @param where
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Table, typename ..._Args>
-			static int select_count(std::string const& where, _Args&&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				sql_record record = execute<sql_result>(boost::str(boost::format("select count(`id`) as count from `%1%` where %2%;")
-					% type.get_name()
-					% where), std::forward<_Args>(args)...);
-				return record.value<int>("count");
-			}
-			/**
-			 * @brief 更新
-			 * @param set
-			 * @param where
-			 * @param ...args
-			 */
-			template<typename _Table, typename ..._Args>
-			static void update(std::string const& set, std::string const& where, _Args &&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("update `%1%` set %2% where %3%;") % type.get_name() % set % where);
-				execute<void>(sql, std::forward<_Args>(args)...);
-			}
-			/**
-			 * @brief 更新
-			 * @tparam _Table
-			 * @param value
-			 */
-			template<typename _Table>
-			static void update(_Table const& value, std::vector<std::string> const& sets = {}, std::vector<std::string> const& wheres = { "id" }) {
-				rttr::type type = rttr::type::get<_Table>();
-				auto propertys = type.get_properties();
-				std::pair<std::vector<std::string>, std::vector<std::string>> fields;
-				std::vector<rttr::variant> params;
-				for (auto& property : propertys) {
-					std::string prop_name;
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
-						continue;
-					}
-					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-						prop_name = prop_var_name.get_value<std::string>();
-					}
-					else {
-						prop_name = std::string(property.get_name());
-					}
-					boost::algorithm::to_upper(prop_name);
-					if (sets.empty() || sets.end() != std::find_if(sets.begin(), sets.end(), __iequals(prop_name))) {
-						fields.first.push_back(prop_name + "=?");
-						params.push_back(property.get_value(value));
+				/**
+				 * @brief 查询
+				 * @tparam _Table 结构体
+				 * @tparam ..._Args 参数列表
+				 * @param where 条件
+				 * @param ...args 参数
+				 * @return 返回值
+				 */
+				template<typename _Table, typename ..._Args>
+				static std::vector<std::shared_ptr<_Table>> select_ptr(std::string const& where, _Args &&...args) {
+					std::vector<std::shared_ptr<_Table>> result;
+					auto values = select<_Table>(where, std::forward<_Args>(args)...);
+					for (auto& it : values) {
+						result.push_back(std::make_shared<_Table>(it));
 					}
+					return result;
 				}
-				std::vector<std::string> where = wheres.empty() ? std::vector<std::string>{"id"} : wheres;
-				for (auto& property : propertys) {
-					std::string prop_name;
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
-						continue;
-					}
-					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-						prop_name = prop_var_name.get_value<std::string>();
-					}
-					else {
-						prop_name = std::string(property.get_name());
-					}
-					boost::algorithm::to_upper(prop_name);
-					if (where.end() != std::find_if(where.begin(), where.end(), __iequals(prop_name))) {
-						fields.second.push_back(prop_name + "=?");
-						params.push_back(property.get_value(value));
-					}
+				/**
+				 * @brief 查询
+				 * @tparam _Table 结构体
+				 * @return 返回值
+				 */
+				template<typename _Table>
+				static std::vector<std::shared_ptr<_Table>> select_ptr() {
+					return select_ptr<_Table>("1=?", 1);
 				}
-				execute<void>(boost::str(boost::format("update `%1%` set %2% where %3%;") % type.get_name() % boost::join(fields.first, ",") % boost::join(fields.second, " and ")), (std::vector<rttr::variant>&) params);
-			}
-			/**
-			 * @brief 更新
-			 * @tparam _Table
-			 * @param values
-			 */
-			template<typename _Table>
-			static void update(std::vector<_Table> const& values, std::vector<std::string> const& sets = {}, std::vector<std::string> const& wheres = { "id" }) {
-				for (auto& it : values) {
-					update(it, sets, wheres);
+				/**
+				 * @brief 分页查询
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param page
+				 * @param count
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Table, typename ..._Args>
+				static std::vector<_Table> select_page(int page, int count, std::string const& where, _Args &&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("select * from `%1%` where %2% limit %3%,%4%;") % type.get_name() % where % ((page - 1) * count) % count);
+					sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
+					return record.value<_Table>();
 				}
-			}
-			/**
-			 * @brief 删除
-			 * @tparam _Table
-			 * @tparam ..._Args
-			 * @param where
-			 * @param ...args
-			 */
-			template<typename _Table, typename ..._Args>
-			static void remove(std::string const& where, _Args &&...args) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("delete from `%1%` where %2%;") % type.get_name() % where);
-				execute<void>(sql, std::forward<_Args>(args)...);
-			}
-			/**
-			 * @brief 删除
-			 * @tparam _Table
-			 * @param value
-			 */
-			template<typename _Table>
-			static void remove(_Table const& value) {
-				rttr::type type = rttr::type::get<_Table>();
-				auto propertys = type.get_properties();
-				int id = 0;
-				for (auto& property : propertys) {
-					std::string prop_name;
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
-						continue;
-					}
-					if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
-						prop_name = prop_var_name.get_value<std::string>();
-					}
-					else {
-						prop_name = std::string(property.get_name());
+				/**
+				 * @brief 查询数量
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Table, typename ..._Args>
+				static int select_page_count(std::string const& where, _Args &&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("select count(0) as count from `%1%` where %2% ;") % type.get_name() % where);
+					sql_record record = execute<sql_result>(sql, std::forward<_Args>(args)...);
+					return record.value<int>("count");
+				}
+				/**
+				 * @brief 分页查询数量
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Table, typename ..._Args>
+				static int select_web_page_count(_Args &&...args) {
+					std::vector<rttr::variant> sql_value;
+					std::vector<std::string>   sql_where;
+					if constexpr (sizeof...(_Args) > 0) {
+						auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
+						utils::for_each(tuple, [&](auto& it) {
+							it.get_value(sql_where, sql_value); });
 					}
-					boost::algorithm::to_upper(prop_name);
-					if (prop_name == "ID") {
-						if (property.get_type() != rttr::type::get<int>())
-							throw std::runtime_error("ID不是int类型.");
-						rttr::variant var_value = property.get_value(value);
-						id = var_value.get_value<int>();
-						break;
+					return  select_page_count<_Table, std::vector<rttr::variant>&>(boost::join(sql_where, " and "), sql_value);
+				}
+				/**
+				 * @brief sql_value分页查询
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param page
+				 * @param count
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Table, typename ..._Args>
+				static std::vector<_Table> select_web_page(int page, int count, _Args &&...args) {
+					std::vector<rttr::variant> sql_value;
+					std::vector<std::string>   sql_where;
+					if constexpr (sizeof...(_Args) > 0) {
+						auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
+						utils::for_each(tuple, [&](auto& it) {
+							it.get_value(sql_where, sql_value); });
 					}
+					return  select_page<_Table, std::vector<rttr::variant>&>(page, count, boost::join(sql_where, " and "), sql_value);
 				}
-				std::string sql = boost::str(boost::format("delete from `%1%` where id=?;") % type.get_name());
-				execute<void>(sql, id);
-			}
-			/**
-			 * @brief 删除
-			 * @tparam _Table
-			 * @param values
-			 */
-			template<typename _Table>
-			static void remove(std::vector<_Table> const& values) {
-				for (auto& it : values) {
-					remove(it);
+				/**
+				 * @brief 分页查询
+				 * @tparam _Table
+				 * @param page
+				 * @param count
+				 * @return
+				 */
+				template<typename _Table>
+				static std::vector<_Table> select_page(int page, int count) {
+					return select_page<_Table>(page, count, "1=?", 1);
 				}
-			}
-			/**
-			 * @brief 删除
-			 * @tparam _Table
-			 * @param id
-			 */
-			template<typename _Table>
-			static void remove(int id) {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("delete from `%1%` where id=?;") % type.get_name());
-				execute<void>(sql, id);
-			}
-			/**
-			 * @brief 删除
-			 * @tparam _Table
-			 */
-			template<typename _Table>
-			static void remove() {
-				rttr::type type = rttr::type::get<_Table>();
-				std::string sql = boost::str(boost::format("delete from `%1%`;") % type.get_name());
-				execute<void>(sql);
-			}
-			/**
-			 * @brief 执行
-			 * @tparam _Ret
-			 * @tparam ..._Args
-			 * @param sql
-			 * @param ...args
-			 * @return
-			 */
-			template<typename _Ret, typename ..._Args>
-			static _Ret execute(std::string const& sql, _Args &&...args) {
-				sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
-				sql_query query(conn);
-				return query.execute<_Ret>(sql, std::forward<_Args>(args)...);
-			}
-			/**
-			 * @brief 执行
-			 * @tparam _Ret
-			 * @param sql
-			 * @param args
-			 * @return
-			 */
-			template<typename _Ret>
-			static _Ret execute(std::string const& sql, std::vector<rttr::variant>& args) {
-				sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
-				sql_query query(conn);
-				return query.execute<_Ret>(sql, args);
-			}
-			/**
-			 * @brief 事务
-			 * @tparam _Fn
-			 * @param fn
-			 */
-			template<typename _Fn>
-			static bool transaction(_Fn&& fn, std::exception& ec) {
-				sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
-				sql_query query(conn);
-				try {
-					query.begin_transaction();
-					fn(query);
-					query.end_transaction();
-					return true;
+				/**
+				 * @brief 分页查询
+				 * @tparam _Table
+				 * @param page
+				 * @param count
+				 * @param where
+				 * @param args
+				 * @return
+				 */
+				template<typename _Table>
+				static std::vector<_Table> select_page(int page, int count, std::string const& where, std::vector<rttr::variant>& args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("select * from `%1%` where %2% limit %3%,%4%;") % type.get_name() % where % ((page - 1) * count) % count);
+					sql_record record = execute<sql_result>(sql, args);
+					return record.value<_Table>();
 				}
-				catch (std::exception const& e) {
-					query.rollback_transaction();
-					ec = e;
-					return false;
+				/**
+				 * @brief 查询最小值
+				 * @tparam _Ret 返回值类型
+				 * @tparam ..._Args 参数列表
+				 * @tparam _Table
+				 * @param field
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Ret, typename _Table, typename ..._Args>
+				static _Ret select_min(std::string const& field, std::string const& where, _Args&&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					sql_record record = execute<sql_result>(boost::str(boost::format("select min(`%1%`) as min from `%2%` where %3%;")
+						% field
+						% type.get_name()
+						% where), std::forward<_Args>(args)...);
+					return record.value<_Ret>("min");
 				}
-			}
-			/**
-			 * @brief 备份表
-			 * @tparam _Table 表
-			 * @param time_field 时间字段
-			 * @param retained_day 保留天数
-			 * @param backup_day 备份天数
-			 */
-			template<typename _Table>
-			static void backup(std::string const& time_field, int retained_day, int backup_day) {
-				do {
+				/**
+				 * @brief 查询最大值
+				 * @tparam _Ret
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param field
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Ret, typename _Table, typename ..._Args>
+				static _Ret select_max(std::string const& field, std::string const& where, _Args&&...args) {
 					rttr::type type = rttr::type::get<_Table>();
-					std::string table_name(type.get_name());
-					auto property = type.get_property(time_field);
-					if (!property.is_valid())
-						return;
-					std::string prop_name;
-					rttr::variant no_sql = property.get_metadata("NoSql");
-					rttr::variant prop_var_name = property.get_metadata("Sql");
-					if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>())
-						return;
-					if (prop_var_name.get_type() == rttr::type::get<std::string>())
-						prop_name = prop_var_name.get_value<std::string>();
-					else
-						prop_name = std::string(property.get_name());
-					auto count = select<_Table>("1=? limit 1;", 1);
-					if (count.empty())
-						return;
-					datetime min_time = select_min<datetime, _Table>(time_field, "1=?;", 1);
-					datetime current_time = datetime::current_time_stamp();
-					current_time.add_day(-retained_day);
-					if (min_time >= current_time)
-						return;
-					std::string current_time_str = min_time.to_string("yyyyMMdd");
-					sql_result record = execute<sql_result>(boost::str(boost::format("select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME like '%1%%%';") % table_name));
-					bool is_create = true;
-					std::string backup_table_name;
-					while (record.next()) {
-						if (record.is_null("TABLE_NAME"))
-							continue;
-						backup_table_name = record.get<std::string>("TABLE_NAME");
-						if (backup_table_name.size() - 18 != table_name.size())
+					sql_record record = execute<sql_result>(boost::str(boost::format("select max(`%1%`) as max from `%2%` where %3%;")
+						% field
+						% type.get_name()
+						% where), std::forward<_Args>(args)...);
+					return record.value<_Ret>("max");
+				}
+				/**
+				 * @brief 汇总
+				 * @tparam _Ret
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param field
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Ret, typename _Table, typename ..._Args>
+				static _Ret select_sum(std::string const& field, std::string const& where, _Args&&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					sql_record record = execute<sql_result>(boost::str(boost::format("select sum(`%1%`) as sum from `%2%` where %3%;")
+						% field
+						% type.get_name()
+						% where), std::forward<_Args>(args)...);
+					return record.value<_Ret>("sum");
+				}
+				/**
+				 * @brief 查询数量
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param field
+				 * @param where
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Table, typename ..._Args>
+				static int select_count(std::string const& where, _Args&&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					sql_record record = execute<sql_result>(boost::str(boost::format("select count(`id`) as count from `%1%` where %2%;")
+						% type.get_name()
+						% where), std::forward<_Args>(args)...);
+					return record.value<int>("count");
+				}
+				/**
+				 * @brief 更新
+				 * @param set
+				 * @param where
+				 * @param ...args
+				 */
+				template<typename _Table, typename ..._Args>
+				static void update(std::string const& set, std::string const& where, _Args &&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("update `%1%` set %2% where %3%;") % type.get_name() % set % where);
+					execute<void>(sql, std::forward<_Args>(args)...);
+				}
+				/**
+				 * @brief 更新
+				 * @tparam _Table
+				 * @param value
+				 */
+				template<typename _Table>
+				static void update(_Table const& value, std::vector<std::string> const& sets = {}, std::vector<std::string> const& wheres = { "id" }) {
+					rttr::type type = rttr::type::get<_Table>();
+					auto propertys = type.get_properties();
+					std::pair<std::vector<std::string>, std::vector<std::string>> fields;
+					std::vector<rttr::variant> params;
+					for (auto& property : propertys) {
+						std::string prop_name;
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
 							continue;
-						std::string backup_begin_time = backup_table_name.substr(table_name.size() + 1, 8);
-						std::string backup_end_time = backup_table_name.substr(table_name.size() + 10, 8);
-						auto is_digit = [](char c) { return std::isdigit(static_cast<unsigned char>(c)) != 0; };
-						if (backup_begin_time.empty() ||
-							!std::all_of(backup_begin_time.begin(), backup_begin_time.end(), is_digit) ||
-							backup_end_time.empty() ||
-							!std::all_of(backup_end_time.begin(), backup_end_time.end(), is_digit))
+						}
+						if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+							prop_name = prop_var_name.get_value<std::string>();
+						}
+						else {
+							prop_name = std::string(property.get_name());
+						}
+						boost::algorithm::to_upper(prop_name);
+						if (sets.empty() || sets.end() != std::find_if(sets.begin(), sets.end(), __iequals(prop_name))) {
+							fields.first.push_back(prop_name + "=?");
+							params.push_back(property.get_value(value));
+						}
+					}
+					std::vector<std::string> where = wheres.empty() ? std::vector<std::string>{"id"} : wheres;
+					for (auto& property : propertys) {
+						std::string prop_name;
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
 							continue;
-						if (current_time_str >= backup_begin_time && current_time_str <= backup_end_time) {
-							is_create = false;
-							break;
+						}
+						if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+							prop_name = prop_var_name.get_value<std::string>();
+						}
+						else {
+							prop_name = std::string(property.get_name());
+						}
+						boost::algorithm::to_upper(prop_name);
+						if (where.end() != std::find_if(where.begin(), where.end(), __iequals(prop_name))) {
+							fields.second.push_back(prop_name + "=?");
+							params.push_back(property.get_value(value));
 						}
 					}
-					std::exception ec;
-					bool succ = transaction([&](sql_query& query) {
-						if (is_create) {
-							datetime begin_time = min_time;
-							datetime end_time = min_time;
-							end_time.add_day(backup_day);
-							backup_table_name = boost::str(boost::format("%1%_%2%_%3%") % table_name % begin_time.to_string("yyyyMMdd") % end_time.to_string("yyyyMMdd"));
-							query.execute<void>(boost::str(boost::format("CREATE TABLE %1% LIKE %2%;") % backup_table_name % table_name));
+					execute<void>(boost::str(boost::format("update `%1%` set %2% where %3%;") % type.get_name() % boost::join(fields.first, ",") % boost::join(fields.second, " and ")), (std::vector<rttr::variant>&) params);
+				}
+				/**
+				 * @brief 更新
+				 * @tparam _Table
+				 * @param values
+				 */
+				template<typename _Table>
+				static void update(std::vector<_Table> const& values, std::vector<std::string> const& sets = {}, std::vector<std::string> const& wheres = { "id" }) {
+					for (auto& it : values) {
+						update(it, sets, wheres);
+					}
+				}
+				/**
+				 * @brief 删除
+				 * @tparam _Table
+				 * @tparam ..._Args
+				 * @param where
+				 * @param ...args
+				 */
+				template<typename _Table, typename ..._Args>
+				static void remove(std::string const& where, _Args &&...args) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("delete from `%1%` where %2%;") % type.get_name() % where);
+					execute<void>(sql, std::forward<_Args>(args)...);
+				}
+				/**
+				 * @brief 删除
+				 * @tparam _Table
+				 * @param value
+				 */
+				template<typename _Table>
+				static void remove(_Table const& value) {
+					rttr::type type = rttr::type::get<_Table>();
+					auto propertys = type.get_properties();
+					int id = 0;
+					for (auto& property : propertys) {
+						std::string prop_name;
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>()) {
+							continue;
+						}
+						if (prop_var_name.get_type() == rttr::type::get<std::string>()) {
+							prop_name = prop_var_name.get_value<std::string>();
 						}
-						datetime backup_begin_time;
-						datetime backup_end_time;
-						std::string backup_time_str = backup_table_name.substr(table_name.size() + 1, 8);
-						backup_time_str += " 00:00:00";
-						backup_time_str.insert(backup_time_str.begin() + 4, '-');
-						backup_time_str.insert(backup_time_str.begin() + 7, '-');
-						backup_begin_time.from_string(backup_time_str);
-						backup_time_str = backup_table_name.substr(table_name.size() + 10, 8);
-						backup_time_str += " 23:59:59";
-						backup_time_str.insert(backup_time_str.begin() + 4, '-');
-						backup_time_str.insert(backup_time_str.begin() + 7, '-');
-						backup_end_time.from_string(backup_time_str);
-						if (current_time < backup_end_time)
-							backup_end_time = current_time;
-						if (backup_begin_time.time_stamp() < 0) {
-							backup_begin_time = 0;
+						else {
+							prop_name = std::string(property.get_name());
+						}
+						boost::algorithm::to_upper(prop_name);
+						if (prop_name == "ID") {
+							if (property.get_type() != rttr::type::get<int>())
+								throw std::runtime_error("ID不是int类型.");
+							rttr::variant var_value = property.get_value(value);
+							id = var_value.get_value<int>();
+							break;
 						}
-						if (backup_end_time.time_stamp() < 0) {
-							backup_begin_time = 0;
+					}
+					std::string sql = boost::str(boost::format("delete from `%1%` where id=?;") % type.get_name());
+					execute<void>(sql, id);
+				}
+				/**
+				 * @brief 删除
+				 * @tparam _Table
+				 * @param values
+				 */
+				template<typename _Table>
+				static void remove(std::vector<_Table> const& values) {
+					for (auto& it : values) {
+						remove(it);
+					}
+				}
+				/**
+				 * @brief 删除
+				 * @tparam _Table
+				 * @param id
+				 */
+				template<typename _Table>
+				static void remove(int id) {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("delete from `%1%` where id=?;") % type.get_name());
+					execute<void>(sql, id);
+				}
+				/**
+				 * @brief 删除
+				 * @tparam _Table
+				 */
+				template<typename _Table>
+				static void remove() {
+					rttr::type type = rttr::type::get<_Table>();
+					std::string sql = boost::str(boost::format("delete from `%1%`;") % type.get_name());
+					execute<void>(sql);
+				}
+				/**
+				 * @brief 执行
+				 * @tparam _Ret
+				 * @tparam ..._Args
+				 * @param sql
+				 * @param ...args
+				 * @return
+				 */
+				template<typename _Ret, typename ..._Args>
+				static _Ret execute(std::string const& sql, _Args &&...args) {
+					sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
+					sql_query query(conn);
+					return query.execute<_Ret>(sql, std::forward<_Args>(args)...);
+				}
+				/**
+				 * @brief 执行
+				 * @tparam _Ret
+				 * @param sql
+				 * @param args
+				 * @return
+				 */
+				template<typename _Ret>
+				static _Ret execute(std::string const& sql, std::vector<rttr::variant>& args) {
+					sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
+					sql_query query(conn);
+					return query.execute<_Ret>(sql, args);
+				}
+				/**
+				 * @brief 事务
+				 * @tparam _Fn
+				 * @param fn
+				 */
+				template<typename _Fn>
+				static bool transaction(_Fn&& fn, std::exception& ec) {
+					sql_connect conn = orm::sql_connect_pool::open<_SqlConnectConfig>();
+					sql_query query(conn);
+					try {
+						query.begin_transaction();
+						fn(query);
+						query.end_transaction();
+						return true;
+					}
+					catch (std::exception const& e) {
+						query.rollback_transaction();
+						ec = e;
+						return false;
+					}
+				}
+				/**
+				 * @brief 备份表
+				 * @tparam _Table 表
+				 * @param time_field 时间字段
+				 * @param retained_day 保留天数
+				 * @param backup_day 备份天数
+				 */
+				template<typename _Table>
+				static void backup(std::string const& time_field, int retained_day, int backup_day) {
+					do {
+						rttr::type type = rttr::type::get<_Table>();
+						std::string table_name(type.get_name());
+						auto property = type.get_property(time_field);
+						if (!property.is_valid())
+							return;
+						std::string prop_name;
+						rttr::variant no_sql = property.get_metadata("NoSql");
+						rttr::variant prop_var_name = property.get_metadata("Sql");
+						if (no_sql.get_type() == rttr::type::get<bool>() && no_sql.get_value<bool>())
+							return;
+						if (prop_var_name.get_type() == rttr::type::get<std::string>())
+							prop_name = prop_var_name.get_value<std::string>();
+						else
+							prop_name = std::string(property.get_name());
+						auto count = select<_Table>("1=? limit 1;", 1);
+						if (count.empty())
+							return;
+						datetime min_time = select_min<datetime, _Table>(time_field, "1=?;", 1);
+						datetime current_time = datetime::current_time_stamp();
+						current_time.add_day(-retained_day);
+						if (min_time >= current_time)
+							return;
+						std::string current_time_str = min_time.to_string("yyyyMMdd");
+						sql_result record = execute<sql_result>(boost::str(boost::format("select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME like '%1%%%';") % table_name));
+						bool is_create = true;
+						std::string backup_table_name;
+						while (record.next()) {
+							if (record.is_null("TABLE_NAME"))
+								continue;
+							backup_table_name = record.get<std::string>("TABLE_NAME");
+							if (backup_table_name.size() - 18 != table_name.size())
+								continue;
+							std::string backup_begin_time = backup_table_name.substr(table_name.size() + 1, 8);
+							std::string backup_end_time = backup_table_name.substr(table_name.size() + 10, 8);
+							auto is_digit = [](char c) { return std::isdigit(static_cast<unsigned char>(c)) != 0; };
+							if (backup_begin_time.empty() ||
+								!std::all_of(backup_begin_time.begin(), backup_begin_time.end(), is_digit) ||
+								backup_end_time.empty() ||
+								!std::all_of(backup_end_time.begin(), backup_end_time.end(), is_digit))
+								continue;
+							if (current_time_str >= backup_begin_time && current_time_str <= backup_end_time) {
+								is_create = false;
+								break;
+							}
 						}
-						query.execute<void>(boost::str(boost::format("insert into %1% select * from %2% where `%3%`>='%4%' and `%3%`<='%5%' limit 100000;")
-							% backup_table_name
-							% table_name
-							% time_field
-							% backup_begin_time.to_string("yyyy-MM-dd HH:mm:ss")
-							% backup_end_time.to_string("yyyy-MM-dd HH:mm:ss")));
+						std::exception ec;
+						bool succ = transaction([&](sql_query& query) {
+							if (is_create) {
+								datetime begin_time = min_time;
+								datetime end_time = min_time;
+								end_time.add_day(backup_day);
+								backup_table_name = boost::str(boost::format("%1%_%2%_%3%") % table_name % begin_time.to_string("yyyyMMdd") % end_time.to_string("yyyyMMdd"));
+								query.execute<void>(boost::str(boost::format("CREATE TABLE %1% LIKE %2%;") % backup_table_name % table_name));
+							}
+							datetime backup_begin_time;
+							datetime backup_end_time;
+							std::string backup_time_str = backup_table_name.substr(table_name.size() + 1, 8);
+							backup_time_str += " 00:00:00";
+							backup_time_str.insert(backup_time_str.begin() + 4, '-');
+							backup_time_str.insert(backup_time_str.begin() + 7, '-');
+							backup_begin_time.from_string(backup_time_str);
+							backup_time_str = backup_table_name.substr(table_name.size() + 10, 8);
+							backup_time_str += " 23:59:59";
+							backup_time_str.insert(backup_time_str.begin() + 4, '-');
+							backup_time_str.insert(backup_time_str.begin() + 7, '-');
+							backup_end_time.from_string(backup_time_str);
+							if (current_time < backup_end_time)
+								backup_end_time = current_time;
+							if (backup_begin_time.time_stamp() < 0) {
+								backup_begin_time = 0;
+							}
+							if (backup_end_time.time_stamp() < 0) {
+								backup_begin_time = 0;
+							}
+							query.execute<void>(boost::str(boost::format("insert into %1% select * from %2% where `%3%`>='%4%' and `%3%`<='%5%' limit 100000;")
+								% backup_table_name
+								% table_name
+								% time_field
+								% backup_begin_time.to_string("yyyy-MM-dd HH:mm:ss")
+								% backup_end_time.to_string("yyyy-MM-dd HH:mm:ss")));
 
-						query.execute<void>(boost::str(boost::format("delete from %1% where %2%>='%3%' and %2%<='%4%' limit 100000;")
-							% table_name
-							% time_field
-							% backup_begin_time.to_string("yyyy-MM-dd HH:mm:ss")
-							% backup_end_time.to_string("yyyy-MM-dd HH:mm:ss")));
-						}, ec);
-					if (!succ) {
-						throw ec;
+							query.execute<void>(boost::str(boost::format("delete from %1% where %2%>='%3%' and %2%<='%4%' limit 100000;")
+								% table_name
+								% time_field
+								% backup_begin_time.to_string("yyyy-MM-dd HH:mm:ss")
+								% backup_end_time.to_string("yyyy-MM-dd HH:mm:ss")));
+							}, ec);
+						if (!succ) {
+							throw ec;
+						}
+					} while (true);
+				}
+				/**
+				 * @brief 查询所有备份表
+				 * @tparam _Table
+				 * @return
+				 */
+				template<typename _Table>
+				static std::vector<std::string> get_all_backup_tables() {
+					std::vector<std::string> result;
+					rttr::type type = rttr::type::get<_Table>();
+					std::string table_name(type.get_name());
+					std::string sql = "select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME like '" + table_name + "_%';";
+					sql_result res = execute<sql_result>(sql);
+					while (res.next()) {
+						if (res.is_null("TABLE_NAME"))
+							continue;
+						std::string backup_table_name = res.get<std::string>("TABLE_NAME");
+						std::string pattern = "^" + table_name + "_[0-9]{8}_[0-9]{8}$";
+						if (!utils::regex_check(backup_table_name, pattern))
+							continue;
+						result.push_back(backup_table_name);
 					}
-				} while (true);
-			}
-			/**
-			 * @brief 查询所有备份表
-			 * @tparam _Table
-			 * @return
-			 */
-			template<typename _Table>
-			static std::vector<std::string> get_all_backup_tables() {
-				std::vector<std::string> result;
-				rttr::type type = rttr::type::get<_Table>();
-				std::string table_name(type.get_name());
-				std::string sql = "select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA in (select database()) and TABLE_NAME like '" + table_name + "_%';";
-				sql_result res = execute<sql_result>(sql);
-				while (res.next()) {
-					if (res.is_null("TABLE_NAME"))
-						continue;
-					std::string backup_table_name = res.get<std::string>("TABLE_NAME");
-					std::string pattern = "^" + table_name + "_[0-9]{8}_[0-9]{8}$";
-					if (!utils::regex_check(backup_table_name, pattern))
-						continue;
-					result.push_back(backup_table_name);
+					return result;
 				}
-				return result;
-			}
-			/**
-			 * @brief 删除备份
-			 * @tparam _Table
-			 * @param reserve
-			 */
-			template<typename _Table>
-			static void backup_remove(int reserve) {
+				/**
+				 * @brief 删除备份
+				 * @tparam _Table
+				 * @param reserve
+				 */
+				template<typename _Table>
+				static void backup_remove(int reserve) {
 
-			}
-		};
+				}
+			};
+		}
 	}
 }

+ 620 - 616
robot/robotics/serialization.hpp

@@ -16,641 +16,645 @@
 #include "datetime.hpp"
 #include "utils.hpp"
 
-namespace robotics::v3::archive {
-    enum class binary_type_enum {
-        INT = 1,
-        INT64,
-        BOOL,
-        FLOAT,
-        DOUBLE,
-        UCHAR,
-        STRING,
-        DATETIME,
-        STRUCT,
-        LISTINT,
-        LISTUCHAR,
-        LISTSTRING,
-        LISTSTRUCT
-    };
+namespace robotics {
+    namespace v3 {
+        namespace archive {
+            enum class binary_type_enum {
+                INT = 1,
+                INT64,
+                BOOL,
+                FLOAT,
+                DOUBLE,
+                UCHAR,
+                STRING,
+                DATETIME,
+                STRUCT,
+                LISTINT,
+                LISTUCHAR,
+                LISTSTRING,
+                LISTSTRUCT
+            };
 
-    static inline int count_bytes(size_t num) {
-        int bytes = 0;
-        while (num > 0) {
-            bytes++;
-            num >>= 8;
-        }
-        return bytes;
-    }
-    static inline int count_param(std::vector<std::uint8_t> value) {
-        int result = 0;
-        while (!value.empty()) {
-            result++;
-            int count = value[0] & 7;
-            size_t size = 0;
-            for (size_t i = 0; i < count; ++i) {
-                size += std::int64_t(value[i + 1]) << (8 * i);
-            }
-            value.erase(value.begin(), value.begin() + count + size + 1);
-        }
-        return result;
-    }
-    static inline void to_binary_t(binary_type_enum type, std::vector<std::uint8_t> const& value, std::vector<std::uint8_t>& result) {
-        std::uint8_t tag = std::uint8_t(type) << 4;
-        size_t size = value.size();
-        int count = count_bytes(size);
-        tag += count;
-        result.push_back(tag);
-        for (int i = 0; i < count; ++i) {
-            result.push_back(std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), value.begin(), value.end());
-    }
-    static inline void to_binary_t(binary_type_enum type, std::string const& value, std::vector<std::uint8_t>& result) {
-        std::uint8_t tag = std::uint8_t(type) << 4;
-        size_t size = value.size();
-        int count = count_bytes(size);
-        tag += count;
-        result.push_back(tag);
-        for (int i = 0; i < count; ++i) {
-            result.push_back(std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), value.begin(), value.end());
-    }
-    static inline void to_binary_t(binary_type_enum type, std::int64_t value, std::vector<std::uint8_t>& result) {
-        std::vector<std::uint8_t> tmp;
-        std::uint8_t tag = std::uint8_t(type) << 4;
-        if (value < 0) {
-            tag += 1 << 3;
-            value = std::abs(value);
-        }
-        do {
-            tmp.push_back((std::uint8_t)value);
-            value >>= 8;
-        } while (value > 0);
-        size_t size = tmp.size();
-        int count = count_bytes(size);
-        tag += count;
-        result.push_back(tag);
-        for (int i = 0; i < count; ++i) {
-            result.push_back(std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), tmp.begin(), tmp.end());
-    }
+            static inline int count_bytes(size_t num) {
+                int bytes = 0;
+                while (num > 0) {
+                    bytes++;
+                    num >>= 8;
+                }
+                return bytes;
+            }
+            static inline int count_param(std::vector<std::uint8_t> value) {
+                int result = 0;
+                while (!value.empty()) {
+                    result++;
+                    int count = value[0] & 7;
+                    size_t size = 0;
+                    for (size_t i = 0; i < count; ++i) {
+                        size += std::int64_t(value[i + 1]) << (8 * i);
+                    }
+                    value.erase(value.begin(), value.begin() + count + size + 1);
+                }
+                return result;
+            }
+            static inline void to_binary_t(binary_type_enum type, std::vector<std::uint8_t> const& value, std::vector<std::uint8_t>& result) {
+                std::uint8_t tag = std::uint8_t(type) << 4;
+                size_t size = value.size();
+                int count = count_bytes(size);
+                tag += count;
+                result.push_back(tag);
+                for (int i = 0; i < count; ++i) {
+                    result.push_back(std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), value.begin(), value.end());
+            }
+            static inline void to_binary_t(binary_type_enum type, std::string const& value, std::vector<std::uint8_t>& result) {
+                std::uint8_t tag = std::uint8_t(type) << 4;
+                size_t size = value.size();
+                int count = count_bytes(size);
+                tag += count;
+                result.push_back(tag);
+                for (int i = 0; i < count; ++i) {
+                    result.push_back(std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), value.begin(), value.end());
+            }
+            static inline void to_binary_t(binary_type_enum type, std::int64_t value, std::vector<std::uint8_t>& result) {
+                std::vector<std::uint8_t> tmp;
+                std::uint8_t tag = std::uint8_t(type) << 4;
+                if (value < 0) {
+                    tag += 1 << 3;
+                    value = std::abs(value);
+                }
+                do {
+                    tmp.push_back((std::uint8_t)value);
+                    value >>= 8;
+                } while (value > 0);
+                size_t size = tmp.size();
+                int count = count_bytes(size);
+                tag += count;
+                result.push_back(tag);
+                for (int i = 0; i < count; ++i) {
+                    result.push_back(std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), tmp.begin(), tmp.end());
+            }
 
-    static inline void to_binary(int value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::INT, value, result);
-    }
-    static inline void to_binary(std::int64_t value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::INT64, value, result);
-    }
-    static inline void to_binary(bool value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::BOOL, value ? 1 : 0, result);
-    }
-    static inline void to_binary(float value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::FLOAT, std::int64_t(value * 1000000), result);
-    }
-    static inline void to_binary(double value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::DOUBLE, std::int64_t(value * 10000000000000000), result);
-    }
-    static inline void to_binary(std::uint8_t value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::UCHAR, value, result);
-    }
-    static inline void to_binary(robotics::v3::datetime const& value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::DATETIME, value.time_stamp(), result);
-    }
-    static inline void to_binary(std::string const& value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::STRING, value, result);
-    }
-    static inline void to_binary(char* value, std::vector<std::uint8_t>& result) {
-        to_binary(std::string(value), result);
-    }
-    static inline void to_binary(const char* value, std::vector<std::uint8_t>& result) {
-        to_binary(std::string(value), result);
-    }
-    static inline void to_binary(std::vector<std::uint8_t> const& value, std::vector<std::uint8_t>& result) {
-        to_binary_t(binary_type_enum::LISTUCHAR, value, result);
-    }
-    static inline void to_binary(std::vector<int> const& value, std::vector<std::uint8_t>& result) {
-        std::vector<std::uint8_t> tmp;
-        std::uint8_t tag = std::uint8_t(binary_type_enum::LISTINT) << 4;
-        for (auto& it : value) {
-            to_binary(it, tmp);
-        }
-        size_t size = tmp.size();
-        int count = count_bytes(size);
-        tag += count;
-        tmp.insert(tmp.begin(), tag);
-        for (int i = 0; i < count; ++i) {
-            tmp.insert(tmp.begin() + 1 + i, std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), tmp.begin(), tmp.end());
-    }
-    static inline void to_binary(std::vector<std::string> const& value, std::vector<std::uint8_t>& result) {
-        std::vector<std::uint8_t> tmp;
-        std::uint8_t tag = std::uint8_t(binary_type_enum::LISTSTRING) << 4;
-        for (auto& it : value) {
-            to_binary(it, tmp);
-        }
-        size_t size = tmp.size();
-        int count = count_bytes(size);
-        tag += count;
-        tmp.insert(tmp.begin(), tag);
-        for (int i = 0; i < count; ++i) {
-            tmp.insert(tmp.begin() + 1 + i, std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), tmp.begin(), tmp.end());
-    }
-    static inline void to_binary(rttr::instance const& value, std::vector<std::uint8_t>& result);
-    static inline void to_binary(rttr::variant_sequential_view const& value, std::vector<std::uint8_t>& result) {
-        std::vector<std::uint8_t> tmp;
-        std::uint8_t tag = std::uint8_t(binary_type_enum::LISTSTRUCT) << 4;
-        for (auto& it : value) {
-            to_binary(it.extract_wrapped_value(), tmp);
-        }
-        size_t size = tmp.size();
-        int count = count_bytes(size);
-        tag += count;
-        result.push_back(tag);
-        for (int i = 0; i < count; ++i) {
-            result.push_back(std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), tmp.begin(), tmp.end());
-    }
-    static inline void to_binary(rttr::instance const& value, std::vector<std::uint8_t>& result) {
-        std::vector<std::uint8_t> tmp;
-        std::uint8_t tag = std::uint8_t(binary_type_enum::STRUCT) << 4;
-        auto properties = value.get_derived_type().get_properties();
-        for (auto& property : properties) {
-            rttr::variant no_archive = property.get_metadata("NoArchive");
-            if (no_archive.get_type() == rttr::type::get<bool>() && no_archive.get_value<bool>())
-                continue;
-            if (rttr::type::get<int>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<int>(), tmp);
+            static inline void to_binary(int value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::INT, value, result);
             }
-            else if (rttr::type::get<std::int64_t>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::int64_t>(), tmp);
+            static inline void to_binary(std::int64_t value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::INT64, value, result);
             }
-            else if (rttr::type::get<bool>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<bool>(), tmp);
+            static inline void to_binary(bool value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::BOOL, value ? 1 : 0, result);
             }
-            else if (rttr::type::get<double>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<double>(), tmp);
+            static inline void to_binary(float value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::FLOAT, std::int64_t(value * 1000000), result);
             }
-            else if (rttr::type::get<std::uint8_t>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::uint8_t>(), tmp);
+            static inline void to_binary(double value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::DOUBLE, std::int64_t(value * 10000000000000000), result);
             }
-            else if (rttr::type::get<robotics::v3::datetime>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<robotics::v3::datetime>(), tmp);
+            static inline void to_binary(std::uint8_t value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::UCHAR, value, result);
             }
-            else if (rttr::type::get<std::string>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::string>(), tmp);
+            static inline void to_binary(robotics::v3::datetime const& value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::DATETIME, value.time_stamp(), result);
             }
-            else if (rttr::type::get<std::vector<std::uint8_t>>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::vector<std::uint8_t>>(), tmp);
+            static inline void to_binary(std::string const& value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::STRING, value, result);
             }
-            else if (rttr::type::get<std::vector<int>>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::vector<int>>(), tmp);
+            static inline void to_binary(char* value, std::vector<std::uint8_t>& result) {
+                to_binary(std::string(value), result);
             }
-            else if (rttr::type::get<std::vector<std::string>>() == property.get_type()) {
-                to_binary(property.get_value(value).get_value<std::vector<std::string>>(), tmp);
+            static inline void to_binary(const char* value, std::vector<std::uint8_t>& result) {
+                to_binary(std::string(value), result);
             }
-            else if (property.get_type().is_sequential_container()) {
-                to_binary(property.get_value(value).create_sequential_view(), tmp);
+            static inline void to_binary(std::vector<std::uint8_t> const& value, std::vector<std::uint8_t>& result) {
+                to_binary_t(binary_type_enum::LISTUCHAR, value, result);
             }
-            else if (property.get_type().is_class()) {
-                to_binary(property.get_value(value), tmp);
+            static inline void to_binary(std::vector<int> const& value, std::vector<std::uint8_t>& result) {
+                std::vector<std::uint8_t> tmp;
+                std::uint8_t tag = std::uint8_t(binary_type_enum::LISTINT) << 4;
+                for (auto& it : value) {
+                    to_binary(it, tmp);
+                }
+                size_t size = tmp.size();
+                int count = count_bytes(size);
+                tag += count;
+                tmp.insert(tmp.begin(), tag);
+                for (int i = 0; i < count; ++i) {
+                    tmp.insert(tmp.begin() + 1 + i, std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), tmp.begin(), tmp.end());
+            }
+            static inline void to_binary(std::vector<std::string> const& value, std::vector<std::uint8_t>& result) {
+                std::vector<std::uint8_t> tmp;
+                std::uint8_t tag = std::uint8_t(binary_type_enum::LISTSTRING) << 4;
+                for (auto& it : value) {
+                    to_binary(it, tmp);
+                }
+                size_t size = tmp.size();
+                int count = count_bytes(size);
+                tag += count;
+                tmp.insert(tmp.begin(), tag);
+                for (int i = 0; i < count; ++i) {
+                    tmp.insert(tmp.begin() + 1 + i, std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), tmp.begin(), tmp.end());
+            }
+            static inline void to_binary(rttr::instance const& value, std::vector<std::uint8_t>& result);
+            static inline void to_binary(rttr::variant_sequential_view const& value, std::vector<std::uint8_t>& result) {
+                std::vector<std::uint8_t> tmp;
+                std::uint8_t tag = std::uint8_t(binary_type_enum::LISTSTRUCT) << 4;
+                for (auto& it : value) {
+                    to_binary(it.extract_wrapped_value(), tmp);
+                }
+                size_t size = tmp.size();
+                int count = count_bytes(size);
+                tag += count;
+                result.push_back(tag);
+                for (int i = 0; i < count; ++i) {
+                    result.push_back(std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), tmp.begin(), tmp.end());
+            }
+            static inline void to_binary(rttr::instance const& value, std::vector<std::uint8_t>& result) {
+                std::vector<std::uint8_t> tmp;
+                std::uint8_t tag = std::uint8_t(binary_type_enum::STRUCT) << 4;
+                auto properties = value.get_derived_type().get_properties();
+                for (auto& property : properties) {
+                    rttr::variant no_archive = property.get_metadata("NoArchive");
+                    if (no_archive.get_type() == rttr::type::get<bool>() && no_archive.get_value<bool>())
+                        continue;
+                    if (rttr::type::get<int>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<int>(), tmp);
+                    }
+                    else if (rttr::type::get<std::int64_t>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::int64_t>(), tmp);
+                    }
+                    else if (rttr::type::get<bool>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<bool>(), tmp);
+                    }
+                    else if (rttr::type::get<double>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<double>(), tmp);
+                    }
+                    else if (rttr::type::get<std::uint8_t>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::uint8_t>(), tmp);
+                    }
+                    else if (rttr::type::get<robotics::v3::datetime>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<robotics::v3::datetime>(), tmp);
+                    }
+                    else if (rttr::type::get<std::string>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::string>(), tmp);
+                    }
+                    else if (rttr::type::get<std::vector<std::uint8_t>>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::vector<std::uint8_t>>(), tmp);
+                    }
+                    else if (rttr::type::get<std::vector<int>>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::vector<int>>(), tmp);
+                    }
+                    else if (rttr::type::get<std::vector<std::string>>() == property.get_type()) {
+                        to_binary(property.get_value(value).get_value<std::vector<std::string>>(), tmp);
+                    }
+                    else if (property.get_type().is_sequential_container()) {
+                        to_binary(property.get_value(value).create_sequential_view(), tmp);
+                    }
+                    else if (property.get_type().is_class()) {
+                        to_binary(property.get_value(value), tmp);
+                    }
+                }
+                size_t size = tmp.size();
+                int count = count_bytes(size);
+                tag += count;
+                result.push_back(tag);
+                for (int i = 0; i < count; ++i) {
+                    result.push_back(std::uint8_t(size >> (8 * i)));
+                }
+                result.insert(result.end(), tmp.begin(), tmp.end());
             }
-        }
-        size_t size = tmp.size();
-        int count = count_bytes(size);
-        tag += count;
-        result.push_back(tag);
-        for (int i = 0; i < count; ++i) {
-            result.push_back(std::uint8_t(size >> (8 * i)));
-        }
-        result.insert(result.end(), tmp.begin(), tmp.end());
-    }
 
-    static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::vector<std::uint8_t>& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
-            throw std::runtime_error("data type error");
-        }
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        result.assign(value.begin() + count + 1, value.begin() + count + size + 1);
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
-    static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::string& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
-            throw std::runtime_error("data type error");
-        }
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        result.assign(value.begin() + count + 1, value.begin() + count + size + 1);
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
-    static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::int64_t& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
-            throw std::runtime_error("data type error");
-        }
-        result = 0;
-        bool symbol = value[0] & 8;
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        std::vector<std::uint8_t> tmp(value.begin() + 1 + count, value.begin() + 1 + count + size);
-        for (size_t i = 0; i < tmp.size(); ++i) {
-            result += std::int64_t(tmp[i]) << (8 * i);
-        }
-        if (symbol) {
-            result *= -1;
-        }
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
+            static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::vector<std::uint8_t>& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
+                    throw std::runtime_error("data type error");
+                }
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                result.assign(value.begin() + count + 1, value.begin() + count + size + 1);
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
+            static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::string& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
+                    throw std::runtime_error("data type error");
+                }
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                result.assign(value.begin() + count + 1, value.begin() + count + size + 1);
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
+            static inline void binary_to_t(std::vector<std::uint8_t>& value, binary_type_enum type, std::int64_t& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(type)) {
+                    throw std::runtime_error("data type error");
+                }
+                result = 0;
+                bool symbol = value[0] & 8;
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                std::vector<std::uint8_t> tmp(value.begin() + 1 + count, value.begin() + 1 + count + size);
+                for (size_t i = 0; i < tmp.size(); ++i) {
+                    result += std::int64_t(tmp[i]) << (8 * i);
+                }
+                if (symbol) {
+                    result *= -1;
+                }
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
 
-    static inline void binary_to(std::vector<std::uint8_t>& value, int& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::INT, tmp);
-        result = tmp;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::int64_t& result) {
-        binary_to_t(value, binary_type_enum::INT64, result);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, bool& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::BOOL, tmp);
-        result = tmp != 0;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, float& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::FLOAT, tmp);
-        result = float(tmp) / 1000000;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, double& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::DOUBLE, tmp);
-        result = double(tmp) / 10000000000000000;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::uint8_t& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::UCHAR, tmp);
-        result = tmp;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, robotics::v3::datetime& result) {
-        std::int64_t tmp = 0;
-        binary_to_t(value, binary_type_enum::DATETIME, tmp);
-        result = tmp;
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::string& result) {
-        binary_to_t(value, binary_type_enum::STRING, result);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<std::uint8_t>& result) {
-        binary_to_t(value, binary_type_enum::LISTUCHAR, result);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<int>& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTINT)) {
-            throw std::runtime_error("data type error");
-        }
-        result.clear();
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
-        while (!data.empty()) {
-            result.push_back(0);
-            binary_to(data, result[result.size() - 1]);
-        }
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<std::string>& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTSTRING)) {
-            throw std::runtime_error("data type error");
-        }
-        result.clear();
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
-        while (!data.empty()) {
-            result.push_back("");
-            binary_to(data, result[result.size() - 1]);
-        }
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, rttr::instance result);
-    static inline void binary_to(std::vector<std::uint8_t>& value, rttr::variant_sequential_view& result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTSTRUCT)) {
-            throw std::runtime_error("data type error");
-        }
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
-        int count_p = count_param(data);
-        result.set_size(count_p);
-        for (size_t i = 0; i < count_p; ++i) {
-            rttr::variant tmp = result.get_value(i).extract_wrapped_value();
-            binary_to(data, tmp);
-            result.set_value(i, tmp);
-        }
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
-    static inline void binary_to(std::vector<std::uint8_t>& value, rttr::instance result) {
-        if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::STRUCT)) {
-            throw std::runtime_error("data type error");
-        }
-        int count = value[0] & 7;
-        size_t size = 0;
-        for (size_t i = 0; i < count; ++i) {
-            size += std::int64_t(value[i + 1]) << (8 * i);
-        }
-        std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
-        auto properties = result.get_derived_type().get_properties();
-        for (auto& property : properties) {
-            rttr::variant no_archive = property.get_metadata("NoArchive");
-            if (no_archive.get_type() == rttr::type::get<bool>() && no_archive.get_value<bool>())
-                continue;
-            if (rttr::type::get<int>() == property.get_type()) {
-                int tmp = 0;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::int64_t>() == property.get_type()) {
+            static inline void binary_to(std::vector<std::uint8_t>& value, int& result) {
                 std::int64_t tmp = 0;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<bool>() == property.get_type()) {
-                bool tmp = false;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<double>() == property.get_type()) {
-                double tmp = 0;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::uint8_t>() == property.get_type()) {
-                std::uint8_t tmp = 0;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<robotics::v3::datetime>() == property.get_type()) {
-                robotics::v3::datetime tmp;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::string>() == property.get_type()) {
-                std::string tmp;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::vector<std::uint8_t>>() == property.get_type()) {
-                std::vector<std::uint8_t> tmp;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::vector<int>>() == property.get_type()) {
-                std::vector<int> tmp;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (rttr::type::get<std::vector<std::string>>() == property.get_type()) {
-                std::vector<std::string> tmp;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            else if (property.get_type().is_sequential_container()) {
-                rttr::variant var = property.get_value(result);
-                auto view = var.create_sequential_view();
-                binary_to(data, view);
-                property.set_value(result, var);
-            }
-            else if (property.get_type().is_class()) {
-                rttr::variant tmp = property.get_value(result);;
-                binary_to(data, tmp);
-                property.set_value(result, tmp);
-            }
-            if (data.empty())
-                break;
-        }
-        value.erase(value.begin(), value.begin() + count + size + 1);
-    }
+                binary_to_t(value, binary_type_enum::INT, tmp);
+                result = tmp;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::int64_t& result) {
+                binary_to_t(value, binary_type_enum::INT64, result);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, bool& result) {
+                std::int64_t tmp = 0;
+                binary_to_t(value, binary_type_enum::BOOL, tmp);
+                result = tmp != 0;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, float& result) {
+                std::int64_t tmp = 0;
+                binary_to_t(value, binary_type_enum::FLOAT, tmp);
+                result = float(tmp) / 1000000;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, double& result) {
+                std::int64_t tmp = 0;
+                binary_to_t(value, binary_type_enum::DOUBLE, tmp);
+                result = double(tmp) / 10000000000000000;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::uint8_t& result) {
+                std::int64_t tmp = 0;
+                binary_to_t(value, binary_type_enum::UCHAR, tmp);
+                result = tmp;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, robotics::v3::datetime& result) {
+                std::int64_t tmp = 0;
+                binary_to_t(value, binary_type_enum::DATETIME, tmp);
+                result = tmp;
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::string& result) {
+                binary_to_t(value, binary_type_enum::STRING, result);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<std::uint8_t>& result) {
+                binary_to_t(value, binary_type_enum::LISTUCHAR, result);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<int>& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTINT)) {
+                    throw std::runtime_error("data type error");
+                }
+                result.clear();
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
+                while (!data.empty()) {
+                    result.push_back(0);
+                    binary_to(data, result[result.size() - 1]);
+                }
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, std::vector<std::string>& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTSTRING)) {
+                    throw std::runtime_error("data type error");
+                }
+                result.clear();
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
+                while (!data.empty()) {
+                    result.push_back("");
+                    binary_to(data, result[result.size() - 1]);
+                }
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, rttr::instance result);
+            static inline void binary_to(std::vector<std::uint8_t>& value, rttr::variant_sequential_view& result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::LISTSTRUCT)) {
+                    throw std::runtime_error("data type error");
+                }
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
+                int count_p = count_param(data);
+                result.set_size(count_p);
+                for (size_t i = 0; i < count_p; ++i) {
+                    rttr::variant tmp = result.get_value(i).extract_wrapped_value();
+                    binary_to(data, tmp);
+                    result.set_value(i, tmp);
+                }
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
+            static inline void binary_to(std::vector<std::uint8_t>& value, rttr::instance result) {
+                if (value.empty() || (value[0] >> 4) != std::uint8_t(binary_type_enum::STRUCT)) {
+                    throw std::runtime_error("data type error");
+                }
+                int count = value[0] & 7;
+                size_t size = 0;
+                for (size_t i = 0; i < count; ++i) {
+                    size += std::int64_t(value[i + 1]) << (8 * i);
+                }
+                std::vector<std::uint8_t> data(value.begin() + count + 1, value.begin() + count + size + 1);
+                auto properties = result.get_derived_type().get_properties();
+                for (auto& property : properties) {
+                    rttr::variant no_archive = property.get_metadata("NoArchive");
+                    if (no_archive.get_type() == rttr::type::get<bool>() && no_archive.get_value<bool>())
+                        continue;
+                    if (rttr::type::get<int>() == property.get_type()) {
+                        int tmp = 0;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::int64_t>() == property.get_type()) {
+                        std::int64_t tmp = 0;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<bool>() == property.get_type()) {
+                        bool tmp = false;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<double>() == property.get_type()) {
+                        double tmp = 0;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::uint8_t>() == property.get_type()) {
+                        std::uint8_t tmp = 0;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<robotics::v3::datetime>() == property.get_type()) {
+                        robotics::v3::datetime tmp;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::string>() == property.get_type()) {
+                        std::string tmp;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::vector<std::uint8_t>>() == property.get_type()) {
+                        std::vector<std::uint8_t> tmp;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::vector<int>>() == property.get_type()) {
+                        std::vector<int> tmp;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (rttr::type::get<std::vector<std::string>>() == property.get_type()) {
+                        std::vector<std::string> tmp;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    else if (property.get_type().is_sequential_container()) {
+                        rttr::variant var = property.get_value(result);
+                        auto view = var.create_sequential_view();
+                        binary_to(data, view);
+                        property.set_value(result, var);
+                    }
+                    else if (property.get_type().is_class()) {
+                        rttr::variant tmp = property.get_value(result);;
+                        binary_to(data, tmp);
+                        property.set_value(result, tmp);
+                    }
+                    if (data.empty())
+                        break;
+                }
+                value.erase(value.begin(), value.begin() + count + size + 1);
+            }
 
-    class stream {
-    public:
-        /**
-         * @brief 构造
-         */
-        stream() {
-        }
-        /**
-         * @brief 构造
-         * @param data
-         */
-        stream(std::vector<std::uint8_t> const& data)
-            :data_(data) {
-        }
-        /**
-         * @brief 构造
-         * @param data
-         */
-        stream(std::string_view data) {
-            data_.assign(data.begin(), data.end());
-        }
-        /**
-         * @brief 数据
-         * @return
-         */
-        std::vector<std::uint8_t> data() {
-            return data_;
-        }
-        /**
-         * @brief 空
-         * @return
-         */
-        bool empty() {
-            return data_.empty();
-        }
-        /**
-         * @brief 清空
-         */
-        void clear() {
-            data_.clear();
-        }
-        /**
-         * @brief 添加
-         * @param value
-         */
-        void add(stream const& value) {
-            data_.insert(data_.end(), value.data_.begin(), value.data_.end());
-        }
-        /**
-         * @brief 添加
-         * @param value
-         * @return
-         */
-        stream& operator +=(stream const& value) {
-            add(value);
-            return *this;
-        }
-        /**
-         * @brief 序列化
-         * @tparam _Type
-         * @param value
-         * @return
-         */
-        template<typename _Type>
-        stream& serialize(_Type const& value) {
-            to_binary(value, data_);
-            return *this;
-        }
-        /**
-         * @brief 序列化
-         * @tparam ..._Args
-         * @param value
-         * @return
-         */
-        template<typename ..._Args>
-        stream& serialize(std::tuple<_Args...> const& value) {
-            v3::utils::for_each(value, [this](auto& it) {
-                (*this) << it;
-                });
-            return *this;
-        }
-        /**
-         * @brief 反序列化
-         * @tparam _Type
-         * @param value
-         * @return
-         */
-        template<typename _Type>
-        stream& deserialize(_Type& value) {
-            binary_to(data_, value);
-            return *this;
-        }
-        /**
-         * @brief 反序列化
-         * @tparam ..._Args
-         * @param value
-         * @return
-         */
-        template<typename ..._Args>
-        stream& deserialize(std::tuple<_Args...>& value) {
-            v3::utils::for_each_reference(value, [this](auto& it) {
-                (*this) >> it;
-                });
-            return *this;
-        }
-        /**
-         * @brief 序列化
-         * @tparam _Type
-         * @param value
-         * @return
-         */
-        template<typename _Type>
-        stream& operator <<(_Type const& value) {
-            return serialize(value);
-        }
-        /**
-         * @brief 序列化
-         * @tparam ..._Args
-         * @param value
-         * @return
-         */
-        template<typename ..._Args>
-        stream& operator <<(std::tuple<_Args...> const& value) {
-            return serialize(value);
-        }
-        /**
-         * @brief 反序列化
-         * @tparam _Type
-         * @param value
-         * @return
-         */
-        template<typename _Type>
-        stream& operator >>(_Type& value) {
-            return deserialize(value);
-        }
-        /**
-         * @brief 反序列化
-         * @tparam ..._Args
-         * @param value
-         * @return
-         */
-        template<typename ..._Args>
-        stream& operator >>(std::tuple<_Args...>& value) {
-            return deserialize(value);
-        }
-    private:
-        /**
-         * @brief 数据
-         */
-        std::vector<std::uint8_t> data_;
-    };
+            class stream {
+            public:
+                /**
+                 * @brief 构造
+                 */
+                stream() {
+                }
+                /**
+                 * @brief 构造
+                 * @param data
+                 */
+                stream(std::vector<std::uint8_t> const& data)
+                    :data_(data) {
+                }
+                /**
+                 * @brief 构造
+                 * @param data
+                 */
+                stream(std::string_view data) {
+                    data_.assign(data.begin(), data.end());
+                }
+                /**
+                 * @brief 数据
+                 * @return
+                 */
+                std::vector<std::uint8_t> data() {
+                    return data_;
+                }
+                /**
+                 * @brief 空
+                 * @return
+                 */
+                bool empty() {
+                    return data_.empty();
+                }
+                /**
+                 * @brief 清空
+                 */
+                void clear() {
+                    data_.clear();
+                }
+                /**
+                 * @brief 添加
+                 * @param value
+                 */
+                void add(stream const& value) {
+                    data_.insert(data_.end(), value.data_.begin(), value.data_.end());
+                }
+                /**
+                 * @brief 添加
+                 * @param value
+                 * @return
+                 */
+                stream& operator +=(stream const& value) {
+                    add(value);
+                    return *this;
+                }
+                /**
+                 * @brief 序列化
+                 * @tparam _Type
+                 * @param value
+                 * @return
+                 */
+                template<typename _Type>
+                stream& serialize(_Type const& value) {
+                    to_binary(value, data_);
+                    return *this;
+                }
+                /**
+                 * @brief 序列化
+                 * @tparam ..._Args
+                 * @param value
+                 * @return
+                 */
+                template<typename ..._Args>
+                stream& serialize(std::tuple<_Args...> const& value) {
+                    v3::utils::for_each(value, [this](auto& it) {
+                        (*this) << it;
+                        });
+                    return *this;
+                }
+                /**
+                 * @brief 反序列化
+                 * @tparam _Type
+                 * @param value
+                 * @return
+                 */
+                template<typename _Type>
+                stream& deserialize(_Type& value) {
+                    binary_to(data_, value);
+                    return *this;
+                }
+                /**
+                 * @brief 反序列化
+                 * @tparam ..._Args
+                 * @param value
+                 * @return
+                 */
+                template<typename ..._Args>
+                stream& deserialize(std::tuple<_Args...>& value) {
+                    v3::utils::for_each_reference(value, [this](auto& it) {
+                        (*this) >> it;
+                        });
+                    return *this;
+                }
+                /**
+                 * @brief 序列化
+                 * @tparam _Type
+                 * @param value
+                 * @return
+                 */
+                template<typename _Type>
+                stream& operator <<(_Type const& value) {
+                    return serialize(value);
+                }
+                /**
+                 * @brief 序列化
+                 * @tparam ..._Args
+                 * @param value
+                 * @return
+                 */
+                template<typename ..._Args>
+                stream& operator <<(std::tuple<_Args...> const& value) {
+                    return serialize(value);
+                }
+                /**
+                 * @brief 反序列化
+                 * @tparam _Type
+                 * @param value
+                 * @return
+                 */
+                template<typename _Type>
+                stream& operator >>(_Type& value) {
+                    return deserialize(value);
+                }
+                /**
+                 * @brief 反序列化
+                 * @tparam ..._Args
+                 * @param value
+                 * @return
+                 */
+                template<typename ..._Args>
+                stream& operator >>(std::tuple<_Args...>& value) {
+                    return deserialize(value);
+                }
+            private:
+                /**
+                 * @brief 数据
+                 */
+                std::vector<std::uint8_t> data_;
+            };
 
-    class ifunction {
-    public:
-        virtual v3::archive::stream invoke(v3::archive::stream as) = 0;
-    };
-    template<typename _Func>
-    class function : public ifunction {
-    public:
-        function(_Func&& fn) {
-            fn_ = std::move(fn);
-        }
-        v3::archive::stream invoke(v3::archive::stream as) override {
-            typename v3::function_traits<_Func>::param_remove_reference_and_const_type params;
-            as >> params;
-            if constexpr (std::is_same<typename v3::function_traits<_Func>::return_type, void>::value) {
-                std::apply([&](auto const&...args) ->v3::function_traits<_Func>::return_type {
-                    return std::invoke(fn_, args...);
-                    }, params);
-            }
-            else {
-                as << std::apply([&](auto const&...args) ->v3::function_traits<_Func>::return_type {
-                    return std::invoke(fn_, args...);
-                    }, params);
-            }
-            return as;
-        }
-    private:
-        v3::function_traits<_Func>::stl_function_type fn_;
-    };
+            class ifunction {
+            public:
+                virtual v3::archive::stream invoke(v3::archive::stream as) = 0;
+            };
+            template<typename _Func>
+            class function : public ifunction {
+            public:
+                function(_Func&& fn) {
+                    fn_ = std::move(fn);
+                }
+                v3::archive::stream invoke(v3::archive::stream as) override {
+                    typename v3::function_traits<_Func>::param_remove_reference_and_const_type params;
+                    as >> params;
+                    if constexpr (std::is_same<typename v3::function_traits<_Func>::return_type, void>::value) {
+                        std::apply([&](auto const&...args) ->v3::function_traits<_Func>::return_type {
+                            return std::invoke(fn_, args...);
+                            }, params);
+                    }
+                    else {
+                        as << std::apply([&](auto const&...args) ->v3::function_traits<_Func>::return_type {
+                            return std::invoke(fn_, args...);
+                            }, params);
+                    }
+                    return as;
+                }
+            private:
+                v3::function_traits<_Func>::stl_function_type fn_;
+            };
 
-    template<typename _KeyType>
-    class function_manage {
-    public:
-        template<typename _Func, typename _This>
-        void bind(_KeyType const& name, _Func&& fn, _This&& ths) {
-            bind(name, (typename v3::function_traits<_Func>::stl_function_type)(std::bind_front(std::forward<_Func>(fn), std::forward<_This>(ths))));
-        }
-        template<typename _Func>
-        void bind(_KeyType const& name, _Func&& fn) {
-            func_list_[name] = std::make_shared<function<_Func>>(std::forward<_Func>(fn));
+            template<typename _KeyType>
+            class function_manage {
+            public:
+                template<typename _Func, typename _This>
+                void bind(_KeyType const& name, _Func&& fn, _This&& ths) {
+                    bind(name, (typename v3::function_traits<_Func>::stl_function_type)(std::bind_front(std::forward<_Func>(fn), std::forward<_This>(ths))));
+                }
+                template<typename _Func>
+                void bind(_KeyType const& name, _Func&& fn) {
+                    func_list_[name] = std::make_shared<function<_Func>>(std::forward<_Func>(fn));
+                }
+                v3::archive::stream invoke(_KeyType const& name, v3::archive::stream as) {
+                    if (func_list_.find(name) == func_list_.end()) {
+                        return {};
+                    }
+                    as = func_list_[name]->invoke(as);
+                    return as;
+                }
+            private:
+                std::map<_KeyType, std::shared_ptr<ifunction>> func_list_;
+            };
         }
-        v3::archive::stream invoke(_KeyType const& name, v3::archive::stream as) {
-            if (func_list_.find(name) == func_list_.end()) {
-                return {};
-            }
-            as = func_list_[name]->invoke(as);
-            return as;
-        }
-    private:
-        std::map<_KeyType, std::shared_ptr<ifunction>> func_list_;
-    };
+    }
 }

+ 1593 - 1591
robot/robotics/sql_linq.hpp

@@ -22,1822 +22,1824 @@
 #include "orm.hpp"
 #include "logger.hpp"
 
-namespace robotics::v3 {
-    /**
-     * @brief 执行类型
-     */
-    enum sql_event_type {
+namespace robotics {
+    namespace v3 {
         /**
-         * @brief 添加
+         * @brief 执行类型
          */
-        Insert = 0,
-        /**
-         * @brief 删除
-         */
-        Delete,
-        /**
-         * @brief 更新
-         */
-        Update,
-        /**
-         * @brief 查询
-         */
-        Select,
-        /**
-         * @brief 查询数量
-         */
-        Count,
-        /**
-         * @brief 错误
-         */
-        Error
-    };
-    /**
-     * @brief 排序
-     */
-    enum sql_order_by_type {
-        /**
-         * @brief 升序
-         */
-        Asc,
-        /**
-         * @brief 降序
-         */
-        Desc
-    };
-    /**
-     * @brief 表达式
-     */
-    struct sql_expression {
-        /**
-         * @brief 表达式类型
-         */
-        enum symbol_type {
+        enum sql_event_type {
             /**
-             * @brief 无效表达式
+             * @brief 添加
              */
-            Invalid = 0,
+            Insert = 0,
             /**
-             * @brief =
+             * @brief 删除
              */
-            Equal,
+            Delete,
             /**
-             * @brief ==
+             * @brief 更新
              */
-            EqualEqual,
+            Update,
             /**
-             * @brief !=
+             * @brief 查询
              */
-            NotEqual,
+            Select,
             /**
-             * @brief >
+             * @brief 查询数量
              */
-            Greater,
+            Count,
             /**
-             * @brief <
+             * @brief 错误
              */
-            Less,
+            Error
+        };
+        /**
+         * @brief 排序
+         */
+        enum sql_order_by_type {
             /**
-             * @brief >=
+             * @brief 升序
              */
-            GreaterEqual,
+            Asc,
             /**
-             * @brief <=
+             * @brief 降序
              */
-            LessEqual,
+            Desc
+        };
+        /**
+         * @brief 表达式
+         */
+        struct sql_expression {
             /**
-             * @brief in
+             * @brief 表达式类型
              */
-            In,
+            enum symbol_type {
+                /**
+                 * @brief 无效表达式
+                 */
+                Invalid = 0,
+                /**
+                 * @brief =
+                 */
+                Equal,
+                /**
+                 * @brief ==
+                 */
+                EqualEqual,
+                /**
+                 * @brief !=
+                 */
+                NotEqual,
+                /**
+                 * @brief >
+                 */
+                Greater,
+                /**
+                 * @brief <
+                 */
+                Less,
+                /**
+                 * @brief >=
+                 */
+                GreaterEqual,
+                /**
+                 * @brief <=
+                 */
+                LessEqual,
+                /**
+                 * @brief in
+                 */
+                In,
+                /**
+                 * @brief like
+                 */
+                Like,
+                /**
+                 * @brief &&
+                 */
+                And,
+                /**
+                 * @brief ||
+                 */
+                Or,
+                /**
+                 * @brief 逗号
+                 */
+                Comma,
+                /**
+                 * @brief 排序
+                 */
+                OrderBy,
+                /**
+                 * @brief 分页
+                 */
+                Limit,
+                /**
+                 * @brief 分隔符
+                 */
+                Separator
+            };
             /**
-             * @brief like
+             * @brief 括号
              */
-            Like,
+            enum brace_type {
+                /**
+                 * @brief 无效
+                 */
+                Not,
+                /**
+                 * @brief 开
+                 */
+                On,
+                /**
+                 * @brief 关
+                 */
+                Off,
+                /**
+                 * @brief 开关
+                 */
+                OnOff
+            };
             /**
-             * @brief &&
+             * @brief 字段名称
              */
-            And,
+            std::string name;
             /**
-             * @brief ||
+             * @brief 表达式符号
              */
-            Or,
+            symbol_type symbol = symbol_type::Invalid;
             /**
-             * @brief 逗号
+             * @brief 
              */
-            Comma,
+            std::vector<rttr::variant> values;
             /**
-             * @brief 排序
+             * @brief 括号
              */
-            OrderBy,
+            brace_type brace = brace_type::Not;
             /**
              * @brief 分页
              */
-            Limit,
+            std::pair<int, int> limit = std::pair(0, 0);
             /**
-             * @brief 分隔符
+             * @brief 排序
              */
-            Separator
+            std::vector<std::pair<std::string, sql_order_by_type>> order_by;
         };
         /**
-         * @brief 括号
+         * @brief sql参数
          */
-        enum brace_type {
+        struct sql_param {
             /**
-             * @brief 无效
+             * @brief sql
              */
-            Not,
+            std::string sql;
             /**
-             * @brief 开
+             * @brief 返回值
              */
-            On,
+            rttr::variant result;
             /**
-             * @brief 关
-             */
-            Off,
+            * @brief 执行类型
+            */
+            sql_event_type event_type;
             /**
-             * @brief 开关
+             * @brief 参数
              */
-            OnOff
+            std::vector<rttr::variant> params;
         };
         /**
-         * @brief 字段名称
-         */
-        std::string name;
-        /**
-         * @brief 表达式符号
+         * @brief web查询条件
+         * @tparam _Type
          */
-        symbol_type symbol = symbol_type::Invalid;
-        /**
-         * @brief 值
-         */
-        std::vector<rttr::variant> values;
-        /**
-         * @brief 括号
-         */
-        brace_type brace = brace_type::Not;
-        /**
-         * @brief 分页
-         */
-        std::pair<int, int> limit = std::pair(0, 0);
-        /**
-         * @brief 排序
-         */
-        std::vector<std::pair<std::string, sql_order_by_type>> order_by;
-    };
-    /**
-     * @brief sql参数
-     */
-    struct sql_param {
-        /**
-         * @brief sql
-         */
-        std::string sql;
-        /**
-         * @brief 返回值
-         */
-        rttr::variant result;
-        /**
-        * @brief 执行类型
-        */
-        sql_event_type event_type;
-        /**
-         * @brief 参数
-         */
-        std::vector<rttr::variant> params;
-    };
-    /**
-     * @brief web查询条件
-     * @tparam _Type
-     */
-    template<typename _Type>
-    class sql_where_web {
-    public:
-        /**
-         * @brief 重置
-         */
-        void reset() {
-            where_.clear();
-        }
-        template<typename _Param>
-        sql_where_web& operator<<(_Param& value) {
-            where_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
-            return *this;
-        }
-        sql_where_web& operator==(std::string const& value) {
-            rttr::variant result;
-            rttr::type type = v3::utils::property_type<_Type>(where_[where_.size() - 1].name);
-            if (get_value(result, value, type)) {
-                if (type.is_sequential_container()) {
-                    where_[where_.size() - 1].symbol = sql_expression::Like;
+        template<typename _Type>
+        class sql_where_web {
+        public:
+            /**
+             * @brief 重置
+             */
+            void reset() {
+                where_.clear();
+            }
+            template<typename _Param>
+            sql_where_web& operator<<(_Param& value) {
+                where_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
+                return *this;
+            }
+            sql_where_web& operator==(std::string const& value) {
+                rttr::variant result;
+                rttr::type type = v3::utils::property_type<_Type>(where_[where_.size() - 1].name);
+                if (get_value(result, value, type)) {
+                    if (type.is_sequential_container()) {
+                        where_[where_.size() - 1].symbol = sql_expression::Like;
+                    }
+                    else {
+                        where_[where_.size() - 1].symbol = sql_expression::EqualEqual;
+                    }
+                    where_[where_.size() - 1].values.push_back(result);
                 }
                 else {
-                    where_[where_.size() - 1].symbol = sql_expression::EqualEqual;
+                    where_.pop_back();
                 }
-                where_[where_.size() - 1].values.push_back(result);
+                return *this;
             }
-            else {
-                where_.pop_back();
+            sql_where_web& operator!=(std::string const& value) {
+                rttr::variant result;
+                if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
+                    where_[where_.size() - 1].symbol = sql_expression::NotEqual;
+                    where_[where_.size() - 1].values.push_back(result);
+                }
+                else {
+                    where_.pop_back();
+                }
+                return *this;
             }
-            return *this;
-        }
-        sql_where_web& operator!=(std::string const& value) {
-            rttr::variant result;
-            if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
-                where_[where_.size() - 1].symbol = sql_expression::NotEqual;
-                where_[where_.size() - 1].values.push_back(result);
+            sql_where_web& operator>(std::string const& value) {
+                rttr::variant result;
+                if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
+                    where_[where_.size() - 1].symbol = sql_expression::Greater;
+                    where_[where_.size() - 1].values.push_back(result);
+                }
+                else {
+                    where_.pop_back();
+                }
+                return *this;
             }
-            else {
-                where_.pop_back();
+            sql_where_web& operator<(std::string const& value) {
+                rttr::variant result;
+                if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
+                    where_[where_.size() - 1].symbol = sql_expression::Less;
+                    where_[where_.size() - 1].values.push_back(result);
+                }
+                else {
+                    where_.pop_back();
+                }
+                return *this;
             }
-            return *this;
-        }
-        sql_where_web& operator>(std::string const& value) {
-            rttr::variant result;
-            if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
-                where_[where_.size() - 1].symbol = sql_expression::Greater;
-                where_[where_.size() - 1].values.push_back(result);
+            sql_where_web& operator>=(std::string const& value) {
+                rttr::variant result;
+                if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
+                    where_[where_.size() - 1].symbol = sql_expression::GreaterEqual;
+                    where_[where_.size() - 1].values.push_back(result);
+                }
+                else {
+                    where_.pop_back();
+                }
+                return *this;
             }
-            else {
-                where_.pop_back();
+            sql_where_web& operator<=(std::string const& value) {
+                rttr::variant result;
+                if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
+                    where_[where_.size() - 1].symbol = sql_expression::LessEqual;
+                    where_[where_.size() - 1].values.push_back(result);
+                }
+                else {
+                    where_.pop_back();
+                }
+                return *this;
             }
-            return *this;
-        }
-        sql_where_web& operator<(std::string const& value) {
-            rttr::variant result;
-            if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
-                where_[where_.size() - 1].symbol = sql_expression::Less;
-                where_[where_.size() - 1].values.push_back(result);
+            sql_where_web& operator and(sql_where_web<_Type>& value) {
+                if (where_.empty() || where_.size() % 2)
+                    return *this;
+                insert_child(value);
+                insert_and();
+                return *this;
             }
-            else {
-                where_.pop_back();
+            sql_where_web& operator or(sql_where_web<_Type>& value) {
+                if (where_.empty() || where_.size() % 2)
+                    return *this;
+                insert_child(value);
+                insert_or();
+                return *this;
             }
-            return *this;
-        }
-        sql_where_web& operator>=(std::string const& value) {
-            rttr::variant result;
-            if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
-                where_[where_.size() - 1].symbol = sql_expression::GreaterEqual;
-                where_[where_.size() - 1].values.push_back(result);
+            _Type* operator->() {
+                return &type_;
             }
-            else {
-                where_.pop_back();
+            /**
+             * @brief 获取数据
+             * @return
+             */
+            std::vector<sql_expression> get_sql_expression_value() {
+                return where_;
             }
-            return *this;
-        }
-        sql_where_web& operator<=(std::string const& value) {
-            rttr::variant result;
-            if (get_value(result, value, v3::utils::property_type<_Type>(where_[where_.size() - 1].name))) {
-                where_[where_.size() - 1].symbol = sql_expression::LessEqual;
-                where_[where_.size() - 1].values.push_back(result);
+            operator std::vector<sql_expression>() {
+                return where_;
             }
-            else {
-                where_.pop_back();
+            /**
+             * @brief 添加分页
+             * @param page
+             * @param page_size
+             */
+            void add_limit(unsigned int page, unsigned int page_size) {
+                where_.push_back(sql_expression{ "",sql_expression::Limit,{},sql_expression::OnOff ,std::pair(page, page_size),{} });
             }
-            return *this;
-        }
-        sql_where_web& operator and(sql_where_web<_Type>& value) {
-            if (where_.empty() || where_.size() % 2)
-                return *this;
-            insert_child(value);
-            insert_and();
-            return *this;
-        }
-        sql_where_web& operator or(sql_where_web<_Type>& value) {
-            if (where_.empty() || where_.size() % 2)
-                return *this;
-            insert_child(value);
-            insert_or();
-            return *this;
-        }
-        _Type* operator->() {
-            return &type_;
-        }
-        /**
-         * @brief 获取数据
-         * @return
-         */
-        std::vector<sql_expression> get_sql_expression_value() {
-            return where_;
-        }
-        operator std::vector<sql_expression>() {
-            return where_;
-        }
-        /**
-         * @brief 添加分页
-         * @param page
-         * @param page_size
-         */
-        void add_limit(unsigned int page, unsigned int page_size) {
-            where_.push_back(sql_expression{ "",sql_expression::Limit,{},sql_expression::OnOff ,std::pair(page, page_size),{} });
-        }
-        /**
-         * @brief 添加排序
-         * @param value
-         */
-        void add_order_by(sql_expression const& value) {
-            where_.push_back(value);
-        }
-    private:
+            /**
+             * @brief 添加排序
+             * @param value
+             */
+            void add_order_by(sql_expression const& value) {
+                where_.push_back(value);
+            }
+        private:
+            /**
+             * @brief 获取值
+             * @param value
+             * @param value_type
+             * @return
+             */
+            bool get_value(rttr::variant& result, std::string const& value, rttr::type type) {
+                if (value.empty())
+                    return false;
+                if (type == rttr::type::get<int>()) {
+                    result = std::atoi(value.c_str());
+                }
+                else if (type == rttr::type::get<bool>()) {
+                    result = value == "true" || value == "True" || value == "TRUE";
+                }
+                else if (type == rttr::type::get<double>()) {
+                    result = std::atof(value.c_str());
+                }
+                else if (type == rttr::type::get<long>()) {
+                    result = std::atol(value.c_str());
+                }
+                else if (type == rttr::type::get<float>()) {
+                    result = (float)std::atof(value.c_str());
+                }
+                else if (type == rttr::type::get<std::int64_t>()) {
+                    result = (std::int64_t)std::atoll(value.c_str());
+                }
+                else if (type == rttr::type::get<v3::datetime>()) {
+                    result = v3::datetime(value);
+                }
+                else if (type == rttr::type::get<std::string>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<int>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<bool>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<double>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<long>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<float>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<std::string>>()) {
+                    result = value;
+                }
+                else if (type == rttr::type::get<std::vector<datetime>>()) {
+                    result = value;
+                }
+                else {
+                    return false;
+                }
+                return true;
+            }
+            /**
+             * @brief 添加子表达式
+             */
+            void insert_child(sql_where_web<_Type>& value) {
+                if (&value != this) {
+                    if (value.where_.size() > 1) {
+                        value.where_[0].brace = sql_expression::On;
+                        value.where_[value.where_.size() - 1].brace = sql_expression::Off;
+                    }
+                    where_.insert(where_.end(), value.where_.begin(), value.where_.end());
+                }
+            }
+            /**
+             * @brief 添加and连接符
+             */
+            void insert_and() {
+                for (size_t i = where_.size() - 1; i >= 0; --i) {
+                    if (i - 1 >= 0) {
+                        if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i - 1].symbol > 0 && where_[i - 1].symbol < sql_expression::And) {
+                            where_.insert(where_.begin() + i, sql_expression{ "",sql_expression::And,{},sql_expression::Not,std::pair(0, 0),{} });
+                            return;
+                        }
+                    }
+                }
+            }
+            /**
+             * @brief 添加or连接符
+             */
+            void insert_or() {
+                for (size_t i = 0; i < where_.size(); ++i) {
+                    if (where_.size() > i + 1) {
+                        if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i + 1].symbol > 0 && where_[i + 1].symbol < sql_expression::And) {
+                            where_.insert(where_.begin() + i + 1, sql_expression{ "",sql_expression::Or,{},sql_expression::Not,std::pair(0, 0),{} });
+                            return;
+                        }
+                    }
+                }
+            }
+        private:
+            _Type type_;
+            std::vector<sql_expression> where_;
+        };
         /**
-         * @brief 获取值
-         * @param value
-         * @param value_type
-         * @return
+         * @brief 条件
+         * @tparam _Type
          */
-        bool get_value(rttr::variant& result, std::string const& value, rttr::type type) {
-            if (value.empty())
-                return false;
-            if (type == rttr::type::get<int>()) {
-                result = std::atoi(value.c_str());
+        template<typename _Type>
+        class sql_where {
+        public:
+            /**
+             * @brief 重置
+             */
+            void reset() {
+                where_.clear();
             }
-            else if (type == rttr::type::get<bool>()) {
-                result = value == "true" || value == "True" || value == "TRUE";
+            template<typename _Param>
+            sql_where& operator<<(_Param& value) {
+                if (where_.empty() || where_[where_.size() - 1].values.size() == 1) {
+                    where_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
+                }
+                else {
+                    where_[where_.size() - 1].name = v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_));
+                }
+                return *this;
             }
-            else if (type == rttr::type::get<double>()) {
-                result = std::atof(value.c_str());
+            template<typename _Value>
+            sql_where& operator==(_Value const& value) {
+                rttr::variant type = v3::utils::property_type<_Type>(where_[where_.size() - 1].name);
+                if (type.is_sequential_container()) {
+                    where_[where_.size() - 1].symbol = sql_expression::Like;
+                }
+                else {
+                    where_[where_.size() - 1].symbol = sql_expression::EqualEqual;
+                }
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<long>()) {
-                result = std::atol(value.c_str());
+            template<typename _Value>
+            sql_where& operator!=(_Value const& value) {
+                where_[where_.size() - 1].symbol = sql_expression::NotEqual;
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<float>()) {
-                result = (float)std::atof(value.c_str());
+            template<typename _Value>
+            sql_where& operator>(_Value const& value) {
+                where_[where_.size() - 1].symbol = sql_expression::Greater;
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<std::int64_t>()) {
-                result = (std::int64_t)std::atoll(value.c_str());
+            template<typename _Value>
+            sql_where& operator<(_Value const& value) {
+                where_[where_.size() - 1].symbol = sql_expression::Less;
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<v3::datetime>()) {
-                result = v3::datetime(value);
+            template<typename _Value>
+            sql_where& operator>=(_Value const& value) {
+                where_[where_.size() - 1].symbol = sql_expression::GreaterEqual;
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<std::string>()) {
-                result = value;
+            template<typename _Value>
+            sql_where& operator<=(_Value const& value) {
+                where_[where_.size() - 1].symbol = sql_expression::LessEqual;
+                where_[where_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (type == rttr::type::get<std::vector<int>>()) {
-                result = value;
+            void operator=(sql_where_web<_Type>& value) {
+                where_ = value.get_sql_expression_value();
             }
-            else if (type == rttr::type::get<std::vector<bool>>()) {
-                result = value;
+            template<typename..._Args>
+            sql_where& in(_Args const&...args) {
+                where_.push_back(sql_expression{ "",sql_expression::In,{},sql_expression::OnOff ,std::pair(0, 0),{} });
+                v3::utils::for_each(std::make_tuple(args...), [this](auto it)
+                    {
+                        where_[where_.size() - 1].values.insert(where_[where_.size() - 1].values.begin(), it);
+                    });
+                return *this;
             }
-            else if (type == rttr::type::get<std::vector<double>>()) {
-                result = value;
+            template<typename _Value>
+            sql_where& in(std::vector<_Value> const& values) {
+                where_.push_back(sql_expression{ "",sql_expression::In,{},sql_expression::OnOff,std::pair(0, 0),{} });
+                where_[where_.size() - 1].values.assign(values.begin(), values.end());
+                return *this;
             }
-            else if (type == rttr::type::get<std::vector<long>>()) {
-                result = value;
+            sql_where& operator and(sql_where<_Type>& value) {
+                insert_child(value);
+                insert_and();
+                return *this;
             }
-            else if (type == rttr::type::get<std::vector<float>>()) {
-                result = value;
+            sql_where& operator or(sql_where<_Type>& value) {
+                insert_child(value);
+                insert_or();
+                return *this;
             }
-            else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
-                result = value;
+            _Type* operator->() {
+                return &type_;
             }
-            else if (type == rttr::type::get<std::vector<std::string>>()) {
-                result = value;
+            operator std::vector<sql_expression>() {
+                return where_;
             }
-            else if (type == rttr::type::get<std::vector<datetime>>()) {
-                result = value;
+            /**
+             * @brief 添加分页
+             * @param page
+             * @param page_size
+             */
+            void add_limit(unsigned int page, unsigned int page_size) {
+                where_.push_back(sql_expression{ "",sql_expression::Limit,{},sql_expression::OnOff ,std::pair(page, page_size),{} });
             }
-            else {
-                return false;
+            /**
+             * @brief 添加排序
+             * @param value
+             */
+            void add_order_by(sql_expression const& value) {
+                where_.push_back(value);
             }
-            return true;
-        }
-        /**
-         * @brief 添加子表达式
-         */
-        void insert_child(sql_where_web<_Type>& value) {
-            if (&value != this) {
-                if (value.where_.size() > 1) {
-                    value.where_[0].brace = sql_expression::On;
-                    value.where_[value.where_.size() - 1].brace = sql_expression::Off;
+        private:
+            /**
+             * @brief 添加子表达式
+             */
+            void insert_child(sql_where<_Type>& value) {
+                if (&value != this) {
+                    if (value.where_.size() > 1) {
+                        value.where_[0].brace = sql_expression::On;
+                        value.where_[value.where_.size() - 1].brace = sql_expression::Off;
+                    }
+                    where_.insert(where_.end(), value.where_.begin(), value.where_.end());
                 }
-                where_.insert(where_.end(), value.where_.begin(), value.where_.end());
             }
-        }
-        /**
-         * @brief 添加and连接符
-         */
-        void insert_and() {
-            for (size_t i = where_.size() - 1; i >= 0; --i) {
-                if (i - 1 >= 0) {
-                    if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i - 1].symbol > 0 && where_[i - 1].symbol < sql_expression::And) {
-                        where_.insert(where_.begin() + i, sql_expression{ "",sql_expression::And,{},sql_expression::Not,std::pair(0, 0),{} });
-                        return;
+            /**
+             * @brief 添加and连接符
+             */
+            void insert_and() {
+                for (size_t i = where_.size() - 1; i >= 0; --i) {
+                    if (i - 1 >= 0) {
+                        if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i - 1].symbol > 0 && where_[i - 1].symbol < sql_expression::And) {
+                            where_.insert(where_.begin() + i, sql_expression{ "",sql_expression::And,{},sql_expression::Not,std::pair(0, 0),{} });
+                            return;
+                        }
                     }
                 }
             }
-        }
-        /**
-         * @brief 添加or连接符
-         */
-        void insert_or() {
-            for (size_t i = 0; i < where_.size(); ++i) {
-                if (where_.size() > i + 1) {
-                    if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i + 1].symbol > 0 && where_[i + 1].symbol < sql_expression::And) {
-                        where_.insert(where_.begin() + i + 1, sql_expression{ "",sql_expression::Or,{},sql_expression::Not,std::pair(0, 0),{} });
-                        return;
+            /**
+             * @brief 添加or连接符
+             */
+            void insert_or() {
+                for (size_t i = 0; i < where_.size(); ++i) {
+                    if (where_.size() > i + 1) {
+                        if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i + 1].symbol > 0 && where_[i + 1].symbol < sql_expression::And) {
+                            where_.insert(where_.begin() + i + 1, sql_expression{ "",sql_expression::Or,{},sql_expression::Not,std::pair(0, 0),{} });
+                            return;
+                        }
                     }
                 }
             }
-        }
-    private:
-        _Type type_;
-        std::vector<sql_expression> where_;
-    };
-    /**
-     * @brief 条件
-     * @tparam _Type
-     */
-    template<typename _Type>
-    class sql_where {
-    public:
+        private:
+            _Type type_;
+            std::vector<sql_expression> where_;
+        };
         /**
-         * @brief 重置
+         * @brief 排序
+         * @tparam _Type
          */
-        void reset() {
-            where_.clear();
-        }
-        template<typename _Param>
-        sql_where& operator<<(_Param& value) {
-            if (where_.empty() || where_[where_.size() - 1].values.size() == 1) {
-                where_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
+        template<typename _Type>
+        class sql_order_by {
+        public:
+            template<typename _Param>
+            sql_order_by& operator<<(_Param& value) {
+                order_by_.symbol = sql_expression::OrderBy;
+                order_by_.order_by.push_back(std::pair(v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)), Asc));
+                return *this;
             }
-            else {
-                where_[where_.size() - 1].name = v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_));
+            sql_order_by& operator<<(sql_order_by_type type) {
+                if (!order_by_.order_by.empty()) {
+                    order_by_.order_by[order_by_.order_by.size() - 1].second = type;
+                }
+                return*this;
             }
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator==(_Value const& value) {
-            rttr::variant type = v3::utils::property_type<_Type>(where_[where_.size() - 1].name);
-            if (type.is_sequential_container()) {
-                where_[where_.size() - 1].symbol = sql_expression::Like;
+            _Type* operator->() {
+                return &type_;
             }
-            else {
-                where_[where_.size() - 1].symbol = sql_expression::EqualEqual;
+            operator sql_expression() {
+                return order_by_;
             }
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator!=(_Value const& value) {
-            where_[where_.size() - 1].symbol = sql_expression::NotEqual;
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator>(_Value const& value) {
-            where_[where_.size() - 1].symbol = sql_expression::Greater;
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator<(_Value const& value) {
-            where_[where_.size() - 1].symbol = sql_expression::Less;
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator>=(_Value const& value) {
-            where_[where_.size() - 1].symbol = sql_expression::GreaterEqual;
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& operator<=(_Value const& value) {
-            where_[where_.size() - 1].symbol = sql_expression::LessEqual;
-            where_[where_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        void operator=(sql_where_web<_Type>& value) {
-            where_ = value.get_sql_expression_value();
-        }
-        template<typename..._Args>
-        sql_where& in(_Args const&...args) {
-            where_.push_back(sql_expression{ "",sql_expression::In,{},sql_expression::OnOff ,std::pair(0, 0),{} });
-            v3::utils::for_each(std::make_tuple(args...), [this](auto it)
-                {
-                    where_[where_.size() - 1].values.insert(where_[where_.size() - 1].values.begin(), it);
-                });
-            return *this;
-        }
-        template<typename _Value>
-        sql_where& in(std::vector<_Value> const& values) {
-            where_.push_back(sql_expression{ "",sql_expression::In,{},sql_expression::OnOff,std::pair(0, 0),{} });
-            where_[where_.size() - 1].values.assign(values.begin(), values.end());
-            return *this;
-        }
-        sql_where& operator and(sql_where<_Type>& value) {
-            insert_child(value);
-            insert_and();
-            return *this;
-        }
-        sql_where& operator or(sql_where<_Type>& value) {
-            insert_child(value);
-            insert_or();
-            return *this;
-        }
-        _Type* operator->() {
-            return &type_;
-        }
-        operator std::vector<sql_expression>() {
-            return where_;
-        }
-        /**
-         * @brief 添加分页
-         * @param page
-         * @param page_size
-         */
-        void add_limit(unsigned int page, unsigned int page_size) {
-            where_.push_back(sql_expression{ "",sql_expression::Limit,{},sql_expression::OnOff ,std::pair(page, page_size),{} });
-        }
-        /**
-         * @brief 添加排序
-         * @param value
-         */
-        void add_order_by(sql_expression const& value) {
-            where_.push_back(value);
-        }
-    private:
+        private:
+            _Type type_;
+            sql_expression order_by_;
+        };
         /**
-         * @brief 添加子表达式
+         * @brief 更新
+         * @tparam _Type
          */
-        void insert_child(sql_where<_Type>& value) {
-            if (&value != this) {
-                if (value.where_.size() > 1) {
-                    value.where_[0].brace = sql_expression::On;
-                    value.where_[value.where_.size() - 1].brace = sql_expression::Off;
-                }
-                where_.insert(where_.end(), value.where_.begin(), value.where_.end());
+        template<typename _Type>
+        class sql_update {
+        public:
+            /**
+             * @brief 重置
+             */
+            void reset() {
+                update_.clear();
             }
-        }
-        /**
-         * @brief 添加and连接符
-         */
-        void insert_and() {
-            for (size_t i = where_.size() - 1; i >= 0; --i) {
-                if (i - 1 >= 0) {
-                    if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i - 1].symbol > 0 && where_[i - 1].symbol < sql_expression::And) {
-                        where_.insert(where_.begin() + i, sql_expression{ "",sql_expression::And,{},sql_expression::Not,std::pair(0, 0),{} });
-                        return;
-                    }
-                }
+            template<typename _Param>
+            sql_update& operator<<(_Param& value) {
+                update_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
+                return *this;
             }
-        }
-        /**
-         * @brief 添加or连接符
-         */
-        void insert_or() {
-            for (size_t i = 0; i < where_.size(); ++i) {
-                if (where_.size() > i + 1) {
-                    if (where_[i].symbol > 0 && where_[i].symbol < sql_expression::And && where_[i + 1].symbol > 0 && where_[i + 1].symbol < sql_expression::And) {
-                        where_.insert(where_.begin() + i + 1, sql_expression{ "",sql_expression::Or,{},sql_expression::Not,std::pair(0, 0),{} });
-                        return;
-                    }
-                }
-            }
-        }
-    private:
-        _Type type_;
-        std::vector<sql_expression> where_;
-    };
-    /**
-     * @brief 排序
-     * @tparam _Type
-     */
-    template<typename _Type>
-    class sql_order_by {
-    public:
-        template<typename _Param>
-        sql_order_by& operator<<(_Param& value) {
-            order_by_.symbol = sql_expression::OrderBy;
-            order_by_.order_by.push_back(std::pair(v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)), Asc));
-            return *this;
-        }
-        sql_order_by& operator<<(sql_order_by_type type) {
-            if (!order_by_.order_by.empty()) {
-                order_by_.order_by[order_by_.order_by.size() - 1].second = type;
-            }
-            return*this;
-        }
-        _Type* operator->() {
-            return &type_;
-        }
-        operator sql_expression() {
-            return order_by_;
-        }
-    private:
-        _Type type_;
-        sql_expression order_by_;
-    };
-    /**
-     * @brief 更新
-     * @tparam _Type
-     */
-    template<typename _Type>
-    class sql_update {
-    public:
-        /**
-         * @brief 重置
-         */
-        void reset() {
-            update_.clear();
-        }
-        template<typename _Param>
-        sql_update& operator<<(_Param& value) {
-            update_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
-            return *this;
-        }
-        template<typename _Value>
-        sql_update& operator=(_Value const& value) {
-            update_[update_.size() - 1].symbol = sql_expression::Equal;
-            update_[update_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Param>
-        sql_update& operator,(_Param const& param) {
-            update_.insert(update_.begin() + (update_.size() - 1), sql_expression{ "",sql_expression::Comma,{},sql_expression::Not,std::pair(0, 0),{} });
-            return *this;
-        }
-        _Type* operator->() {
-            return &type_;
-        }
-        operator std::vector<sql_expression>() {
-            return update_;
-        }
-    private:
-        _Type type_;
-        std::vector<sql_expression> update_;
-    };
-    /**
-     * @brief 插入
-     * @tparam _Type
-     */
-    template<typename _Type>
-    class sql_insert {
-    public:
-        /**
-         * @brief 重置
-         */
-        void reset() {
-            insert_.clear();
-        }
-        template<typename _Param>
-        sql_insert& operator<<(_Param& value) {
-            insert_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
-            return *this;
-        }
-        template<typename _Value>
-        sql_insert& operator=(_Value const& value) {
-            insert_[insert_.size() - 1].symbol = sql_expression::Equal;
-            insert_[insert_.size() - 1].values.push_back(value);
-            return *this;
-        }
-        template<typename _Param>
-        sql_insert& operator,(_Param const& param) {
-            insert_.insert(insert_.begin() + (insert_.size() - 1), sql_expression{ "",sql_expression::Comma,{},sql_expression::Not,std::pair(0, 0),{} });
-            return *this;
-        }
-        _Type* operator->() {
-            return &type_;
-        }
-        operator std::vector<sql_expression>() {
-            return insert_;
-        }
-        void add(_Type const& value) {
-            set_sql_expression(value);
-        }
-    private:
-        void set_sql_expression(_Type const& value) {
-            rttr::type type = rttr::type::get<_Type>();
-            rttr::array_range<rttr::property> props = type.get_properties();
-
-            int index = 0;
-            for (auto const& it : props) {
-                v3::sql_expression item;
-                if (it.get_type() == rttr::type::get<int>() ||
-                    it.get_type() == rttr::type::get<bool>() ||
-                    it.get_type() == rttr::type::get<double>() ||
-                    it.get_type() == rttr::type::get<long>() ||
-                    it.get_type() == rttr::type::get<float>() ||
-                    it.get_type() == rttr::type::get<std::int64_t>() ||
-                    it.get_type() == rttr::type::get<v3::datetime>() ||
-                    it.get_type() == rttr::type::get<std::string>() ||
-                    it.get_type() == rttr::type::get<std::vector<int>>() ||
-                    it.get_type() == rttr::type::get<std::vector<bool>>() ||
-                    it.get_type() == rttr::type::get<std::vector<double>>() ||
-                    it.get_type() == rttr::type::get<std::vector<long>>() ||
-                    it.get_type() == rttr::type::get<std::vector<float>>() ||
-                    it.get_type() == rttr::type::get<std::vector<std::int64_t>>() ||
-                    it.get_type() == rttr::type::get<std::vector<std::string>>() ||
-                    it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
-                    item.name = it.get_name().data();
-                    item.values.push_back(it.get_value(value));
-                    item.symbol = v3::sql_expression::Equal;
-                }
-                else {
-                    ++index;
-                    continue;
-                }
-                if (index + 1 == props.size()) {
-                    insert_.push_back(item);
-                }
-                else {
-                    insert_.push_back(item);
-                    insert_.push_back(v3::sql_expression{ "",v3::sql_expression::Comma,{},v3::sql_expression::Not,std::pair(0, 0),{} });
-                }
-                ++index;
-            }
-
-        }
-    private:
-        _Type type_;
-        std::vector<sql_expression> insert_;
-    };
-    /**
-     * @brief sql执行
-     * @param param
-     * @return
-     */
-    template<typename _ConnConfig>
-    static rttr::variant on_sql_linq_execute(v3::sql_param& param) {
-#ifdef _DEBUG
-        LOG_INFO << "SQL:" << param.sql << " 参数数量:" << param.params.size();
-#endif // !_DEBUG
-        cppdb::session              session = v3::orm::sql_connect_pool::open<_ConnConfig>();
-        cppdb::statement            stmt = session << param.sql;
-
-        for (auto& it : param.params) {
-            if (it.get_type() == rttr::type::get<int>()) {
-                stmt << it.get_value<int>();
-            }
-            else if (it.get_type() == rttr::type::get<bool>()) {
-                stmt << (it.get_value<bool>() ? 1 : 0);
-            }
-            else if (it.get_type() == rttr::type::get<double>()) {
-                stmt << it.get_value<double>();
-            }
-            else if (it.get_type() == rttr::type::get<long>()) {
-                stmt << it.get_value<long>();
-            }
-            else if (it.get_type() == rttr::type::get<float>()) {
-                stmt << it.get_value<float>();
-            }
-            else if (it.get_type() == rttr::type::get<std::int64_t>()) {
-                stmt << it.get_value<std::int64_t>();
+            template<typename _Value>
+            sql_update& operator=(_Value const& value) {
+                update_[update_.size() - 1].symbol = sql_expression::Equal;
+                update_[update_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (it.get_type() == rttr::type::get<v3::datetime>()) {
-                v3::datetime time = it.get_value<v3::datetime>();
-                stmt << (std::tm)time;
+            template<typename _Param>
+            sql_update& operator,(_Param const& param) {
+                update_.insert(update_.begin() + (update_.size() - 1), sql_expression{ "",sql_expression::Comma,{},sql_expression::Not,std::pair(0, 0),{} });
+                return *this;
             }
-            else if (it.get_type() == rttr::type::get<std::string>()) {
-                stmt << it.get_value<std::string>();
+            _Type* operator->() {
+                return &type_;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<int>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<int>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+            operator std::vector<sql_expression>() {
+                return update_;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<bool>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<bool>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+        private:
+            _Type type_;
+            std::vector<sql_expression> update_;
+        };
+        /**
+         * @brief 插入
+         * @tparam _Type
+         */
+        template<typename _Type>
+        class sql_insert {
+        public:
+            /**
+             * @brief 重置
+             */
+            void reset() {
+                insert_.clear();
             }
-            else if (it.get_type() == rttr::type::get<std::vector<double>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<double>>(), ",");
-                stmt << value;
+            template<typename _Param>
+            sql_insert& operator<<(_Param& value) {
+                insert_.push_back(sql_expression{ v3::utils::property_sql_name<_Type>(v3::utils::pointer_obj_cast<std::size_t>(value) - v3::utils::pointer_obj_cast<std::size_t>(type_)),sql_expression::Invalid,{},sql_expression::Not,std::pair(0, 0),{} });
+                return *this;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<long>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<long>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+            template<typename _Value>
+            sql_insert& operator=(_Value const& value) {
+                insert_[insert_.size() - 1].symbol = sql_expression::Equal;
+                insert_[insert_.size() - 1].values.push_back(value);
+                return *this;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<float>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<float>>(), ",");
-                stmt << value;
+            template<typename _Param>
+            sql_insert& operator,(_Param const& param) {
+                insert_.insert(insert_.begin() + (insert_.size() - 1), sql_expression{ "",sql_expression::Comma,{},sql_expression::Not,std::pair(0, 0),{} });
+                return *this;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<std::int64_t>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+            _Type* operator->() {
+                return &type_;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<std::string>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<std::string>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+            operator std::vector<sql_expression>() {
+                return insert_;
             }
-            else if (it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
-                std::string value = v3::utils::join(it.get_value<std::vector<v3::datetime>>(), ",");
-                it = value;
-                stmt << it.get_value<std::string>();
+            void add(_Type const& value) {
+                set_sql_expression(value);
             }
-        }
+        private:
+            void set_sql_expression(_Type const& value) {
+                rttr::type type = rttr::type::get<_Type>();
+                rttr::array_range<rttr::property> props = type.get_properties();
 
-        if (v3::sql_event_type::Count == param.event_type) {
-            int count = 0;
-            cppdb::result res = stmt.query();
-            if (res.next()) {
-                count = res.get<int>("count");
-            }
-            return count;
-        }
-        else if (v3::sql_event_type::Insert == param.event_type) {
-            stmt.exec();
-            return true;
-        }
-        else if (v3::sql_event_type::Delete == param.event_type) {
-            stmt.exec();
-            return true;
-        }
-        else if (v3::sql_event_type::Update == param.event_type) {
-            stmt.exec();
-            return true;
-        }
-        else if (v3::sql_event_type::Select == param.event_type) {
-            cppdb::result res = stmt.query();
-            auto view = param.result.create_sequential_view();
-            rttr::type type = view.get_value_type();
-            while (res.next()) {
-                rttr::variant item = type.create();
-                for (auto const& it : item.get_type().get_properties()) {
-                    auto noSql = it.get_metadata("NoSql");
-                    if (noSql.get_type() != rttr::type::get<bool>() || noSql.get_value<bool>()) {
+                int index = 0;
+                for (auto const& it : props) {
+                    v3::sql_expression item;
+                    if (it.get_type() == rttr::type::get<int>() ||
+                        it.get_type() == rttr::type::get<bool>() ||
+                        it.get_type() == rttr::type::get<double>() ||
+                        it.get_type() == rttr::type::get<long>() ||
+                        it.get_type() == rttr::type::get<float>() ||
+                        it.get_type() == rttr::type::get<std::int64_t>() ||
+                        it.get_type() == rttr::type::get<v3::datetime>() ||
+                        it.get_type() == rttr::type::get<std::string>() ||
+                        it.get_type() == rttr::type::get<std::vector<int>>() ||
+                        it.get_type() == rttr::type::get<std::vector<bool>>() ||
+                        it.get_type() == rttr::type::get<std::vector<double>>() ||
+                        it.get_type() == rttr::type::get<std::vector<long>>() ||
+                        it.get_type() == rttr::type::get<std::vector<float>>() ||
+                        it.get_type() == rttr::type::get<std::vector<std::int64_t>>() ||
+                        it.get_type() == rttr::type::get<std::vector<std::string>>() ||
+                        it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
+                        item.name = it.get_name().data();
+                        item.values.push_back(it.get_value(value));
+                        item.symbol = v3::sql_expression::Equal;
+                    }
+                    else {
+                        ++index;
                         continue;
                     }
-                    std::string field_name;
-                    rttr::variant sql_name = it.get_metadata("Sql");
-                    if (sql_name.is_type<std::string>())
-                        field_name = sql_name.get_value<std::string>();
-                    else
-                        field_name = it.get_name().data();
+                    if (index + 1 == props.size()) {
+                        insert_.push_back(item);
+                    }
+                    else {
+                        insert_.push_back(item);
+                        insert_.push_back(v3::sql_expression{ "",v3::sql_expression::Comma,{},v3::sql_expression::Not,std::pair(0, 0),{} });
+                    }
+                    ++index;
+                }
+
+            }
+        private:
+            _Type type_;
+            std::vector<sql_expression> insert_;
+        };
+        /**
+         * @brief sql执行
+         * @param param
+         * @return
+         */
+        template<typename _ConnConfig>
+        static rttr::variant on_sql_linq_execute(v3::sql_param& param) {
+    #ifdef _DEBUG
+            LOG_INFO << "SQL:" << param.sql << " 参数数量:" << param.params.size();
+    #endif // !_DEBUG
+            cppdb::session              session = v3::orm::sql_connect_pool::open<_ConnConfig>();
+            cppdb::statement            stmt = session << param.sql;
+
+            for (auto& it : param.params) {
+                if (it.get_type() == rttr::type::get<int>()) {
+                    stmt << it.get_value<int>();
+                }
+                else if (it.get_type() == rttr::type::get<bool>()) {
+                    stmt << (it.get_value<bool>() ? 1 : 0);
+                }
+                else if (it.get_type() == rttr::type::get<double>()) {
+                    stmt << it.get_value<double>();
+                }
+                else if (it.get_type() == rttr::type::get<long>()) {
+                    stmt << it.get_value<long>();
+                }
+                else if (it.get_type() == rttr::type::get<float>()) {
+                    stmt << it.get_value<float>();
+                }
+                else if (it.get_type() == rttr::type::get<std::int64_t>()) {
+                    stmt << it.get_value<std::int64_t>();
+                }
+                else if (it.get_type() == rttr::type::get<v3::datetime>()) {
+                    v3::datetime time = it.get_value<v3::datetime>();
+                    stmt << (std::tm)time;
+                }
+                else if (it.get_type() == rttr::type::get<std::string>()) {
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<int>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<int>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<bool>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<bool>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<double>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<double>>(), ",");
+                    stmt << value;
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<long>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<long>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<float>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<float>>(), ",");
+                    stmt << value;
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<std::int64_t>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<std::string>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<std::string>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+                else if (it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
+                    std::string value = v3::utils::join(it.get_value<std::vector<v3::datetime>>(), ",");
+                    it = value;
+                    stmt << it.get_value<std::string>();
+                }
+            }
 
-                    if (it.get_type() == rttr::type::get<int>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<int>(field_name));
+            if (v3::sql_event_type::Count == param.event_type) {
+                int count = 0;
+                cppdb::result res = stmt.query();
+                if (res.next()) {
+                    count = res.get<int>("count");
+                }
+                return count;
+            }
+            else if (v3::sql_event_type::Insert == param.event_type) {
+                stmt.exec();
+                return true;
+            }
+            else if (v3::sql_event_type::Delete == param.event_type) {
+                stmt.exec();
+                return true;
+            }
+            else if (v3::sql_event_type::Update == param.event_type) {
+                stmt.exec();
+                return true;
+            }
+            else if (v3::sql_event_type::Select == param.event_type) {
+                cppdb::result res = stmt.query();
+                auto view = param.result.create_sequential_view();
+                rttr::type type = view.get_value_type();
+                while (res.next()) {
+                    rttr::variant item = type.create();
+                    for (auto const& it : item.get_type().get_properties()) {
+                        auto noSql = it.get_metadata("NoSql");
+                        if (noSql.get_type() != rttr::type::get<bool>() || noSql.get_value<bool>()) {
+                            continue;
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<bool>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<int>(field_name) > 0);
+                        std::string field_name;
+                        rttr::variant sql_name = it.get_metadata("Sql");
+                        if (sql_name.is_type<std::string>())
+                            field_name = sql_name.get_value<std::string>();
+                        else
+                            field_name = it.get_name().data();
+
+                        if (it.get_type() == rttr::type::get<int>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<int>(field_name));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<double>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<double>(field_name));
+                        else if (it.get_type() == rttr::type::get<bool>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<int>(field_name) > 0);
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<long>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<long>(field_name));
+                        else if (it.get_type() == rttr::type::get<double>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<double>(field_name));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<float>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<float>(field_name));
+                        else if (it.get_type() == rttr::type::get<long>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<long>(field_name));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::int64_t>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<std::int64_t>(field_name));
+                        else if (it.get_type() == rttr::type::get<float>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<float>(field_name));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<v3::datetime>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, datetime(res.get<std::string>(field_name)));
+                        else if (it.get_type() == rttr::type::get<std::int64_t>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<std::int64_t>(field_name));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::string>()) {
-                        if (!res.is_null(field_name)) {
-                            it.set_value(item, res.get<std::string>(field_name));
+                        else if (it.get_type() == rttr::type::get<v3::datetime>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, datetime(res.get<std::string>(field_name)));
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<int>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<int> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(std::atoi(it1.c_str()));
+                        else if (it.get_type() == rttr::type::get<std::string>()) {
+                            if (!res.is_null(field_name)) {
+                                it.set_value(item, res.get<std::string>(field_name));
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<bool>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<bool> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                if (it1 == "1" || it1 == "true" || it1 == "True" || it1 == "TRUE")
-                                    vec.push_back(true);
-                                else
-                                    vec.push_back(false);
+                        else if (it.get_type() == rttr::type::get<std::vector<int>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<int> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(std::atoi(it1.c_str()));
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<double>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<double> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(std::atof(it1.c_str()));
+                        else if (it.get_type() == rttr::type::get<std::vector<bool>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<bool> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    if (it1 == "1" || it1 == "true" || it1 == "True" || it1 == "TRUE")
+                                        vec.push_back(true);
+                                    else
+                                        vec.push_back(false);
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<long>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<long> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(std::atol(it1.c_str()));
+                        else if (it.get_type() == rttr::type::get<std::vector<double>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<double> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(std::atof(it1.c_str()));
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<float>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<float> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(std::atol(it1.c_str()));
+                        else if (it.get_type() == rttr::type::get<std::vector<long>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<long> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(std::atol(it1.c_str()));
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<float> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(std::atoll(it1.c_str()));
+                        else if (it.get_type() == rttr::type::get<std::vector<float>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<float> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(std::atol(it1.c_str()));
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<std::string>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<std::string> vec = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            it.set_value(item, vec);
+                        else if (it.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<float> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(std::atoll(it1.c_str()));
+                                }
+                                it.set_value(item, vec);
+                            }
                         }
-                    }
-                    else if (it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
-                        if (!res.is_null(field_name)) {
-                            std::vector<v3::datetime> vec;
-                            std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
-                            for (auto& it1 : split_value) {
-                                vec.push_back(v3::datetime(it1));
+                        else if (it.get_type() == rttr::type::get<std::vector<std::string>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<std::string> vec = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                it.set_value(item, vec);
+                            }
+                        }
+                        else if (it.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
+                            if (!res.is_null(field_name)) {
+                                std::vector<v3::datetime> vec;
+                                std::vector<std::string> split_value = v3::utils::split_trim(res.get<std::string>(field_name), ",");
+                                for (auto& it1 : split_value) {
+                                    vec.push_back(v3::datetime(it1));
+                                }
+                                it.set_value(item, vec);
                             }
-                            it.set_value(item, vec);
                         }
                     }
+                    view.insert(view.end(), item);
                 }
-                view.insert(view.end(), item);
-            }
-            return param.result;
-        }
-        return false;
-    }
-    /**
-     * @brief sql连接
-     */
-    struct sql_connect_config {
-        operator std::string() {
-            static std::string g_connect_str;
-            if (g_connect_str.empty())
-                g_connect_str = robotics::v3::config::read<std::string>("SQL", "CONNSTR", "mysql:host=127.0.0.1;database=mvc;user=root;password=123456;");
-            return g_connect_str;
-        }
-    };
-    /**
-     * @brief mysql
-     */
-    class mysql_linq {
-    public:
-        mysql_linq(std::vector<robotics::v3::sql_expression> const& sql_params, std::string const& table_name, robotics::v3::sql_event_type type) :
-            sql_params_(sql_params),
-            table_name_(table_name),
-            type_(type) {
-        }
-        operator robotics::v3::sql_param() {
-            static std::map<robotics::v3::sql_expression::symbol_type, std::string> symbol_list = {
-                { robotics::v3::sql_expression::Equal,          "="         },
-                { robotics::v3::sql_expression::EqualEqual,     "="         },
-                { robotics::v3::sql_expression::NotEqual,       "<>"        },
-                { robotics::v3::sql_expression::Greater,        ">"         },
-                { robotics::v3::sql_expression::Less,           "<"         },
-                { robotics::v3::sql_expression::GreaterEqual,   ">="        },
-                { robotics::v3::sql_expression::LessEqual,      "<="        },
-                { robotics::v3::sql_expression::In,             " in"       },
-                { robotics::v3::sql_expression::Like,           " like "    },
-                { robotics::v3::sql_expression::And,            " and "     },
-                { robotics::v3::sql_expression::Or,             " or "      },
-                { robotics::v3::sql_expression::Comma,          ","         },
-                { robotics::v3::sql_expression::OrderBy,        " order by "},
-                { robotics::v3::sql_expression::Limit,          " limit "   }
-            };
-            if (robotics::v3::sql_event_type::Insert == type_) {
-                return insert(symbol_list);
-            }
-            else if (robotics::v3::sql_event_type::Delete == type_) {
-                return remove(symbol_list);
-            }
-            else if (robotics::v3::sql_event_type::Update == type_) {
-                return update(symbol_list);
-            }
-            else if (robotics::v3::sql_event_type::Select == type_) {
-                return select(symbol_list);
+                return param.result;
             }
-            else if (robotics::v3::sql_event_type::Count == type_) {
-                return count(symbol_list);
-            }
-            return robotics::v3::sql_param{ "",rttr::type::get<void>(), robotics::v3::sql_event_type::Error ,{} };
+            return false;
         }
-    private:
         /**
-         * @brief 添加
-         * @param symbol_list
-         * @return
+         * @brief sql连接
          */
-        robotics::v3::sql_param insert(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
-            robotics::v3::sql_param result = { "",true, type_ ,{} };
-            std::vector<std::string> field_list;
-            for (auto& it : sql_params_) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        field_list.push_back(it.name);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                }
+        struct sql_connect_config {
+            operator std::string() {
+                static std::string g_connect_str;
+                if (g_connect_str.empty())
+                    g_connect_str = robotics::v3::config::read<std::string>("SQL", "CONNSTR", "mysql:host=127.0.0.1;database=mvc;user=root;password=123456;");
+                return g_connect_str;
             }
-            result.sql = fmt::format("insert into {0}({1}) values({2});", table_name_, robotics::v3::utils::join(field_list, ","), robotics::v3::utils::join("?", field_list.size(), ","));
-            return result;
-        }
+        };
         /**
-         * @brief 删除
-         * @param symbol_list
-         * @return
+         * @brief mysql
          */
-        robotics::v3::sql_param remove(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
-            robotics::v3::sql_param result = { "",true, type_ ,{} };
-            result.sql = fmt::format("delete from {0} where ", table_name_);
-            for (auto& it : sql_params_) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
-                        result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
-                        result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
-                        result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
+        class mysql_linq {
+        public:
+            mysql_linq(std::vector<robotics::v3::sql_expression> const& sql_params, std::string const& table_name, robotics::v3::sql_event_type type) :
+                sql_params_(sql_params),
+                table_name_(table_name),
+                type_(type) {
+            }
+            operator robotics::v3::sql_param() {
+                static std::map<robotics::v3::sql_expression::symbol_type, std::string> symbol_list = {
+                    { robotics::v3::sql_expression::Equal,          "="         },
+                    { robotics::v3::sql_expression::EqualEqual,     "="         },
+                    { robotics::v3::sql_expression::NotEqual,       "<>"        },
+                    { robotics::v3::sql_expression::Greater,        ">"         },
+                    { robotics::v3::sql_expression::Less,           "<"         },
+                    { robotics::v3::sql_expression::GreaterEqual,   ">="        },
+                    { robotics::v3::sql_expression::LessEqual,      "<="        },
+                    { robotics::v3::sql_expression::In,             " in"       },
+                    { robotics::v3::sql_expression::Like,           " like "    },
+                    { robotics::v3::sql_expression::And,            " and "     },
+                    { robotics::v3::sql_expression::Or,             " or "      },
+                    { robotics::v3::sql_expression::Comma,          ","         },
+                    { robotics::v3::sql_expression::OrderBy,        " order by "},
+                    { robotics::v3::sql_expression::Limit,          " limit "   }
+                };
+                if (robotics::v3::sql_event_type::Insert == type_) {
+                    return insert(symbol_list);
                 }
-                else if (it.symbol == robotics::v3::sql_expression::And) {
-                    result.sql += symbol_list[it.symbol];
+                else if (robotics::v3::sql_event_type::Delete == type_) {
+                    return remove(symbol_list);
                 }
-                else if (it.symbol == robotics::v3::sql_expression::Or) {
-                    result.sql += symbol_list[it.symbol];
+                else if (robotics::v3::sql_event_type::Update == type_) {
+                    return update(symbol_list);
                 }
-                else if (it.symbol == robotics::v3::sql_expression::Comma) {
-                    result.sql += symbol_list[it.symbol];
+                else if (robotics::v3::sql_event_type::Select == type_) {
+                    return select(symbol_list);
                 }
-                else if (it.symbol == robotics::v3::sql_expression::Limit) {
-                    if (it.limit.first == 0) {
-                        result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
-                    }
-                    else {
-                        result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
-                    }
+                else if (robotics::v3::sql_event_type::Count == type_) {
+                    return count(symbol_list);
                 }
+                return robotics::v3::sql_param{ "",rttr::type::get<void>(), robotics::v3::sql_event_type::Error ,{} };
             }
-            result.sql += ";";
-            return result;
-        }
-        /**
-         * @brief 更新
-         * @param symbol_list
-         * @return
-         */
-        robotics::v3::sql_param update(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
-            robotics::v3::sql_param result = { "",true, type_ ,{} };
-            std::vector<robotics::v3::sql_expression> where_param;
-            std::vector<robotics::v3::sql_expression> update_param;
-            bool ok = false;
-            std::string where_sql, set_sql;
-            for (auto const& it : sql_params_) {
-                if (it.symbol == robotics::v3::sql_expression::Separator) {
-                    ok = true;
-                    continue;
-                }
-                if (!ok) {
-                    where_param.push_back(it);
-                }
-                else {
-                    update_param.push_back(it);
+        private:
+            /**
+             * @brief 添加
+             * @param symbol_list
+             * @return
+             */
+            robotics::v3::sql_param insert(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
+                robotics::v3::sql_param result = { "",true, type_ ,{} };
+                std::vector<std::string> field_list;
+                for (auto& it : sql_params_) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            field_list.push_back(it.name);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
+                    }
                 }
+                result.sql = fmt::format("insert into {0}({1}) values({2});", table_name_, robotics::v3::utils::join(field_list, ","), robotics::v3::utils::join("?", field_list.size(), ","));
+                return result;
             }
-            //更新
-            for (auto& it : update_param) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        set_sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+            /**
+             * @brief 删除
+             * @param symbol_list
+             * @return
+             */
+            robotics::v3::sql_param remove(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
+                robotics::v3::sql_param result = { "",true, type_ ,{} };
+                result.sql = fmt::format("delete from {0} where ", table_name_);
+                for (auto& it : sql_params_) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
+                            result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
+                            result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
+                            result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
-                        set_sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                    else if (it.symbol == robotics::v3::sql_expression::And) {
+                        result.sql += symbol_list[it.symbol];
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
-                        set_sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                    else if (it.symbol == robotics::v3::sql_expression::Or) {
+                        result.sql += symbol_list[it.symbol];
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
-                        set_sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                    else if (it.symbol == robotics::v3::sql_expression::Comma) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Limit) {
+                        if (it.limit.first == 0) {
+                            result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
+                        }
+                        else {
+                            result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
+                        }
                     }
                 }
-                else if (it.symbol == robotics::v3::sql_expression::And) {
-                    set_sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Or) {
-                    set_sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Comma) {
-                    set_sql += symbol_list[it.symbol];
-                }
+                result.sql += ";";
+                return result;
             }
-            //条件
-            for (auto& it : where_param) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        where_sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
-                        where_sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
-                        where_sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
-                        where_sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
-                        result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+            /**
+             * @brief 更新
+             * @param symbol_list
+             * @return
+             */
+            robotics::v3::sql_param update(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
+                robotics::v3::sql_param result = { "",true, type_ ,{} };
+                std::vector<robotics::v3::sql_expression> where_param;
+                std::vector<robotics::v3::sql_expression> update_param;
+                bool ok = false;
+                std::string where_sql, set_sql;
+                for (auto const& it : sql_params_) {
+                    if (it.symbol == robotics::v3::sql_expression::Separator) {
+                        ok = true;
+                        continue;
                     }
-                }
-                else if (it.symbol == robotics::v3::sql_expression::And) {
-                    where_sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Or) {
-                    where_sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Comma) {
-                    where_sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
-                    where_sql += symbol_list[it.symbol] + order_by_join(it.order_by);
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Limit) {
-                    if (it.limit.first == 0) {
-                        result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
+                    if (!ok) {
+                        where_param.push_back(it);
                     }
                     else {
-                        result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
+                        update_param.push_back(it);
                     }
                 }
-            }
-
-            if (where_sql.empty()) {
-                result.sql = fmt::format("update {0} set {1};", table_name_, set_sql);
-            }
-            else {
-                result.sql = fmt::format("update {0} set {1} where {2};", table_name_, set_sql, where_sql);
-            }
-
-            return result;
-        }
-        /**
-         * @brief 查询
-         * @param symbol_list
-         * @return
-         */
-        robotics::v3::sql_param select(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
-            robotics::v3::sql_param result = { "",true, type_ ,{} };
-            result.sql = fmt::format("select * from {0} where ", table_name_);
-            for (auto& it : sql_params_) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
+                //更新
+                for (auto& it : update_param) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            set_sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
                             result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
-                        else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
-                                }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
-                            }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
+                            set_sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
+                            set_sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
                             result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
-                        else {
-                            result.sql += fmt::format("(({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
-                                }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
-                            }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
+                            set_sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
+                    else if (it.symbol == robotics::v3::sql_expression::And) {
+                        set_sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Or) {
+                        set_sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Comma) {
+                        set_sql += symbol_list[it.symbol];
+                    }
+                }
+                //条件
+                for (auto& it : where_param) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            where_sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
                             result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
-                        else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?))", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
-                                }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
-                            }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
+                            where_sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
+                            where_sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
+                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
+                            where_sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
                             result.params.insert(result.params.end(), it.values.begin(), it.values.end());
                         }
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::And) {
+                        where_sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Or) {
+                        where_sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Comma) {
+                        where_sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
+                        where_sql += symbol_list[it.symbol] + order_by_join(it.order_by);
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Limit) {
+                        if (it.limit.first == 0) {
+                            result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
+                        }
                         else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
-                                }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
-                            }
+                            result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
                         }
                     }
                 }
-                else if (it.symbol == robotics::v3::sql_expression::And) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Or) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Comma) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
-                    result.sql += symbol_list[it.symbol] + order_by_join(it.order_by);
+
+                if (where_sql.empty()) {
+                    result.sql = fmt::format("update {0} set {1};", table_name_, set_sql);
                 }
-                else if (it.symbol == robotics::v3::sql_expression::Limit) {
-                    if (it.limit.first == 0) {
-                        result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
-                    }
-                    else {
-                        result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
-                    }
+                else {
+                    result.sql = fmt::format("update {0} set {1} where {2};", table_name_, set_sql, where_sql);
                 }
+
+                return result;
             }
-            result.sql += ";";
-            return result;
-        }
-        /**
-         * @brief 查询数量
-         * @param symbol_list
-         * @return
-         */
-        robotics::v3::sql_param count(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
-            robotics::v3::sql_param result = { "",true, type_ ,{} };
-            result.sql = fmt::format("select count(0) as count from {0} where ", table_name_);
-            for (auto& it : sql_params_) {
-                if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
-                    if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
-                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                        }
-                        else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
+            /**
+             * @brief 查询
+             * @param symbol_list
+             * @return
+             */
+            robotics::v3::sql_param select(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
+                robotics::v3::sql_param result = { "",true, type_ ,{} };
+                result.sql = fmt::format("select * from {0} where ", table_name_);
+                for (auto& it : sql_params_) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
                             }
                         }
-                    }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
-                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
-                        }
-                        else {
-                            result.sql += fmt::format("(({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("(({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
+                            }
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?))", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
+                            }
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
                             }
                         }
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
-                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                    else if (it.symbol == robotics::v3::sql_expression::And) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Or) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Comma) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
+                        result.sql += symbol_list[it.symbol] + order_by_join(it.order_by);
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Limit) {
+                        if (it.limit.first == 0) {
+                            result.sql += fmt::format("{0}{1}", symbol_list[it.symbol], it.limit.second);
                         }
                         else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?))", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
-                                }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
-                                }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
-                            }
+                            result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
                         }
                     }
-                    else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
-                        if (it.symbol != v3::sql_expression::Like) {
-                            result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
-                            result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                }
+                result.sql += ";";
+                return result;
+            }
+            /**
+             * @brief 查询数量
+             * @param symbol_list
+             * @return
+             */
+            robotics::v3::sql_param count(std::map<robotics::v3::sql_expression::symbol_type, std::string>& symbol_list) {
+                robotics::v3::sql_param result = { "",true, type_ ,{} };
+                result.sql = fmt::format("select count(0) as count from {0} where ", table_name_);
+                for (auto& it : sql_params_) {
+                    if (it.symbol > 0 && it.symbol < robotics::v3::sql_expression::And) {
+                        if (it.brace == robotics::v3::sql_expression::brace_type::Not) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}?", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
+                                }
+                            }
                         }
-                        else {
-                            result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
-                            if (!it.values.empty()) {
-                                std::vector<rttr::variant> vec;
-                                std::string v;
-                                if (it.values[0].get_type() == rttr::type::get<std::string>()) {
-                                    v = it.values[0].get_value<std::string>();
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::On) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("({0}{1}?", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("(({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
-                                    v = it.values[0].get_value<const char*>();
+                            }
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::Off) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}?)", it.name, symbol_list[it.symbol]);
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?))", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                else if (it.values[0].get_type() == rttr::type::get<char*>()) {
-                                    v = it.values[0].get_value<char*>();
+                            }
+                        }
+                        else if (it.brace == robotics::v3::sql_expression::brace_type::OnOff) {
+                            if (it.symbol != v3::sql_expression::Like) {
+                                result.sql += fmt::format("{0}{1}({2})", it.name, symbol_list[it.symbol], robotics::v3::utils::join("?", it.values.size(), ","));
+                                result.params.insert(result.params.end(), it.values.begin(), it.values.end());
+                            }
+                            else {
+                                result.sql += fmt::format("({0}{1}? or {0}{1}? or {0}{1}? or {0}{1}?)", it.name, symbol_list[it.symbol]);
+                                if (!it.values.empty()) {
+                                    std::vector<rttr::variant> vec;
+                                    std::string v;
+                                    if (it.values[0].get_type() == rttr::type::get<std::string>()) {
+                                        v = it.values[0].get_value<std::string>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<const char*>()) {
+                                        v = it.values[0].get_value<const char*>();
+                                    }
+                                    else if (it.values[0].get_type() == rttr::type::get<char*>()) {
+                                        v = it.values[0].get_value<char*>();
+                                    }
+                                    vec.push_back(v);
+                                    vec.push_back("%," + v);
+                                    vec.push_back(v + ",%");
+                                    vec.push_back("%," + v + ",%");
+                                    result.params.insert(result.params.end(), vec.begin(), vec.end());
                                 }
-                                vec.push_back(v);
-                                vec.push_back("%," + v);
-                                vec.push_back(v + ",%");
-                                vec.push_back("%," + v + ",%");
-                                result.params.insert(result.params.end(), vec.begin(), vec.end());
                             }
                         }
                     }
+                    else if (it.symbol == robotics::v3::sql_expression::And) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Or) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Comma) {
+                        result.sql += symbol_list[it.symbol];
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
+                        result.sql += symbol_list[it.symbol] + order_by_join(it.order_by);
+                    }
+                    else if (it.symbol == robotics::v3::sql_expression::Limit) {
+                        result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
+                    }
                 }
-                else if (it.symbol == robotics::v3::sql_expression::And) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Or) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Comma) {
-                    result.sql += symbol_list[it.symbol];
-                }
-                else if (it.symbol == robotics::v3::sql_expression::OrderBy) {
-                    result.sql += symbol_list[it.symbol] + order_by_join(it.order_by);
-                }
-                else if (it.symbol == robotics::v3::sql_expression::Limit) {
-                    result.sql += fmt::format("{0}{1},{2}", symbol_list[it.symbol], (it.limit.first - 1) * it.limit.second, it.limit.second);
+                result.sql += ";";
+                return result;
+            }
+        private:
+            std::string order_by_join(std::vector<std::pair<std::string, robotics::v3::sql_order_by_type>> const& value) {
+                static std::map<robotics::v3::sql_order_by_type, std::string> order_by_list =
+                {
+                    {robotics::v3::sql_order_by_type::Asc,"asc"},
+                    {robotics::v3::sql_order_by_type::Desc,"desc"}
+                };
+                std::string result;
+                for (auto i = 0; i < value.size(); ++i) {
+                    if (value.size() == i + 1) {
+                        result += fmt::format("{0} {1}", value[i].first, order_by_list[value[i].second]);
+                    }
+                    else {
+                        result += fmt::format("{0} {1},", value[i].first, order_by_list[value[i].second]);
+                    }
                 }
+                return result;
             }
-            result.sql += ";";
-            return result;
-        }
-    private:
-        std::string order_by_join(std::vector<std::pair<std::string, robotics::v3::sql_order_by_type>> const& value) {
-            static std::map<robotics::v3::sql_order_by_type, std::string> order_by_list =
-            {
-                {robotics::v3::sql_order_by_type::Asc,"asc"},
-                {robotics::v3::sql_order_by_type::Desc,"desc"}
-            };
-            std::string result;
-            for (auto i = 0; i < value.size(); ++i) {
-                if (value.size() == i + 1) {
-                    result += fmt::format("{0} {1}", value[i].first, order_by_list[value[i].second]);
+        private:
+            robotics::v3::sql_event_type                  type_ = robotics::v3::sql_event_type::Error;
+            std::string                                         table_name_;
+            std::vector<robotics::v3::sql_expression>     sql_params_;
+        };
+        /**
+         * @brief 异常
+         */
+        class sql_linq_category :
+            public boost::system::error_category {
+        public:
+            sql_linq_category(std::string const& err) :
+                err_(err) {
+            }
+            const char* name() const noexcept { return "sql_linq"; }
+            std::string message(int ev) const { return err_; }
+        private:
+            std::string err_;
+        };
+        /**
+         * @brief linq
+         * @tparam _Type
+         */
+        template<typename _Type, typename _SqlType = v3::mysql_linq, typename _ConnConfig = v3::sql_connect_config>
+        class sql_linq {
+        public:
+            sql_linq() {
+                execute_event_ = std::bind_front(v3::on_sql_linq_execute<_ConnConfig>);
+            }
+            /**
+             * @brief 重置
+             * @return
+             */
+            sql_linq& reset() {
+                if (reset_) {
+                    insert_.reset();
+                    where_.reset();
+                    update_.reset();
                 }
                 else {
-                    result += fmt::format("{0} {1},", value[i].first, order_by_list[value[i].second]);
+                    reset_ = true;
                 }
+                return *this;
             }
-            return result;
-        }
-    private:
-        robotics::v3::sql_event_type                  type_ = robotics::v3::sql_event_type::Error;
-        std::string                                         table_name_;
-        std::vector<robotics::v3::sql_expression>     sql_params_;
-    };
-    /**
-     * @brief 异常
-     */
-    class sql_linq_category :
-        public boost::system::error_category {
-    public:
-        sql_linq_category(std::string const& err) :
-            err_(err) {
-        }
-        const char* name() const noexcept { return "sql_linq"; }
-        std::string message(int ev) const { return err_; }
-    private:
-        std::string err_;
-    };
-    /**
-     * @brief linq
-     * @tparam _Type
-     */
-    template<typename _Type, typename _SqlType = v3::mysql_linq, typename _ConnConfig = v3::sql_connect_config>
-    class sql_linq {
-    public:
-        sql_linq() {
-            execute_event_ = std::bind_front(v3::on_sql_linq_execute<_ConnConfig>);
-        }
-        /**
-         * @brief 重置
-         * @return
-         */
-        sql_linq& reset() {
-            if (reset_) {
-                insert_.reset();
-                where_.reset();
-                update_.reset();
+            /**
+             * @brief sql执行回调
+             * @param fn
+             * @return
+             */
+            sql_linq& execute_bind(std::function<rttr::variant(sql_param&)> const& fn) {
+                execute_event_ = fn;
+                return *this;
             }
-            else {
-                reset_ = true;
+            /**
+             * @brief 查询
+             * @param fn
+             * @return
+             */
+            sql_linq& where(std::function<sql_where<_Type>(sql_where<_Type>)> const& fn) {
+                where_ = fn(where_);
+                sql_event_type_ = sql_event_type::Select;
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief sql执行回调
-         * @param fn
-         * @return
-         */
-        sql_linq& execute_bind(std::function<rttr::variant(sql_param&)> const& fn) {
-            execute_event_ = fn;
-            return *this;
-        }
-        /**
-         * @brief 查询
-         * @param fn
-         * @return
-         */
-        sql_linq& where(std::function<sql_where<_Type>(sql_where<_Type>)> const& fn) {
-            where_ = fn(where_);
-            sql_event_type_ = sql_event_type::Select;
-            return *this;
-        }
-        /**
-         * @brief 查询
-         * @param fn
-         * @return
-         */
-        sql_linq& where_web(std::function<sql_where_web<_Type>(sql_where_web<_Type>)> const& fn) {
-            sql_where_web<_Type> ret = fn(sql_where_web<_Type>());
-            where_ = ret;
-            sql_event_type_ = sql_event_type::Select;
-            return *this;
-        }
-        /**
-         * @brief 分页
-         * @param page
-         * @param page_size
-         * @return
-         */
-        sql_linq& limit(unsigned int page, unsigned int page_size) {
-            where_.add_limit(page, page_size);
-            sql_event_type_ = sql_event_type::Select;
-            return *this;
-        }
-        /**
-         * @brief 排序
-         * @param sql_order_by
-         * @return
-         */
-        sql_linq& order_by(std::function<sql_order_by<_Type>(sql_order_by<_Type>)> const& fn) {
-            where_.add_order_by(fn(sql_order_by<_Type>()));
-            sql_event_type_ = sql_event_type::Select;
-            return *this;
-        }
-        /**
-         * @brief 更新
-         * @param fn
-         * @return
-         */
-        sql_linq& update(std::function<sql_update<_Type>(sql_update<_Type>)> const& fn) {
-            update_ = fn(update_);
-            sql_event_type_ = sql_event_type::Update;
-            return *this;
-        }
-        /**
-         * @brief 删除
-         * @return
-         */
-        sql_linq& remove() {
-            sql_event_type_ = sql_event_type::Delete;
-            return *this;
-        }
-        /**
-         * @brief 插入
-         * @param fn
-         * @return
-         */
-        sql_linq& insert(std::function<sql_insert<_Type>(sql_insert<_Type>)> const& fn) {
-            insert_ = fn(insert_);
-            sql_event_type_ = sql_event_type::Insert;
-            return *this;
-        }
-        /**
-         * @brief 添加
-         * @param value
-         * @return
-         */
-        sql_linq& insert(_Type const& value) {
-            insert_.add(value);
-            sql_event_type_ = sql_event_type::Insert;
-            return *this;
-        }
-        /**
-         * @brief 数量
-         * @return
-         */
-        sql_linq& count() {
-            sql_event_type_ = sql_event_type::Count;
-            return *this;
-        }
-        /**
-         * @brief 不清空条件语句
-         * @return
-         */
-        sql_linq& count_no_reset() {
-            reset_ = false;
-            sql_event_type_ = sql_event_type::Count;
-            return *this;
-        }
-        /**
-         * @brief 提交
-         * @return
-         */
-        sql_linq& submit(rttr::variant& value) {
-            sql_param param = { "",false, sql_event_type_ ,{} };
-            //插入
-            if (sql_event_type::Insert == sql_event_type_) {
-                param = _SqlType(insert_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
-                reset();
-            }
-            //删除
-            else if (sql_event_type::Delete == sql_event_type_) {
-                param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
-                reset();
-            }
-            //更新
-            else if (sql_event_type::Update == sql_event_type_) {
-                std::vector<sql_expression> where_param = where_;
-                std::vector<sql_expression> update_param = update_;
-                where_param.push_back(sql_expression{ "",sql_expression::Separator,{},sql_expression::Not,std::pair(0, 0),{} });
-                where_param.insert(where_param.end(), update_param.begin(), update_param.end());
-                param = _SqlType(where_param, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
-                reset();
-            }
-            //查询
-            else if (sql_event_type::Select == sql_event_type_) {
-                param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
-                param.result = std::vector<_Type>();
-                reset();
-            }
-            //数量
-            else if (sql_event_type::Count == sql_event_type_) {
-                param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
-                reset();
-            }
-            else {
+            /**
+             * @brief 查询
+             * @param fn
+             * @return
+             */
+            sql_linq& where_web(std::function<sql_where_web<_Type>(sql_where_web<_Type>)> const& fn) {
+                sql_where_web<_Type> ret = fn(sql_where_web<_Type>());
+                where_ = ret;
+                sql_event_type_ = sql_event_type::Select;
                 return *this;
             }
-            if (execute_event_) {
-                try {
-                    value = execute_event_(param);
+            /**
+             * @brief 分页
+             * @param page
+             * @param page_size
+             * @return
+             */
+            sql_linq& limit(unsigned int page, unsigned int page_size) {
+                where_.add_limit(page, page_size);
+                sql_event_type_ = sql_event_type::Select;
+                return *this;
+            }
+            /**
+             * @brief 排序
+             * @param sql_order_by
+             * @return
+             */
+            sql_linq& order_by(std::function<sql_order_by<_Type>(sql_order_by<_Type>)> const& fn) {
+                where_.add_order_by(fn(sql_order_by<_Type>()));
+                sql_event_type_ = sql_event_type::Select;
+                return *this;
+            }
+            /**
+             * @brief 更新
+             * @param fn
+             * @return
+             */
+            sql_linq& update(std::function<sql_update<_Type>(sql_update<_Type>)> const& fn) {
+                update_ = fn(update_);
+                sql_event_type_ = sql_event_type::Update;
+                return *this;
+            }
+            /**
+             * @brief 删除
+             * @return
+             */
+            sql_linq& remove() {
+                sql_event_type_ = sql_event_type::Delete;
+                return *this;
+            }
+            /**
+             * @brief 插入
+             * @param fn
+             * @return
+             */
+            sql_linq& insert(std::function<sql_insert<_Type>(sql_insert<_Type>)> const& fn) {
+                insert_ = fn(insert_);
+                sql_event_type_ = sql_event_type::Insert;
+                return *this;
+            }
+            /**
+             * @brief 添加
+             * @param value
+             * @return
+             */
+            sql_linq& insert(_Type const& value) {
+                insert_.add(value);
+                sql_event_type_ = sql_event_type::Insert;
+                return *this;
+            }
+            /**
+             * @brief 数量
+             * @return
+             */
+            sql_linq& count() {
+                sql_event_type_ = sql_event_type::Count;
+                return *this;
+            }
+            /**
+             * @brief 不清空条件语句
+             * @return
+             */
+            sql_linq& count_no_reset() {
+                reset_ = false;
+                sql_event_type_ = sql_event_type::Count;
+                return *this;
+            }
+            /**
+             * @brief 提交
+             * @return
+             */
+            sql_linq& submit(rttr::variant& value) {
+                sql_param param = { "",false, sql_event_type_ ,{} };
+                //插入
+                if (sql_event_type::Insert == sql_event_type_) {
+                    param = _SqlType(insert_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
+                    reset();
                 }
-                catch (std::exception const& ec) {
-                    error_code_ = -1;
-                    error_message_ = ec.what();
+                //删除
+                else if (sql_event_type::Delete == sql_event_type_) {
+                    param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
+                    reset();
                 }
+                //更新
+                else if (sql_event_type::Update == sql_event_type_) {
+                    std::vector<sql_expression> where_param = where_;
+                    std::vector<sql_expression> update_param = update_;
+                    where_param.push_back(sql_expression{ "",sql_expression::Separator,{},sql_expression::Not,std::pair(0, 0),{} });
+                    where_param.insert(where_param.end(), update_param.begin(), update_param.end());
+                    param = _SqlType(where_param, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
+                    reset();
+                }
+                //查询
+                else if (sql_event_type::Select == sql_event_type_) {
+                    param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
+                    param.result = std::vector<_Type>();
+                    reset();
+                }
+                //数量
+                else if (sql_event_type::Count == sql_event_type_) {
+                    param = _SqlType(where_, std::string(rttr::type::get<_Type>().get_name()), sql_event_type_);
+                    reset();
+                }
+                else {
+                    return *this;
+                }
+                if (execute_event_) {
+                    try {
+                        value = execute_event_(param);
+                    }
+                    catch (std::exception const& ec) {
+                        error_code_ = -1;
+                        error_message_ = ec.what();
+                    }
+                }
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief 提交
-         * @return
-         */
-        sql_linq& submit() {
-            submit(value_);
-            return *this;
-        }
-        /**
-         * @brief 提交
-         * @tparam _Ret
-         * @param value
-         * @return
-         */
-        template<typename _Ret>
-        sql_linq& submit(_Ret& value) {
-            rttr::variant ret;
-            submit(ret);
-            if (ret.get_type() == rttr::type::get<_Ret>()) {
-                value = ret.get_value<_Ret>();
-            }
-            return *this;
-        }
-        /**
-         * @brief 提交
-         * @param value
-         * @return
-         */
-        sql_linq& submit(std::vector<_Type>& value) {
-            rttr::variant ret;
-            submit(ret);
-            if (ret.get_type() == rttr::type::get<std::vector<_Type>>()) {
-                value = ret.get_value<std::vector<_Type>>();
+            /**
+             * @brief 提交
+             * @return
+             */
+            sql_linq& submit() {
+                submit(value_);
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief 错误
-         * @param message
-         * @param code
-         * @return
-         */
-        sql_linq& error(std::string& message, int& code) {
-            if (error_code_ != 0) {
-                code = error_code_;
-                message = error_message_;
+            /**
+             * @brief 提交
+             * @tparam _Ret
+             * @param value
+             * @return
+             */
+            template<typename _Ret>
+            sql_linq& submit(_Ret& value) {
+                rttr::variant ret;
+                submit(ret);
+                if (ret.get_type() == rttr::type::get<_Ret>()) {
+                    value = ret.get_value<_Ret>();
+                }
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief 错误
-         * @param message
-         * @param success
-         * @return
-         */
-        sql_linq& error(std::string& message, bool& success) {
-            if (error_code_ != 0) {
-                success = false;
-                message = error_message_;
+            /**
+             * @brief 提交
+             * @param value
+             * @return
+             */
+            sql_linq& submit(std::vector<_Type>& value) {
+                rttr::variant ret;
+                submit(ret);
+                if (ret.get_type() == rttr::type::get<std::vector<_Type>>()) {
+                    value = ret.get_value<std::vector<_Type>>();
+                }
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief 错误
-         * @param code
-         * @return
-         */
-        sql_linq& error(int& code) {
-            if (error_code_ != 0) {
-                code = error_code_;
+            /**
+             * @brief 错误
+             * @param message
+             * @param code
+             * @return
+             */
+            sql_linq& error(std::string& message, int& code) {
+                if (error_code_ != 0) {
+                    code = error_code_;
+                    message = error_message_;
+                }
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief 错误
-         * @param message
-         * @return
-         */
-        sql_linq& error(std::string& message) {
-            if (error_code_ != 0) {
-                message = error_message_;
+            /**
+             * @brief 错误
+             * @param message
+             * @param success
+             * @return
+             */
+            sql_linq& error(std::string& message, bool& success) {
+                if (error_code_ != 0) {
+                    success = false;
+                    message = error_message_;
+                }
+                return *this;
             }
-            return *this;
-        }
-        /**
-         * @brief
-         * @return
-         */
-        std::shared_ptr<_Type> first() {
-            std::shared_ptr<_Type> result;
-            std::vector<_Type> values = value_.get_value<std::vector<_Type>>();
-            if (!values.empty()) {
-                result.reset(new _Type(values[0]));
+            /**
+             * @brief 错误
+             * @param code
+             * @return
+             */
+            sql_linq& error(int& code) {
+                if (error_code_ != 0) {
+                    code = error_code_;
+                }
+                return *this;
             }
-            return result;
-        }
-        operator std::shared_ptr<_Type>() {
-            return first();
-        }
-        template<typename _Ret>
-        operator _Ret() {
-            if constexpr (std::is_same<rttr::variant, _Ret>::value) {
-                return value_;
+            /**
+             * @brief 错误
+             * @param message
+             * @return
+             */
+            sql_linq& error(std::string& message) {
+                if (error_code_ != 0) {
+                    message = error_message_;
+                }
+                return *this;
+            }
+            /**
+             * @brief
+             * @return
+             */
+            std::shared_ptr<_Type> first() {
+                std::shared_ptr<_Type> result;
+                std::vector<_Type> values = value_.get_value<std::vector<_Type>>();
+                if (!values.empty()) {
+                    result.reset(new _Type(values[0]));
+                }
+                return result;
             }
-            else {
-                return value_.get_value<_Ret>();
+            operator std::shared_ptr<_Type>() {
+                return first();
             }
-        }
-    private:
-        int error_code_ = 0;
-        bool reset_ = true;
-        rttr::variant value_;
-        sql_where<_Type> where_;
-        sql_update<_Type> update_;
-        sql_insert<_Type> insert_;
-        std::string error_message_;
-        sql_event_type sql_event_type_ = sql_event_type::Error;
-        std::function<rttr::variant(sql_param&)> execute_event_;
-    };
+            template<typename _Ret>
+            operator _Ret() {
+                if constexpr (std::is_same<rttr::variant, _Ret>::value) {
+                    return value_;
+                }
+                else {
+                    return value_.get_value<_Ret>();
+                }
+            }
+        private:
+            int error_code_ = 0;
+            bool reset_ = true;
+            rttr::variant value_;
+            sql_where<_Type> where_;
+            sql_update<_Type> update_;
+            sql_insert<_Type> insert_;
+            std::string error_message_;
+            sql_event_type sql_event_type_ = sql_event_type::Error;
+            std::function<rttr::variant(sql_param&)> execute_event_;
+        };
+    }
 }

+ 262 - 260
robot/robotics/text_stream.hpp

@@ -16,283 +16,285 @@
 #include "datetime.hpp"
 #include "json.hpp"
 
-namespace robotics::v3 {
-	/**
-	 * @brief
-	 */
-	class text_stream {
-	public:
-		/**
-		 * @brief char
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(char value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator<<(const char* value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator<<(char* value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief string
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::string const& value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief string_view
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::string_view value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief int
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(int value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(bool value) {
-			ss_ << (value ? "true" : "false");
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(datetime value) {
-			ss_ << value.to_string();
-			return *this;
-		}
-		/**
-		 * @brief long
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(long value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief double
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(double value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(float value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::exception const& value) {
-			ss_ << value.what();
-			return *this;
-		}
+namespace robotics {
+	namespace v3 {
 		/**
 		 * @brief
-		 * @param value
-		 * @return
 		 */
-		text_stream& operator <<(std::size_t const& value) {
-			ss_ << value;
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		template<typename _Type>
-		text_stream& operator <<(_Type const& value) {
-			ss_ << json_convert::serialize(value);
-			return *this;
-		}
-		//list
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<char> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+		class text_stream {
+		public:
+			/**
+			 * @brief char
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(char value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator<<(const char* value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator<<(char* value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief string
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::string const& value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief string_view
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::string_view value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief int
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(int value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(bool value) {
+				ss_ << (value ? "true" : "false");
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(datetime value) {
+				ss_ << value.to_string();
+				return *this;
+			}
+			/**
+			 * @brief long
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(long value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief double
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(double value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(float value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::exception const& value) {
+				ss_ << value.what();
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::size_t const& value) {
+				ss_ << value;
+				return *this;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			template<typename _Type>
+			text_stream& operator <<(_Type const& value) {
+				ss_ << json_convert::serialize(value);
+				return *this;
+			}
+			//list
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<char> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<std::string> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<std::string> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<int> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<int> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<bool> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i] ? "true" : "false";
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<bool> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i] ? "true" : "false";
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<datetime> values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i].to_string();
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<datetime> values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i].to_string();
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<long> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<long> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<double> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<double> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @return
-		 */
-		text_stream& operator <<(std::vector<float> const& values) {
-			ss_ << "(";
-			for (size_t i = 0; i < values.size(); ++i) {
-				ss_ << values[i];
-				if (i + 1 != values.size()) {
-					ss_ << ",";
+			/**
+			 * @brief
+			 * @param value
+			 * @return
+			 */
+			text_stream& operator <<(std::vector<float> const& values) {
+				ss_ << "(";
+				for (size_t i = 0; i < values.size(); ++i) {
+					ss_ << values[i];
+					if (i + 1 != values.size()) {
+						ss_ << ",";
+					}
 				}
+				ss_ << ")";
+				return *this;
 			}
-			ss_ << ")";
-			return *this;
-		}
-		/**
-		 * @brief
-		 * @return
-		 */
-		std::string str() {
-			return ss_.str();
-		}
-		/**
-		 * @brief
-		 */
-		operator std::string() {
-			return str();
-		}
-	private:
-		//
-		std::stringstream ss_;
-	};
+			/**
+			 * @brief
+			 * @return
+			 */
+			std::string str() {
+				return ss_.str();
+			}
+			/**
+			 * @brief
+			 */
+			operator std::string() {
+				return str();
+			}
+		private:
+			//
+			std::stringstream ss_;
+		};
+	}
 }

+ 39 - 37
robot/robotics/thread_pool.hpp

@@ -52,43 +52,45 @@ if (!this->robotics::v3::thread_pool<std::remove_reference<decltype(*this)>::typ
 }
 #endif // REGISTER_ASYNC_FUNC
 
-namespace robotics::v3 {
-	/**
-	 * @brief 线程池
-	 */
-    template<typename _Type>
-    class thread_pool {
-    public:
+namespace robotics {
+	namespace v3 {
 		/**
-		 * @brief
-		 * @param size
+		 * @brief 线程池
 		 */
-		thread_pool(std::uint32_t size = 1) :
-			__thread_pool__(size),
-			__size__(size) {
-		}
-		/**
-		 * @brief
-		 */
-		virtual ~thread_pool() {
-			join();
-		}
-		/**
-		 * @brief
-		 */
-		void join() {
-			__thread_pool__.join();
-		}
-	protected:
-        template<typename _Fn, typename _This, typename... _Args>
-        bool submit(_Fn&& fn, _This&& ths, _Args&&... args) {
-            if (__size__ == 0 || __thread_pool__.executor().running_in_this_thread())
-                return true;
-            asio::post(__thread_pool__, std::bind(std::forward<_Fn>(fn), std::forward<_This>(ths), std::forward<_Args>(args)...));
-            return false;
-        }
-    private:
-        std::uint32_t __size__ = 1;
-        asio::thread_pool __thread_pool__;
-    };
+		template<typename _Type>
+		class thread_pool {
+		public:
+			/**
+			 * @brief
+			 * @param size
+			 */
+			thread_pool(std::uint32_t size = 1) :
+				__thread_pool__(size),
+				__size__(size) {
+			}
+			/**
+			 * @brief
+			 */
+			virtual ~thread_pool() {
+				join();
+			}
+			/**
+			 * @brief
+			 */
+			void join() {
+				__thread_pool__.join();
+			}
+		protected:
+			template<typename _Fn, typename _This, typename... _Args>
+			bool submit(_Fn&& fn, _This&& ths, _Args&&... args) {
+				if (__size__ == 0 || __thread_pool__.executor().running_in_this_thread())
+					return true;
+				asio::post(__thread_pool__, std::bind(std::forward<_Fn>(fn), std::forward<_This>(ths), std::forward<_Args>(args)...));
+				return false;
+			}
+		private:
+			std::uint32_t __size__ = 1;
+			asio::thread_pool __thread_pool__;
+		};
+	}
 }

+ 95 - 93
robot/robotics/timer.hpp

@@ -14,101 +14,103 @@
 #include "event_wait_for.hpp"
 #include "delegates.hpp"
 
-namespace robotics::v3 {
-    class timer {
-    public:
-        /**
-         * @brief 构造
-         */
-        timer() :
-            number_of_times_(0) {
-        }
-        /**
-         * @brief 析构
-         */
-        ~timer() {
-            stop();
-        }
-        /**
-         * @brief 启动
-         * @param ms
-         */
-        void start(time_t ms) {
-            set_timer_interval(ms);
-            start();
-        }
-        /**
-         * @brief 设置时间
-         * @param ms
-         */
-        void set_timer_interval(int ms) {
-            time_ = ms;
-        }
-        /**
-         * @brief 启动
-         */
-        void start() {
-            if (thread_.joinable()) {
-                return;
+namespace robotics {
+    namespace v3 {
+        class timer {
+        public:
+            /**
+             * @brief 构造
+             */
+            timer() :
+                number_of_times_(0) {
             }
-            thread_ = std::thread(&timer::thread_work, this);
-        }
-        /**
-         * @brief 停止
-         */
-        void stop() {
-            run_ = false;
-            event_wait_for_.notify();
-            event_wait_for_run_.notify();
-            if (thread_.joinable())
-                thread_.join();
-        }
-        /**
-         * @brief 是否启动
-         * @return
-         */
-        bool is_started() {
-            return run_;
-        }
-        /**
-         * @brief 设置次数
-         * @param count
-         */
-        void set_number_of_times(unsigned int count) {
-            number_of_times_ = count;
-            event_wait_for_run_.notify();
-        }
-        /**
-         * @brief 定时器回调
-         */
-        robotics::v3::delegates<> timeout_event;
-    private:
-        void thread_work() {
-            run_ = true;
-            do {
-                unsigned int count = 0;
-                while (run_) {
-                    if (number_of_times_ > 0) {
-                        count++;
-                        if (count > number_of_times_) {
-                            break;
+            /**
+             * @brief 析构
+             */
+            ~timer() {
+                stop();
+            }
+            /**
+             * @brief 启动
+             * @param ms
+             */
+            void start(time_t ms) {
+                set_timer_interval(ms);
+                start();
+            }
+            /**
+             * @brief 设置时间
+             * @param ms
+             */
+            void set_timer_interval(int ms) {
+                time_ = ms;
+            }
+            /**
+             * @brief 启动
+             */
+            void start() {
+                if (thread_.joinable()) {
+                    return;
+                }
+                thread_ = std::thread(&timer::thread_work, this);
+            }
+            /**
+             * @brief 停止
+             */
+            void stop() {
+                run_ = false;
+                event_wait_for_.notify();
+                event_wait_for_run_.notify();
+                if (thread_.joinable())
+                    thread_.join();
+            }
+            /**
+             * @brief 是否启动
+             * @return
+             */
+            bool is_started() {
+                return run_;
+            }
+            /**
+             * @brief 设置次数
+             * @param count
+             */
+            void set_number_of_times(unsigned int count) {
+                number_of_times_ = count;
+                event_wait_for_run_.notify();
+            }
+            /**
+             * @brief 定时器回调
+             */
+            robotics::v3::delegates<> timeout_event;
+        private:
+            void thread_work() {
+                run_ = true;
+                do {
+                    unsigned int count = 0;
+                    while (run_) {
+                        if (number_of_times_ > 0) {
+                            count++;
+                            if (count > number_of_times_) {
+                                break;
+                            }
                         }
-                    }
 
-                    if (event_wait_for_.wait(time_)) {
-                        break;
+                        if (event_wait_for_.wait(time_)) {
+                            break;
+                        }
+                        timeout_event();
                     }
-                    timeout_event();
-                }
-            } while (run_ && event_wait_for_run_.wait(0xffffffff));
-            run_ = false;
-        }
-    private:
-        bool run_ = false;
-        time_t time_ = 1000;
-        std::thread thread_;
-        unsigned int number_of_times_ = 0;
-        robotics::v3::event_wait_for event_wait_for_;
-        robotics::v3::event_wait_for event_wait_for_run_;
-    };
+                } while (run_ && event_wait_for_run_.wait(0xffffffff));
+                run_ = false;
+            }
+        private:
+            bool run_ = false;
+            time_t time_ = 1000;
+            std::thread thread_;
+            unsigned int number_of_times_ = 0;
+            robotics::v3::event_wait_for event_wait_for_;
+            robotics::v3::event_wait_for event_wait_for_run_;
+        };
+    }
 }

+ 1156 - 1154
robot/robotics/utils.hpp

@@ -48,1231 +48,1233 @@
 #define SET_CONSOLE_UTF8
 #endif
 
-namespace robotics::v3 {
-	namespace utils {
-		template<typename _Type>
-		inline bool rttr_type(rttr::type const& type) {
-			return type == rttr::type::get<_Type>();
-		}
-		inline std::any rttr_variant_to_any(rttr::variant const& value) {
-			if (rttr_type<int>(value.get_type())) {
-				return value.get_value<int>();
-			}
-			else if (rttr_type<bool>(value.get_type())) {
-				return value.get_value<bool>();
-			}
-			else if (rttr_type<double>(value.get_type())) {
-				return value.get_value<double>();
-			}
-			else if (rttr_type<long>(value.get_type())) {
-				return value.get_value<long>();
-			}
-			else if (rttr_type<float>(value.get_type())) {
-				return value.get_value<float>();
-			}
-			else if (rttr_type<std::int64_t>(value.get_type())) {
-				return value.get_value<std::int64_t>();
-			}
-			else if (rttr_type<std::string>(value.get_type())) {
-				return value.get_value<std::string>();
-			}
-			else if (rttr_type<datetime>(value.get_type())) {
-				return value.get_value<datetime>();
-			}
-			else if (rttr_type<std::vector<int>>(value.get_type())) {
-				return value.get_value<std::vector<int>>();
-			}
-			else if (rttr_type<std::vector<bool>>(value.get_type())) {
-				return value.get_value< std::vector<bool>>();
-			}
-			else if (rttr_type<std::vector<double>>(value.get_type())) {
-				return value.get_value<std::vector<double>>();
-			}
-			else if (rttr_type<std::vector<long>>(value.get_type())) {
-				return value.get_value<std::vector<long>>();
+namespace robotics {
+	namespace v3 {
+		namespace utils {
+			template<typename _Type>
+			inline bool rttr_type(rttr::type const& type) {
+				return type == rttr::type::get<_Type>();
+			}
+			inline std::any rttr_variant_to_any(rttr::variant const& value) {
+				if (rttr_type<int>(value.get_type())) {
+					return value.get_value<int>();
+				}
+				else if (rttr_type<bool>(value.get_type())) {
+					return value.get_value<bool>();
+				}
+				else if (rttr_type<double>(value.get_type())) {
+					return value.get_value<double>();
+				}
+				else if (rttr_type<long>(value.get_type())) {
+					return value.get_value<long>();
+				}
+				else if (rttr_type<float>(value.get_type())) {
+					return value.get_value<float>();
+				}
+				else if (rttr_type<std::int64_t>(value.get_type())) {
+					return value.get_value<std::int64_t>();
+				}
+				else if (rttr_type<std::string>(value.get_type())) {
+					return value.get_value<std::string>();
+				}
+				else if (rttr_type<datetime>(value.get_type())) {
+					return value.get_value<datetime>();
+				}
+				else if (rttr_type<std::vector<int>>(value.get_type())) {
+					return value.get_value<std::vector<int>>();
+				}
+				else if (rttr_type<std::vector<bool>>(value.get_type())) {
+					return value.get_value< std::vector<bool>>();
+				}
+				else if (rttr_type<std::vector<double>>(value.get_type())) {
+					return value.get_value<std::vector<double>>();
+				}
+				else if (rttr_type<std::vector<long>>(value.get_type())) {
+					return value.get_value<std::vector<long>>();
+				}
+				else if (rttr_type<std::vector<float>>(value.get_type())) {
+					return value.get_value<std::vector<float>>();
+				}
+				else if (rttr_type<std::vector<std::int64_t>>(value.get_type())) {
+					return value.get_value<std::vector<std::int64_t>>();
+				}
+				else if (rttr_type<std::vector<std::string>>(value.get_type())) {
+					return value.get_value<std::vector<std::string>>();
+				}
+				else if (rttr_type<std::vector<datetime>>(value.get_type())) {
+					return value.get_value<std::vector<datetime>>();
+				}
+				else {
+					throw std::runtime_error("转换类型错误");
+				}
 			}
-			else if (rttr_type<std::vector<float>>(value.get_type())) {
-				return value.get_value<std::vector<float>>();
+			/**
+			 * @brief 格式化输出
+			 * @tparam ..._Args
+			 * @param fmt
+			 * @param ...args
+			 * @return
+			 */
+			template<typename... _Args>
+			inline std::string format(std::string const& fmt, _Args const& ...args) {
+				return fmt::vformat(fmt, fmt::make_format_args(args...));
+			}
+			/**
+			 * @brief 调用
+			 * @tparam _Fn
+			 * @tparam _Arg1
+			 * @tparam ..._Args
+			 * @param fn
+			 * @param arg1
+			 * @param tuple
+			 * @return
+			 */
+			template<typename _Fn, typename _Arg1, typename ..._Args>
+			inline v3::function_traits<_Fn>::return_type invoke(_Fn&& fn, _Arg1&& arg1, std::tuple<_Args...>const& tuple) {
+				return std::apply([&](auto const&...args) ->v3::function_traits<_Fn>::return_type {
+					return std::invoke(std::forward<_Fn>(fn), std::forward<_Arg1>(arg1), args...);
+					}, tuple);
+			}
+			/**
+			 * @brief 调用
+			 * @tparam _Fn
+			 * @tparam _Arg1
+			 * @tparam ..._Args
+			 * @param fn
+			 * @param arg1
+			 * @param ...args
+			 * @return
+			 */
+			template<typename _Fn, typename _Arg1, typename ..._Args>
+			inline v3::function_traits<_Fn>::return_type invoke(_Fn&& fn, _Arg1&& arg1, _Args const&...args) {
+				return std::invoke(std::forward<_Fn>(fn), std::forward<_Arg1>(arg1), args...);
 			}
-			else if (rttr_type<std::vector<std::int64_t>>(value.get_type())) {
-				return value.get_value<std::vector<std::int64_t>>();
+			/**
+			 * @brief 获取时间戳
+			 * @return
+			 */
+			inline time_t steady_time_stamp() {
+				return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()).time_since_epoch()).count();
+			}
+			/**
+			 * @brief base64加密
+			 * @param value
+			 * @return
+			 */
+			inline std::string base64_encode(std::string const& value) {
+				std::string result;
+				std::size_t len = value.size();
+				result.resize(boost::beast::detail::base64::encoded_size(len));
+				result.resize(boost::beast::detail::base64::encode(&result[0], &value[0], len));
+				return result;
 			}
-			else if (rttr_type<std::vector<std::string>>(value.get_type())) {
-				return value.get_value<std::vector<std::string>>();
+			/**
+			 * @brief base64解密
+			 * @param value
+			 * @return
+			 */
+			inline std::string base64_decode(std::string const& value) {
+				std::string result_str;
+				std::size_t len = value.size();
+				result_str.resize(boost::beast::detail::base64::decoded_size(len));
+				auto result = boost::beast::detail::base64::decode(&result_str[0], value.data(), len);
+				if (result_str.size() < result.first) {
+					return "";
+				}
+				result_str.resize(result.first);
+				return result_str;
+			}
+			/**
+			 * @brief base64加密
+			 * @param value
+			 * @return
+			 */
+			inline std::vector<std::uint8_t> base64_encode(std::vector<std::uint8_t>const& value) {
+				std::vector<std::uint8_t> result;
+				std::size_t len = value.size();
+				result.resize(boost::beast::detail::base64::encoded_size(len));
+				result.resize(boost::beast::detail::base64::encode(&result[0], &value[0], len));
+				return result;
 			}
-			else if (rttr_type<std::vector<datetime>>(value.get_type())) {
-				return value.get_value<std::vector<datetime>>();
+			/**
+			 * @brief base64解密
+			 * @param value
+			 * @return
+			 */
+			inline std::vector<std::uint8_t> base64_decode(std::vector<std::uint8_t> const& value) {
+				std::vector<std::uint8_t> result_vec;
+				std::size_t len = value.size();
+				result_vec.resize(boost::beast::detail::base64::decoded_size(len));
+				auto result = boost::beast::detail::base64::decode(&result_vec[0], (const char*)&value[0], len);
+				if (result_vec.size() < result.first) {
+					return {};
+				}
+				result_vec.resize(result.first);
+				return result_vec;
+			}
+			/**
+			 * @brief uuid
+			 * @return
+			 */
+			inline std::string uuid() {
+				boost::uuids::uuid uid = boost::uuids::random_generator()();
+				const std::string uid_str = boost::uuids::to_string(uid);
+				return uid_str;
+			}
+			/**
+			 * @brief MD5加密
+			 * @param value
+			 * @return
+			 */
+			template<typename _First>
+			inline std::string md5(_First&& value) {
+				union
+				{
+					boost::uuids::detail::md5::digest_type n_;
+					std::uint8_t c_[16];
+				}digest_type, digest_char;
+
+				boost::uuids::detail::md5 hash;
+				for (auto c : value) {
+					hash.process_byte(c);
+				}
+				hash.get_digest(digest_type.n_);
+				digest_char = digest_type;
+				digest_char.c_[0] = digest_type.c_[3];
+				digest_char.c_[1] = digest_type.c_[2];
+				digest_char.c_[2] = digest_type.c_[1];
+				digest_char.c_[3] = digest_type.c_[0];
+				digest_char.c_[4] = digest_type.c_[7];
+				digest_char.c_[5] = digest_type.c_[6];
+				digest_char.c_[6] = digest_type.c_[5];
+				digest_char.c_[7] = digest_type.c_[4];
+				digest_char.c_[8] = digest_type.c_[11];
+				digest_char.c_[9] = digest_type.c_[10];
+				digest_char.c_[10] = digest_type.c_[9];
+				digest_char.c_[11] = digest_type.c_[8];
+				digest_char.c_[12] = digest_type.c_[15];
+				digest_char.c_[13] = digest_type.c_[14];
+				digest_char.c_[14] = digest_type.c_[13];
+				digest_char.c_[15] = digest_type.c_[12];
+				std::string result;
+				boost::algorithm::hex(&digest_char.c_[0], &digest_char.c_[0] + sizeof(boost::uuids::detail::md5::digest_type), std::back_inserter(result));
+				return result;
 			}
-			else {
-				throw std::runtime_error("转换类型错误");
+			/**
+			 * @brief MD5加密
+			 * @param value
+			 * @return
+			 */
+			template<typename _First>
+			inline std::vector<std::uint8_t> md5_byte(_First&& value) {
+				std::vector<std::uint8_t> result;
+				union
+				{
+					boost::uuids::detail::md5::digest_type n_;
+					std::uint8_t c_[16];
+				}digest_type;
+
+				boost::uuids::detail::md5 hash;
+				for (auto c : value) {
+					hash.process_byte(c);
+				}
+				hash.get_digest(digest_type.n_);
+				result.push_back(digest_type.c_[3]);
+				result.push_back(digest_type.c_[2]);
+				result.push_back(digest_type.c_[1]);
+				result.push_back(digest_type.c_[0]);
+				result.push_back(digest_type.c_[7]);
+				result.push_back(digest_type.c_[6]);
+				result.push_back(digest_type.c_[5]);
+				result.push_back(digest_type.c_[4]);
+				result.push_back(digest_type.c_[11]);
+				result.push_back(digest_type.c_[10]);
+				result.push_back(digest_type.c_[9]);
+				result.push_back(digest_type.c_[8]);
+				result.push_back(digest_type.c_[15]);
+				result.push_back(digest_type.c_[14]);
+				result.push_back(digest_type.c_[13]);
+				result.push_back(digest_type.c_[12]);
+				return result;
 			}
-		}
-		/**
-		 * @brief 格式化输出
-		 * @tparam ..._Args
-		 * @param fmt
-		 * @param ...args
-		 * @return
-		 */
-		template<typename... _Args>
-		inline std::string format(std::string const& fmt, _Args const& ...args) {
-			return fmt::vformat(fmt, fmt::make_format_args(args...));
-		}
-		/**
-		 * @brief 调用
-		 * @tparam _Fn
-		 * @tparam _Arg1
-		 * @tparam ..._Args
-		 * @param fn
-		 * @param arg1
-		 * @param tuple
-		 * @return
-		 */
-		template<typename _Fn, typename _Arg1, typename ..._Args>
-		inline v3::function_traits<_Fn>::return_type invoke(_Fn&& fn, _Arg1&& arg1, std::tuple<_Args...>const& tuple) {
-			return std::apply([&](auto const&...args) ->v3::function_traits<_Fn>::return_type {
-				return std::invoke(std::forward<_Fn>(fn), std::forward<_Arg1>(arg1), args...);
-				}, tuple);
-		}
-		/**
-		 * @brief 调用
-		 * @tparam _Fn
-		 * @tparam _Arg1
-		 * @tparam ..._Args
-		 * @param fn
-		 * @param arg1
-		 * @param ...args
-		 * @return
-		 */
-		template<typename _Fn, typename _Arg1, typename ..._Args>
-		inline v3::function_traits<_Fn>::return_type invoke(_Fn&& fn, _Arg1&& arg1, _Args const&...args) {
-			return std::invoke(std::forward<_Fn>(fn), std::forward<_Arg1>(arg1), args...);
-		}
-		/**
-		 * @brief 获取时间戳
-		 * @return
-		 */
-		inline time_t steady_time_stamp() {
-			return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now()).time_since_epoch()).count();
-		}
-		/**
-		 * @brief base64加密
-		 * @param value
-		 * @return
-		 */
-		inline std::string base64_encode(std::string const& value) {
-			std::string result;
-			std::size_t len = value.size();
-			result.resize(boost::beast::detail::base64::encoded_size(len));
-			result.resize(boost::beast::detail::base64::encode(&result[0], &value[0], len));
-			return result;
-		}
-		/**
-		 * @brief base64解密
-		 * @param value
-		 * @return
-		 */
-		inline std::string base64_decode(std::string const& value) {
-			std::string result_str;
-			std::size_t len = value.size();
-			result_str.resize(boost::beast::detail::base64::decoded_size(len));
-			auto result = boost::beast::detail::base64::decode(&result_str[0], value.data(), len);
-			if (result_str.size() < result.first) {
-				return "";
+			/**
+			 * @brief 正则校验
+			 * @param value
+			 * @param pattern
+			 * @return
+			 */
+			inline bool regex_check(std::string const& value, std::string const& pattern) {
+				std::regex re(pattern);
+				return std::regex_match(value, re);
+			}
+			/**
+			 * @brief 字符串替换
+			 * @param value
+			 * @param old_str
+			 * @param new_str
+			 * @return
+			 */
+			inline std::string replace(std::string const& value, std::string const& old_str, std::string const& new_str) {
+				std::string result = value;
+				for (std::string::size_type pos(0); pos != std::string::npos; pos += new_str.length()) {
+					pos = result.find(old_str, pos);
+					if (pos != std::string::npos)
+						result.replace(pos, old_str.length(), new_str);
+					else
+						break;
+				}
+				return result;
 			}
-			result_str.resize(result.first);
-			return result_str;
-		}
-		/**
-		 * @brief base64加密
-		 * @param value
-		 * @return
-		 */
-		inline std::vector<std::uint8_t> base64_encode(std::vector<std::uint8_t>const& value) {
-			std::vector<std::uint8_t> result;
-			std::size_t len = value.size();
-			result.resize(boost::beast::detail::base64::encoded_size(len));
-			result.resize(boost::beast::detail::base64::encode(&result[0], &value[0], len));
-			return result;
-		}
-		/**
-		 * @brief base64解密
-		 * @param value
-		 * @return
-		 */
-		inline std::vector<std::uint8_t> base64_decode(std::vector<std::uint8_t> const& value) {
-			std::vector<std::uint8_t> result_vec;
-			std::size_t len = value.size();
-			result_vec.resize(boost::beast::detail::base64::decoded_size(len));
-			auto result = boost::beast::detail::base64::decode(&result_vec[0], (const char*)&value[0], len);
-			if (result_vec.size() < result.first) {
-				return {};
+			/**
+			 * @brief 字符串替换
+			 * @param value
+			 * @param old_str
+			 * @param new_str
+			 * @return
+			 */
+			inline std::string replace(std::string const& value, std::vector<std::string> const& old_str, std::string const& new_str) {
+				std::string result = value;
+				for (auto& it : old_str) {
+					result = replace(result, it, new_str);
+				}
+				return result;
 			}
-			result_vec.resize(result.first);
-			return result_vec;
-		}
-		/**
-		 * @brief uuid
-		 * @return
-		 */
-		inline std::string uuid() {
-			boost::uuids::uuid uid = boost::uuids::random_generator()();
-			const std::string uid_str = boost::uuids::to_string(uid);
-			return uid_str;
-		}
-		/**
-		 * @brief MD5加密
-		 * @param value
-		 * @return
-		 */
-		template<typename _First>
-		inline std::string md5(_First&& value) {
-			union
-			{
-				boost::uuids::detail::md5::digest_type n_;
-				std::uint8_t c_[16];
-			}digest_type, digest_char;
-
-			boost::uuids::detail::md5 hash;
-			for (auto c : value) {
-				hash.process_byte(c);
-			}
-			hash.get_digest(digest_type.n_);
-			digest_char = digest_type;
-			digest_char.c_[0] = digest_type.c_[3];
-			digest_char.c_[1] = digest_type.c_[2];
-			digest_char.c_[2] = digest_type.c_[1];
-			digest_char.c_[3] = digest_type.c_[0];
-			digest_char.c_[4] = digest_type.c_[7];
-			digest_char.c_[5] = digest_type.c_[6];
-			digest_char.c_[6] = digest_type.c_[5];
-			digest_char.c_[7] = digest_type.c_[4];
-			digest_char.c_[8] = digest_type.c_[11];
-			digest_char.c_[9] = digest_type.c_[10];
-			digest_char.c_[10] = digest_type.c_[9];
-			digest_char.c_[11] = digest_type.c_[8];
-			digest_char.c_[12] = digest_type.c_[15];
-			digest_char.c_[13] = digest_type.c_[14];
-			digest_char.c_[14] = digest_type.c_[13];
-			digest_char.c_[15] = digest_type.c_[12];
-			std::string result;
-			boost::algorithm::hex(&digest_char.c_[0], &digest_char.c_[0] + sizeof(boost::uuids::detail::md5::digest_type), std::back_inserter(result));
-			return result;
-		}
-		/**
-		 * @brief MD5加密
-		 * @param value
-		 * @return
-		 */
-		template<typename _First>
-		inline std::vector<std::uint8_t> md5_byte(_First&& value) {
-			std::vector<std::uint8_t> result;
-			union
-			{
-				boost::uuids::detail::md5::digest_type n_;
-				std::uint8_t c_[16];
-			}digest_type;
-
-			boost::uuids::detail::md5 hash;
-			for (auto c : value) {
-				hash.process_byte(c);
-			}
-			hash.get_digest(digest_type.n_);
-			result.push_back(digest_type.c_[3]);
-			result.push_back(digest_type.c_[2]);
-			result.push_back(digest_type.c_[1]);
-			result.push_back(digest_type.c_[0]);
-			result.push_back(digest_type.c_[7]);
-			result.push_back(digest_type.c_[6]);
-			result.push_back(digest_type.c_[5]);
-			result.push_back(digest_type.c_[4]);
-			result.push_back(digest_type.c_[11]);
-			result.push_back(digest_type.c_[10]);
-			result.push_back(digest_type.c_[9]);
-			result.push_back(digest_type.c_[8]);
-			result.push_back(digest_type.c_[15]);
-			result.push_back(digest_type.c_[14]);
-			result.push_back(digest_type.c_[13]);
-			result.push_back(digest_type.c_[12]);
-			return result;
-		}
-		/**
-		 * @brief 正则校验
-		 * @param value
-		 * @param pattern
-		 * @return
-		 */
-		inline bool regex_check(std::string const& value, std::string const& pattern) {
-			std::regex re(pattern);
-			return std::regex_match(value, re);
-		}
-		/**
-		 * @brief 字符串替换
-		 * @param value
-		 * @param old_str
-		 * @param new_str
-		 * @return
-		 */
-		inline std::string replace(std::string const& value, std::string const& old_str, std::string const& new_str) {
-			std::string result = value;
-			for (std::string::size_type pos(0); pos != std::string::npos; pos += new_str.length()) {
-				pos = result.find(old_str, pos);
-				if (pos != std::string::npos)
-					result.replace(pos, old_str.length(), new_str);
-				else
-					break;
+			/**
+			 * @brief 字符串分割
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<std::string> split(std::string const& value, std::string const& c) {
+				std::vector<std::string> result;
+				if (value.empty()) {
+					result.push_back(value);
+					return result;
+				}
+				std::string strs = value + c;
+				size_t pos = strs.find(c);
+				while (pos != strs.npos) {
+					std::string temp = strs.substr(0, pos);
+					result.push_back(temp);
+					strs = strs.substr(pos + c.size(), strs.size());
+					pos = strs.find(c);
+				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 字符串替换
-		 * @param value
-		 * @param old_str
-		 * @param new_str
-		 * @return
-		 */
-		inline std::string replace(std::string const& value, std::vector<std::string> const& old_str, std::string const& new_str) {
-			std::string result = value;
-			for (auto& it : old_str) {
-				result = replace(result, it, new_str);
+			/**
+			 * @brief 分割字符串头尾清空
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<std::string> split_trim(std::string const& value, std::string const& c) {
+				std::vector<std::string> result;
+				if (value.empty() || value[0] == 0) {
+					return result;
+				}
+				std::string strs = value + c;
+				size_t pos = strs.find(c);
+				while (pos != strs.npos) {
+					std::string temp = strs.substr(0, pos);
+					result.push_back(temp);
+					strs = strs.substr(pos + c.size(), strs.size());
+					pos = strs.find(c);
+				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 字符串分割
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<std::string> split(std::string const& value, std::string const& c) {
-			std::vector<std::string> result;
-			if (value.empty()) {
-				result.push_back(value);
+			/**
+			 * @brief 分割字符串到int列表
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<int> split_int(std::string const& value, std::string const& c) {
+				std::vector<int> result;
+				if (value.empty() || value[0] == 0) {
+					return result;
+				}
+				std::string strs = value + c;
+				size_t pos = strs.find(c);
+				while (pos != strs.npos) {
+					std::string temp = strs.substr(0, pos);
+					result.push_back(std::atoi(temp.c_str()));
+					strs = strs.substr(pos + c.size(), strs.size());
+					pos = strs.find(c);
+				}
 				return result;
 			}
-			std::string strs = value + c;
-			size_t pos = strs.find(c);
-			while (pos != strs.npos) {
-				std::string temp = strs.substr(0, pos);
-				result.push_back(temp);
-				strs = strs.substr(pos + c.size(), strs.size());
-				pos = strs.find(c);
+			/**
+			 * @brief 字符串分割
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<std::string> split(std::string const& value, char c) {
+				return split(value, std::string(1, c));
+			}
+			/**
+			 * @brief 分割字符串
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<std::string> split_trim(std::string const& value, char c) {
+				return split_trim(value, std::string(1, c));
+			}
+			/**
+			 * @brief 分割字符串
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::vector<int> split_int(std::string const& value, char c) {
+				return split_int(value, std::string(1, c));
+			}
+			/**
+			 * @brief 删除首位空
+			 * @param value
+			 * @return
+			 */
+			inline std::string trim(std::string const& value) {
+				std::string result = value;
+				boost::trim(result);
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 分割字符串头尾清空
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<std::string> split_trim(std::string const& value, std::string const& c) {
-			std::vector<std::string> result;
-			if (value.empty() || value[0] == 0) {
+			/**
+			 * @brief 删除右边空
+			 * @param value
+			 * @return
+			 */
+			inline std::string trim_right(std::string const& value) {
+				std::string result = value;
+				boost::trim_right(result);
 				return result;
 			}
-			std::string strs = value + c;
-			size_t pos = strs.find(c);
-			while (pos != strs.npos) {
-				std::string temp = strs.substr(0, pos);
-				result.push_back(temp);
-				strs = strs.substr(pos + c.size(), strs.size());
-				pos = strs.find(c);
+			/**
+			 * @brief 删除左边空
+			 * @param value
+			 * @return
+			 */
+			inline std::string trim_left(std::string const& value) {
+				std::string result = value;
+				boost::trim_left(result);
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 分割字符串到int列表
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<int> split_int(std::string const& value, std::string const& c) {
-			std::vector<int> result;
-			if (value.empty() || value[0] == 0) {
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @param count
+			 * @return
+			 */
+			inline std::string pad_left(std::string const& value, char c, int count) {
+				if (count <= value.size())
+					return value;
+				return std::string().append(count - value.size(), c) + value;
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @param count
+			 * @return
+			 */
+			inline std::string pad_left(int value, char c, int count) {
+				return pad_left(std::to_string(value), c, count);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @param count
+			 * @return
+			 */
+			inline std::string pad_right(std::string const& value, char c, int count) {
+				if (count <= value.size())
+					return value;
+				return value + std::string().append(count - value.size(), c);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @param count
+			 * @return
+			 */
+			inline std::string pad_right(int value, char c, int count) {
+				return pad_right(std::to_string(value), c, count);
+			}
+			/**
+			 * @brief 转大写
+			 * @param value
+			 * @return
+			 */
+			inline std::string to_upper(std::string const& value) {
+				return boost::to_upper_copy(value);
+			}
+			/**
+			 * @brief 转小写
+			 * @param value
+			 * @return
+			 */
+			inline std::string to_lower(std::string const& value) {
+				return boost::to_lower_copy(value);
+			}
+			/**
+			 * @brief aes加密
+			 * @param value
+			 * @param key
+			 * @return
+			 */
+			inline std::vector<std::uint8_t> aes_encode(std::vector<std::uint8_t> const& value, std::string const& key) {
+				BOOST_ASSERT(key.size() == 16 || key.size() == 24 || key.size() == 32);
+				std::vector<std::uint8_t> value_ = value;
+				std::string				  key_ = key;
+				std::vector<std::uint8_t> result;
+				AES_KEY aesKey;
+				AES_set_encrypt_key((const unsigned char*)key_.c_str(), key_.size() * 8, &aesKey);
+				int remainder = value_.size() % AES_BLOCK_SIZE;
+				int paddingSize = (remainder == 0) ? AES_BLOCK_SIZE : (AES_BLOCK_SIZE - remainder);
+				std::fill_n(std::back_inserter(value_), paddingSize, paddingSize);
+				result.resize(value_.size());
+				for (int i = 0; i < value_.size() / AES_BLOCK_SIZE; ++i) {
+					AES_ecb_encrypt(&value_[AES_BLOCK_SIZE * i], &result[AES_BLOCK_SIZE * i], &aesKey, AES_ENCRYPT);
+				}
 				return result;
 			}
-			std::string strs = value + c;
-			size_t pos = strs.find(c);
-			while (pos != strs.npos) {
-				std::string temp = strs.substr(0, pos);
-				result.push_back(std::atoi(temp.c_str()));
-				strs = strs.substr(pos + c.size(), strs.size());
-				pos = strs.find(c);
+			/**
+			 * @brief aes解密
+			 * @param value
+			 * @param key
+			 * @return
+			 */
+			inline std::vector<std::uint8_t> aes_decode(std::vector<std::uint8_t> const& value, std::string const& key) {
+				BOOST_ASSERT(key.size() == 16 || key.size() == 24 || key.size() == 32);
+				std::vector<std::uint8_t> value_ = value;
+				std::string				  key_ = key;
+				std::vector<std::uint8_t> result;
+				AES_KEY aesKey;
+				AES_set_decrypt_key((const unsigned char*)key_.c_str(), key_.size() * 8, &aesKey);
+				int remainder = value_.size() % AES_BLOCK_SIZE;
+				int paddingSize = (remainder == 0) ? AES_BLOCK_SIZE : (AES_BLOCK_SIZE - remainder);
+				result.resize(value_.size() + paddingSize);
+				for (int i = 0; i < value_.size() / AES_BLOCK_SIZE; i++) {
+					AES_ecb_encrypt(&value_[AES_BLOCK_SIZE * i], &result[AES_BLOCK_SIZE * i], &aesKey, AES_DECRYPT);
+				}
+				if (value_.size()) {
+					int outCount = result[value_.size() - 1];
+					result.resize(value_.size() - outCount);
+				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 字符串分割
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<std::string> split(std::string const& value, char c) {
-			return split(value, std::string(1, c));
-		}
-		/**
-		 * @brief 分割字符串
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<std::string> split_trim(std::string const& value, char c) {
-			return split_trim(value, std::string(1, c));
-		}
-		/**
-		 * @brief 分割字符串
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::vector<int> split_int(std::string const& value, char c) {
-			return split_int(value, std::string(1, c));
-		}
-		/**
-		 * @brief 删除首位空
-		 * @param value
-		 * @return
-		 */
-		inline std::string trim(std::string const& value) {
-			std::string result = value;
-			boost::trim(result);
-			return result;
-		}
-		/**
-		 * @brief 删除右边空
-		 * @param value
-		 * @return
-		 */
-		inline std::string trim_right(std::string const& value) {
-			std::string result = value;
-			boost::trim_right(result);
-			return result;
-		}
-		/**
-		 * @brief 删除左边空
-		 * @param value
-		 * @return
-		 */
-		inline std::string trim_left(std::string const& value) {
-			std::string result = value;
-			boost::trim_left(result);
-			return result;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @param count
-		 * @return
-		 */
-		inline std::string pad_left(std::string const& value, char c, int count) {
-			if (count <= value.size())
-				return value;
-			return std::string().append(count - value.size(), c) + value;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @param count
-		 * @return
-		 */
-		inline std::string pad_left(int value, char c, int count) {
-			return pad_left(std::to_string(value), c, count);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @param count
-		 * @return
-		 */
-		inline std::string pad_right(std::string const& value, char c, int count) {
-			if (count <= value.size())
-				return value;
-			return value + std::string().append(count - value.size(), c);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @param count
-		 * @return
-		 */
-		inline std::string pad_right(int value, char c, int count) {
-			return pad_right(std::to_string(value), c, count);
-		}
-		/**
-		 * @brief 转大写
-		 * @param value
-		 * @return
-		 */
-		inline std::string to_upper(std::string const& value) {
-			return boost::to_upper_copy(value);
-		}
-		/**
-		 * @brief 转小写
-		 * @param value
-		 * @return
-		 */
-		inline std::string to_lower(std::string const& value) {
-			return boost::to_lower_copy(value);
-		}
-		/**
-		 * @brief aes加密
-		 * @param value
-		 * @param key
-		 * @return
-		 */
-		inline std::vector<std::uint8_t> aes_encode(std::vector<std::uint8_t> const& value, std::string const& key) {
-			BOOST_ASSERT(key.size() == 16 || key.size() == 24 || key.size() == 32);
-			std::vector<std::uint8_t> value_ = value;
-			std::string				  key_ = key;
-			std::vector<std::uint8_t> result;
-			AES_KEY aesKey;
-			AES_set_encrypt_key((const unsigned char*)key_.c_str(), key_.size() * 8, &aesKey);
-			int remainder = value_.size() % AES_BLOCK_SIZE;
-			int paddingSize = (remainder == 0) ? AES_BLOCK_SIZE : (AES_BLOCK_SIZE - remainder);
-			std::fill_n(std::back_inserter(value_), paddingSize, paddingSize);
-			result.resize(value_.size());
-			for (int i = 0; i < value_.size() / AES_BLOCK_SIZE; ++i) {
-				AES_ecb_encrypt(&value_[AES_BLOCK_SIZE * i], &result[AES_BLOCK_SIZE * i], &aesKey, AES_ENCRYPT);
-			}
-			return result;
-		}
-		/**
-		 * @brief aes解密
-		 * @param value
-		 * @param key
-		 * @return
-		 */
-		inline std::vector<std::uint8_t> aes_decode(std::vector<std::uint8_t> const& value, std::string const& key) {
-			BOOST_ASSERT(key.size() == 16 || key.size() == 24 || key.size() == 32);
-			std::vector<std::uint8_t> value_ = value;
-			std::string				  key_ = key;
-			std::vector<std::uint8_t> result;
-			AES_KEY aesKey;
-			AES_set_decrypt_key((const unsigned char*)key_.c_str(), key_.size() * 8, &aesKey);
-			int remainder = value_.size() % AES_BLOCK_SIZE;
-			int paddingSize = (remainder == 0) ? AES_BLOCK_SIZE : (AES_BLOCK_SIZE - remainder);
-			result.resize(value_.size() + paddingSize);
-			for (int i = 0; i < value_.size() / AES_BLOCK_SIZE; i++) {
-				AES_ecb_encrypt(&value_[AES_BLOCK_SIZE * i], &result[AES_BLOCK_SIZE * i], &aesKey, AES_DECRYPT);
-			}
-			if (value_.size()) {
-				int outCount = result[value_.size() - 1];
-				result.resize(value_.size() - outCount);
-			}
-			return result;
-		}
-		/**
-		 * @brief des加密
-		 * @param clearText
-		 * @param key
-		 * @return
-		 */
-		inline std::string des_encrypt(std::string const& clearText, std::string const& key) {
-			std::string cipherText;
-			DES_cblock keyEncrypt;
-			memset(keyEncrypt, 0, 8);
-			// 构造补齐后的密钥    
-			if (key.length() <= 8)
-				memcpy(keyEncrypt, key.c_str(), key.length());
-			else
-				memcpy(keyEncrypt, key.c_str(), 8);
-			// 密钥置换    
-			DES_key_schedule keySchedule;
-			DES_set_key_unchecked(&keyEncrypt, &keySchedule);
-			// 循环加密,每8字节一次    
-			const_DES_cblock inputText;
-			DES_cblock outputText;
-			std::vector<unsigned char> vecCiphertext;
-			unsigned char tmp[8];
-			for (int i = 0; i < clearText.length() / 8; i++) {
-				memcpy(inputText, clearText.c_str() + i * 8, 8);
-				DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
-				memcpy(tmp, outputText, 8);
+			/**
+			 * @brief des加密
+			 * @param clearText
+			 * @param key
+			 * @return
+			 */
+			inline std::string des_encrypt(std::string const& clearText, std::string const& key) {
+				std::string cipherText;
+				DES_cblock keyEncrypt;
+				memset(keyEncrypt, 0, 8);
+				// 构造补齐后的密钥    
+				if (key.length() <= 8)
+					memcpy(keyEncrypt, key.c_str(), key.length());
+				else
+					memcpy(keyEncrypt, key.c_str(), 8);
+				// 密钥置换    
+				DES_key_schedule keySchedule;
+				DES_set_key_unchecked(&keyEncrypt, &keySchedule);
+				// 循环加密,每8字节一次    
+				const_DES_cblock inputText;
+				DES_cblock outputText;
+				std::vector<unsigned char> vecCiphertext;
+				unsigned char tmp[8];
+				for (int i = 0; i < clearText.length() / 8; i++) {
+					memcpy(inputText, clearText.c_str() + i * 8, 8);
+					DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
+					memcpy(tmp, outputText, 8);
 
-				for (int j = 0; j < 8; j++)
-					vecCiphertext.push_back(tmp[j]);
-			}
-			if (clearText.length() % 8 != 0) {
-				int tmp1 = clearText.length() / 8 * 8;
-				int tmp2 = clearText.length() - tmp1;
-				memset(inputText, 0, 8);
-				memcpy(inputText, clearText.c_str() + tmp1, tmp2);
-				// 加密函数    
-				DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
-				memcpy(tmp, outputText, 8);
-				for (int j = 0; j < 8; j++)
-					vecCiphertext.push_back(tmp[j]);
-			}
-			cipherText.clear();
-			cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());
-			return cipherText;
-		}
-		/**
-		 * @brief des解密
-		 * @param cipherText
-		 * @param key
-		 * @return
-		 */
-		inline std::string des_decrypt(std::string const& cipherText, std::string const& key) {
-			std::string clearText; // 明文    
+					for (int j = 0; j < 8; j++)
+						vecCiphertext.push_back(tmp[j]);
+				}
+				if (clearText.length() % 8 != 0) {
+					int tmp1 = clearText.length() / 8 * 8;
+					int tmp2 = clearText.length() - tmp1;
+					memset(inputText, 0, 8);
+					memcpy(inputText, clearText.c_str() + tmp1, tmp2);
+					// 加密函数    
+					DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
+					memcpy(tmp, outputText, 8);
+					for (int j = 0; j < 8; j++)
+						vecCiphertext.push_back(tmp[j]);
+				}
+				cipherText.clear();
+				cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());
+				return cipherText;
+			}
+			/**
+			 * @brief des解密
+			 * @param cipherText
+			 * @param key
+			 * @return
+			 */
+			inline std::string des_decrypt(std::string const& cipherText, std::string const& key) {
+				std::string clearText; // 明文    
 
-			DES_cblock keyEncrypt;
-			memset(keyEncrypt, 0, 8);
+				DES_cblock keyEncrypt;
+				memset(keyEncrypt, 0, 8);
 
-			if (key.length() <= 8)
-				memcpy(keyEncrypt, key.c_str(), key.length());
-			else
-				memcpy(keyEncrypt, key.c_str(), 8);
+				if (key.length() <= 8)
+					memcpy(keyEncrypt, key.c_str(), key.length());
+				else
+					memcpy(keyEncrypt, key.c_str(), 8);
 
-			DES_key_schedule keySchedule;
-			DES_set_key_unchecked(&keyEncrypt, &keySchedule);
+				DES_key_schedule keySchedule;
+				DES_set_key_unchecked(&keyEncrypt, &keySchedule);
 
-			const_DES_cblock inputText;
-			DES_cblock outputText;
-			std::vector<unsigned char> vecCleartext;
-			unsigned char tmp[8];
+				const_DES_cblock inputText;
+				DES_cblock outputText;
+				std::vector<unsigned char> vecCleartext;
+				unsigned char tmp[8];
 
-			for (int i = 0; i < cipherText.length() / 8; i++) {
-				memcpy(inputText, cipherText.c_str() + i * 8, 8);
-				DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
-				memcpy(tmp, outputText, 8);
+				for (int i = 0; i < cipherText.length() / 8; i++) {
+					memcpy(inputText, cipherText.c_str() + i * 8, 8);
+					DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
+					memcpy(tmp, outputText, 8);
 
-				for (int j = 0; j < 8; j++)
-					vecCleartext.push_back(tmp[j]);
-			}
+					for (int j = 0; j < 8; j++)
+						vecCleartext.push_back(tmp[j]);
+				}
 
-			if (cipherText.length() % 8 != 0) {
-				int tmp1 = cipherText.length() / 8 * 8;
-				int tmp2 = cipherText.length() - tmp1;
-				memset(inputText, 0, 8);
-				memcpy(inputText, cipherText.c_str() + tmp1, tmp2);
-				// 解密函数    
-				DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
-				memcpy(tmp, outputText, 8);
+				if (cipherText.length() % 8 != 0) {
+					int tmp1 = cipherText.length() / 8 * 8;
+					int tmp2 = cipherText.length() - tmp1;
+					memset(inputText, 0, 8);
+					memcpy(inputText, cipherText.c_str() + tmp1, tmp2);
+					// 解密函数    
+					DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
+					memcpy(tmp, outputText, 8);
 
-				for (int j = 0; j < 8; j++)
-					vecCleartext.push_back(tmp[j]);
-			}
+					for (int j = 0; j < 8; j++)
+						vecCleartext.push_back(tmp[j]);
+				}
 
-			clearText.clear();
-			clearText.assign(vecCleartext.begin(), vecCleartext.end());
+				clearText.clear();
+				clearText.assign(vecCleartext.begin(), vecCleartext.end());
 
-			return clearText;
-		}
-		/**
-		 * @brief 编码类型
-		 */
-		enum encode { ANSI = 1, UTF16_LE, UTF16_BE, UTF8_BOM, UTF8 };
-		/**
-		 * @brief
-		 * @param data
-		 * @param size
-		 * @return
-		 */
-		inline encode is_utf8_data(const uint8_t* data, size_t size) {
-			bool bAnsi = true;
-			uint8_t ch = 0x00;
-			int32_t nBytes = 0;
-			for (auto i = 0; i < size; i++) {
-				ch = *(data + i);
-				if ((ch & 0x80) != 0x00) {
-					bAnsi = false;
-				}
-				if (nBytes == 0) {
-					if (ch >= 0x80) {
-						if (ch >= 0xFC && ch <= 0xFD) {
-							nBytes = 6;
-						}
-						else if (ch >= 0xF8) {
-							nBytes = 5;
-						}
-						else if (ch >= 0xF0) {
-							nBytes = 4;
-						}
-						else if (ch >= 0xE0) {
-							nBytes = 3;
-						}
-						else if (ch >= 0xC0) {
-							nBytes = 2;
+				return clearText;
+			}
+			/**
+			 * @brief 编码类型
+			 */
+			enum encode { ANSI = 1, UTF16_LE, UTF16_BE, UTF8_BOM, UTF8 };
+			/**
+			 * @brief
+			 * @param data
+			 * @param size
+			 * @return
+			 */
+			inline encode is_utf8_data(const uint8_t* data, size_t size) {
+				bool bAnsi = true;
+				uint8_t ch = 0x00;
+				int32_t nBytes = 0;
+				for (auto i = 0; i < size; i++) {
+					ch = *(data + i);
+					if ((ch & 0x80) != 0x00) {
+						bAnsi = false;
+					}
+					if (nBytes == 0) {
+						if (ch >= 0x80) {
+							if (ch >= 0xFC && ch <= 0xFD) {
+								nBytes = 6;
+							}
+							else if (ch >= 0xF8) {
+								nBytes = 5;
+							}
+							else if (ch >= 0xF0) {
+								nBytes = 4;
+							}
+							else if (ch >= 0xE0) {
+								nBytes = 3;
+							}
+							else if (ch >= 0xC0) {
+								nBytes = 2;
+							}
+							else {
+								return encode::ANSI;
+							}
+							nBytes--;
 						}
-						else {
+					}
+					else {
+						if ((ch & 0xC0) != 0x80) {
 							return encode::ANSI;
 						}
 						nBytes--;
 					}
 				}
+				if (nBytes > 0 || bAnsi) {
+					return encode::ANSI;
+				}
+				return encode::UTF8;
+			}
+			/**
+			 * @brief
+			 * @param data
+			 * @param size
+			 * @return
+			 */
+			inline encode detect_encode(const uint8_t* data, size_t size) {
+				if (size > 2 && data[0] == 0xFF && data[1] == 0xFE) {
+					return encode::UTF16_LE;
+				}
+				else if (size > 2 && data[0] == 0xFE && data[1] == 0xFF) {
+					return encode::UTF16_BE;
+				}
+				else if (size > 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) {
+					return encode::UTF8_BOM;
+				}
 				else {
-					if ((ch & 0xC0) != 0x80) {
-						return encode::ANSI;
-					}
-					nBytes--;
+					return is_utf8_data(data, size);
 				}
 			}
-			if (nBytes > 0 || bAnsi) {
-				return encode::ANSI;
-			}
-			return encode::UTF8;
-		}
-		/**
+			/**
 		 * @brief
-		 * @param data
-		 * @param size
+		 * @param str
 		 * @return
 		 */
-		inline encode detect_encode(const uint8_t* data, size_t size) {
-			if (size > 2 && data[0] == 0xFF && data[1] == 0xFE) {
-				return encode::UTF16_LE;
-			}
-			else if (size > 2 && data[0] == 0xFE && data[1] == 0xFF) {
-				return encode::UTF16_BE;
-			}
-			else if (size > 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) {
-				return encode::UTF8_BOM;
-			}
-			else {
-				return is_utf8_data(data, size);
-			}
-		}
-		/**
-	 * @brief
-	 * @param str
-	 * @return
-	 */
-		inline std::wstring gbk_to_unicode(const std::string& str) {
-			std::wstring result;
-			std::mbstate_t state{ };
-			const char* src = str.data();
-			size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
-			if (len != static_cast<size_t>(-1)) {
-				std::unique_ptr<wchar_t[]> buff(new wchar_t[len + 1]);
-				len = std::mbsrtowcs(buff.get(), &src, len, &state);
+			inline std::wstring gbk_to_unicode(const std::string& str) {
+				std::wstring result;
+				std::mbstate_t state{ };
+				const char* src = str.data();
+				size_t len = std::mbsrtowcs(nullptr, &src, 0, &state);
 				if (len != static_cast<size_t>(-1)) {
-					result.assign(buff.get(), len);
+					std::unique_ptr<wchar_t[]> buff(new wchar_t[len + 1]);
+					len = std::mbsrtowcs(buff.get(), &src, len, &state);
+					if (len != static_cast<size_t>(-1)) {
+						result.assign(buff.get(), len);
+					}
 				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief
-		 * @param wstr
-		 * @return
-		 */
-		inline std::string unicode_to_gbk(std::wstring wstr) {
-			std::string result;
-			std::mbstate_t state{ };
-			const wchar_t* src = wstr.data();
-			size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
-			if (len != static_cast<size_t>(-1)) {
-				std::unique_ptr<char[]> buff(new char[len + 1]);
-				len = std::wcsrtombs(buff.get(), &src, len, &state);
+			/**
+			 * @brief
+			 * @param wstr
+			 * @return
+			 */
+			inline std::string unicode_to_gbk(std::wstring wstr) {
+				std::string result;
+				std::mbstate_t state{ };
+				const wchar_t* src = wstr.data();
+				size_t len = std::wcsrtombs(nullptr, &src, 0, &state);
 				if (len != static_cast<size_t>(-1)) {
-					result.assign(buff.get(), len);
+					std::unique_ptr<char[]> buff(new char[len + 1]);
+					len = std::wcsrtombs(buff.get(), &src, len, &state);
+					if (len != static_cast<size_t>(-1)) {
+						result.assign(buff.get(), len);
+					}
 				}
-			}
-			return result;
-		}
-		/**
-		 * @brief OK
-		 * @param wstr
-		 * @return
-		 */
-		inline std::string unicode_to_utf8(const std::wstring& wstr) {
-			try {
-				std::wstring_convert<std::codecvt_utf8<wchar_t>> wcv;
-				return wcv.to_bytes(wstr);
-			}
-			catch (...) {}
-			return "";
-		}
-		/**
-		 * @brief
-		 * @param str
-		 * @return
-		 */
-		inline std::wstring utf8_to_unicode(const std::string& str) {
-			try {
-				std::wstring_convert<std::codecvt_utf8<wchar_t>> wcv;
-				return wcv.from_bytes(str);
-			}
-			catch (...) {}
-			return L"";
-		}
-		/**
-		* @brief
-		* @param str
-		* @return
-		*/
-		inline std::string utf8_to_gbk(const std::string& str) {
-			return unicode_to_gbk(utf8_to_unicode(str));
-		}
-		/**
-		 * @brief
-		 * @param str
-		 * @return
-		 */
-		inline std::string gbk_to_utf8(const std::string& str) {
-			return unicode_to_utf8(gbk_to_unicode(str));
-		}
-		/**
-		 * @brief 转ut8
-		 * @param value
-		 * @return
-		 */
-		inline std::string to_utf8(std::string const& value) {
-			std::string result = value;
-			encode type = detect_encode((std::uint8_t*)result.data(), result.size());
-			if (encode::ANSI == type) {
-				return gbk_to_utf8(result);
-			}
-			else if (encode::UTF16_LE == type) {
 				return result;
 			}
-			else if (encode::UTF16_BE == type) {
-				return result;
+			/**
+			 * @brief OK
+			 * @param wstr
+			 * @return
+			 */
+			inline std::string unicode_to_utf8(const std::wstring& wstr) {
+				try {
+					std::wstring_convert<std::codecvt_utf8<wchar_t>> wcv;
+					return wcv.to_bytes(wstr);
+				}
+				catch (...) {}
+				return "";
 			}
-			else if (encode::UTF8_BOM == type) {
-				result.erase(0, 3);
+			/**
+			 * @brief
+			 * @param str
+			 * @return
+			 */
+			inline std::wstring utf8_to_unicode(const std::string& str) {
+				try {
+					std::wstring_convert<std::codecvt_utf8<wchar_t>> wcv;
+					return wcv.from_bytes(str);
+				}
+				catch (...) {}
+				return L"";
+			}
+			/**
+			* @brief
+			* @param str
+			* @return
+			*/
+			inline std::string utf8_to_gbk(const std::string& str) {
+				return unicode_to_gbk(utf8_to_unicode(str));
+			}
+			/**
+			 * @brief
+			 * @param str
+			 * @return
+			 */
+			inline std::string gbk_to_utf8(const std::string& str) {
+				return unicode_to_utf8(gbk_to_unicode(str));
+			}
+			/**
+			 * @brief 转ut8
+			 * @param value
+			 * @return
+			 */
+			inline std::string to_utf8(std::string const& value) {
+				std::string result = value;
+				encode type = detect_encode((std::uint8_t*)result.data(), result.size());
+				if (encode::ANSI == type) {
+					return gbk_to_utf8(result);
+				}
+				else if (encode::UTF16_LE == type) {
+					return result;
+				}
+				else if (encode::UTF16_BE == type) {
+					return result;
+				}
+				else if (encode::UTF8_BOM == type) {
+					result.erase(0, 3);
+					return result;
+				}
+				else if (encode::UTF8 == type) {
+					return result;
+				}
 				return result;
 			}
-			else if (encode::UTF8 == type) {
+			/**
+			 * @brief 转ut8BOM
+			 * @param value
+			 * @return
+			 */
+			inline std::string to_utf8_bom(std::string const& value) {
+				std::string result = to_utf8(value);
+				result.insert(0, 3, (std::uint8_t)0xEF);
+				result[1] = (std::uint8_t)0xBB;
+				result[2] = (std::uint8_t)0xBF;
 				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief 转ut8BOM
-		 * @param value
-		 * @return
-		 */
-		inline std::string to_utf8_bom(std::string const& value) {
-			std::string result = to_utf8(value);
-			result.insert(0, 3, (std::uint8_t)0xEF);
-			result[1] = (std::uint8_t)0xBB;
-			result[2] = (std::uint8_t)0xBF;
-			return result;
-		}
-		/**
-		 * @brief 转ansi
-		 * @param value
-		 * @return
-		 */
-		inline std::string to_ansi(std::string const& value) {
-			std::string result = value;
-			encode type = detect_encode((std::uint8_t*)result.data(), result.size());
-			if (encode::ANSI == type) {
+			/**
+			 * @brief 转ansi
+			 * @param value
+			 * @return
+			 */
+			inline std::string to_ansi(std::string const& value) {
+				std::string result = value;
+				encode type = detect_encode((std::uint8_t*)result.data(), result.size());
+				if (encode::ANSI == type) {
+					return result;
+				}
+				else if (encode::UTF16_LE == type) {
+					return result;
+				}
+				else if (encode::UTF16_BE == type) {
+					return result;
+				}
+				else if (encode::UTF8_BOM == type) {
+					result.erase(0, 3);
+					return utf8_to_gbk(result);
+				}
+				else if (encode::UTF8 == type) {
+					return utf8_to_gbk(result);
+				}
 				return result;
 			}
-			else if (encode::UTF16_LE == type) {
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::string to_dec_string(std::vector<std::uint8_t> const& value, std::string const& c) {
+				std::string result;
+				for (int i = 0; i < value.size(); ++i) {
+					if (1 + i == value.size()) {
+						result += std::to_string(value[i]);
+					}
+					else {
+						result += std::to_string(value[i]) + c;
+					}
+				}
 				return result;
 			}
-			else if (encode::UTF16_BE == type) {
+			/**
+			 * @brief
+			 * @tparam _Count
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			template<int _Count>
+			inline std::string to_dec_string(std::array<std::uint8_t, _Count> const& value, std::string const& c) {
+				return to_dec_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::string to_dec_string(std::string_view value, std::string const& c) {
+				return to_dec_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::string to_hex_string(std::vector<std::uint8_t> const& value, std::string const& c) {
+				std::string result;
+				for (int i = 0; i < value.size(); ++i) {
+					std::stringstream ioss;
+					std::string tmp;
+					ioss << std::hex << int(value[i]);
+					tmp = ioss.str();
+					if (tmp.size() == 1) {
+						tmp = "0" + tmp;
+					}
+					if (1 + i == value.size()) {
+						result += "0x" + tmp;
+					}
+					else {
+						result += "0x" + tmp + c;
+					}
+				}
 				return result;
 			}
-			else if (encode::UTF8_BOM == type) {
-				result.erase(0, 3);
-				return utf8_to_gbk(result);
-			}
-			else if (encode::UTF8 == type) {
-				return utf8_to_gbk(result);
-			}
-			return result;
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::string to_dec_string(std::vector<std::uint8_t> const& value, std::string const& c) {
-			std::string result;
-			for (int i = 0; i < value.size(); ++i) {
-				if (1 + i == value.size()) {
-					result += std::to_string(value[i]);
+			/**
+			 * @brief
+			 * @tparam _Count
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			template<int _Count>
+			inline std::string to_hex_string(std::array<std::uint8_t, _Count> const& value, std::string const& c) {
+				return to_hex_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param c
+			 * @return
+			 */
+			inline std::string to_hex_string(std::string_view value, std::string const& c) {
+				return to_hex_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
+			}
+			/**
+			 * @brief 随机数
+			 * @param min
+			 * @param max
+			 * @return
+			 */
+			inline int random(int min, int max) {
+				std::random_device r;
+				std::default_random_engine e1(r());
+				std::uniform_int_distribution<int> uniform_dist(min, max);
+				return uniform_dist(e1);
+			}
+			/**
+			 * @brief
+			 * @tparam _Type
+			 * @param values
+			 * @param c
+			 * @return
+			 */
+			template<typename _Type>
+			inline std::string join(std::vector<_Type> const& values, std::string const& c) {
+				std::vector<std::string> params;
+				for (auto it : values) {
+					params.push_back(std::to_string(it));
 				}
-				else {
-					result += std::to_string(value[i]) + c;
+				return join(params, c);
+			}
+			/**
+			 * @brief
+			 * @param values
+			 * @param c
+			 * @return
+			 */
+			template<>
+			inline std::string join<std::string>(std::vector<std::string> const& values, std::string const& c) {
+				return boost::join(values, c);
+			}
+			/**
+			 * @brief
+			 * @param values
+			 * @param c
+			 * @return
+			 */
+			template<>
+			inline std::string join<bool>(std::vector<bool>const& values, std::string const& c) {
+				std::vector<std::string> params;
+				for (auto it : values) {
+					params.push_back(it ? "true" : "false");
 				}
-			}
-			return result;
-		}
-		/**
-		 * @brief
-		 * @tparam _Count
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		template<int _Count>
-		inline std::string to_dec_string(std::array<std::uint8_t, _Count> const& value, std::string const& c) {
-			return to_dec_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::string to_dec_string(std::string_view value, std::string const& c) {
-			return to_dec_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::string to_hex_string(std::vector<std::uint8_t> const& value, std::string const& c) {
-			std::string result;
-			for (int i = 0; i < value.size(); ++i) {
-				std::stringstream ioss;
-				std::string tmp;
-				ioss << std::hex << int(value[i]);
-				tmp = ioss.str();
-				if (tmp.size() == 1) {
-					tmp = "0" + tmp;
-				}
-				if (1 + i == value.size()) {
-					result += "0x" + tmp;
+				return join(params, c);
+			}
+			/**
+			 * @brief
+			 * @param values
+			 * @param c
+			 * @return
+			 */
+			template<>
+			inline std::string join<datetime>(std::vector<datetime> const& values, std::string const& c) {
+				std::vector<std::string> params;
+				for (auto it : values) {
+					params.push_back(it.to_string());
 				}
-				else {
-					result += "0x" + tmp + c;
+				return join(params, c);
+			}
+			/**
+			 * @brief
+			 * @param value
+			 * @param count
+			 * @param c
+			 * @return
+			 */
+			inline std::string join(std::string const& value, int count, std::string const& c) {
+				std::vector<std::string> vec;
+				vec.assign(count, value);
+				return join(vec, c);
+			}
+			inline auto split_http_form(std::string const& value, std::pair<std::string, std::string> const& pattern = { "&","=" }) {
+				std::map<std::string, std::string> result;
+				auto itemValues = split(value, pattern.first);
+				for (auto itemValue : itemValues) {
+					auto items = split(itemValue, pattern.second);
+					if (items.size() == 2) {
+						std::string key = http::url_encode(items[0]);
+						std::string value = http::url_decode(items[1]);
+						result[key] = value;
+					}
 				}
+				return result;
 			}
-			return result;
-		}
-		/**
-		 * @brief
-		 * @tparam _Count
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		template<int _Count>
-		inline std::string to_hex_string(std::array<std::uint8_t, _Count> const& value, std::string const& c) {
-			return to_hex_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param c
-		 * @return
-		 */
-		inline std::string to_hex_string(std::string_view value, std::string const& c) {
-			return to_hex_string(std::vector<std::uint8_t>(value.begin(), value.end()), c);
-		}
-		/**
-		 * @brief 随机数
-		 * @param min
-		 * @param max
-		 * @return
-		 */
-		inline int random(int min, int max) {
-			std::random_device r;
-			std::default_random_engine e1(r());
-			std::uniform_int_distribution<int> uniform_dist(min, max);
-			return uniform_dist(e1);
-		}
-		/**
-		 * @brief
-		 * @tparam _Type
-		 * @param values
-		 * @param c
-		 * @return
-		 */
-		template<typename _Type>
-		inline std::string join(std::vector<_Type> const& values, std::string const& c) {
-			std::vector<std::string> params;
-			for (auto it : values) {
-				params.push_back(std::to_string(it));
-			}
-			return join(params, c);
-		}
-		/**
-		 * @brief
-		 * @param values
-		 * @param c
-		 * @return
-		 */
-		template<>
-		inline std::string join<std::string>(std::vector<std::string> const& values, std::string const& c) {
-			return boost::join(values, c);
-		}
-		/**
-		 * @brief
-		 * @param values
-		 * @param c
-		 * @return
-		 */
-		template<>
-		inline std::string join<bool>(std::vector<bool>const& values, std::string const& c) {
-			std::vector<std::string> params;
-			for (auto it : values) {
-				params.push_back(it ? "true" : "false");
-			}
-			return join(params, c);
-		}
-		/**
-		 * @brief
-		 * @param values
-		 * @param c
-		 * @return
-		 */
-		template<>
-		inline std::string join<datetime>(std::vector<datetime> const& values, std::string const& c) {
-			std::vector<std::string> params;
-			for (auto it : values) {
-				params.push_back(it.to_string());
-			}
-			return join(params, c);
-		}
-		/**
-		 * @brief
-		 * @param value
-		 * @param count
-		 * @param c
-		 * @return
-		 */
-		inline std::string join(std::string const& value, int count, std::string const& c) {
-			std::vector<std::string> vec;
-			vec.assign(count, value);
-			return join(vec, c);
-		}
-		inline auto split_http_form(std::string const& value, std::pair<std::string, std::string> const& pattern = { "&","=" }) {
-			std::map<std::string, std::string> result;
-			auto itemValues = split(value, pattern.first);
-			for (auto itemValue : itemValues) {
-				auto items = split(itemValue, pattern.second);
-				if (items.size() == 2) {
-					std::string key = http::url_encode(items[0]);
-					std::string value = http::url_decode(items[1]);
-					result[key] = value;
-				}
-			}
-			return result;
-		}
-		/**
-		 * @brief
-		 * @tparam _Fn
-		 * @tparam _Tuple
-		 * @tparam I
-		 */
-		template<typename _Fn, typename _Tuple, std::size_t I>
-		struct for_each_impl {
-			static void invoke(_Tuple const& tuple, _Fn&& fn) {
-				fn(std::get<I - 1>(tuple));
-				for_each_impl<_Fn, _Tuple, I - 1>::invoke(tuple, std::forward<_Fn>(fn));
-			}
-		};
-		/**
-		 * @brief
-		 * @tparam _Fn
-		 * @tparam _Tuple
-		 */
-		template<typename _Fn, typename _Tuple>
-		struct for_each_impl<_Fn, _Tuple, 1> {
-			static void invoke(_Tuple const& tuple, _Fn&& fn) {
-				fn(std::get<0>(tuple));
-			}
-		};
-		/**
-		 * @brief
-		 * @tparam _Fn
-		 * @tparam ..._Args
-		 * @param tuple
-		 * @param fn
-		 */
-		template<typename _Fn, typename ..._Args>
-		inline void for_each(std::tuple<_Args...>const& tuple, _Fn&& fn) {
-			for_each_impl<_Fn, std::tuple<_Args...>, sizeof...(_Args)>::invoke(tuple, std::forward<_Fn>(fn));
-		}
-		/**
-		* @brief
-		* @tparam _Fn
-		* @tparam _Tuple
-		* @tparam I
-		*/
-		template<typename _Fn, typename _Tuple, std::size_t I>
-		struct for_each_reference_impl {
-			static void invoke(_Tuple& tuple, _Fn&& fn) {
-				fn(std::get<I - 1>(tuple));
-				for_each_reference_impl<_Fn, _Tuple, I - 1>::invoke(tuple, std::forward<_Fn>(fn));
-			}
-		};
-		/**
-		 * @brief
-		 * @tparam _Fn
-		 * @tparam _Tuple
-		 */
-		template<typename _Fn, typename _Tuple>
-		struct for_each_reference_impl<_Fn, _Tuple, 1> {
-			static void invoke(_Tuple& tuple, _Fn&& fn) {
-				fn(std::get<0>(tuple));
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam _Tuple
+			 * @tparam I
+			 */
+			template<typename _Fn, typename _Tuple, std::size_t I>
+			struct for_each_impl {
+				static void invoke(_Tuple const& tuple, _Fn&& fn) {
+					fn(std::get<I - 1>(tuple));
+					for_each_impl<_Fn, _Tuple, I - 1>::invoke(tuple, std::forward<_Fn>(fn));
+				}
+			};
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam _Tuple
+			 */
+			template<typename _Fn, typename _Tuple>
+			struct for_each_impl<_Fn, _Tuple, 1> {
+				static void invoke(_Tuple const& tuple, _Fn&& fn) {
+					fn(std::get<0>(tuple));
+				}
+			};
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam ..._Args
+			 * @param tuple
+			 * @param fn
+			 */
+			template<typename _Fn, typename ..._Args>
+			inline void for_each(std::tuple<_Args...>const& tuple, _Fn&& fn) {
+				for_each_impl<_Fn, std::tuple<_Args...>, sizeof...(_Args)>::invoke(tuple, std::forward<_Fn>(fn));
+			}
+			/**
+			* @brief
+			* @tparam _Fn
+			* @tparam _Tuple
+			* @tparam I
+			*/
+			template<typename _Fn, typename _Tuple, std::size_t I>
+			struct for_each_reference_impl {
+				static void invoke(_Tuple& tuple, _Fn&& fn) {
+					fn(std::get<I - 1>(tuple));
+					for_each_reference_impl<_Fn, _Tuple, I - 1>::invoke(tuple, std::forward<_Fn>(fn));
+				}
+			};
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam _Tuple
+			 */
+			template<typename _Fn, typename _Tuple>
+			struct for_each_reference_impl<_Fn, _Tuple, 1> {
+				static void invoke(_Tuple& tuple, _Fn&& fn) {
+					fn(std::get<0>(tuple));
+				}
+			};
+			/**
+			 * @brief
+			 * @tparam _Fn
+			 * @tparam ..._Args
+			 * @param tuple
+			 * @param fn
+			 */
+			template<typename _Fn, typename ..._Args>
+			inline void for_each_reference(std::tuple<_Args...>& tuple, _Fn&& fn) {
+				for_each_reference_impl<_Fn, std::tuple<_Args...>, sizeof...(_Args)>::invoke(tuple, std::forward<_Fn>(fn));
+			}
+			/**
+			 * @brief
+			 * @tparam _Type
+			 */
+			template<typename _Type>
+			struct traits_prop_type {};
+			/**
+			 * @brief
+			 * @tparam _PropType
+			 * @tparam _Type
+			 */
+			template<typename _PropType, typename _Type>
+			struct traits_prop_type<_PropType _Type::*> {
+				using prop_type = _PropType;
+			};
+			/**
+			 * @brief 不区分大小写字符串比较
+			 * @param a
+			 * @param b
+			 * @return
+			 */
+			inline bool case_insensitive_compare(const std::string& a, const std::string& b) {
+				return std::equal(a.begin(), a.end(), b.begin(), b.end(),
+					[](char a_ch, char b_ch) {
+						return std::tolower(static_cast<unsigned char>(a_ch)) == std::tolower(static_cast<unsigned char>(b_ch));
+					});
+			}
+			/**
+			 * @brief 获取地址
+			 * @tparam _Ret
+			 * @tparam _PropPtr
+			 * @param ptr
+			 * @return
+			 */
+			template<typename _Ret, typename _Prop>
+			inline _Ret pointer_cast(_Prop ptr) {
+				return *static_cast<_Ret*>(static_cast<void*>(&ptr));
+			}
+			/**
+			 * @brief
+			 * @tparam _Ret
+			 * @tparam _PropPtr
+			 * @param ptr
+			 * @return
+			 */
+			template<typename _Ret, typename _Prop>
+			inline _Ret pointer_obj_cast(_Prop& ptr) {
+				return reinterpret_cast<_Ret>(static_cast<void*>(&ptr));
+			}
+			/**
+			 * @brief 通过偏移地址获取属性名称
+			 * @tparam _Type
+			 * @param offset
+			 * @return
+			 */
+			template<typename _Type>
+			inline std::string property_sql_name(int offset) {
+				for (auto& it : rttr::type::get<_Type>().get_properties()) {
+					rttr::variant var = it.get_metadata("Offset");
+					if (var.is_type<int>() && var.get_value<int>() == offset) {
+						rttr::variant prop = it.get_metadata("Sql");
+						if (prop.is_type<std::string>()) {
+							return prop.get_value<std::string>();
+						}
+						else {
+							return it.get_name().data();
+						}
+					}
+				}
+				return {};
 			}
-		};
-		/**
-		 * @brief
-		 * @tparam _Fn
-		 * @tparam ..._Args
-		 * @param tuple
-		 * @param fn
-		 */
-		template<typename _Fn, typename ..._Args>
-		inline void for_each_reference(std::tuple<_Args...>& tuple, _Fn&& fn) {
-			for_each_reference_impl<_Fn, std::tuple<_Args...>, sizeof...(_Args)>::invoke(tuple, std::forward<_Fn>(fn));
-		}
-		/**
-		 * @brief
-		 * @tparam _Type
-		 */
-		template<typename _Type>
-		struct traits_prop_type {};
-		/**
-		 * @brief
-		 * @tparam _PropType
-		 * @tparam _Type
-		 */
-		template<typename _PropType, typename _Type>
-		struct traits_prop_type<_PropType _Type::*> {
-			using prop_type = _PropType;
-		};
-		/**
-		 * @brief 不区分大小写字符串比较
-		 * @param a
-		 * @param b
-		 * @return
-		 */
-		inline bool case_insensitive_compare(const std::string& a, const std::string& b) {
-			return std::equal(a.begin(), a.end(), b.begin(), b.end(),
-				[](char a_ch, char b_ch) {
-					return std::tolower(static_cast<unsigned char>(a_ch)) == std::tolower(static_cast<unsigned char>(b_ch));
-				});
-		}
-		/**
-		 * @brief 获取地址
-		 * @tparam _Ret
-		 * @tparam _PropPtr
-		 * @param ptr
-		 * @return
-		 */
-		template<typename _Ret, typename _Prop>
-		inline _Ret pointer_cast(_Prop ptr) {
-			return *static_cast<_Ret*>(static_cast<void*>(&ptr));
-		}
-		/**
-		 * @brief
-		 * @tparam _Ret
-		 * @tparam _PropPtr
-		 * @param ptr
-		 * @return
-		 */
-		template<typename _Ret, typename _Prop>
-		inline _Ret pointer_obj_cast(_Prop& ptr) {
-			return reinterpret_cast<_Ret>(static_cast<void*>(&ptr));
-		}
-		/**
-		 * @brief 通过偏移地址获取属性名称
-		 * @tparam _Type
-		 * @param offset
-		 * @return
-		 */
-		template<typename _Type>
-		inline std::string property_sql_name(int offset) {
-			for (auto& it : rttr::type::get<_Type>().get_properties()) {
-				rttr::variant var = it.get_metadata("Offset");
-				if (var.is_type<int>() && var.get_value<int>() == offset) {
+			/**
+			 * @brief 获取变量类型
+			 * @tparam _Type
+			 * @param name
+			 * @return
+			 */
+			template<typename _Type>
+			inline rttr::type property_type(std::string const& name) {
+				for (auto& it : rttr::type::get<_Type>().get_properties()) {
 					rttr::variant prop = it.get_metadata("Sql");
-					if (prop.is_type<std::string>()) {
-						return prop.get_value<std::string>();
-					}
-					else {
-						return it.get_name().data();
+					if ((prop.is_type<std::string>() && prop.get_value<std::string>() == name) || it.get_name().data() == name) {
+						return it.get_type();
 					}
 				}
-			}
-			return {};
-		}
-		/**
-		 * @brief 获取变量类型
-		 * @tparam _Type
-		 * @param name
-		 * @return
-		 */
-		template<typename _Type>
-		inline rttr::type property_type(std::string const& name) {
-			for (auto& it : rttr::type::get<_Type>().get_properties()) {
-				rttr::variant prop = it.get_metadata("Sql");
-				if ((prop.is_type<std::string>() && prop.get_value<std::string>() == name) || it.get_name().data() == name) {
-					return it.get_type();
+				return rttr::type::get<void>();
+			}
+			/**
+			 * @brief 大端序
+			 * @return
+			 */
+			inline bool is_big_endian() {
+				short tmp = 1;
+				char c = *(char*)&tmp;
+				return c != 1;
+			}
+			/**
+			 * @brief 字节序转换
+			 * @param value
+			 * @return
+			 */
+			inline std::uint8_t swap_endian(std::uint8_t value) {
+				return (value >> 4) | (value << 4);
+			}
+			/**
+			 * @brief 字节序转换
+			 * @param values
+			 * @return
+			 */
+			inline std::vector<std::uint8_t> swap_endian(std::vector<std::uint8_t> const& values) {
+				std::vector<std::uint8_t> result;
+				for (auto const& it : values) {
+					result.push_back(swap_endian(it));
 				}
+				return result;
 			}
-			return rttr::type::get<void>();
-		}
-		/**
-		 * @brief 大端序
-		 * @return
-		 */
-		inline bool is_big_endian() {
-			short tmp = 1;
-			char c = *(char*)&tmp;
-			return c != 1;
-		}
-		/**
-		 * @brief 字节序转换
-		 * @param value
-		 * @return
-		 */
-		inline std::uint8_t swap_endian(std::uint8_t value) {
-			return (value >> 4) | (value << 4);
-		}
-		/**
-		 * @brief 字节序转换
-		 * @param values
-		 * @return
-		 */
-		inline std::vector<std::uint8_t> swap_endian(std::vector<std::uint8_t> const& values) {
-			std::vector<std::uint8_t> result;
-			for (auto const& it : values) {
-				result.push_back(swap_endian(it));
-			}
-			return result;
-		}
-		/**
-		 * @brief 设置当前进城运行路径
-		 * @param filepath
-		 */
-		inline void set_current_directory(std::filesystem::path const& path) {
-			std::filesystem::current_path(path);
-		}
-		/**
-		 * @brief 执行文件路径
-		 * @return
-		 */
-		inline std::filesystem::path execute_file_path() {
-			return std::filesystem::current_path();
+			/**
+			 * @brief 设置当前进城运行路径
+			 * @param filepath
+			 */
+			inline void set_current_directory(std::filesystem::path const& path) {
+				std::filesystem::current_path(path);
+			}
+			/**
+			 * @brief 执行文件路径
+			 * @return
+			 */
+			inline std::filesystem::path execute_file_path() {
+				return std::filesystem::current_path();
+			}
+			/**
+			 * @brief 程序运行时间
+			*/
+			class run_time {
+			public:
+				void start() {
+					start_ = std::chrono::high_resolution_clock::now();
+				}
+				void stop() {
+					end_ = std::chrono::high_resolution_clock::now();
+				}
+				double time() {
+					std::chrono::duration<long long, std::micro> duration = std::chrono::duration_cast<std::chrono::microseconds>(end_ - start_);
+					return double(duration.count()) / 1000.00;
+				}
+			private:
+				std::chrono::time_point<std::chrono::high_resolution_clock> start_;
+				std::chrono::time_point<std::chrono::high_resolution_clock> end_;
+			};
 		}
-		/**
-		 * @brief 程序运行时间
-		*/
-		class run_time {
-		public:
-			void start() {
-				start_ = std::chrono::high_resolution_clock::now();
-			}
-			void stop() {
-				end_ = std::chrono::high_resolution_clock::now();
-			}
-			double time() {
-				std::chrono::duration<long long, std::micro> duration = std::chrono::duration_cast<std::chrono::microseconds>(end_ - start_);
-				return double(duration.count()) / 1000.00;
-			}
-		private:
-			std::chrono::time_point<std::chrono::high_resolution_clock> start_;
-			std::chrono::time_point<std::chrono::high_resolution_clock> end_;
-		};
 	}
 }

File diff suppressed because it is too large
+ 378 - 602
robot/robotics/web_service.hpp


Some files were not shown because too many files changed in this diff