source: cpp/frams/util/list.h

Last change on this file was 1314, checked in by Maciej Komosinski, 2 weeks 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
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2024  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#ifndef _LIST_H_
6#define _LIST_H_
7
8#include <stdlib.h>
9#include <string.h>
10#include <common/nonstd.h>
11#include <common/realloc-free0size.h>
12
13//#define SLISTSTATS
14
15#ifdef SLISTSTATS
16#include <stdio.h>
17class SListStats
18{
19public:
20        int objects, allocations, copied, totalmem, usedmem;
21        SListStats() :objects(0), allocations(0), copied(0), totalmem(0), usedmem() {}
22        ~SListStats()
23        {
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",
32                        objects, allocations, copied, totalmem, (usedmem * 100) / totalmem);
33        }
34};
35#endif
36
37
38template<class T> class SListTempl
39{
40protected:
41        int have, used, pos; // ile,zaj,poz
42        T *mem;
43        void resize(int x)
44        {
45                if (mem || x)
46                {
47                        mem = (T*)realloc_free0size(mem, x*sizeof(T));
48#ifdef SLISTSTATS
49                        SListStats::stats.allocations++;
50                        SListStats::stats.copied += sizeof(T)*min(x, have);
51#endif
52                }
53                have = x;
54        }
55
56public:
57
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)
63        {}
64        ~SListTempl()
65        {
66#ifdef SLISTSTATS
67                SListStats::stats.objects++;
68                SListStats::stats.totalmem += sizeof(T)*have;
69                SListStats::stats.usedmem += sizeof(T)*used;
70#endif
71                hardclear();
72        }
73
74        void needSize(int s)
75        {
76                if (s > have) resize(s + 3 + s / 8);
77        }
78        void operator+=(const T& e) ///< append one element
79        {
80                append(e);
81        }
82        void operator-=(const T& e) ///< remove one element
83        {
84                int i; if ((i = find(e)) >= 0) remove(i);
85        }
86        void remove(int i, int n = 1) ///< remove n elements from position i
87        {
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;
93        }
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;
103                for (int i = 0; i < size(); i++) if (l.mem[i] != mem[i]) return 0;
104                return 1;
105        }
106        int find(const T& e) const ///< return position of element, or -1 if not found
107        {
108                for (int i = 0; i<size(); i++) if (mem[i] == e) return i;
109                return -1;
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());
153                if (mem != NULL)
154                        memcpy(mem, src.mem, src.size()*sizeof(T));
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        }
166};
167
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_++)
170
171// usage example: FOREACH(char*,t,thelist) printf("t=%s\n",t);
172
173template<class T> class PtrListTempl : public SListTempl < T >
174{
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        }
180
181        T get(int i) const { return operator()(i); }
182        T& getref(int i) const { return SListTempl<T>::get(i); }
183};
184
185
186        typedef PtrListTempl<void*> SList;
187
188#endif
Note: See TracBrowser for help on using the repository browser.