source: tags/ms_r18q1/CORE/arb_strarray.h

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