greenJson_C++_Lib 之九:宏泛型编程实现JSON类

利用符号 ”##“ 和 ”#“ 进行宏泛型编码,结合C++虚函数指针表格,建立JSON类的反射机制,并进行JSON处理。
在这里插入图片描述

	//<Part.九> JSON类声明宏定义

	//所有的成员指针的数据内存都在堆上

	//成员函数访问命令
	enum FuncAccessCommand {
		FuncAccessCommand_SetMemberByKeyValue	= 1,//设置值到成员,主要用于原子数据类型的设置
		FuncAccessCommand_GetKeyValueByMember	= 2,//获取格式字符串
		FuncAccessCommand_GetMemberFieldInfo	= 3,//获取成员变量
		FuncAccessCommand_SetMemberByJsonObject	= 4,//设置成员变量,可以用于JSON对象的直接设置,或者数组中对象的直接设置
		FuncAccessCommand_InitMemberValue		= 5//初始化成员
	};

//声明JSON类,基类统一为jsonObjectBaseClass
#define JSON_CLASS_DECLARE_BEGIN(className) \
	class className : public jsonObjectBaseClass {\
		public: \
			/*构造函数*/\
			className(){\
				if(className::smMemberMetaInfo.isNull()){\
					className::initClassMemberMeta(this); \
				}\
				initObject();\
			}\
			/*拷贝构造函数*/\
			className(const className & e){\
				this->cloneObject(e);\
			}\
			/*解析构造函数*/\
			className(const string& json){\
				if(className::smMemberMetaInfo.isNull()){\
					className::initClassMemberMeta(this); \
				}\
				this->toObject(json);\
			}\
			/*赋值函数*/\
			className & operator=(const className& e) {\
				this->cloneObject(e);\
				return *this;\
			}\
			/*赋值函数*/\
			className & operator=(const string& json) {\
				this->toObject(json);\
				return *this;\
			}\
			virtual ~className(){\
			}\
			/*定义成员函数指针类型--如果key为空则表示要获取格式化字符串;否则表示要使用键进行设置*/\
			typedef bool (className::* funcAccessById)(jsonObjectMemberInfo & memInfo, FuncAccessCommand method, string * strKvPair, jsonStringParser * kvp);\
		private:\
			/*注册器调用,生成各成员的操作入口*/\
			static void initClassMemberMeta(className * pClsObj);\
			static autoPointer<map<string, jsonObjectMemberInfo> > smMemberMetaInfo;\
			/*各成员的声明顺序,用于toString时*/\
			static autoPointer<vector<string> > svMemberMetaOrder;\
			/*成员的数量=类大小-减内存回收器大小-虚函数表格指针大小*/\
			static int getMemberCount(){\
				return (sizeof(className) - sizeof(memoryGarbageCollector) - sizeof(greenInt*)) / sizeof(greenInt*);\
			}\
			/*内存回收器*/\
			memoryGarbageCollector memGarbage;/*对象各自管理申请的内存*/\
			friend class Register##className;
	
//声明类的指针数据成员,其可以进行set/get操作。
#define JSON_CLASS_DECLARE_MEMBER(TYPE, ID) \
		public:\
			/*定义成员变量*/\
			TYPE * ID;\
			/*设置成员值,入参指针所指内存将交接给JSON对象*/\
			void handOver_##ID(const TYPE * pSrc){\
				set##ID(pSrc, MemoryCtrlType_Handover);\
			}\
			/*设置成员值,入参指针所指内存给JSON对象引用*/\
			void reference_##ID(const TYPE * pSrc){\
				set##ID(pSrc, MemoryCtrlType_Reference);\
			}\
			/*设置成员值,入参指针所指内存将被JSON对象复制一份*/\
			void deepCopy_##ID(const TYPE * pSrc){\
				set##ID(pSrc, MemoryCtrlType_DeepCopy);\
			}\
			/*设置成员值*/\
			void setValue_##ID(const TYPE & ID){\
				this->ID = new TYPE(ID);\
				memGarbage.add(this->ID);\
			} \
			/*设置成员指针为NULL*/\
			void setNull_##ID(){\
				this->ID = NULL;\
			} \
			/*获取成员指针值*/\
			TYPE * get_##ID(){\
				return this->ID;\
			}\
			/*获取成员值*/\
			TYPE & getValue_##ID() {\
				assert(this->ID);\
				return *this->ID;\
			}\
			/*判断成员指针是否为NULL*/\
			bool isNull_##ID(){\
				return this->ID == NULL;\
			} \
		private:\
			void set##ID(const TYPE * pSrc, MemoryCtrlType ptrCtrlType/*接管外部指针内存的方式*/){\
				if(NULL == pSrc){\
					this->ID = NULL;\
				}else{\
					if(ptrCtrlType == MemoryCtrlType_DeepCopy){\
						this->ID = (TYPE *)::cloneObject(pSrc);\
						memGarbage.add(this->ID);\
					}\
					else {\
						this->ID = (TYPE*)pSrc;\
						if(ptrCtrlType == MemoryCtrlType_Handover){\
							memGarbage.add(this->ID);\
						}\
					}\
				}\
			} \
			static void sSet##ID(jsonObjectMemberInfo & memInfo, const TYPE * pSrc){\
				TYPE ** ppID/*=&ID*/ = memInfo.getMemPtrAddr<TYPE>();\
				TYPE * asID = (TYPE *)*ppID;\
				if(NULL == pSrc){\
					*ppID = NULL;\
				}else{\
					memoryGarbageCollector & mg = memInfo.getMemGarbage(); \
					if(memInfo.inputDataCtrlType == MemoryCtrlType_DeepCopy){\
						*ppID = asID = (TYPE *)::cloneObject(pSrc);\
						mg.add(asID);\
					}\
					else {\
						*ppID = asID = (TYPE*)pSrc;\
						/*接管外部指针内存的方式*/\
						if(memInfo.inputDataCtrlType == MemoryCtrlType_Handover){\
							mg.add(asID);\
						}\
					}\
				}\
			} \
			/*定义将成员变量转字符串的virtual方法:注意由于不同编译器对直接使用虚函数表格调用虚函数支持不同,在此不要使用this指针。*/\
			virtual bool access##ID(jsonObjectMemberInfo & memInfo, FuncAccessCommand method, string * strKvPair, jsonStringParser * kvp){ \
				TYPE ** ppID/*=&ID*/ = memInfo.getMemPtrAddr<TYPE>();\
				TYPE * asID = (TYPE *)*ppID;\
				if(FuncAccessCommand_GetKeyValueByMember == method){\
					assert(strKvPair);\
					string value;\
					if (NULL == asID) {\
						value = "null";\
					}\
					else {\
						data2String(value, *asID);\
					}\
					/*json的key:value*/\
					string key = #ID;\
					*strKvPair = "\"" + key + "\":" + value;\
					return true;\
				}\
				if (FuncAccessCommand_SetMemberByKeyValue == method) {\
					assert(kvp && kvp->getCurrentKeyValue());\
					/*根据JSON字符串生成值*/\
					string& value = kvp->getCurrentKeyValue()->value;\
					if(value == JSON_NULL_STRING){\
						*ppID = NULL;\
						return true;\
					}\
					string2DataPtr(asID, *kvp);\
					*ppID = asID;\
					memoryGarbageCollector & mg = memInfo.getMemGarbage(); \
					mg.add(asID);\
					return true;\
				}\
				if (FuncAccessCommand_SetMemberByJsonObject == method) {\
					/*将pSrc设置到ID*/\
					TYPE * pSrc = (TYPE *)memInfo.ptrInputData;\
					sSet##ID(memInfo, pSrc);\
					return true;\
				}\
				if (FuncAccessCommand_InitMemberValue == method) {\
					*ppID = NULL;\
					return true;\
				}\
				if (FuncAccessCommand_GetMemberFieldInfo == method) {\
					/*只返回公共信息*/\
					memInfo.metaName = #ID; \
					memInfo.metaType = #TYPE;\
					memInfo.metaCate = MemberDefineCategory_Single;\
					return true;\
				}\
				return false;\
			}							

