source: tags/testbuild/CORE/arb_strarray.h

Last change on this file was 12848, checked in by westram, 10 years ago
  • reintegrates 'fix' into 'trunk'
    • removes calls to aw_string_selection and aw_string_selection2awar (implementing another step for #179)
  • adds:
File size: 6.9 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    void uniq(CharPtrArray_compare_fun compare, void *client_data);
123    void sort_and_uniq(CharPtrArray_compare_fun compare, void *client_data) {
124        /*! sort the array and remove all duplicates
125         * @param compare function defining order on elements (@see e.g. GB_string_comparator)
126         * @param client_data user parameter forwarded to compare
127         */
128        sort(compare, client_data);
129        uniq(compare, client_data);
130    }
131};
132
133class StrArray : public CharPtrArray {
134    virtual void free_elem(int i) OVERRIDE {
135        freenull(str[i]);
136    }
137
138public:
139    StrArray() {}
140    virtual ~StrArray() OVERRIDE { erase(); }
141
142    void erase() { erase_elems(); }
143
144    void put(char *elem) { // tranfers ownership!
145        int i    = elems;
146        reserve_space(i+1, true);
147        arb_assert(allocated_index(i));
148        str[i]   = elem;
149        str[i+1] = NULL; // sentinel
150        elems++;
151        arb_assert(ok());
152    }
153
154    char *replace(int i, char *elem) { // transfers ownership (in both directions!)
155        arb_assert(elem_index(i));
156        char *old = str[i];
157        str[i]    = elem;
158        arb_assert(ok());
159        return old;
160    }
161};
162
163class ConstStrArray : public CharPtrArray { // derived from a Noncopyable
164    char *memblock;
165
166    virtual void free_elem(int i) OVERRIDE { str[i] = NULL; }
167
168public:
169    ConstStrArray() : memblock(NULL) {}
170    virtual ~ConstStrArray() OVERRIDE { free(memblock); }
171
172    void set_memblock(char *block) {
173        // hold one memblock until destruction
174        arb_assert(!memblock);
175        memblock = block;
176    }
177
178    void erase() {
179        erase_elems();
180        freenull(memblock);
181    }
182
183    void put(const char *elem) {
184        int i    = elems;
185        reserve_space(i+1, true);
186        arb_assert(allocated_index(i));
187        str[i]   = const_cast<char*>(elem);
188        str[i+1] = NULL; // sentinel
189        elems++;
190        arb_assert(ok());
191    }
192
193    const char *replace(int i, const char *elem) {
194        arb_assert(elem_index(i));
195        const char *old = str[i];
196        str[i]    = const_cast<char*>(elem);
197        arb_assert(ok());
198        return old;
199    }
200};
201
202
203void GBT_splitNdestroy_string(ConstStrArray& names, char*& namelist, const char *separator, bool dropEmptyTokens);
204void GBT_splitNdestroy_string(ConstStrArray& dest, char*& namelist, char separator);
205
206inline void GBT_split_string(ConstStrArray& dest, const char *namelist, const char *separator, bool dropEmptyTokens) {
207    //! same as GBT_splitNdestroy_string, but w/o destroying namelist
208    char *dup = strdup(namelist);
209    GBT_splitNdestroy_string(dest, dup, separator, dropEmptyTokens);
210}
211inline void GBT_split_string(ConstStrArray& dest, const char *namelist, char separator) {
212    char *dup = strdup(namelist);
213    GBT_splitNdestroy_string(dest, dup, separator);
214    // cppcheck-suppress memleak (GBT_splitNdestroy_string takes ownership of 'dup')
215}
216
217char *GBT_join_names(const CharPtrArray& names, char separator);
218int   GBT_names_index_of(const CharPtrArray& names, const char *search_for);
219void  GBT_names_erase(CharPtrArray& names, int index);
220void  GBT_names_add(ConstStrArray& names, int insert_before, const char *name);
221void  GBT_names_move(CharPtrArray& names, int old_index, int new_index);
222
223#else
224#error arb_strarray.h included twice
225#endif // ARB_STRARRAY_H
Note: See TracBrowser for help on using the repository browser.