src/global/SAL_list.h

00001 /*
00002     SAL - Simple Application Library
00003     Copyright (C) 2006-2006 Kronon
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Lesser General Public
00007     License as published by the Free Software Foundation; either
00008     version 2.1 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Lesser General Public License for more details.
00014 
00015     You should have received a copy of the GNU Lesser General Public
00016     License along with this library; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019     Kronon
00020     kronon88@users.sourceforge.net
00021 */
00022 
00023 //SAL list class
00024 //Created by Kronon
00025 
00026 #ifndef SAL_LIST_H
00027 #define SAL_LIST_H
00028 
00029 //Include for error messaging system
00030 #include "SAL_console.h"
00031 
00032 template<class SAL_list_entry>
00033 class salList
00034 {
00035         private:
00036                 struct SAL_list_node
00037                 {
00038                         public:
00039                                 SAL_list_node *next;
00040                                 SAL_list_node *previous;
00041                                 SAL_list_entry entry;
00042                 };
00043                 
00044                 //Nr. of entries
00045                 int size;
00046                 SAL_list_node *begin;
00047                 SAL_list_node *end;
00048                 SAL_list_node *current;
00049                 Uint32 loop_position;
00050         
00051         public:
00052         
00053                 salList();
00054                 //Functions for accessing the list
00055                 int append(SAL_list_entry );                                                            //Add an new entry to the end of the list
00056                 int pop();                                                                                                      //Remove the last entry
00057                 int top(SAL_list_entry &);                                                                      //Read the last entry
00058                 
00059                 int clear();                                                                                            //Clear the list
00060                 bool isEmpty();                                                                                         //Is the list empty?
00061                 int getSize();                                                                                          //Get the size of the list
00062                 
00063                 int funcRemove(bool (*)(SAL_list_entry, SAL_list_entry), SAL_list_entry condition, int times = -1);     //Remove entries using an function
00064                 
00065                 //For/While loop functionality
00066                 bool inLoop(int stepSize=1);                                                            //while(list.inWhile(increment)){ }
00067                 SAL_list_entry getLoopEntry();                                                          //Get current loop entry
00068                 void setLoopBegin();                                                                            //Set walk truh pointer to beginning of list
00069                 
00070                 //Operators of the list
00071                 SAL_list_entry operator[]( int position);                                       //Get variable from given point
00072                 int operator-=( SAL_list_entry entry);                                          //Remove variable from list
00073 
00074 };
00075 
00076 //Constructor
00077 template<class SAL_list_entry> 
00078 salList<SAL_list_entry>::salList()
00079 {
00080         begin = end = current = NULL;
00081         size = 0;
00082         loop_position =0;
00083 }
00084 
00085 //Remove the last entry of the list
00086 template<class SAL_list_entry> 
00087 int salList<SAL_list_entry>::clear()
00088 {
00089         //Remove the last nodes in the list
00090         SAL_list_node *node;
00091         while(begin != NULL)
00092         {
00093                 node = begin->next;
00094                 delete begin;
00095                 begin = node;           
00096         }
00097         begin = end = current = NULL;
00098         
00099         //Decrease list size
00100         size = 0;
00101         return 0;
00102 }
00103 
00104 //Remove the last entry of the list
00105 template<class SAL_list_entry> 
00106 int salList<SAL_list_entry>::pop()
00107 {
00108         if(size == 0)
00109                 return -1;
00110         
00111         //Remove the last node in the list
00112         SAL_list_entry *node = end;
00113         end = end->previous;
00114         delete node;
00115         
00116         //Decrease list size
00117         size--;
00118         return 0;
00119 }
00120 
00121 //Get the last entry of the list
00122 template<class SAL_list_entry> 
00123 int salList<SAL_list_entry>::top(SAL_list_entry &entry)
00124 {
00125         if(size == 0)
00126                 return -1;
00127         
00128         entry = end->entry;
00129         return 0;
00130 }
00131 
00132 //Add an entry to the end of the list
00133 template<class SAL_list_entry> 
00134 int salList<SAL_list_entry>::append(SAL_list_entry entry)
00135 {
00136         SAL_list_node *node = new SAL_list_node;
00137         node->next = NULL;
00138         node->entry = entry;
00139         
00140         if( begin == NULL)
00141                 begin = node;
00142         else
00143                 end->next = node;
00144         
00145         node->previous = end;
00146         end = node;
00147         size++;
00148         
00149         return 0;
00150 }
00151 
00152 //Return the size of the list
00153 template<class SAL_list_entry> 
00154 int salList<SAL_list_entry>::getSize()
00155 {
00156         return size;
00157 }
00158 
00159 //Check if the list is empty
00160 template<class SAL_list_entry> 
00161 bool salList<SAL_list_entry>::isEmpty()
00162 {
00163         return (size == 0);
00164 }
00165 
00166 //Get the n'th entry and return it
00167 template<class SAL_list_entry> 
00168 SAL_list_entry salList<SAL_list_entry>::operator[](int pos)
00169 {
00170         //Some basic sanity checks
00171         if(size == 0)
00172         {
00173 #ifdef SAL_DEBUG_ON
00174                 salError("The size of your list is 0, there is nothing to be found");
00175 #endif
00176                 return 0;
00177         }
00178         else if(pos >= size)
00179         {
00180 #ifdef SAL_DEBUG_ON
00181                 salError("You want to search outside the list, there is nothing to be found");
00182 #endif
00183                 return 0;
00184         }
00185         
00186         // Find the "pos"'t target
00187         SAL_list_node *node= begin;
00188         for(int i = 0; i < pos; i++)
00189         {
00190                 node=node->next;
00191         }
00192         return node->entry;
00193 }
00194 
00195 //Remove 1 entry with the value of given value
00196 template<class SAL_list_entry> 
00197 int salList<SAL_list_entry>::operator-=(SAL_list_entry entry)
00198 {
00199         if(size == 0)
00200         {
00201 #ifdef SAL_DEBUG_ON
00202                 salError(" The size of your list is %i, there is nothing to be found",size);
00203 #endif
00204                 return 0;
00205         }
00206         
00207         SAL_list_node *node, *next_node;        //Node that run truh list, node that gets deleted
00208         node = begin;
00209         do
00210         {
00211                 next_node = node->next;
00212                 
00213                 if(node->entry == entry)
00214                 {
00215                         size--;
00216                         //Route list around current node
00217                         if(node->previous == NULL)              //First node doesn't have a previous node
00218                         {
00219                                 begin = node->next;                     //Make next node first node
00220                                 if(begin != NULL)
00221                                         begin->previous = NULL;
00222                         }
00223                         else
00224                         {
00225                                 node->previous->next = node->next;
00226                                 if(node->next != NULL)
00227                                         node->next->previous = node->previous;
00228                         }
00229                         
00230                         //Delete node
00231                         if(node == current)                     //Current node should alway point to valid node
00232                                 setLoopBegin();
00233                         delete node;
00234                         
00235                         if(size == 0)
00236                                 clear();
00237                         return 1;
00238                 }
00239                 node = next_node;
00240                 
00241         }
00242         while(node != NULL);
00243         return 0;
00244 }
00245 
00246 //Remove 1 value by selection criterium given by function
00247 //When funtion returns "not false" the routine will delete the node
00248 template<class SAL_list_entry> 
00249 int salList<SAL_list_entry>::funcRemove(bool (*function)(SAL_list_entry, SAL_list_entry), SAL_list_entry condition, int times)
00250 {
00251         SAL_list_node *node = begin, *next_node;
00252         if(node == NULL)
00253         {
00254 #ifdef SAL_DEBUG_ON
00255                 salError("The size of your list is %i, there is nothing to be found", size);
00256 #endif
00257                 return 0;
00258         }
00259         do
00260         {
00261                 next_node = node->next;
00262                 if((*function)(node->entry,condition))
00263                 {
00264                         size--;
00265 
00266                         //Route list around current node
00267                         if(node == begin)                               //First node doesn't have a previous node
00268                                 begin = node->next;                     //Make next node first node
00269                         else
00270                                 node->previous->next = node->next;
00271                         
00272                         if(node == end)
00273                                 end = node->previous;
00274                         else
00275                                 node->next->previous = node->previous;
00276                         
00277                         if(node == current)                     //Current node should alway point to valid node
00278                                 setLoopBegin();
00279                         //Delete node
00280                         delete node;
00281                         
00282                         if(size == 0)
00283                                 clear();
00284                         return 1;
00285                 }
00286                 node = next_node;
00287                 
00288                 if(times != -1)                                         //Count back times that are left
00289                         times--;
00290         }
00291         while(node != NULL && times != 0);
00292 #ifdef SAL_DEBUG_ON
00293         printf("##Nothing found\n\n\n");
00294 #endif
00295         return 0;
00296 }
00297 
00298 //while/for loop functionality
00299 
00300 template<class SAL_list_entry>
00301 void salList<SAL_list_entry>::setLoopBegin()                                                                    //Set walk truh pointer to beginning of list
00302 {
00303         loop_position = 0;                                                                                                                      //(loop_position++)
00304         current = begin;
00305 }
00306 
00307 template<class SAL_list_entry> 
00308 bool salList<SAL_list_entry>::inLoop(int stepSize)                                                              //while(list.inLoop()){ }
00309 {
00310         loop_position++;
00311         if(size == 0)                                                                                                                           //Only loop truh filled lists
00312                 return false;
00313         if(loop_position > (Uint32)size)                                                                                        //We have passed the end of the list so loop no further;)
00314                 return false;
00315         
00316         if(loop_position != 1)                                                                                                          //Also show first node;)
00317         {
00318                 if(current != NULL)
00319                         for(int i=0; i < stepSize; i++)
00320                                 current = current->next;
00321         }
00322         
00323         return true;
00324 }
00325 
00326 template<class SAL_list_entry> 
00327 SAL_list_entry salList<SAL_list_entry>::getLoopEntry()                                                  //Get current walk truh entry
00328 {
00329         if(current != NULL)
00330                 return current->entry;
00331                 
00332 #ifdef SAL_DEBUG_ON
00333         printf("Size = %i\n",size);     //debug
00334                 
00335         //After this line debug
00336         printf("salList: Error entry doesn't exist\n");
00337 #endif
00338         return current->entry;
00339 }
00340 
00341 #endif