source: tags/ms_r16q2/CORE/arb_strarray.h

Last change on this file was 14228, checked in by westram, 9 years ago
  • GBT_names_eraseCharPtrArray::safe_remove
File size: 7.5 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    void move(int from, int to);
101
102    void remove(int i) {
103        arb_assert(ok());
104        arb_assert(elem_index(i));
105        free_elem(i);
106        while (size_t(i) < elems) { // move elems incl. sentinel
107            str[i] = str[i+1];
108            ++i;
109        }
110        elems--;
111        arb_assert(ok());
112    }
113    void safe_remove(int i) {
114        //! like remove, but does NOOP if index out of bounds
115        if (elem_index(i)) remove(i);
116    }
117
118    void resize(int newsize) {
119        // truncates array to 'newsize'
120        for (int i = size()-1; i >= newsize; i--) {
121            remove(i);
122        }
123    }
124    void clear() { resize(0); }
125
126    void sort(CharPtrArray_compare_fun compare, void *client_data);
127    void uniq(CharPtrArray_compare_fun compare, void *client_data);
128    void sort_and_uniq(CharPtrArray_compare_fun compare, void *client_data) {
129        /*! sort the array and remove all duplicates
130         * @param compare function defining order on elements (@see e.g. GB_string_comparator)
131         * @param client_data user parameter forwarded to compare
132         */
133        sort(compare, client_data);
134        uniq(compare, client_data);
135    }
136
137    int index_of(const char *search_for) const;
138};
139
140class StrArray : public CharPtrArray {
141    virtual void free_elem(int i) OVERRIDE {
142        freenull(str[i]);
143    }
144
145public:
146    StrArray() {}
147    virtual ~StrArray() OVERRIDE { erase(); }
148
149    void erase() { erase_elems(); }
150
151    void put(char *elem) { // tranfers ownership!
152        int i    = elems;
153        reserve_space(i+1, true);
154        arb_assert(allocated_index(i));
155        str[i]   = elem;
156        str[i+1] = NULL; // sentinel
157        elems++;
158        arb_assert(ok());
159    }
160    void put_before(int insert_before, char *elem) { // tranfers ownership of elem!
161        // insert a new 'name' before position 'insert_before'
162        // if 'insert_before' == -1 (or bigger than array size) -> append at end
163        put(elem);
164        if (insert_before<int(size())) {
165            move(-1, insert_before);
166        }
167    }
168
169    char *replace(int i, char *elem) { // transfers ownership (in both directions!)
170        arb_assert(elem_index(i));
171        char *old = str[i];
172        str[i]    = elem;
173        arb_assert(ok());
174        return old;
175    }
176};
177
178class ConstStrArray : public CharPtrArray { // derived from a Noncopyable
179    char *memblock;
180
181    virtual void free_elem(int i) OVERRIDE { str[i] = NULL; }
182
183public:
184    ConstStrArray() : memblock(NULL) {}
185    virtual ~ConstStrArray() OVERRIDE { free(memblock); }
186
187    void set_memblock(char *block) {
188        // hold one memblock until destruction
189        arb_assert(!memblock);
190        memblock = block;
191    }
192
193    void erase() {
194        erase_elems();
195        freenull(memblock);
196    }
197
198    void put(const char *elem) {
199        int i    = elems;
200        reserve_space(i+1, true);
201        arb_assert(allocated_index(i));
202        str[i]   = const_cast<char*>(elem);
203        str[i+1] = NULL; // sentinel
204        elems++;
205        arb_assert(ok());
206    }
207    void put_before(int insert_before, const char *elem) {
208        // insert a new 'name' before position 'insert_before'
209        // if 'insert_before' == -1 (or bigger than array size) -> append at end
210        put(elem);
211        if (insert_before<int(size())) {
212            move(-1, insert_before);
213        }
214    }
215
216    const char *replace(int i, const char *elem) {
217        arb_assert(elem_index(i));
218        const char *old = str[i];
219        str[i]    = const_cast<char*>(elem);
220        arb_assert(ok());
221        return old;
222    }
223
224};
225
226
227void GBT_splitNdestroy_string(ConstStrArray& names, char*& namelist, const char *separator, bool dropEmptyTokens);
228void GBT_splitNdestroy_string(ConstStrArray& dest, char*& namelist, char separator);
229
230inline void GBT_split_string(ConstStrArray& dest, const char *namelist, const char *separator, bool dropEmptyTokens) {
231    //! same as GBT_splitNdestroy_string, but w/o destroying namelist
232    char *dup = strdup(namelist);
233    GBT_splitNdestroy_string(dest, dup, separator, dropEmptyTokens);
234}
235inline void GBT_split_string(ConstStrArray& dest, const char *namelist, char separator) {
236    char *dup = strdup(namelist);
237    GBT_splitNdestroy_string(dest, dup, separator);
238    // cppcheck-suppress memleak (GBT_splitNdestroy_string takes ownership of 'dup')
239}
240
241char *GBT_join_strings(const CharPtrArray& strings, char separator);
242
243#else
244#error arb_strarray.h included twice
245#endif // ARB_STRARRAY_H
Note: See TracBrowser for help on using the repository browser.