當前位置: 首頁>>代碼示例>>C++>>正文


C++ GetNextNode函數代碼示例

本文整理匯總了C++中GetNextNode函數的典型用法代碼示例。如果您正苦於以下問題:C++ GetNextNode函數的具體用法?C++ GetNextNode怎麽用?C++ GetNextNode使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。


在下文中一共展示了GetNextNode函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的C++代碼示例。

示例1: ProcessExternedOpcode

/**
  Process some op codes which is out side of current form.
  
  @param FormData                Pointer to the form data.

  @return EFI_SUCCESS            Pass the statement success.

**/
VOID
ProcessExternedOpcode (
  IN FORM_DISPLAY_ENGINE_FORM       *FormData
  )
{
  LIST_ENTRY                    *Link;
  LIST_ENTRY                    *NestLink;
  FORM_DISPLAY_ENGINE_STATEMENT *Statement;
  FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;

  Link = GetFirstNode (&FormData->StatementListOSF);
  while (!IsNull (&FormData->StatementListOSF, Link)) {
    Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
    Link = GetNextNode (&FormData->StatementListOSF, Link);

    ProcessUserOpcode(Statement->OpCode);
  }

  Link = GetFirstNode (&FormData->StatementListHead);
  while (!IsNull (&FormData->StatementListHead, Link)) {
    Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
    Link = GetNextNode (&FormData->StatementListHead, Link);

    ProcessUserOpcode(Statement->OpCode);

    NestLink = GetFirstNode (&Statement->NestStatementList);
    while (!IsNull (&Statement->NestStatementList, NestLink)) {
      NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);
      NestLink = GetNextNode (&Statement->NestStatementList, NestLink);

      ProcessUserOpcode(NestStatement->OpCode);
    }

  }
}
開發者ID:B-Rich,項目名稱:edk2,代碼行數:43,代碼來源:CustomizedDisplayLibInternal.c

示例2: strcpy

//////////////////////////////////////////////////////////////////////////////////
//  Function: xml_get_child_tag
//	Gets the position of the child tag.
//
XmlNode CXmlDocument::GetChildNode(XmlNode node, char* szTag)
{
	char szCurrentTag[32];
	char* szChildTag;

	// get parent node tag
	strcpy(szCurrentTag,GetNodeTag(node));

	// get child node
	node = GetNextNode(node);
	while (node>0)
	{
		// get child node tag
		szChildTag = GetNodeTag(node);

		// does the child's tag match the one we're looking for
		if ( !strcmpi(szChildTag,szTag) )
			return node;

		// is this actually the parent's closing tag?
		else if ( !strcmpi(&szChildTag[1],szCurrentTag) )
			return 0;

		node = GetNextNode(node);
	}

	return 0;
}
開發者ID:2BReality,項目名稱:xbmc,代碼行數:32,代碼來源:XmlDocument.cpp

示例3: GetStorageFromQuestionId

/**
  Get the FORM_BROWSER_STATEMENT that matches the Question's value.
    
  @param FormSet                  The Form Set.
  @param QuestionId               QuestionId
   
  @retval FORM_BROWSER_STATEMENT*   FORM_BROWSER_STATEMENT that match Question's value.
  @retval NULL                      If the Form Set does not have EFI_IFR_VARSTORE.
**/
FORM_BROWSER_STATEMENT *
GetStorageFromQuestionId (
  IN CONST FORM_BROWSER_FORMSET * FormSet,
  IN       EFI_QUESTION_ID        QuestionId
  )
{
  LIST_ENTRY             *FormList;
  LIST_ENTRY             *StatementList;
  FORM_BROWSER_FORM      *Form;
  FORM_BROWSER_STATEMENT *Statement;

  FormList = GetFirstNode (&FormSet->FormListHead);

  while (!IsNull (&FormSet->FormListHead, FormList)) {
    Form = FORM_BROWSER_FORM_FROM_LINK (FormList);

    StatementList = GetFirstNode (&Form->StatementListHead);

    while (!IsNull (&Form->StatementListHead, StatementList)) {
      Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementList);
      if ((QuestionId == Statement->QuestionId) && (Statement->Storage != NULL)) {
        //
        // UEFI Question ID is unique in a FormSet.
        //
        ASSERT (Statement->Storage->Type == EFI_HII_VARSTORE_BUFFER);
        return Statement;
      }
      StatementList = GetNextNode (&Form->StatementListHead, StatementList);
    }

    FormList = GetNextNode (&FormSet->FormListHead, FormList);
  }
  
  return NULL;
}
開發者ID:AshleyDeSimone,項目名稱:edk2,代碼行數:44,代碼來源:ConfigAccess.c

