当前位置: 首页>>代码示例>>C++>>正文


C++ CComplexArray::Insert方法代码示例

本文整理汇总了C++中CComplexArray::Insert方法的典型用法代码示例。如果您正苦于以下问题:C++ CComplexArray::Insert方法的具体用法?C++ CComplexArray::Insert怎么用?C++ CComplexArray::Insert使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在CComplexArray的用法示例。


在下文中一共展示了CComplexArray::Insert方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: OnStartSession

bool CUserInfoSession::OnStartSession (const SArchonMessage &Msg, DWORD dwTicket)

//	OnStartSession
//
//	Start

	{
	//	Send an Aeon message to get the user record

	CComplexArray *pPayload = new CComplexArray;
	pPayload->Insert(USERS_TABLE_NAME);
	pPayload->Insert(m_sUsernameKey);

	//	Send message

	ISessionHandler::SendMessageCommand(ADDRESS_AEON_COMMAND,
			MSG_AEON_GET_VALUE,
			GenerateAddress(PORT_CRYPTOSAUR_COMMAND),
			CDatum(pPayload),
			MESSAGE_TIMEOUT);

	//	Expect reply

	return true;
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:25,代码来源:UserInfo.cpp

示例2: SendMessageReplyOnWrite

void CEsperEngine::SendMessageReplyOnWrite (CDatum dConnection, DWORD dwBytesTransferred, const SArchonMessage &OriginalMsg)

//	SendMessageReplyOnWrite
//
//	Reply with Esper.onWrite

	{
	CComplexArray *pPayload = new CComplexArray;
	pPayload->Insert(dwBytesTransferred);
	pPayload->Insert(dConnection);

	m_pProcess->SendMessageReply(MSG_ESPER_ON_WRITE, CDatum(pPayload), OriginalMsg);
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:13,代码来源:CEsperEngine.cpp

示例3: CreateFromAttributeList

bool CDatum::CreateFromAttributeList (const CAttributeList &Attribs, CDatum *retdDatum)

//	CreateFromAttributeList
//
//	Creates a datum from an attribute list

	{
	int i;

	TArray<CString> AllAttribs;
	Attribs.GetAll(&AllAttribs);

	if (AllAttribs.GetCount() == 0)
		{
		*retdDatum = CDatum();
		return true;
		}

	CComplexArray *pArray = new CComplexArray;
	for (i = 0; i < AllAttribs.GetCount(); i++)
		pArray->Insert(AllAttribs[i]);

	*retdDatum = CDatum(pArray);
	return true;
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:25,代码来源:CDatum.cpp

示例4: MsgGetTables

void CAeonEngine::MsgGetTables (const SArchonMessage &Msg, const CHexeSecurityCtx *pSecurityCtx)

//	MsgGetTables
//
//	Aeon.getTables

	{
	int i;

	if (!m_bReady)
		{
		SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, ERR_NOT_READY, Msg);
		return;
		}

	//	Get a list of all tables

	TArray<CAeonTable *> AllTables;
	GetTables(&AllTables);

	//	Return an array of table descriptors

	CComplexArray *pArray = new CComplexArray;
	for (i = 0; i < AllTables.GetCount(); i++)
		{
		if (pSecurityCtx && !pSecurityCtx->IsNamespaceAccessible(AllTables[i]->GetName()))
			continue;

		pArray->Insert(AllTables[i]->GetDesc());
		}

	//	Reply

	SendMessageReply(MSG_AEON_RESULT_TABLES, CDatum(pArray), Msg);
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:35,代码来源:CAeonEngine.cpp

示例5: SendMessageReplyOnRead

void CEsperEngine::SendMessageReplyOnRead (CDatum dConnection, CString &sData, const SArchonMessage &OriginalMsg)

//	SendMessageReplyOnRead
//
//	Reply with Esper.onRead

	{
	int iDataLen = sData.GetLength();
	CDatum dData;
	CDatum::CreateStringFromHandoff(sData, &dData);

	CComplexArray *pPayload = new CComplexArray;
	pPayload->Insert(dData);
	pPayload->Insert((int)iDataLen);
	pPayload->Insert(dConnection);

	m_pProcess->SendMessageReply(MSG_ESPER_ON_READ, CDatum(pPayload), OriginalMsg);
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:18,代码来源:CEsperEngine.cpp

示例6: GenerateEntry

CDatum CMnemosynthDb::GenerateEntry (int iCollectionIndex, const CString &sKey, SEntry *pEntry)

//	GenerateEntry
//
//	Generates an entry of the form:
//		0: collection index
//		1: key
//		2: value
//		3: sequence

	{
	CComplexArray *pArray = new CComplexArray;
	pArray->Insert(iCollectionIndex);
	pArray->Insert(sKey);
	pArray->Insert(pEntry->dValue);
	pArray->Insert((int)pEntry->dwSequence);

	return CDatum(pArray);
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:19,代码来源:CMnemosynthDb.cpp

示例7: OnModuleStart

bool CArchonProcess::OnModuleStart (void)

//	OnModuleStart
//
//	Sends a message to central process telling it our status

	{
	//	If we're not the CentralModule then we need to send a message to
	//	this machine's Exarch telling it that we have started.

	if (!m_bCentralModule && !m_bConsoleMode)
		{
		//	Figure out the Mnemosynth sequence number for this endpoint at this
		//	point in time. We send it over to Exarch so that it waits until it
		//	synchronizes to that point before assuming that loading is complete.

		CString sEndpoint = CMnemosynthDb::GenerateEndpointName(GetMachineName(), GetModuleName());
		DWORD dwSeq = m_MnemosynthDb.GetSequence(sEndpoint);
		ASSERT(dwSeq != 0xffffffff);
		if (dwSeq == 0xffffffff)
			{
			Log(MSG_LOG_ERROR, ERR_UNABLE_TO_OPEN_MNEMOSYNTH);
			return false;
			}

		//	Compose the message

		CComplexArray *pArray = new CComplexArray;
		pArray->Insert(m_sName);
		pArray->Insert((int)dwSeq);

		if (!SendMessageCommand(ADDR_EXARCH_COMMAND, MSG_EXARCH_ON_MODULE_START, NULL_STR, 0, CDatum(pArray)))
			{
			Log(MSG_LOG_ERROR, ERR_UNABLE_TO_SEND_TO_EXARCH);
			return false;
			}
		}

	//	Done

	return true;
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:42,代码来源:CArchonProcess.cpp

示例8: ReportVolumeFailure

void CArchonProcess::ReportVolumeFailure (const CString &sFilespec, const CString &sOperation)

//	ReportVolumeFailure
//
//	And engine calls this method when it fails reading/writing to the given
//	filespec.

	{
	//	We log from here so that we transmit the module that ran into the problem.

	Log(MSG_LOG_ERROR, strPattern(ERR_DISK, sFilespec));

	//	Send a message to Exarch to check the volume.

	CComplexArray *pArray = new CComplexArray;
	pArray->Insert(sFilespec);
	if (!sOperation.IsEmpty())
		pArray->Insert(sOperation);

	SendMessageCommand(ADDR_EXARCH_COMMAND, MSG_EXARCH_REPORT_DISK_ERROR, NULL_STR, 0, CDatum(pArray));
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:21,代码来源:CArchonProcess.cpp

示例9: UpdateLoginFailure

bool CUserInfoSession::UpdateLoginFailure (void)

//	UpdateLoginFailure
//
//	Update the user record with the most recent failure

	{
	//	Set our state

	m_iState = stateWaitingForFailureUpdate;

	//	Mutate the record to set the login date

	CComplexStruct *pRecord = new CComplexStruct;
	pRecord->SetElement(FIELD_LOGIN_FAILURE_COUNT, CDatum((int)1));

	CComplexStruct *pMutation = new CComplexStruct;
	pMutation->SetElement(FIELD_LAST_LOGIN_FAILURE_ON, MUTATE_DATE_MODIFIED);
	pMutation->SetElement(FIELD_LOGIN_FAILURE_COUNT, MUTATE_INCREMENT);

	//	Create a payload

	CComplexArray *pPayload = new CComplexArray;
	pPayload->Insert(USERS_TABLE_NAME);
	pPayload->Insert(m_sUsernameKey);
	pPayload->Insert(CDatum(pRecord));
	pPayload->Insert(CDatum(pMutation));

	//	Send message

	ISessionHandler::SendMessageCommand(ADDRESS_AEON_COMMAND,
			MSG_AEON_MUTATE,
			GenerateAddress(PORT_CRYPTOSAUR_COMMAND),
			CDatum(pPayload),
			MESSAGE_TIMEOUT);

	//	Expect reply

	return true;
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:40,代码来源:UserInfo.cpp

示例10: GenerateCollectionsArray

CDatum CMnemosynthDb::GenerateCollectionsArray (void)

//	GenerateCollectionsArray
//
//	Creates an array of collection names.
//
//	NOTE: Our callers rely on the fact that this includes all colelctions,
//	even ones with no entries.

	{
	int i;

	CComplexArray *pCollections = new CComplexArray;
	for (i = 0; i < m_Collections.GetCount(); i++)
		pCollections->Insert(m_Collections.GetKey(i));

	return CDatum(pCollections);
	}
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:18,代码来源:CMnemosynthDb.cpp

示例11: GenerateDelta

void CMnemosynthDb::GenerateDelta (TArray<SMnemosynthUpdate> *retUpdates, CDatum *retdLocalUpdates)

//	GenerateDelta
//
//	Generates a list of changes since the last time we called this

	{
	CSmartLock Lock(m_cs);

	int i, j;

	//	Edge conditions

	if (m_Endpoints.GetCount() == 0)
		{
		*retdLocalUpdates = CDatum();
		return;
		}

	//	If we are not the central module, then we only need to
	//	generate a list of updates made by our own endpoint
	//	(and send it to our central module).

	if (!m_pProcess->IsCentralModule())
		{
		if (GetLocalEndpoint().dwSeqRecv > GetLocalEndpoint().dwSeqSent)
			{
			SMnemosynthUpdate *pUpdate = retUpdates->Insert();
			pUpdate->sDestEndpoint = strPattern("%s/CentralModule", m_pProcess->GetMachineName());

			//	Generate a payload for our updates

			CComplexArray *pEntries = new CComplexArray;
			for (i = 0; i < m_Collections.GetCount(); i++)
				{
				const CString &sCollection = m_Collections.GetKey(i);
				SCollection *pCollection = &m_Collections[i];

				for (j = 0; j < pCollection->Entries.GetCount(); j++)
					{
					SEntry *pEntry = &pCollection->Entries[j];
					if (pEntry->dwOwnerID == 0 && pEntry->dwSequence > GetLocalEndpoint().dwSeqSent)
						{
						CDatum dEntry = GenerateEntry(i, pCollection->Entries.GetKey(j), pEntry);
						pEntries->Insert(dEntry);

						//	If this entry is Nil then we can deleted. (We don't
						//	need it as a deletion stub since we just composed
						//	the update. If this message gets lost we need to
						//	resend everything).

						if (pCollection->Entries.GetValue(j).dValue.IsNil())
							{
							pCollection->Entries.Delete(j);
							j--;
							}
						}
					}
				}

			//	Create the payload

			CComplexStruct *pPayload = new CComplexStruct;
			pPayload->SetElement(STR_COLLECTIONS, GenerateCollectionsArray());
			pPayload->SetElement(STR_ENDPOINT, GetLocalEndpoint().sName);
			pPayload->SetElement(STR_ENTRIES, CDatum(pEntries));
			pPayload->SetElement(FIELD_PROCESS_ID, CDatum(GetLocalEndpoint().dwProcessID));

			//	Add it

			CDatum dLocalUpdates = CDatum(pPayload);
			pUpdate->Payloads.Insert(dLocalUpdates);

			//	Return it

			*retdLocalUpdates = dLocalUpdates;
			}
		else
			*retdLocalUpdates = CDatum();
		}

	//	Otherwise, loop over all endpoints and generate a different
	//	update entry for each one that we need to handle

	else
		{
		bool bFullUpdateNeeded = false;
		for (i = 1; i < m_Endpoints.GetCount(); i++)
			if (m_Endpoints[i].bFullUpdate)
				{
				bFullUpdateNeeded = true;
				break;
				}

		//	Collections

		CDatum dCollections = GenerateCollectionsArray();

		//	We end up creating one or two arrays of deltas. The first
		//	array has all the changes since we last generated a delta
//.........这里部分代码省略.........
开发者ID:gmoromisato,项目名称:Hexarc,代码行数:101,代码来源:CMnemosynthDb.cpp

示例12: Log

void CArchonProcess::Log (const CString &sMsg, const CString &sText)

//	Log
//
//	Log a status or error from the engine

	{
	CString sAddress;

	//	In console mode we just output

	if (m_bConsoleMode)
		{
		LogBlackBox(strPattern("%s: %s", sMsg, sText));
		return;
		}

	//	We don't want to recurse, so we keep track here.

	static __declspec(thread) bool bInLog = false;
	if (bInLog)
		{
#ifdef DEBUG
		printf("ERROR: Unable to log: %s\n", (LPSTR)sText);
#endif
		return;
		}

	bInLog = true;

	//	Protect ourselves in case we crash

	try
		{
		//	If we are Arcology Prime, then we send to our machine's Exarch

		if (m_bArcologyPrime)
			sAddress = ADDRESS_EXARCH_LOG;

		//	Otherwise we need to send to Arcology Prime

		else
			{
			//	NOTE: We can't easily cache this because Arcology Prime might change
			//	(if it restarts, for example).

			sAddress = m_Transporter.GenerateMachineAddress(STR_ARCOLOGY_PRIME, ADDRESS_EXARCH_LOG);
			if (sAddress.IsEmpty())
				{
				bInLog = false;
				return;
				}
			}

		//	Compose the message

		SArchonMessage Msg;
		Msg.sMsg = sMsg;
		Msg.sReplyAddr = ADDR_NULL;
		Msg.dwTicket = 0;

		//	Log the message and the machine/module that it came from

		CComplexArray *pArray = new CComplexArray;
		pArray->Insert(sText);
		pArray->Insert(GenerateAddress(PORT_ARC_LOG));
		Msg.dPayload = CDatum(pArray);

		//	NOTE: We need to use a real address (instead of a virtual port) because the log
		//	command is used before virtual ports replicate to all modules.

		SendMessage(sAddress, Msg);
		}
	catch (...)
		{
#ifdef DEBUG
		printf("ERROR: Crash in log.\n");
#endif
		}

	bInLog = false;
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:82,代码来源:CArchonProcess.cpp

示例13: OnProcessMessage

bool CUserInfoSession::OnProcessMessage (const SArchonMessage &Msg)

//	OnProcessMessage
//
//	We received a reply from Aeon

	{
	int i;

	//	If this is an error, then we return the error back to the client

	if (IsError(Msg))
		{
		SendMessageReplyError(MSG_ERROR_UNABLE_TO_COMPLY, Msg.dPayload);
		return false;
		}

	//	If we're waiting for the user record, then see if we can process it now.

	if (m_iState == stateWaitingForUserRecord)
		{
		//	Cryptosaur.getUser

		if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_GET_USER))
			{
			CDatum dUserData = Msg.dPayload;

			//	If the user does not exist, then we return Nil

			if (dUserData.IsNil())
				{
				SendMessageReply(MSG_REPLY_DATA, CDatum());
				return false;
				}

			//	Generate a sanitized user record

			CComplexStruct *pReply = new CComplexStruct;
			pReply->SetElement(FIELD_USERNAME, dUserData.GetElement(FIELD_USERNAME));

			//	Sanitize rights

			CDatum dRights = dUserData.GetElement(FIELD_RIGHTS);
			if (!m_sScope.IsEmpty())
				{
				CComplexArray *pRights = new CComplexArray;

				for (i = 0; i < dRights.GetCount(); i++)
					if (strStartsWith(dRights.GetElement(i), m_sScope))
						pRights->Insert(dRights.GetElement(i));

				pReply->SetElement(FIELD_RIGHTS, CDatum(pRights));
				}
			else
				pReply->SetElement(FIELD_RIGHTS, dRights);

			//	Done

			SendMessageReply(MSG_REPLY_DATA, CDatum(pReply));
			return false;
			}

		//	If we get back nil then the user does not exist.

		else if (Msg.dPayload.IsNil())
			{
			SendMessageReplyError(MSG_ERROR_DOES_NOT_EXIST, strPattern(ERR_UNKNOWN_USERNAME, m_sUsername));
			return false;
			}

		//	Otherwise, we handle the result based on the original message

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_CHECK_PASSWORD_SHA1))
			{
			//	Get the parameters from the original message

			CDatum dChallenge = GetOriginalMsg().dPayload.GetElement(1);
			CDatum dResponse = GetOriginalMsg().dPayload.GetElement(2);

			//	Get the password has from the response

			CDatum dAuthDesc = Msg.dPayload.GetElement(FIELD_AUTH_DESC);
			CDatum dPasswordHash = dAuthDesc.GetElement(FIELD_CREDENTIALS);

			//	Create a response to the challenge based on the password hash that
			//	we have stored.

			CDatum dCorrect = CAI1Protocol::CreateSHAPasswordChallengeResponse(dPasswordHash, dChallenge);

			//	Compare the correct response to the actual

			if ((const CIPInteger &)dResponse == (const CIPInteger &)dCorrect)
				return UpdateLoginSuccess(stateWaitingForSuccessUpdate);
			else
				return UpdateLoginFailure();
			}

		//	Cryptosaur.hasRights

		else if (strEquals(GetOriginalMsg().sMsg, MSG_CRYPTOSAUR_HAS_RIGHTS))
//.........这里部分代码省略.........
开发者ID:kronosaur,项目名称:Hexarc,代码行数:101,代码来源:UserInfo.cpp

示例14: WriteDesc

void CAeonView::WriteDesc (CComplexStruct *pDesc)

//	WriteDesc
//
//	Write out a description of the view.

	{
	int i;

	//	ID

	if (m_dwID)
		pDesc->SetElement(FIELD_ID, CDatum((int)m_dwID));

	//	Name

	if (!m_sName.IsEmpty())
		pDesc->SetElement(FIELD_NAME, m_sName);

	//	Dimensions

	if (IsSecondaryView())
		{
		//	Secondary views always have an extra dimension (used for the disambiguating rowKey).

		int iDimsToSave = m_Dims.GetCount() - 1;

		//	Save the user-created dimensions.

		pDesc->SetElement(FIELD_X, CAeonTable::GetDimensionDescForSecondaryView(m_Dims[0], m_Keys[0]));
		if (iDimsToSave > 1)
			{
			pDesc->SetElement(FIELD_Y, CAeonTable::GetDimensionDescForSecondaryView(m_Dims[1], m_Keys[1]));
			if (iDimsToSave > 2)
				pDesc->SetElement(FIELD_Z, CAeonTable::GetDimensionDescForSecondaryView(m_Dims[2], m_Keys[2]));
			}
		}
	else
		{
		pDesc->SetElement(FIELD_X, CAeonTable::GetDimensionDesc(m_Dims[0]));
		if (m_Dims.GetCount() > 1)
			{
			pDesc->SetElement(FIELD_Y, CAeonTable::GetDimensionDesc(m_Dims[1]));
			if (m_Dims.GetCount() > 2)
				pDesc->SetElement(FIELD_Z, CAeonTable::GetDimensionDesc(m_Dims[2]));
			}
		}

	//	Write out columns

	if (m_Columns.GetCount() > 0)
		{
		CComplexArray *pColumns = new CComplexArray;
		for (i = 0; i < m_Columns.GetCount(); i++)
			pColumns->Insert(CDatum(m_Columns[i]));

		pDesc->SetElement(FIELD_COLUMNS, CDatum(pColumns));
		}

	//	Computed columns

	if (!m_ComputedColumns.IsNil())
		pDesc->SetElement(FIELD_COMPUTED_COLUMNS, m_ComputedColumns);

	//	Exclude nil

	if (m_bExcludeNil)
		pDesc->SetElement(FIELD_EXCLUDE_NIL_KEYS, CDatum(CDatum::constTrue));

	//	Write out update sequence number

	if (m_bUpdateNeeded)
		pDesc->SetElement(FIELD_UPDATE_NEEDED, CDatum(CDatum::constTrue));
	}
开发者ID:kronosaur,项目名称:Hexarc,代码行数:74,代码来源:CAeonView.cpp

示例15: ParseFilePath

bool CAeonInterface::ParseFilePath (const CString &sFilePath, const CString &sRoot, int iOffset, const CDateTime &IfModifiedAfter, CString *retsAddr, CString *retsMsg, CDatum *retdPayload)

//	ParseFilePath
//
//	Parses a filePath of the form:
//
//	@Aeon.command/Arc.services/TransPackage.ars
//	/Arc.services/TransPackage.ars
//	./TransPackage.ars
//
//	Returns FALSE if error.

	{
	char *pPos = sFilePath.GetParsePointer();
	char *pPosEnd = pPos + sFilePath.GetLength();

	//	Create a fileDownloadDesc to specify that we not read more than 100K
	//	at a time (so that we don't overload our IPC buffer).

	CComplexStruct *pFDDesc = new CComplexStruct;
	pFDDesc->SetElement(FIELD_PARTIAL_MAX_SIZE, 100000);
	pFDDesc->SetElement(FIELD_PARTIAL_POS, iOffset);
	if (IfModifiedAfter.IsValid())
		pFDDesc->SetElement(FIELD_IF_MODIFIED_AFTER, IfModifiedAfter);

	CDatum dFileDownloadDesc(pFDDesc);

	//	If the path starts with @ then this is an absolute path

	CString sParsedPath;
	if (*pPos == '@')
		{
		//	LATER

		return false;
		}

	//	Is this a service namespace?

	else if (*pPos == '#')
		{
		CString sNamespace;
		if (!CTranspaceInterface::ParseAddress(sFilePath, &sNamespace))
			return false;

		//	Compose a proper download command payload

		CComplexArray *pPayload = new CComplexArray;
		pPayload->Append(sFilePath);
		pPayload->Append(sFilePath);
		pPayload->Append(dFileDownloadDesc);
		CDatum dPayload(pPayload);

		//	Parse the service endpoint

		CString sService(sNamespace.GetParsePointer() + 1);

		//	Encode into the proper payload

		CComplexArray *pPayload2 = new CComplexArray;
		pPayload2->Append(sService);
		pPayload2->Append(MSG_TRANSPACE_DOWNLOAD);
		pPayload2->Append(dPayload);

		//	Done

		*retsAddr = ADDRESS_HYPERION_COMMAND;
		*retsMsg = MSG_HYPERION_SERVICE_MSG;
		*retdPayload = CDatum(pPayload2);
		return true;
		}

	//	If it starts with a slash then it is an Aeon path

	else if (*pPos == '/')
		{
		sParsedPath = sFilePath;
		*retsAddr = ADDR_AEON;
		*retsMsg = MSG_AEON_FILE_DOWNLOAD;

		//	Generate a message for Aeon to load the file

		CComplexArray *pPayload = new CComplexArray;
		pPayload->Insert(sParsedPath);
		pPayload->Insert(dFileDownloadDesc);

		//	Done

		*retdPayload = CDatum(pPayload);
		}

	//	If it starts with a ./ then this is a relative path

	else if (*pPos == '.')
		{
		pPos++;
		if (pPos == pPosEnd || *pPos != '/')
			return false;

		//	Root must be valid
//.........这里部分代码省略.........
开发者ID:kronosaur,项目名称:Hexarc,代码行数:101,代码来源:CAeonInterface.cpp


注:本文中的CComplexArray::Insert方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。