//声明类的指针数组数据成员,可以使用单个、成组的方式增加元素
#define JSON_CLASS_DECLARE_MEMBER_ARRAY(TYPE, ID) \
		public:\
			/*定义成员变量*/\
			vector<TYPE *> * ID;\
			/*设置成员值,入参指针所指内存将交接给JSON对象*/\
			void handOver_##ID(const TYPE * e){\
				add_##ID(e, MemoryCtrlType_Handover);\
			}\
			/*设置成员值,入参指针所指内存给JSON对象引用*/\
			void reference_##ID(const TYPE * e){\
				add_##ID(e, MemoryCtrlType_Reference);\
			}\
			/*设置成员值,入参指针所指内存将被JSON对象复制一份*/\
			void deepCopy_##ID(const TYPE * e){\
				add_##ID(e, MemoryCtrlType_DeepCopy);\
			}\
			/*往成员数组中追加元素*/\
			void addValue_##ID(const TYPE & e) {\
				TYPE * p = new TYPE(e);\
				add_##ID(p, MemoryCtrlType_Handover);\
			} \
			/*往成员数组中追加元素,其内指针所指内存将交接给JSON对象*/\
			void handOver_##ID(const vector<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_Handover);\
			}\
			/*往成员数组中追加元素,其内指针所指内存给JSON对象引用*/\
			void reference_##ID(const vector<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_Reference);\
			}\
			/*往成员数组中追加元素,其内指针所指内存被JSON对象复制一份*/\
			void deepCopy_##ID(const vector<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_DeepCopy);\
			}\
			/*往成员数组中追加元素*/\
			void addValue_##ID(const vector<TYPE> & arry){ \
				for(unsigned int i = 0; i < arry.size(); ++i){\
					const TYPE & t = arry[i];\
					addValue_##ID(t);\
				}\
			} \
			/*往成员数组中追加元素,其内指针所指内存将交接给JSON对象*/\
			void handOver_##ID(const list<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_Handover);\
			}\
			/*往成员数组中追加元素,其内指针所指内存给JSON对象引用*/\
			void reference_##ID(const list<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_Reference);\
			}\
			/*往成员数组中追加元素,其内指针所指内存被JSON对象复制一份*/\
			void deepCopy_##ID(const list<TYPE *> & arry){\
				add_##ID(arry, MemoryCtrlType_DeepCopy);\
			}\
			/*往成员数组中追加元素*/\
			void addValue_##ID(const list<TYPE> & arry){\
				for(list<TYPE>::const_iterator it = arry.begin(); it != arry.end(); ++it){\
					const TYPE & t = *it;\
					addValue_##ID(t);\
				}\
			} \
			/*获取成员数组中元素的指针*/\
			TYPE * getElement_##ID(unsigned int i){ \
				assert(this->ID && 0 <= i && i < this->ID->size()); \
				return (*this->ID)[i];\
			}\
			/*获取成员数组中元素*/\
			TYPE & getElementValue_##ID(unsigned int i){ \
				assert(this->ID && 0 <= i && i < this->ID->size() && (*this->ID)[i]); \
				return *(*this->ID)[i];\
			}\
			/*获取成员数组*/\
			vector<TYPE *> & getValue_##ID() {\
				assert(this->ID);\
				return *this->ID;\
			}\
			/*判断成员数组是否为NULL*/\
			bool isNull_##ID(){\
				return this->ID == NULL;\
			} \
			/*获取成员数组的长度,当数组为NULL时返回-1*/\
			greenInt getLength_##ID(){\
				if(this->ID == NULL){\
					return -1;\
				}\
				return this->ID->size();\
			}\
		private:\
			void add_##ID(const vector<TYPE *> & arry, MemoryCtrlType ptrCtrlType){ \
				for(unsigned int i = 0; i < arry.size(); ++i){\
					const TYPE * t = arry[i];\
					add_##ID(t, ptrCtrlType);\
				}\
			} \
			void add_##ID(const list<TYPE *> & arry, MemoryCtrlType ptrCtrlType){\
				for(list<TYPE *>::const_iterator it = arry.begin(); it != arry.end(); ++it){\
					const TYPE * t = *it;\
					add_##ID(t, ptrCtrlType);\
				}\
			} \
			void add_##ID(const TYPE * e, MemoryCtrlType ptrCtrlType/*接管外部指针内存的方式*/){\
				if(NULL == this->ID){\
					this->ID = new vector<TYPE *>();\
					memGarbage.add(this->ID);\
				}\
				TYPE * pSrc = (TYPE *)e;\
				if(NULL == pSrc){\
					this->ID->push_back(pSrc);\
				}else{\
					if(ptrCtrlType == MemoryCtrlType_DeepCopy){\
						TYPE * pDest = (TYPE *)::cloneObject(pSrc);\
						this->ID->push_back(pDest);\
						memGarbage.add(pDest);\
					}\
					else {\
						this->ID->push_back(pSrc);\
						if(ptrCtrlType == MemoryCtrlType_Handover){\
							memGarbage.add(pSrc);\
						}\
					}\
				}\
			} \
		private:\
			static void sAdd_##ID(jsonObjectMemberInfo & memInfo, const TYPE * e){\
				vector<TYPE *> ** ppID/*=&ID*/ = memInfo.getMemPtrAddr<vector<TYPE *> >();\
				vector<TYPE *> * asID = (vector<TYPE *> *)*ppID;\
				memoryGarbageCollector & mg = memInfo.getMemGarbage(); \
				if(NULL == asID){\
					*ppID = asID = new vector<TYPE *>();\
					mg.add(asID);\
				}\
				TYPE * pSrc = (TYPE *)e;\
				if(NULL == pSrc){\
					asID->push_back(pSrc);\
				}else{\
					if(memInfo.inputDataCtrlType == MemoryCtrlType_DeepCopy){\
						TYPE * pDest = (TYPE *)::cloneObject(pSrc);\
						asID->push_back(pDest);\
						mg.add(pDest);\
					}\
					else {\
						asID->push_back(pSrc);\
						if(memInfo.inputDataCtrlType == MemoryCtrlType_Handover){\
							mg.add(pSrc);\
						}\
					}\
				}\
			} \
			/*定义将成员变量转字符串的virtual方法*/\
			virtual bool access##ID(jsonObjectMemberInfo & memInfo, FuncAccessCommand method, string * strKvPair, jsonStringParser * kvp){ \
				vector<TYPE *> ** ppID/*=&ID*/ = memInfo.getMemPtrAddr<vector<TYPE *> >();\
				vector<TYPE *> * asID = (vector<TYPE *> *)*ppID;\
				memoryGarbageCollector& mg = memInfo.getMemGarbage();\
				if(FuncAccessCommand_GetKeyValueByMember == method){\
					assert(strKvPair);\
					string value;\
					if (NULL == asID) {\
						value = "null";\
					}\
					else {\
						string s;\
						value = "[";\
						for(unsigned int i = 0; i < asID->size(); ++i){\
							const TYPE * t = (*asID)[i];\
							if(NULL == t){\
								s = "null";\
							}else{\
								data2String(s, *t);\
							}\
							value += s;\
							if (i < asID->size() - 1) {\
								value += ",";\
							}\
						}\
						value += "]";\
					}\
					/*json的key:value*/\
					string key = #ID;\
					*strKvPair = "\"" + key + "\":" + value;\
					return true;\
				}\
				if (FuncAccessCommand_SetMemberByKeyValue == method) {\
					assert(kvp && kvp->getCurrentKeyValue());\
					string & value = kvp->getCurrentKeyValue()->value;\
					if(value == JSON_NULL_STRING){\
						*ppID = NULL;\
						return true;\
					}\
					if (value.empty()) {\
						*ppID = asID = new vector<TYPE*>();\
						mg.add(asID);\
						return true;\
					}\
					if(NULL == asID){\
						*ppID = asID = new vector<TYPE *>();\
						mg.add(asID);\
					}\
					string2DataArrayPtr(*asID, *kvp);\
					for(unsigned int i = 0; i < asID->size(); ++i){\
						const TYPE * t = (*asID)[i];\
						mg.add(t);\
					}\
					return true;\
				}\
				if (FuncAccessCommand_GetMemberFieldInfo == method) {\
					memInfo.metaName = #ID; \
					memInfo.metaType = #TYPE;\
					memInfo.metaCate = MemberDefineCategory_Array;\
					return true;\
				}\
				if (FuncAccessCommand_SetMemberByJsonObject == method)/*注意这里是有单个追加、数组克隆两种方式*/ {\
					if(memInfo.inputDataCate == MemberDefineCategory_Single){\
						TYPE * e = (TYPE *)memInfo.ptrInputData;\
						sAdd_##ID(memInfo, e);\
					}else if(memInfo.inputDataCate == MemberDefineCategory_Array){\
						vector<TYPE*>* pSrcList = (vector<TYPE*>*)memInfo.ptrInputData;\
						if(NULL == pSrcList){\
							*ppID = NULL;\
						}else {\
							for (unsigned int i = 0; i < pSrcList->size(); ++i) {\
								const TYPE* e = (*pSrcList)[i];\
								sAdd_##ID(memInfo, e);\
							}\
						}\
					}\
					return true;\
				}\
				if (FuncAccessCommand_InitMemberValue == method) {\
					*ppID = NULL;\
					return true;\
				}\
				return false;\
			}	

