All pastes #420801 Raw Edit

EddieGordo

public text v1 · immutable
·published 2007-04-02 12:17 UTC
rendered paste body
;-
;- Queue (v1.1) Structures & Constants
;-



;- Constants
#Queue_GetResVersion  = 1.1

#String = 4           ;/ indicating a string
#Structure = 5        ;/ indicating a structure



;- Structures
;/
Structure Variant_PB
  StructureUnion      ;/ the union of all PB-types
    b.b               ;/ for byte-interpretation
    w.w               ;/ for word-interpretation
    l.l               ;/ for long-interpretation or pointer to structure
    f.f               ;/ for float-interpretation
    s.s               ;/ for string-interpretation
  EndStructureUnion
  type.l              ;/ [ #Byte | #Word | #Long | #String | #Structure ]
EndStructure



;/
Structure QueueElement Extends Variant_PB
  nextElem.l          ;/ pointer to next QueueElement
  prevElem.l          ;/ pointer to previous QueueElement
EndStructure



;/
Structure Queue
  pHead.l             ;/ pointer to headelement
  pTail.l             ;/ pointer to tailelement
  pActElem.l          ;/ pointer to active element
  numElems.l          ;/ number of elements in queue
  resetFlag.l         ;/ active element placed  {1 = before head | -1 = behind tail}
EndStructure


;IncludeFile "Queue_RESIDENT.pbi" ; include if you don't have "Queue_RESIDENT.res" in your /Residents-directory

;/ 
;- Queue (v1.1)
;/ 
;/ ** not just a queue **
;/
;/ the following procedures give you all you need to handle dynamic data. You can use just the 'pure' 
;/ queue-functionality (enqueue/dequeue) or the 'active element'-browsing for functionality
;/ same as lists. Further you can insert and delete elements anywhere inside this queue.
;/ As elements you might use byte/word/long/float/string-values, or structures.
;/ You can arbitrary mix them inside a queue.
;/
;/ See the Queue_RESIDENT.pbi for details on the 'QueueElement' and the 'Variant_PB' - structure.
;/ 
;/ If you find any bugs please let me know: kurras@schalldesign.de
;/ 
;/ Froggerprogger 12.07.2004
;/ 




;-
;- Basic Procedures
;-
ProcedureDLL.l Queue_Create() ; Create a new queue. Return a pointer to it
  Protected *list.Queue
  *list = AllocateMemory(SizeOf(Queue))
  ProcedureReturn *list
EndProcedure

ProcedureDLL Queue_Clear(*p_list.Queue, p_keepData.l) ; Remove and delete all elements. If p_keepData <> 0 then the data of contained structures won't be deleted.
  If *p_list\pHead
    Protected *actElem.QueueElement
    Protected *lastActElem.QueueElement

    *actElem = *p_list\pHead
    *lastActElem = *actElem
    While *actElem
      *actElem = *actElem\nextElem
      If *lastActElem\type = #Structure And p_keepData = 0
        FreeMemory(*lastActElem\l)
      ElseIf *lastActElem\type = #String
        *lastActElem\s = ""
      EndIf
      FreeMemory(*lastActElem)
      *lastActElem = *actElem
    Wend
    
    *p_list\pHead = 0
    *p_list\pTail = 0
    *p_list\pActElem = 0
    *p_list\numElems = 0
  EndIf
EndProcedure

ProcedureDLL Queue_Destroy(*p_list.Queue, p_keepData.l) ; Remove and delete all elements and destroy queue. If p_keepData <> 0 then the data of contained structures won't be deleted.
  Queue_Clear(*p_list, p_keepData)
  FreeMemory(*p_list)
EndProcedure

ProcedureDLL.s Queue_VersionInfo()
  ProcedureReturn "Queue v1.1 / 12.07.2004 by Froggerprogger"
EndProcedure



;-
;- Enqueue - insert element at head
;-
ProcedureDLL.l Queue_EnqueueB(*p_list.Queue, p_b.b) ; Enqueue a byte-value-element. Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\b = p_b
  *actElem\type = #Byte
  *actElem\prevElem = *p_list\pTail
  
  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
  
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_EnqueueW(*p_list.Queue, p_w.w) ; Enqueue a word-value-element. Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\w = p_w
  *actElem\type = #Word
  *actElem\prevElem = *p_list\pTail
  
  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
  
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_EnqueueL(*p_list.Queue, p_l.l) ; Enqueue a long-value-element. Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\l = p_l
  *actElem\type = #Long
  *actElem\prevElem = *p_list\pTail

  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_EnqueueF(*p_list.Queue, p_f.f) ; Enqueue a float-value-element. Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\f = p_f
  *actElem\type = #Float
  *actElem\prevElem = *p_list\pTail
  
  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_EnqueueS(*p_list.Queue, p_s.s) ; Enqueue a string-value-element. Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\s = p_s
  *actElem\type = #String
  *actElem\prevElem = *p_list\pTail
  
  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_EnqueueStructure(*p_list.Queue, *p_struct.l, p_sizeOfStruct_Or_byRef.l) ; Enqueue a structure-element. Copy it's content (size > 0) or handle as reference (size <= 0). Make it the active element. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *tailElem.QueueElement
  Protected *actData.l
  
  *actElem = AllocateMemory(SizeOf(QueueElement))
  If *actElem = 0
    ProcedureReturn 0
  EndIf
  *actElem\type = #Structure
  *actElem\prevElem = *p_list\pTail
  
  If p_sizeOfStruct_Or_byRef > 0
    *actData = AllocateMemory(p_sizeOfStruct_Or_byRef)
    If *actData = 0
      FreeMemory(*actElem)
      ProcedureReturn 0
    EndIf
    CopyMemory(*p_struct, *actData, p_sizeOfStruct_Or_byRef)
    *actElem\l = *actData
  Else
    *actElem\l = *p_struct
  EndIf
  
  If *p_list\pTail
    *tailElem = *p_list\pTail
    *tailElem\nextElem = *actElem
  Else
    *p_list\pHead = *actElem    
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pTail = *actElem
  
  *p_list\numElems + 1
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure



;-
;- Insertion - insert elements in front of or behind the active element
;-
ProcedureDLL.l Queue_InsertB(*p_list.Queue, p_b.b, p_behind.l) ; Insert a byte-value-element in front of the active element (or behind, if p_behind <> 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\b = p_b
  *newElem\type = #Byte
    
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_InsertW(*p_list.Queue, p_w.w, p_behind.l) ; Insert a word-value-element in front of the active element (or behind, if p_behind <> 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\w = p_w
  *newElem\type = #Word
  
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_InsertL(*p_list.Queue, p_l.l, p_behind.l) ; Insert a long-value-element in front of the active element (or behind, if p_behind <> 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\l = p_l
  *newElem\type = #Long
  
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_InsertF(*p_list.Queue, p_f.f, p_behind.l) ; Insert a float-value-element in front of the active element (or behind, if p_behind <> 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\f = p_f
  *newElem\type = #Float
  
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_InsertS(*p_list.Queue, p_s.s, p_behind.l) ; Insert a string-value-element in front of the active element (or behind, if p_behind <> 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\s = p_s
  *newElem\type = #Word
  
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_InsertStructure(*p_list.Queue, *p_struct.l, p_sizeOfStruct_Or_byRef.l, p_behind.l) ; Insert a structure-element in front of the active element (or behind, if p_behind <> 0). Copy it's content (size > 0) or handle as reference (size <= 0). Make it the active element. Return actElemPointer
  Protected *newElem.QueueElement
  Protected *actElem.QueueElement
  Protected *nextOrPrevElem.QueueElement
  Protected *actData.l

  If *p_list\pActElem = 0
    ProcedureReturn 0
  Else 
    *actElem = *p_list\pActElem
  EndIf

  *newElem = AllocateMemory(SizeOf(QueueElement))
  If *newElem = 0
    ProcedureReturn 0
  EndIf
  
  *newElem\type = #Structure
  
  If p_sizeOfStruct_Or_byRef > 0
    *actData = AllocateMemory(p_sizeOfStruct_Or_byRef)
    If *actData = 0
      FreeMemory(*newElem)
      ProcedureReturn 0
    EndIf
    CopyMemory(*p_struct, *actData, p_sizeOfStruct_Or_byRef)
    *newElem\l = *actData
  Else
    *newElem\l = *p_struct
  EndIf
  
  If p_behind = 0 ; insert in front of *actElem
    *newElem\prevElem = *actElem\prevElem
    If *newElem\prevElem
      *nextOrPrevElem = *newElem\prevElem
      *nextOrPrevElem\nextElem = *newElem
    EndIf
    
    *newElem\nextElem = *actElem

    *actElem\prevElem = *newElem
    
    If *p_list\pHead = *actElem
      *p_list\pHead = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  Else ; insert behind *actElem
    *newElem\prevElem = *actElem
    *newElem\nextElem = *actElem\nextElem
    If *newElem\nextElem
      *nextOrPrevElem = *newElem\nextElem
      *nextOrPrevElem\prevElem = *newElem
    EndIf
    
    *actElem\nextElem = *newElem
    
    If *p_list\pTail = *actElem
      *p_list\pTail = *newElem
    EndIf
    
    *p_list\numElems + 1
  
  EndIf
  
  *p_list\resetFlag = 0
    
  *p_list\pActElem = *newElem
  ProcedureReturn *p_list\pActElem
EndProcedure



;-
;- Set - setting the value of the active element
;-
ProcedureDLL.l Queue_SetValB(*p_list.Queue, p_b.b, p_keepData.l) ; Set a new byte-value for the active element. If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf  
  *actElem\b = p_b
  *actElem\type = #Byte
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SetValW(*p_list.Queue, p_w.w, p_keepData.l) ; Set a new word-value for the active element. If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf  
  *actElem\w = p_w
  *actElem\type = #Word
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SetValL(*p_list.Queue, p_l.l, p_keepData.l) ; Set a new long-value for the active element. If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf  
  *actElem\l = p_l
  *actElem\type = #Long
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SetValF(*p_list.Queue, p_f.f, p_keepData.l) ; Set a new float-value for the active element. If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf  
  *actElem\f = p_f
  *actElem\type = #Float
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SetValS(*p_list.Queue, p_s.s, p_keepData.l) ; Set a new string-value for the active element. If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf
  *actElem\s = p_s
  *actElem\type = #String
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SetValStructure(*p_list.Queue, *p_struct.l, p_sizeOfStruct_Or_byRef.l, p_keepData.l) ; Set a new byte-value for the active element. Copy it's content (size > 0) or handle as reference (size <= 0). If p_keepData <> 0 a previous contained structure won't be freed. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *actData.l
  
  *actElem = *p_list\pActElem
  If p_keepData = 0 And *actElem\type = #Structure
    FreeMemory(*actElem\l)
  ElseIf *actElem\type = #String
    *actElem\s = ""
  EndIf

  If p_sizeOfStruct_Or_byRef > 0
    *actData = AllocateMemory(p_sizeOfStruct_Or_byRef)
    If *actData = 0
      ProcedureReturn 0
    EndIf
    CopyMemory(*p_struct, *actData, p_sizeOfStruct_Or_byRef)
    *actElem\l = *actData
  Else
    *actElem\l = *p_struct
  EndIf
  
  ProcedureReturn *actElem
EndProcedure



;-
;- Information on queue
;-
ProcedureDLL.l Queue_GetNumElems(*p_list.Queue) ; Return the number of Elements in queue (0 = empty queue)
  ProcedureReturn *p_list\numElems
EndProcedure

ProcedureDLL.l Queue_GetHeadElem(*p_list.Queue) ; Return a pointer to the head element of type .QueueElement without changing the active element
  ProcedureReturn *p_list\pHead
EndProcedure

ProcedureDLL.l Queue_GetTailElem(*p_list.Queue) ; Return a pointer to the head element of type .QueueElement without changing the active element
  ProcedureReturn *p_list\pTail
EndProcedure



;-
;- Information on active element
;-
ProcedureDLL.l Queue_GetElement(*p_list.Queue) ; Return a pointer to the active element of type .QueueElement (which extends .Variant_PB)
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_GetElementType(*p_list.Queue) ; Return type of active element (#Byte | ... | #String | #Structure) or -1 on error.
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\type
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

;/ Get Value

ProcedureDLL.b Queue_GetValB(*p_list.Queue) ; Return the byte-interpretation of the active element
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\b
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL.w Queue_GetValW(*p_list.Queue) ; Return the word-interpretation of the active element
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\w
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL.l Queue_GetValL(*p_list.Queue) ; Return the long-interpretation of the active element
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\l
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL.f Queue_GetValF(*p_list.Queue) ; Return the float-interpretation of the active element
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\f
  Else
    ProcedureReturn 0.0
  EndIf
EndProcedure

ProcedureDLL.s Queue_GetValS(*p_list.Queue) ; Return the string-interpretation of the active element
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\s
  Else
    ProcedureReturn "error: no valid list item"
  EndIf
EndProcedure

ProcedureDLL.l Queue_GetValStructure(*p_list.Queue) ; Return the pointer to the active element's structure. (Same as Queue_GetValL)
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *actElem
    ProcedureReturn *actElem\l
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL.s Queue_GetValToString(*p_list.Queue) ; Return a string describing the active element of ANY type
  Protected *actElem.QueueElement
  Protected result$
  
  *actElem = *p_list\pActElem
  If *actElem
    Select *actElem\type
      Case #Byte        : result$ = "(#Byte) "      + Str(*actElem\b)
      Case #Word        : result$ = "(#Word) "      + Str(*actElem\w)
      Case #Long        : result$ = "(#Long) "      + Str(*actElem\l)
      Case #Float       : result$ = "(#Float) "     + StrF(*actElem\f, 8)
      Case #String      : result$ = "(#String) "    + *actElem\s
      Case #Structure   : result$ = "(#Structure) " + Str(*actElem\l)
    EndSelect
    ProcedureReturn result$
  Else
    ProcedureReturn "error: no valid list item"
  EndIf
EndProcedure



;-
;- Navigation - changes on the active element
;-
ProcedureDLL Queue_Reset(*p_list.Queue) ; Set the actElemPointer BEFORE the first element for calling Queue_Next()
  *p_list\pActElem = 0
  *p_list\resetFlag = 1
EndProcedure

ProcedureDLL.l Queue_Next(*p_list.Queue) ; Set the actElemPointer to next element. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  
  If *actElem ; If *actElem <> 0 never the reset-flag is set
    *p_list\pActElem = *actElem\nextElem
    If *p_list\pActElem = 0
      *p_list\resetFlag = -1
    EndIf
    ProcedureReturn *p_list\pActElem    
    
  ElseIf *p_list\resetFlag = 1
    *p_list\resetFlag = 0
    *p_list\pActElem = *p_list\pHead
    ProcedureReturn *p_list\pActElem
    
  Else
    ProcedureReturn 0   
  EndIf
EndProcedure

ProcedureDLL.l Queue_Prev(*p_list.Queue) ; Set the actElemPointer to previous element. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  If *p_list\resetFlag = 0 And *actElem <> 0 
    *p_list\pActElem = *actElem\prevElem
    If *p_list\pActElem = 0
      *p_list\resetFlag = 1
    EndIf
    ProcedureReturn *p_list\pActElem
  
  ElseIf *p_list\resetFlag = -1
    *p_list\resetFlag = 0
    *p_list\pActElem = *p_list\pTail
    ProcedureReturn *p_list\pActElem
    
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL.l Queue_SelectHead(*p_list.Queue) ; Set the actElemPointer to the head of the queue. Return actElemPointer
  *p_list\resetFlag = 0
  *p_list\pActElem = *p_list\pHead
  ProcedureReturn *p_list\pActElem
EndProcedure

ProcedureDLL.l Queue_SelectTail(*p_list.Queue) ; Set the actElemPointer to the tail of the queue. Return actElemPointer
  *p_list\resetFlag = 0
  *p_list\pActElem = *p_list\pTail
  ProcedureReturn *p_list\pActElem  
EndProcedure

ProcedureDLL.l Queue_SelectID(*p_list.Queue, p_id.l) ; Set the actElemPointer to element with given ID (0 = head-element). Return actElemPointer
  Protected *actElem.QueueElement
  Protected count.l
  
  *actElem = *p_list\pHead
  
  While count < p_id And *actElem
    *actElem = *actElem\nextElem
    count + 1
  Wend
  
  *p_list\resetFlag = 0
  
  *p_list\pActElem = *actElem
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_SelectRef(*p_list.Queue, *p_QueueElement.l) ; Set the actElemPointer to element with given QueueElement-pointer. Return actElemPointer
  Protected *actElem.QueueElement
  
  *actElem = *p_list\pHead
  
  While *actElem <> *p_QueueElement And *actElem
    *actElem = *actElem\nextElem
  Wend
  *p_list\resetFlag = 0
  
  *p_list\pActElem = *actElem
  ProcedureReturn *p_list\pActElem
EndProcedure



;-
;- Dequeue - remove an element from head
;-
ProcedureDLL.l Queue_Dequeue(*p_list.Queue, p_keepData.l) ; Dequeue and delete head's element without returning it's value. If p_keepData = 1 then a contained structure won't be deleted (you'll have to free it on your own). If p_keepData = 2 then in addition the QueueElementstructure itself won't be deleted (and you'll have to free it on your own). Keep actElemPointer or reset the list if it was the previous head. Return pointer to new head (if p_keepData = 0) or a pointer to the contained structure (if p_keepData = 1) or a pointer to the dequeued QueueElement-structure (if p_keepData = 2)
  Protected *nextElem.QueueElement
  Protected *headElem.QueueElement
  Protected returnval.l

  *headElem = *p_list\pHead

  If *headElem = 0
    ProcedureReturn #False
  Else
    *nextElem = *headElem\nextElem
  EndIf

  If *headElem = *p_list\pActElem
    *p_list\pActElem = 0
    *p_list\resetFlag = 1
  EndIf

  If *nextElem
    *nextElem\prevElem = 0
  Else
    *p_list\pTail = 0
  EndIf

  *p_list\pHead = *nextElem
  
  If *headElem\type = #Structure And p_keepData < 1
    FreeMemory(*headElem\l)
  ElseIf *headElem\type = #String
    *headElem\s = ""
  EndIf
  
  *p_list\numElems - 1
  
  If p_keepData = 2
    ProcedureReturn *headElem
    
  ElseIf p_keepData = 1
    returnval = *headElem\l
    FreeMemory(*headElem)
    ProcedureReturn returnval
    
  Else
    FreeMemory(*headElem)
    ProcedureReturn *p_list\pHead
    
  EndIf
EndProcedure

ProcedureDLL.l Queue_DequeueElement(*p_list.Queue) ; Dequeue headelement but does NOT free it's memory (you'll have to free it on your own). Keep actElemPointer or set it to head again if it was the previous head. Return pointer to structure .QueueElement (which extends .Variant_PB)
  Protected *actElem.QueueElement
  *actElem = *p_list\pHead
  *struct = *actElem\l
  
  If *actElem = *p_list\pActElem
    *p_list\pActElem = 0
    *p_list\resetFlag = 1
  EndIf
  
  Queue_Dequeue(*p_list, 2)
  ProcedureReturn *struct
EndProcedure

ProcedureDLL.b Queue_DequeueB(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected b.b
  *actElem = *p_list\pHead
  b = *actElem\b
  Queue_Dequeue(*p_list, 0)
  ProcedureReturn b
EndProcedure

ProcedureDLL.w Queue_DequeueW(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected w.w
  *actElem = *p_list\pHead
  w = *actElem\w
  Queue_Dequeue(*p_list, 0)
  ProcedureReturn w
EndProcedure

ProcedureDLL.l Queue_DequeueL(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected l.l
  *actElem = *p_list\pHead
  l = *actElem\b
  Queue_Dequeue(*p_list, 0)
  ProcedureReturn l
EndProcedure

ProcedureDLL.f Queue_DequeueF(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected f.f
  *actElem = *p_list\pHead
  f = *actElem\f
  Queue_Dequeue(*p_list, 0)
  ProcedureReturn f
EndProcedure

ProcedureDLL.s Queue_DequeueS(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected s.s
  *actElem = *p_list\pHead
  If *actElem
    s = *actElem\s
    *actElem\s = ""
  Else
    s = "error: no valid list item"
  EndIf
  Queue_Dequeue(*p_list, 0)
  ProcedureReturn s
EndProcedure

ProcedureDLL.l Queue_DequeueStructure(*p_list.Queue) ; Dequeue headelement but does NOT free the memory of your contained structure (you'll have to free it on your own). Keep actElemPointer or reset list if it was the previous head. Return pointer to the contained structure.
  Protected *actElem.QueueElement
  Protected *struct.l
  *actElem = *p_list\pHead
  *struct = *actElem\l
  Queue_Dequeue(*p_list, 1)
  ProcedureReturn *struct
EndProcedure

ProcedureDLL.s Queue_DequeueToString(*p_list.Queue) ; Dequeue headelement. Keep actElemPointer or reset list if it was the previous head. Return the value of head's element.
  Protected *actElem.QueueElement
  Protected result$
  
  *actElem = *p_list\pHead
  If *actElem <> 0
    Select *actElem\type
      Case #Byte        : result$ = "(#Byte) "      + Str(*actElem\b)
      Case #Word        : result$ = "(#Word) "      + Str(*actElem\w)
      Case #Long        : result$ = "(#Long) "      + Str(*actElem\l)
      Case #Float       : result$ = "(#Float) "     + StrF(*actElem\f, 8)
      Case #String      : result$ = "(#String) "    + *actElem\s
      Case #Structure   : result$ = "(#Structure) " + Str(*actElem\l)
    EndSelect
  Else
    result$ = "error: no valid list item"
  EndIf

  Queue_Dequeue(*p_list, 0)
  
  ProcedureReturn result$

EndProcedure



;-
;- Delete - remove an element from somewhere
;-
ProcedureDLL.l Queue_Delete(*p_list.Queue, p_keepData.l) ; Delete active element. If p_keepData = 1 then a contained structure won't be deleted (you'll have to free it on your own). Set actElemPointer to next one or to tail if it was the previous tail. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *nextElem.QueueElement
  Protected *prevElem.QueueElement
  
  If *p_list\pActElem
    *actElem = *p_list\pActElem
    *nextElem = *actElem\nextElem
    *prevElem = *actElem\prevElem
    If *nextElem And *prevElem
      *nextElem\prevElem = *prevElem
      *prevElem\nextElem = *nextElem
    ElseIf *nextElem
      *nextElem\prevElem = 0
    ElseIf *prevElem
      *prevElem\nextElem = 0
      *p_list\pTail = *prevElem
    Else
      *p_list\pHead = 0
      *p_list\pTail = 0
    EndIf
    
    *p_list\pActElem = *nextElem
   
    If *actElem\type = #Structure And p_keepData = 0
      FreeMemory(*actElem\l)
    ElseIf *actElem\type = #String
      *actElem\s = ""
    EndIf
    
    FreeMemory(*actElem)
     
    *p_list\numElems - 1
    
    If *p_list\pActElem = 0
      *p_list\pActElem = *p_list\pTail
    EndIf
    
    ProcedureReturn *p_list\pActElem

  Else
    ProcedureReturn #False
  EndIf
EndProcedure

ProcedureDLL.l Queue_DeleteID(*p_list.Queue, p_id.l, p_keepData.l) ; Delete element with given ID (0 = head-element). If p_keepData = 1 then a contained structure won't be deleted (you'll have to free it on your own). Keep actElemPointer or reset list if itself was cleared. Return actElemPointer
  Protected *actElem.QueueElement
  *actElem = *p_list\pActElem
  
  If Queue_SelectID(*p_list, p_id) = *actElem
    *actElem = 0
    *p_list\resetFlag = 1
  EndIf
  Queue_Delete(*p_list, p_keepData.l)
  *p_list\pActElem = *actElem
  ProcedureReturn *actElem
EndProcedure

ProcedureDLL.l Queue_DeleteRef(*p_list.Queue, *p_QueueElement.QueueElement, p_keepData.l) ; Delete element with given QueueElement-pointer to it. If p_keepData = 1 then a contained structure won't be deleted (you'll have to free it on your own). Keep actElemPointer or reset list if itself was cleared. Return actElemPointer
  Protected *actElem.QueueElement
  Protected *origActElem.QueueElement
  
  *actElem = *p_list\pHead
  
  While *actElem <> *p_QueueElement And *actElem
    *actElem = *actElem\nextElem
  Wend
  
  *origActElem = *p_list\pActElem
  If *actElem = *p_QueueElement
    *p_list\pActElem = *actElem
    Queue_Delete(*p_list, p_keepData.l)
  EndIf
  
  If *origActElem = *actElem
    *p_list\pActElem = 0
    *p_list\resetFlag = 1
    ProcedureReturn 0
  Else
    *p_list\pActElem = *origActElem
    ProcedureReturn *p_list\pActElem
  EndIf
  
EndProcedure



;-
;-
;-