ARB
arb_strarray.h
Go to the documentation of this file.
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 
29 typedef int (*CharPtrArray_compare_fun)(const void *p0, const void *p1, void *client_data); // same as arb_sort.h@gb_compare_function
30 
31 class CharPtrArray : virtual Noncopyable {
32  size_t allocated;
33 
34 protected:
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 
81 public:
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());
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) {
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) {
123  sort(compare, client_data);
124  uniq(compare, client_data);
125  }
126 
127  int index_of(const char *search_for) const;
128 };
129 
130 class StrArray FINAL_TYPE : public CharPtrArray {
131  void free_elem(int i) OVERRIDE {
132  freenull(str[i]);
133  }
134 
135 public:
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);
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!)
161  char *old = str[i];
162  str[i] = elem;
163  arb_assert(ok());
164  return old;
165  }
166 };
167 
168 class ConstStrArray : public CharPtrArray { // derived from a Noncopyable
169  char *memblock;
170 
171  void free_elem(int i) FINAL_OVERRIDE { str[i] = NULp; }
172 
173 public:
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);
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) {
208  const char *old = str[i];
209  str[i] = const_cast<char*>(elem);
210  arb_assert(ok());
211  return old;
212  }
213 
215 };
216 MARK_NONFINAL_CLASS(ConstStrArray); // @@@ unwanted. cannot be final due to DEBUG-only class StringVectorArray. fix.
217 
219 
220 void GBT_splitNdestroy_string(ConstStrArray& names, char*& namelist, const char *separator, SplitMode mode);
221 void GBT_splitNdestroy_string(ConstStrArray& dest, char*& namelist, char separator);
222 
223 inline void GBT_split_string(ConstStrArray& dest, const char *namelist, const char *separator, SplitMode mode) {
225  char *dup = ARB_strdup(namelist);
226  GBT_splitNdestroy_string(dest, dup, separator, mode);
227 }
228 inline 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 
236 char *GBT_join_strings(const CharPtrArray& strings, char separator);
237 
238 #else
239 #error arb_strarray.h included twice
240 #endif // ARB_STRARRAY_H
#define arb_assert(cond)
Definition: arb_assert.h:245
void set_space(size_t new_allocated)
Definition: arb_strarray.h:48
void put(const char *elem)
Definition: arb_strarray.h:188
size_t size() const
Definition: arb_strarray.h:85
void resize(int newsize)
Definition: arb_strarray.h:108
int(* CharPtrArray_compare_fun)(const void *p0, const void *p1, void *client_data)
Definition: arb_strarray.h:29
~ConstStrArray() OVERRIDE
Definition: arb_strarray.h:175
char * ARB_strdup(const char *str)
Definition: arb_string.h:27
virtual ~CharPtrArray()
Definition: arb_strarray.h:68
void uniq(CharPtrArray_compare_fun compare, void *client_data)
const char * operator[](int i) const
Definition: arb_strarray.h:88
char ** str
Definition: arb_strarray.h:35
void set_memblock(char *block)
Definition: arb_strarray.h:177
bool allocated_index(int i) const
Definition: arb_strarray.h:46
char * replace(int i, char *elem)
Definition: arb_strarray.h:159
bool empty() const
Definition: arb_strarray.h:86
#define FINAL_OVERRIDE
Definition: cxxforward.h:114
void erase_elems()
Definition: arb_strarray.h:72
static FullNameMap names
virtual void free_elem(int i)=0
void swap(int i1, int i2)
Definition: arb_strarray.h:94
int index_of(const char *search_for) const
size_t elems
Definition: arb_strarray.h:36
void GBT_splitNdestroy_string(ConstStrArray &names, char *&namelist, const char *separator, SplitMode mode)
CONSTEXPR_INLINE_Cxx14 void swap(unsigned char &c1, unsigned char &c2)
Definition: ad_io_inline.h:19
void ARB_recalloc(TYPE *&tgt, size_t oelem, size_t nelem)
Definition: arb_mem.h:49
void safe_remove(int i)
Definition: arb_strarray.h:103
void put_before(int insert_before, const char *elem)
Definition: arb_strarray.h:197
void put(char *elem)
Definition: arb_strarray.h:141
void reserve_space(size_t forElems, bool alloc_ahead)
Definition: arb_strarray.h:60
void optimize_space()
Definition: arb_strarray.h:83
bool ok() const
Definition: arb_strarray.h:38
~StrArray() OVERRIDE
Definition: arb_strarray.h:137
void erase()
Definition: arb_strarray.h:139
TYPE * ARB_calloc(size_t nelem)
Definition: arb_mem.h:81
xml element
void put_before(int insert_before, char *elem)
Definition: arb_strarray.h:150
#define OVERRIDE
Definition: cxxforward.h:112
void move(int from, int to)
char * GBT_join_strings(const CharPtrArray &strings, char separator)
MARK_NONFINAL_CLASS(ConstStrArray)
void sort(CharPtrArray_compare_fun compare, void *client_data)
#define NULp
Definition: cxxforward.h:116
void reserve(size_t forElems)
Definition: arb_strarray.h:82
void GBT_split_string(ConstStrArray &dest, const char *namelist, const char *separator, SplitMode mode)
Definition: arb_strarray.h:223
static ED4_block block
Definition: ED4_block.cxx:74
bool elem_index(int i) const
Definition: arb_strarray.h:45
const char * replace(int i, const char *elem)
Definition: arb_strarray.h:206
PREPARE_MARK_NONFINAL_CLASS(ConstStrArray)
SplitMode
Definition: arb_strarray.h:218
void sort_and_uniq(CharPtrArray_compare_fun compare, void *client_data)
Definition: arb_strarray.h:118