Files
2026-08-03 18:42:47 +08:00

221 lines
4.7 KiB
C++

/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* Copyright (c) Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#ifndef _H_ListMacros
#define _H_ListMacros
/* simplest possible single-linked list */
#include"MemoryDebug.h"
#include"Err.h"
#include"Result.h"
#define ListInit(List) List = nullptr
#define ListAppend(List,Elem,Link,ElemType) \
{ \
ElemType *current = (List); \
ElemType *previous = nullptr; \
while(current) \
{ \
previous = current; \
current = current->Link; \
} \
if(previous) \
previous->Link = Elem; \
else \
(List) = Elem; \
(Elem)->Link = nullptr; \
}
/**
* @brief appends element to list
* @param list list to append element to
* @param ele element to append
* @tparam ElemType type of the element
*/
template<typename ElemType>
void ListAppendT(ElemType*& list, ElemType* ele){
ElemType* current = list;
ElemType* previous = nullptr;
while(current){
previous = current;
current = current->next;
}
if(previous){
previous->next = ele;
} else{
list = ele;
}
ele->next = nullptr;
}
#define ListFree(List,Link,ElemType) \
{ \
ElemType *current = List; \
ElemType *previous = nullptr; \
while(current) \
{ \
if(previous) \
mfree(previous); \
previous = current; \
current = current->Link; \
} \
if(previous) \
mfree(previous); \
(List) = nullptr; \
}
#define ListDetach(List,Elem,Link,ElemType) \
{ \
ElemType *current = List; \
ElemType *previous = nullptr; \
while(current) \
{ \
if(current == (Elem)) \
break; \
previous = current; \
current = current->Link; \
} \
if(current) \
{ \
if(previous) \
previous->Link = current->Link; \
else \
(List) = current->Link; \
(Elem)->Link = nullptr; \
} \
}
/**
* @brief removes element from list
* @param list list to remove element from
* @param ele element to remove
* @tparam ElemType type of the element
* @return removed element
* @note Removed element should be same as ele input.
*/
template<typename ElemType>
ElemType* ListDetachT(ElemType*& list, ElemType* ele){
ElemType* current = list;
ElemType* previous = nullptr;
while(current){
if(current == ele){
break;
}
previous = current;
current = current->next;
}
if(current){
if(previous){
previous->next = current->next;
}
else{
list = current->next;
}
ele->next = nullptr;
}
return ele;
}
#define ListDelete(List,Elem,Link,ElemType) \
{ \
ElemType *copy = (Elem); \
ListDetach(List,copy,Link,ElemType); \
mfree(copy); \
}
#define ListIterate(List,Counter,Link) \
( (Counter) = ((List) ? (((Counter) ? (Counter)->Link : (List))) : nullptr))
/* Elem handling routines */
#define ListElemAlloc(G,Elem,ElemType) \
{ \
if(!(Elem)) \
{ \
(Elem) = pymol::malloc<ElemType>(1); \
ErrChkPtr(G,Elem); \
} \
}
#define ListElemCalloc(G,Elem,ElemType) \
{ \
if(!(Elem)) \
{ \
(Elem) = pymol::calloc<ElemType>(1); \
ErrChkPtr(G,Elem); \
} \
}
#define ListElemFree(Elem) { mfree(Elem); Elem = nullptr; }
/**
* Retrives position of element in list
* @param ele target element
* @return position in list
*/
template<typename ElemType>
pymol::Result<std::size_t> ListGetPosition(ElemType*& list, ElemType* ele)
{
ElemType* current = list;
std::size_t i = 0;
for (; current; i++, current = current->next) {
if (current == ele) {
return i;
}
}
return pymol::make_error("Element not found");
}
/**
* Inserts an element at given position
* @param ele target element
* @param pos position in list
*/
template<typename ElemType>
pymol::Result<> ListInsertAt(ElemType*& list, ElemType* ele, std::size_t pos)
{
ElemType* current = list;
ElemType* previous = nullptr;
std::size_t i = 0;
while (current) {
if (i++ == pos) {
ele->next = current;
if (previous) {
previous->next = ele;
}
return {};
}
previous = current;
current = current->next;
}
if (i == pos) {
previous->next = ele;
return {};
}
return pymol::make_error("Invalid pos");
}
#endif /* _H_ListMacros */