source: cpp/frams/util/list.h @ 1334

Last change on this file since 1334 was 1314, checked in by Maciej Komosinski, 6 months ago

Added realloc() implementation that behaves like free() when size==0 - consistently on all platforms, in contrast to standard realloc()

  • Property svn:eol-style set to native
File size: 4.6 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[1314]2// Copyright (C) 1999-2024  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
5#ifndef _LIST_H_
6#define _LIST_H_
7
8#include <stdlib.h>
9#include <string.h>
10#include <common/nonstd.h>
[1314]11#include <common/realloc-free0size.h>
[109]12
13//#define SLISTSTATS
14
15#ifdef SLISTSTATS
16#include <stdio.h>
17class SListStats
18{
[733]19public:
20        int objects, allocations, copied, totalmem, usedmem;
[793]21        SListStats() :objects(0), allocations(0), copied(0), totalmem(0), usedmem() {}
[733]22        ~SListStats()
[109]23        {
[733]24                printf("------------------------\n"
25                        " SListStats:\n"
26                        " objects     = %ld\n"
27                        " allocations = %ld\n"
28                        " copied      = %ld\n"
29                        " total mem   = %ld\n"
30                        " usage       = %ld %%\n"
31                        "------------------------\n",
[793]32                        objects, allocations, copied, totalmem, (usedmem * 100) / totalmem);
[109]33        }
34};
35#endif
36
37
38template<class T> class SListTempl
39{
40protected:
[733]41        int have, used, pos; // ile,zaj,poz
42        T *mem;
43        void resize(int x)
[109]44        {
[733]45                if (mem || x)
[109]46                {
[1314]47                        mem = (T*)realloc_free0size(mem, x*sizeof(T));
[109]48#ifdef SLISTSTATS
[733]49                        SListStats::stats.allocations++;
[793]50                        SListStats::stats.copied += sizeof(T)*min(x, have);
[1314]51#endif
[109]52                }
[733]53                have = x;
[109]54        }
55
56public:
57
[733]58        SListTempl(const SListTempl<T>& src) :have(0), used(0), pos(0), mem(0)
59        {
60                (*this) = src;
61        }
62        SListTempl() :have(0), used(0), pos(0), mem(0)
[109]63        {}
[733]64        ~SListTempl()
[109]65        {
66#ifdef SLISTSTATS
[733]67                SListStats::stats.objects++;
[793]68                SListStats::stats.totalmem += sizeof(T)*have;
69                SListStats::stats.usedmem += sizeof(T)*used;
[109]70#endif
[733]71                hardclear();
[109]72        }
73
[733]74        void needSize(int s)
[109]75        {
[733]76                if (s > have) resize(s + 3 + s / 8);
[109]77        }
[733]78        void operator+=(const T& e) ///< append one element
[109]79        {
[733]80                append(e);
[109]81        }
[733]82        void operator-=(const T& e) ///< remove one element
[109]83        {
[733]84                int i; if ((i = find(e)) >= 0) remove(i);
[109]85        }
[733]86        void remove(int i, int n = 1) ///< remove n elements from position i
[109]87        {
[733]88                if ((i >= size()) || (i<0)) return;
89                if (i>(size() - n)) n = size() - i;
90                if (pos >= i) pos -= n;
91                memmove(mem + i, mem + i + n, sizeof(T)*(used - n - i));
92                used -= n;
[109]93        }
[733]94        void operator-=(int i) { remove(i); } ///< remove element from position i
95        T& operator()(int i) const ///< return element at position i
96        {
97                return mem[i];
98        }
99        bool hasMore() { return pos < size(); }
100        int operator==(const SListTempl<T>& l) const ///< compare list
101        {
102                if (size() != l.size()) return 0;
[793]103                for (int i = 0; i < size(); i++) if (l.mem[i] != mem[i]) return 0;
[733]104                return 1;
105        }
106        int find(const T& e) const ///< return position of element, or -1 if not found
107        {
[781]108                for (int i = 0; i<size(); i++) if (mem[i] == e) return i;
109                return -1;
[733]110        }
111        void append(const T& data) ///< add 1 element
112        {
113                needSize(size() + 1); mem[used++] = data;
114        }
115        void append(const T* data, int n) ///< add n elements
116        {
117                needSize(size() + n);
118                memcpy(mem + used, data, sizeof(T)*n);
119                used += n;
120        }
121        void insert(int p, T* data, int n) ///< insert n elements at position p
122        {
123                if (p>size()) p = size();
124                needSize(size() + n);
125                memmove(mem + p + n, mem + p, sizeof(T)*(size() - p));
126                memcpy(mem + p, data, sizeof(T)*n);
127                if (pos > p) pos += n;
128        }
129        void insert(int p, const T& data) ///< insert 1 element at position p
130        {
131                if (p > size()) p = size();
132                needSize(size() + 1);
133                memmove(mem + p + 1, mem + p, sizeof(T)*(size() - p));
134                if (pos > p) pos++;
135                mem[p] = data;
136                used++;
137        }
138        void set(int p, const T& d)
139        {
140                needSize(p + 1); mem[p] = d; if (used < (p + 1)) used = p + 1;
141        }
142        void setSize(int s)
143        {
144                needSize(s); used = s;
145        }
146        T& get(int i) const { return operator()(i); }
147        void clear() { used = 0; } ///< remove all elements
148        void hardclear() { resize(0); used = 0; } ///< remove all elements and free mem
149        int size() const { return used; } ///< list size
150        void operator=(const SListTempl<T>&src) ///duplicate
151        {
152                setSize(src.size());
[1314]153                if (mem != NULL)
154                        memcpy(mem, src.mem, src.size()*sizeof(T));
[733]155        }
156        void operator+=(const SListTempl<T>&src) ///< append src contents
157        {
158                needSize(size() + src.size());
159                memcpy(mem + used, src.mem, src.size()*sizeof(T));
160                used += src.used;
161        }
162        void trim(int newsiz)
163        {
164                if (newsiz < used) used = newsiz;
165        }
[109]166};
167
[153]168#define FOREACH(type,var,list) for(int _ ## var ## _i_=0,_ ## var ## _tmp_=0; _ ## var ## _i_==0;_ ## var ## _i_++) \
169                for(type var;((_ ## var ## _tmp_=(_ ## var ## _i_<list.size()))?(var=(type)list(_ ## var ## _i_)):0),_ ## var ## _tmp_;_ ## var ## _i_++)
[109]170
171// usage example: FOREACH(char*,t,thelist) printf("t=%s\n",t);
172
[733]173template<class T> class PtrListTempl : public SListTempl < T >
[109]174{
[733]175public:
176        T operator()(int i) const ///< return element at position i
177        {
178                if (i >= this->size()) return 0; else return this->mem[i];
179        }
[109]180
[733]181        T get(int i) const { return operator()(i); }
182        T& getref(int i) const { return SListTempl<T>::get(i); }
[109]183};
184
185
[733]186        typedef PtrListTempl<void*> SList;
[109]187
188#endif
Note: See TracBrowser for help on using the repository browser.