//声明JSON类的结束
#define JSON_CLASS_DECLARE_END \
		public:\
			/*将对象转为JSON字符串*/\
			virtual string toString();\
			/*JSON字符串转为对象*/\
			virtual bool toObject(const string & json);\
			/*初始化对象成员*/\
			virtual void initObject();\
			/*枚举成员信息*/\
			virtual greenInt enumMemberInfo(map<string, jsonObjectMemberInfo> & memInfos);\
			/*获取成员id信息*/\
			virtual bool getMemberInfo(const string & name, jsonObjectMemberInfo & memInfo);\
			/*克隆*/\
			virtual bool cloneObject(const jsonObjectBaseClass& srcObj);\
			/*获取类名*/\
			virtual string getClassName() const;\
		private:\
			/*设置成员的值*/\
			virtual bool setMemberInfo(jsonObjectMemberInfo & memInfo, jsonStringParser* parser);\
		};//The End Of Class Declare.

//JSON类的CPP实现
#define JSON_CLASS_IMPLEMENT(className)\
		class Register##className {\
			public:\
				static jsonObjectBaseClass * instance() {\
					return new className; \
				}\
			private:\
				static const Register _static_register;\
		};\
		const Register Register##className::_static_register(#className, Register##className::instance);\
		/*利用虚函数表格,建立JSON类的反射数据结构*/\
		autoPointer<map<string, jsonObjectMemberInfo> > className::smMemberMetaInfo;\
		autoPointer<vector<string> > className::svMemberMetaOrder;\
		void className::initClassMemberMeta(className * pClsObj){\
			assert(pClsObj);\
			className::smMemberMetaInfo = new map<string, jsonObjectMemberInfo>();\
			className::svMemberMetaOrder = new vector<string>();\
			const int siMemberCount = getMemberCount();\
			for(int i = 0 ; i < siMemberCount; ++i){\
				jsonObjectMemberInfo memInfo;\
				memInfo.ptrOwnObj = pClsObj;\
				memInfo.metaSortOrder = i;\
				/*将虚函数转化为类成员函数地址*/\
				funcAccessById pFun = memInfo.getMemAccessFunc<funcAccessById>();\
				/*获取名称和类型信息*/\
				(pClsObj->*pFun)(memInfo, FuncAccessCommand_GetMemberFieldInfo, NULL, NULL);\
 				(*className::smMemberMetaInfo)[memInfo.metaName] = memInfo;\
				(className::svMemberMetaOrder)->push_back(memInfo.metaName);\
			}\
		}\
		greenInt className::enumMemberInfo(map<string, jsonObjectMemberInfo> & mis){\
			assert(!className::smMemberMetaInfo.isNull());\
			mis.clear();\
			for(map<string, jsonObjectMemberInfo>::iterator it = className::smMemberMetaInfo->begin(); it != className::smMemberMetaInfo->end(); ++it){\
				jsonObjectMemberInfo memInfo = it->second;\
				memInfo.ptrOwnObj = this;\
				mis[memInfo.metaName] = memInfo;\
			}\
			return mis.size();\
		}\
		bool className::getMemberInfo(const string & name, jsonObjectMemberInfo & memInfo){\
			assert(!className::smMemberMetaInfo.isNull());\
			map<string, jsonObjectMemberInfo>::iterator it = className::smMemberMetaInfo->find(name);\
			if( it != className::smMemberMetaInfo->end()){\
				memInfo = it->second;\
				memInfo.ptrOwnObj = this;\
				return true;\
			}\
			/*遇到非成员节点,标空名称*/\
			memInfo.setFake();\
			return false;\
		}\
		bool className::setMemberInfo(jsonObjectMemberInfo & memInfo, jsonStringParser * parser){\
			funcAccessById pFun = memInfo.getMemAccessFunc<funcAccessById>();\
			if (NULL == parser) {\
				(this->*pFun)(memInfo, FuncAccessCommand_SetMemberByJsonObject, NULL, NULL); \
			}\
			else {\
				(this->*pFun)(memInfo, FuncAccessCommand_SetMemberByKeyValue, NULL, parser); \
			}\
			return true;\
		}\
		/*获取类名*/\
		string className::getClassName() const{\
			return #className;\
		}\
		/*JSON类对象转换为json字符串的方法toString*/\
		string className::toString() {\
			assert(!className::smMemberMetaInfo.isNull());\
			assert(!className::svMemberMetaOrder.isNull());\
			string s, json = "{";\
			for(unsigned int i = 0; i < className::svMemberMetaOrder->size(); ++i){\
				jsonObjectMemberInfo memInfo = (*className::smMemberMetaInfo)[(*className::svMemberMetaOrder)[i]];\
				memInfo.ptrOwnObj = this; \
				funcAccessById pFun = memInfo.getMemAccessFunc<funcAccessById>();\
				(this->*pFun)(memInfo, FuncAccessCommand_GetKeyValueByMember, &s, NULL);\
				json += s;\
				if(i < className::svMemberMetaOrder->size() - 1){ json += ","; }\
			}\
			json += "}"; \
			return json;\
		}\
		/*JSON字符串转对象*/\
		bool className::toObject(const string & json){\
			assert(!className::smMemberMetaInfo.isNull());\
			/*清理所有原有成员并释放内存*/\
			initObject();\
			jsonStringParser kvproc;\
			try{\
				if (!kvproc.parseString(json)) {\
					return false;\
				}\
				return kvproc.archiveData(*this);\
			}\
			catch(exception & e){\
				LOG4J_WARN("%s", e.what());\
			}\
			/*清理所有半路生成的成员并释放内存*/\
			initObject();\
			return false;\
		}\
		void className::initObject(){\
			if(!className::smMemberMetaInfo.isNull()){\
				for(map<string, jsonObjectMemberInfo>::iterator it = className::smMemberMetaInfo->begin(); it != className::smMemberMetaInfo->end(); ++it){\
					jsonObjectMemberInfo memInfo = it->second;\
					memInfo.ptrOwnObj = this; \
					funcAccessById pFun = memInfo.getMemAccessFunc<funcAccessById>();\
					(this->*pFun)(memInfo, FuncAccessCommand_InitMemberValue, NULL, NULL);\
				}\
				memGarbage.release();\
			}\
		}\
		bool className::cloneObject(const jsonObjectBaseClass& srcObj){\
			/*清理所有原有成员并释放内存*/\
			initObject();\
			if(this->getClassName() != srcObj.getClassName()){\
				return false;\
			}\
			/*获取来源、目标对象的成员信息*/\
			jsonObjectBaseClass* pSrcObj = (jsonObjectBaseClass*)&srcObj;\
			map<string, jsonObjectMemberInfo> srcFields;\
			pSrcObj->enumMemberInfo(srcFields);\
			/*获取目标对象的成员信息*/\
			map<string, jsonObjectMemberInfo> destFields;\
			this->enumMemberInfo(destFields);\
			/*逐个成员复制*/\
			for(map<string, jsonObjectMemberInfo>::iterator destit = destFields.begin(); destit != destFields.end(); ++destit){\
				const string & mId = destit->first;\
				jsonObjectMemberInfo& destMemInfo = destit->second;\
				map<string, jsonObjectMemberInfo>::iterator srcIt = srcFields.find(mId);\
				if(srcIt != srcFields.end()){\
					jsonObjectMemberInfo & srcMemInfo = srcIt->second;\
					/*使用memInfo默认的Category,是对象复制对象,是数组复制数组*/\
					destMemInfo.inputData2Member((void *)*srcMemInfo.getMemPtrAddr<char>(), \
						MemoryCtrlType_DeepCopy, srcMemInfo.metaCate);\
				}\
			}\
			return true;\
		}
发布了11 篇原创文章 · 获赞 1 · 访问量 298

猜你喜欢

转载自blog.csdn.net/u011697262/article/details/103940865