示例4: GetNextDataRecord

/**
  Search the Head doubly linked list for the passed in MTC. Return the
  matching element in Head and the MTC on the next entry.

  @param Head             Head of Data Log linked list.
  @param ClassFilter      Only match the MTC if it is in the same Class as the
                          ClassFilter.
  @param PtrCurrentMTC    On IN contians MTC to search for. On OUT contians next
                          MTC in the data log list or zero if at end of the list.

  @retval EFI_DATA_LOG_ENTRY  Return pointer to data log data from Head list.
  @retval NULL                If no data record exists.

**/
EFI_DATA_RECORD_HEADER *
GetNextDataRecord (
  IN  LIST_ENTRY          *Head,
  IN  UINT64              ClassFilter,
  IN OUT  UINT64          *PtrCurrentMTC
  )

{
  EFI_DATA_ENTRY          *LogEntry;
  LIST_ENTRY              *Link;
  BOOLEAN                 ReturnFirstEntry;
  EFI_DATA_RECORD_HEADER  *Record;
  EFI_DATA_ENTRY          *NextLogEntry;

  //
  // If MonotonicCount == 0 just return the first one
  //
  ReturnFirstEntry  = (BOOLEAN) (*PtrCurrentMTC == 0);

  Record            = NULL;
  for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
    LogEntry = DATA_ENTRY_FROM_LINK (Link);
    if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {
      //
      // Skip any entry that does not have the correct ClassFilter
      //
      continue;
    }

    if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {
      //
      // Return record to the user
      //
      Record = LogEntry->Record;

      //
      // Calculate the next MTC value. If there is no next entry set
      // MTC to zero.
      //
      *PtrCurrentMTC = 0;
      for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) {
        NextLogEntry = DATA_ENTRY_FROM_LINK (Link);
        if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {
          //
          // Return the MTC of the next thing to search for if found
          //
          *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;
          break;
        }
      }
      //
      // Record found exit loop and return
      //
      break;
    }
  }

  return Record;
}
開發者ID:bhanug,項目名稱:virtualbox,代碼行數:73,代碼來源:DataHub.c

示例5: HiiFindHandles

/**
  Determines the handles that are currently active in the database.

  This function determines the handles that are currently active in the database. 
  For example, a program wishing to create a Setup-like configuration utility would use this call 
  to determine the handles that are available. It would then use calls defined in the forms section 
  below to extract forms and then interpret them.

  @param This                 A pointer to the EFI_HII_PROTOCOL instance.
  @param HandleBufferLength   On input, a pointer to the length of the handle buffer. 
                              On output, the length of the handle buffer that is required for the handles found.
  @param Handle               Pointer to an array of EFI_HII_HANDLE instances returned. 
                              Type EFI_HII_HANDLE is defined in EFI_HII_PROTOCOL.NewPack() in the Packages section.

  @retval EFI_SUCCESS         Handle was updated successfully.
 
  @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates that Handle is too small 
                               to support the number of handles. HandleBufferLength is updated with a value that 
                               will enable the data to fit.
**/
EFI_STATUS
EFIAPI
HiiFindHandles (
  IN     EFI_HII_PROTOCOL *This,
  IN OUT UINT16           *HandleBufferLength,
  OUT    FRAMEWORK_EFI_HII_HANDLE    *Handle
  )
{
  UINT16                      Count;
  LIST_ENTRY                  *Link;
  HII_THUNK_CONTEXT           *ThunkContext;
  HII_THUNK_PRIVATE_DATA      *Private;

  if (HandleBufferLength == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);  

  //
  // Count the number of handles.
  //
  Count = 0;
  Link = GetFirstNode (&Private->ThunkContextListHead);
  while (!IsNull (&Private->ThunkContextListHead, Link)) {
    Count++;
    Link = GetNextNode (&Private->ThunkContextListHead, Link);
  }

  if (Count > *HandleBufferLength) {
    *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
    return EFI_BUFFER_TOO_SMALL;
  }

  //
  // Output the handles.
  //
  Count = 0;
  Link = GetFirstNode (&Private->ThunkContextListHead);
  while (!IsNull (&Private->ThunkContextListHead, Link)) {

    ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link);
    Handle[Count] = ThunkContext->FwHiiHandle;

    Count++;
    Link = GetNextNode (&Private->ThunkContextListHead, Link);

  }

  *HandleBufferLength = (UINT16) (Count * sizeof (FRAMEWORK_EFI_HII_HANDLE));
  return EFI_SUCCESS;
}
開發者ID:ChenFanFnst,項目名稱:edk2,代碼行數:72,代碼來源:HiiDatabase.c

