source: trunk/CORE/arb_strarray.h

Last change on this file was 19430, checked in by westram, 17 months ago
  • un-inline CharPtrArray::remove to get rid of vectorizer warning.
  • note strange vectorization count for gcc 10.2.0
File size: 7.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 ARBTOOLS_H
16#include <arbtools.h>
17#endif
18#ifndef ARB_STRING_H
19#include "arb_string.h"
20#endif
21#ifndef _GLIBCXX_ALGORITHM
22#include <algorithm>
23#endif
24#ifndef _GLIBCXX_CSTDLIB
25#include <cstdlib>
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] && 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
52            if (str) ARB_recalloc(str, allocated, new_allocated);
53            else     ARB_calloc(str, new_allocated);
54
55            allocated = new_allocated;
56            arb_assert(ok());
57        }
58    }
59
60    void reserve_space(size_t forElems, bool alloc_ahead) {
61        if (allocated <= forElems) {
62            forElems = alloc_ahead ? (forElems>7 ? forElems*3/2 : 10) : forElems;
63            set_space(forElems+1); // always allocate one element more (sentinel element)
64        }
65    }
66
67    CharPtrArray() : allocated(0), str(NULp), elems(0) {}
68    virtual ~CharPtrArray() { free(str); }
69
70    virtual void free_elem(int i) = 0;
71
72    void erase_elems() {
73        arb_assert(ok());
74        if (!empty()) {
75            for (size_t i = 0; i<elems; ++i) free_elem(i);
76            elems = 0;
77            arb_assert(ok());
78        }
79    }
80
81public:
82    void reserve(size_t forElems) { reserve_space(forElems, false); }
83    void optimize_space() { set_space(elems+1); }
84
85    size_t size() const { return elems; }
86    bool empty() const { return elems == 0; }
87
88    const char *operator[](int i) const {
89        arb_assert(ok());
90        arb_assert(i >= 0 && size_t(i) <= elems); // allow sentinel access
91        return elems ? str[i] : NULp;
92    }
93
94    void swap(int i1, int i2) {
95        arb_assert(ok());
96        arb_assert(elem_index(i1));
97        arb_assert(elem_index(i2));
98        std::swap(str[i1], str[i2]);
99        arb_assert(ok());
100    }
101    void move(int from, int to);
102    void remove(int i);
103    void safe_remove(int i) {
104        //! like remove, but does NOOP if index out of bounds
105        if (elem_index(i)) remove(i);
106    }
107
108    void resize(int newsize) {
109        // truncates array to 'newsize'
110        for (int i = size()-1; i >= newsize; i--) {
111            remove(i);
112        }
113    }
114    void clear() { resize(0); }
115
116    void sort(CharPtrArray_compare_fun compare, void *client_data);
117    void uniq(CharPtrArray_compare_fun compare, void *client_data);
118    void sort_and_uniq(CharPtrArray_compare_fun compare, void *client_data) {
119        /*! sort the array and remove all duplicates
120         * @param compare function defining order on elements (@see e.g. GB_string_comparator)
121         * @param client_data user parameter forwarded to compare
122         */
123        sort(compare, client_data);
124        uniq(compare, client_data);
125    }
126
127    int index_of(const char *search_for) const;
128};
129
130class StrArray FINAL_TYPE : public CharPtrArray {
131    void free_elem(int i) OVERRIDE {
132        freenull(str[i]);
133    }
134
135public:
136    StrArray() {}
137    ~StrArray() OVERRIDE { erase(); }
138
139    void erase() { erase_elems(); }
140
141    void put(char *elem) { // tranfers ownership!
142        int i    = elems;
143        reserve_space(i+1, true);
144        arb_assert(allocated_index(i));
145        str[i]   = elem;
146        str[i+1] = NULp; // sentinel
147        elems++;
148        arb_assert(ok());
149    }
150    void put_before(int insert_before, char *elem) { // tranfers ownership of elem!
151        // insert a new 'name' before position 'insert_before'
152        // if 'insert_before' == -1 (or bigger than array size) -> append at end
153        put(elem);
154        if (insert_before<int(size())) {
155            move(-1, insert_before);
156        }
157    }
158
159    char *replace(int i, char *elem) { // transfers ownership (in both directions!)
160        arb_assert(elem_index(i));
161        char *old = str[i];
162        str[i]    = elem;
163        arb_assert(ok());
164        return old;
165    }
166};
167
168class ConstStrArray : public CharPtrArray { // derived from a Noncopyable
169    char *memblock;
170
171    void free_elem(int i) FINAL_OVERRIDE { str[i] = NULp; }
172
173public:
174    ConstStrArray() : memblock(NULp) {}
175    ~ConstStrArray() OVERRIDE { free(memblock); }
176
177    void set_memblock(char *block) {
178        // hold one memblock until destruction
179        arb_assert(!memblock);
180        memblock = block;
181    }
182
183    void erase() {
184        erase_elems();
185        freenull(memblock);
186    }
187
188    void put(const char *elem) {
189        int i    = elems;
190        reserve_space(i+1, true);
191        arb_assert(allocated_index(i));
192        str[i]   = const_cast<char*>(elem);
193        str[i+1] = NULp; // sentinel
194        elems++;
195        arb_assert(ok());
196    }
197    void put_before(int insert_before, const char *elem) {
198        // insert a new 'name' before position 'insert_before'
199        // if 'insert_before' == -1 (or bigger than array size) -> append at end
200        put(elem);
201        if (insert_before<int(size())) {
202            move(-1, insert_before);
203        }
204    }
205
206    const char *replace(int i, const char *elem) {
207        arb_assert(elem_index(i));
208        const char *old = str[i];
209        str[i]    = const_cast<char*>(elem);
210        arb_assert(ok());
211        return old;
212    }
213
214    PREPARE_MARK_NONFINAL_CLASS(ConstStrArray);
215};
216MARK_NONFINAL_CLASS(ConstStrArray); // @@@ unwanted. cannot be final due to DEBUG-only class StringVectorArray. fix.
217
218enum SplitMode { SPLIT_DROPEMPTY, SPLIT_KEEPEMPTY };
219
220void GBT_splitNdestroy_string(ConstStrArray& names, char*& namelist, const char *separator, SplitMode mode);
221void GBT_splitNdestroy_string(ConstStrArray& dest, char*& namelist, char separator);
222
223inline void GBT_split_string(ConstStrArray& dest, const char *namelist, const char *separator, SplitMode mode) {
224    //! same as GBT_splitNdestroy_string, but w/o destroying namelist
225    char *dup = ARB_strdup(namelist);
226    GBT_splitNdestroy_string(dest, dup, separator, mode);
227}
228inline void GBT_split_string(ConstStrArray& dest, const char *namelist, char separator) {
229    // Warning: if 'namelist' is an empty string => the array contains ONE entry (also an empty string).
230    // If this seems un-intuitive -> use other flavor above.
231    char *dup = ARB_strdup(namelist);
232    GBT_splitNdestroy_string(dest, dup, separator);
233    // cppcheck-suppress memleak (GBT_splitNdestroy_string takes ownership of 'dup')
234}
235
236char *GBT_join_strings(const CharPtrArray& strings, char separator);
237
238#else
239#error arb_strarray.h included twice
240#endif // ARB_STRARRAY_H
Note: See TracBrowser for help on using the repository browser.