source: branches/stable/CORE/arb_strarray.h

Last change on this file was 11626, checked in by westram, 5 years ago
File size: 6.4 KB
Line 
1// ============================================================ //
2//                                                              //
3//   File      : arb_strarray.h                                 //
4//   Purpose   : handle arrays of strings                       //
5//                                                              //
6//   Coded by Ralf Westram (coder@reallysoft.de) in July 2011   //
7//   Institute of Microbiology (Technical University Munich)    //
8//   http://www.arb-home.de/                                    //
9//                                                              //
10// ============================================================ //
11
12#ifndef ARB_STRARRAY_H
13#define ARB_STRARRAY_H
14
15#ifndef _GLIBCXX_CSTDLIB
16#include <cstdlib>
17#endif
18#ifndef ARBTOOLS_H
19#include <arbtools.h>
20#endif
21#ifndef ARB_ASSERT_H
22#include <arb_assert.h>
23#endif
24#ifndef _GLIBCXX_ALGORITHM
25#include <algorithm>
26#endif
27
28
29typedef int (*CharPtrArray_compare_fun)(const void *p0, const void *p1, void *client_data); // same as arb_sort.h@gb_compare_function
30
31class CharPtrArray : virtual Noncopyable {
32    size_t allocated;
33
34protected:
35    char   **str;
36    size_t   elems;
37
38    bool ok() const {
39        if (!str) {
40            return elems == 0 && allocated == 0;
41        }
42        return str[elems] == NULL && allocated > elems;
43    }
44
45    bool elem_index(int i) const { return i >= 0 && size_t(i)<elems; }
46    bool allocated_index(int i) const { return i >= 0 && size_t(i)<allocated; }
47
48    void set_space(size_t new_allocated) {
49        if (new_allocated != allocated) {
50            arb_assert(ok());
51            size_t memsize = new_allocated*sizeof(*str);
52            str = (char**)(str ? realloc(str, memsize) : malloc(memsize));
53            if (new_allocated>allocated) memset(str+allocated, 0, (new_allocated-allocated)*sizeof(*str));
54            allocated = new_allocated;
55            arb_assert(ok());
56        }
57    }
58
59    void reserve_space(size_t forElems, bool alloc_ahead) {
60        if (allocated <= forElems) {
61            forElems = alloc_ahead ? (forElems>7 ? forElems*3/2 : 10) : forElems;
62            set_space(forElems+1); // always allocate one element more (sentinel element)
63        }
64    }
65
66    CharPtrArray() : allocated(0), str(NULL), elems(0) {}
67    virtual ~CharPtrArray() { free(str); }
68
69    virtual void free_elem(int i) = 0;
70
71    void erase_elems() {
72        arb_assert(ok());
73        if (!empty()) {
74            for (size_t i = 0; i<elems; ++i) free_elem(i);
75            elems = 0;
76            arb_assert(ok());
77        }
78    }
79   
80public:
81    void reserve(size_t forElems) { reserve_space(forElems, false); }
82    void optimize_space() { set_space(elems+1); }
83
84    size_t size() const { return elems; }
85    bool empty() const { return elems == 0; }
86
87    const char *operator[](int i) const {
88        arb_assert(ok());
89        arb_assert(i >= 0 && size_t(i) <= elems); // allow sentinel access
90        return elems ? str[i] : NULL;
91    }
92   
93    void swap(int i1, int i2) {
94        arb_assert(ok());
95        arb_assert(elem_index(i1));
96        arb_assert(elem_index(i2));
97        std::swap(str[i1], str[i2]);
98        arb_assert(ok());
99    }
100
101    void remove(int i) {
102        arb_assert(ok());
103        arb_assert(elem_index(i));
104        free_elem(i);
105        while (size_t(i) < elems) { // move elems incl. sentinel
106            str[i] = str[i+1];
107            ++i;
108        }
109        elems--;
110        arb_assert(ok());
111    }
112
113    void resize(int newsize) {
114        // truncates array to 'newsize'
115        for (int i = size()-1; i >= newsize; i--) {
116            remove(i);
117        }
118    }
119    void clear() { resize(0); }
120
121    void sort(CharPtrArray_compare_fun compare, void *client_data);
122};
123
124class StrArray : public CharPtrArray {
125    virtual void free_elem(int i) OVERRIDE {
126        freenull(str[i]);
127    }
128
129public:
130    StrArray() {}
131    virtual ~StrArray() OVERRIDE { erase(); }
132
133    void erase() { erase_elems(); }
134
135    void put(char *elem) { // tranfers ownership!
136        int i    = elems;
137        reserve_space(i+1, true);
138        arb_assert(allocated_index(i));
139        str[i]   = elem;
140        str[i+1] = NULL; // sentinel
141        elems++;
142        arb_assert(ok());
143    }
144
145    char *replace(int i, char *elem) { // transfers ownership (in both directions!)
146        arb_assert(elem_index(i));
147        char *old = str[i];
148        str[i]    = elem;
149        arb_assert(ok());
150        return old;
151    }
152};
153
154class ConstStrArray : public CharPtrArray { // derived from a Noncopyable
155    char *memblock;
156
157    virtual void free_elem(int i) OVERRIDE { str[i] = NULL; }
158
159public:
160    ConstStrArray() : memblock(NULL) {}
161    virtual ~ConstStrArray() OVERRIDE { free(memblock); }
162
163    void set_memblock(char *block) {
164        // hold one memblock until destruction
165        arb_assert(!memblock);
166        memblock = block;
167    }
168
169    void erase() {
170        erase_elems();
171        freenull(memblock);
172    }
173
174    void put(const char *elem) {
175        int i    = elems;
176        reserve_space(i+1, true);
177        arb_assert(allocated_index(i));
178        str[i]   = const_cast<char*>(elem);
179        str[i+1] = NULL; // sentinel
180        elems++;
181        arb_assert(ok());
182    }
183
184    const char *replace(int i, const char *elem) {
185        arb_assert(elem_index(i));
186        const char *old = str[i];
187        str[i]    = const_cast<char*>(elem);
188        arb_assert(ok());
189        return old;
190    }
191};
192
193
194void GBT_splitNdestroy_string(ConstStrArray& names, char*& namelist, const char *separator, bool dropEmptyTokens);
195void GBT_splitNdestroy_string(ConstStrArray& dest, char*& namelist, char separator);
196
197inline void GBT_split_string(ConstStrArray& dest, const char *namelist, const char *separator, bool dropEmptyTokens) {
198    //! same as GBT_splitNdestroy_string, but w/o destroying namelist
199    char *dup = strdup(namelist);
200    GBT_splitNdestroy_string(dest, dup, separator, dropEmptyTokens);
201}
202inline void GBT_split_string(ConstStrArray& dest, const char *namelist, char separator) {
203    char *dup = strdup(namelist);
204    GBT_splitNdestroy_string(dest, dup, separator);
205    // cppcheck-suppress memleak (GBT_splitNdestroy_string takes ownership of 'dup')
206}
207
208char *GBT_join_names(const CharPtrArray& names, char separator);
209int   GBT_names_index_of(const CharPtrArray& names, const char *search_for);
210void  GBT_names_erase(CharPtrArray& names, int index);
211void  GBT_names_add(ConstStrArray& names, int insert_before, const char *name);
212void  GBT_names_move(CharPtrArray& names, int old_index, int new_index);
213
214#else
215#error arb_strarray.h included twice
216#endif // ARB_STRARRAY_H
Note: See TracBrowser for help on using the repository browser.