示例6: variables

/**
  Sets a list of all Shell-Guid-based environment variables.  this will
  also eliminate all existing shell environment variables (even if they
  are not on the list).

  This function will also deallocate the memory from List.

  @param[in] ListHead           The pointer to LIST_ENTRY from
                                GetShellEnvVarList().

  @retval EFI_SUCCESS           the list was Set sucessfully.
**/
EFI_STATUS
EFIAPI
SetEnvironmentVariableList(
    IN LIST_ENTRY *ListHead
)
{
    ENV_VAR_LIST      VarList;
    ENV_VAR_LIST      *Node;
    EFI_STATUS        Status;
    UINTN             Size;

    InitializeListHead(&VarList.Link);

    //
    // Delete all the current environment variables
    //
    Status = GetEnvironmentVariableList(&VarList.Link);
    ASSERT_EFI_ERROR(Status);

    for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)
                 ; !IsNull(&VarList.Link, &Node->Link)
            ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)
        ) {
        if (Node->Key != NULL) {
            Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);
        }
        ASSERT_EFI_ERROR(Status);
    }

    FreeEnvironmentVariableList(&VarList.Link);

    //
    // set all the variables fron the list
    //
    for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)
                 ; !IsNull(ListHead, &Node->Link)
            ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)
        ) {
        Size = StrSize(Node->Val);
        if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {
            Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);
        } else {
            Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
        }
        ASSERT_EFI_ERROR(Status);
    }
    FreeEnvironmentVariableList(ListHead);

    return (Status);
}
開發者ID:B-Rich,項目名稱:edk2,代碼行數:62,代碼來源:ShellEnvVar.c

示例7: GetNextNode

wxHashTable::Node* wxHashTable::Next()
{
    if( m_curr == NULL )
        GetNextNode( 0 );
    else
    {
        m_curr = m_curr->GetNext();

        if( m_curr == ( (Node*)m_table[m_currBucket] )->GetNext() )
            GetNextNode( m_currBucket + 1 );
    }

    return m_curr;
}
開發者ID:BhaaLseN,項目名稱:dolphin,代碼行數:14,代碼來源:hash.cpp

示例8: GetNextNode

void CXmlDocument::EnumerateNodes(char* szTag, XmlNodeCallback pFunc)
{
	char* szCurrentTag;
	XmlNode node;
	
	node = GetNextNode(XML_ROOT_NODE);
	while (node>0)
	{
		szCurrentTag = GetNodeTag(node);
		if ( !strcmpi(szCurrentTag,szTag) )
			pFunc(szTag,node);

		node = GetNextNode(node);
	}
}
開發者ID:2BReality,項目名稱:xbmc,代碼行數:15,代碼來源:XmlDocument.cpp

示例9: BootMonFsGetImageLength

UINT32
BootMonFsGetImageLength (
  IN BOOTMON_FS_FILE      *File
  )
{
  UINT32                   Index;
  UINT32                   FileSize;
  LIST_ENTRY              *RegionToFlushLink;
  BOOTMON_FS_FILE_REGION  *Region;

  FileSize = 0;

  // Look at all Flash areas to determine file size
  for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) {
    FileSize += File->HwDescription.Region[Index].Size;
  }

  // Add the regions that have not been flushed yet
  for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink);
       !IsNull (&File->RegionToFlushLink, RegionToFlushLink);
       RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink)
       )
  {
    Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
    if (Region->Offset + Region->Size > FileSize) {
      FileSize += Region->Offset + Region->Size;
    }
  }

  return FileSize;
}
開發者ID:EvanLloyd,項目名稱:tianocore,代碼行數:31,代碼來源:BootMonFsDir.c

示例10: ComputeFreeSpace

// Helper function that calculates a rough "free space" by:
// - Taking the media size
// - Subtracting the sum of all file sizes
// - Subtracting the block size times the number of files
//    (To account for the blocks containing the HW_IMAGE_INFO
STATIC
UINT64
ComputeFreeSpace (
  IN BOOTMON_FS_INSTANCE *Instance
  )
{
  LIST_ENTRY   *FileLink;
  UINT64        FileSizeSum;
  UINT64        MediaSize;
  UINTN         NumFiles;
  EFI_BLOCK_IO_MEDIA *Media;
  BOOTMON_FS_FILE *File;

  Media = Instance->BlockIo->Media;
  MediaSize = Media->BlockSize * (Media->LastBlock + 1);

  NumFiles = 0;
  FileSizeSum = 0;
  for (FileLink = GetFirstNode (&Instance->RootFile->Link);
         !IsNull (&Instance->RootFile->Link, FileLink);
         FileLink = GetNextNode (&Instance->RootFile->Link, FileLink)
         )
  {
    File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink);
    FileSizeSum += BootMonFsGetImageLength (File);

    NumFiles++;
  }

  return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles));
}
開發者ID:EvanLloyd,項目名稱:tianocore,代碼行數:36,代碼來源:BootMonFsDir.c

示例11: InternalRemoveAliasFromList

/**
  Remove an alias from the given list.

  @param[in] Alias               The alias to remove.
  @param[in, out] List           The list to search.
**/
BOOLEAN
EFIAPI
InternalRemoveAliasFromList(
  IN CONST CHAR16       *Alias,
  IN OUT LIST_ENTRY     *List
  )
{
  ALIAS_LIST *Node;

  //
  // assert for NULL parameter
  //
  ASSERT(Alias != NULL);

  //
  // check for the Alias
  //
  for ( Node = (ALIAS_LIST *)GetFirstNode(List)
      ; !IsNull(List, &Node->Link)
      ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
     ){
    ASSERT(Node->CommandString != NULL);
    ASSERT(Node->Alias != NULL);
    if (StrCmp(Node->Alias, Alias)==0) {
      RemoveEntryList(&Node->Link);
      FreePool(Node->Alias);
      FreePool(Node->CommandString);
      FreePool(Node);
      return (TRUE);
    }
  }
  return (FALSE);
}
開發者ID:JohnTroony,項目名稱:vector-edk,代碼行數:39,代碼來源:For.c

示例12: UnregisterResetNotify

/**
  Unregister a notification function.

  The UnregisterResetNotify() function removes the previously registered
  notification using RegisterResetNotify().

  @param[in]  This              A pointer to the EFI_RESET_NOTIFICATION_PROTOCOL instance.
  @param[in]  ResetFunction     The pointer to the ResetFunction being unregistered.

  @retval EFI_SUCCESS           The reset notification function was unregistered.
  @retval EFI_INVALID_PARAMETER ResetFunction is NULL.
  @retval EFI_INVALID_PARAMETER The reset notification function specified by ResetFunction was not previously
                                registered using RegisterResetNotify().

**/
EFI_STATUS
EFIAPI
UnregisterResetNotify (
  IN EFI_RESET_NOTIFICATION_PROTOCOL *This,
  IN EFI_RESET_SYSTEM                ResetFunction
  )
{
  RESET_NOTIFICATION_INSTANCE        *Instance;
  LIST_ENTRY                         *Link;
  RESET_NOTIFY_ENTRY                 *Entry;

  if (ResetFunction == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = RESET_NOTIFICATION_INSTANCE_FROM_THIS (This);

  for ( Link = GetFirstNode (&Instance->ResetNotifies)
      ; !IsNull (&Instance->ResetNotifies, Link)
      ; Link = GetNextNode (&Instance->ResetNotifies, Link)
      ) {
    Entry = RESET_NOTIFY_ENTRY_FROM_LINK (Link);
    if (Entry->ResetNotify == ResetFunction) {
      RemoveEntryList (&Entry->Link);
      FreePool (Entry);
      return EFI_SUCCESS;
    }
  }

  return EFI_INVALID_PARAMETER;
}
開發者ID:MattDevo,項目名稱:edk2,代碼行數:46,代碼來源:ResetSystem.c

示例13: UefiIfrGetBufferTypeDefaults

/**
  Get the default value for Buffer Type storage from the FormSet in ThunkContext.
  
  The results can be multiple instances of UEFI_IFR_BUFFER_STORAGE_NODE. 
  They are inserted to the link list.
  
  @param  ThunkContext  Hii thunk context.
  @param  UefiDefaults  The head of link list for the output.

  @retval   EFI_SUCCESS          Successful.
  
**/
EFI_STATUS
UefiIfrGetBufferTypeDefaults (
  IN  HII_THUNK_CONTEXT   *ThunkContext,
  OUT LIST_ENTRY          **UefiDefaults
  )
{
  LIST_ENTRY            *DefaultLink;
  FORMSET_DEFAULTSTORE  *DefaultStore;
  EFI_STATUS            Status;

  ASSERT (UefiDefaults != NULL);

  *UefiDefaults = AllocateZeroPool (sizeof (LIST_ENTRY));
  ASSERT (*UefiDefaults != NULL);
  InitializeListHead (*UefiDefaults);

  DefaultLink = GetFirstNode (&ThunkContext->FormSet->DefaultStoreListHead);
  while (!IsNull (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink)) {
    DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK(DefaultLink);

    Status = GetBufferTypeDefaultId (DefaultStore, ThunkContext->FormSet, *UefiDefaults);
    ASSERT_EFI_ERROR (Status);

    DefaultLink = GetNextNode (&ThunkContext->FormSet->DefaultStoreListHead, DefaultLink);    
  }

  return EFI_SUCCESS;
}
開發者ID:AshleyDeSimone,項目名稱:edk2,代碼行數:40,代碼來源:UefiIfrDefault.c

示例14: EfiBootManagerRegisterBootDescriptionHandler

/**
  Register the platform provided boot description handler.

  @param Handler  The platform provided boot description handler

  @retval EFI_SUCCESS          The handler was registered successfully.
  @retval EFI_ALREADY_STARTED  The handler was already registered.
  @retval EFI_OUT_OF_RESOURCES There is not enough resource to perform the registration.
**/
EFI_STATUS
EFIAPI
EfiBootManagerRegisterBootDescriptionHandler (
  IN EFI_BOOT_MANAGER_BOOT_DESCRIPTION_HANDLER  Handler
  )
{
  LIST_ENTRY                                    *Link;
  BM_BOOT_DESCRIPTION_ENTRY                    *Entry;

  for ( Link = GetFirstNode (&mPlatformBootDescriptionHandlers)
      ; !IsNull (&mPlatformBootDescriptionHandlers, Link)
      ; Link = GetNextNode (&mPlatformBootDescriptionHandlers, Link)
      ) {
    Entry = CR (Link, BM_BOOT_DESCRIPTION_ENTRY, Link, BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE);
    if (Entry->Handler == Handler) {
      return EFI_ALREADY_STARTED;
    }
  }

  Entry = AllocatePool (sizeof (BM_BOOT_DESCRIPTION_ENTRY));
  if (Entry == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Entry->Signature = BM_BOOT_DESCRIPTION_ENTRY_SIGNATURE;
  Entry->Handler   = Handler;
  InsertTailList (&mPlatformBootDescriptionHandlers, &Entry->Link);
  return EFI_SUCCESS;
}
開發者ID:M1cha,項目名稱:edk2,代碼行數:38,代碼來源:BmBootDescription.c

示例15: GetStorageFromConfigString

/**
  Get the EFI_IFR_VARSTORE based the <ConfigHdr> string in a <ConfigRequest>
  or a <ConfigResp> string.
    
  @param FormSet                  The Form Set.
  @param ConfigString             The Configuration String which is defined by UEFI HII.
   
  @retval FORMSET_STORAGE *       The EFI_IFR_VARSTORE where the Question's value is stored.
  @retval NULL                    If the Form Set does not have EFI_IFR_VARSTORE with such ID.
**/
FORMSET_STORAGE *
GetStorageFromConfigString (
  IN CONST FORM_BROWSER_FORMSET *FormSet,
  IN  CONST EFI_STRING          ConfigString
  )
{
  LIST_ENTRY             *StorageList;
  FORMSET_STORAGE        *Storage;
  CHAR16                 *Name;

  if (ConfigString == NULL) {
    return NULL;
  }

  StorageList = GetFirstNode (&FormSet->StorageListHead);

  while (!IsNull (&FormSet->StorageListHead, StorageList)) {
    Storage = FORMSET_STORAGE_FROM_LINK (StorageList);

    if ((Storage->VarStoreId == FormSet->DefaultVarStoreId) && (FormSet->OriginalDefaultVarStoreName != NULL)) {
      Name = FormSet->OriginalDefaultVarStoreName;
    } else {
      Name = Storage->Name;
    }
    
    if (HiiIsConfigHdrMatch (ConfigString, &Storage->Guid, Name)) {
      return Storage;
    }

    StorageList = GetNextNode (&FormSet->StorageListHead, StorageList);
  }

  return NULL;
}
開發者ID:AshleyDeSimone,項目名稱:edk2,代碼行數:44,代碼來源:ConfigAccess.c


注:本文中的GetNextNode函數示例由純淨天空整理自Github/MSDocs等開源代碼及文檔管理平台,相關代碼片段篩選自各路編程大神貢獻的開源項目,源碼版權歸原作者所有,傳播和使用請參考對應項目的License;未經允許,請勿轉載。