ARB
arb_strbuf.cxx
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : arb_strbuf.cxx //
4 // Purpose : "unlimited" output buffer //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================= //
10 
11 #include "arb_strbuf.h"
12 
13 void GBS_strstruct::vnprintf(size_t maxlen, const char *templat, va_list& parg) {
14  ensure_mem(maxlen+1);
15 
16  char *buffer = data+pos;
17  int printed;
18 
19 #ifdef LINUX
20  printed = vsnprintf(buffer, maxlen+1, templat, parg);
21 #else
22  printed = vsprintf(buffer, templat, parg);
23 #endif
24 
25  assert_or_exit(printed >= 0 && (size_t)printed <= maxlen);
26  inc_pos(printed);
27 }
28 
29 void GBS_strstruct::nprintf(size_t maxlen, const char *templat, ...) {
30  va_list parg;
31  va_start(parg, templat);
32  vnprintf(maxlen, templat, parg);
33 }
34 
35 // old interface
36 
38 
39 GBS_strstruct *GBS_stropen(long init_size) {
44  GBS_strstruct *strstr = new GBS_strstruct;
45 
46  arb_assert(init_size>0);
47 
48  if (last_used.get_buffer_size() >= (size_t)init_size) {
49  strstr->reassign_mem(last_used);
50 
51  static short oversized_counter = 0;
52 
53  if ((size_t)init_size*10 < strstr->get_buffer_size()) oversized_counter++;
54  else oversized_counter = 0;
55 
56  if (oversized_counter>10) { // was oversized more than 10 times -> allocate smaller block
57  size_t dummy;
58  free(strstr->release_mem(dummy));
59  strstr->alloc_mem(init_size);
60  }
61  }
62  else {
63  strstr->alloc_mem(init_size);
64  }
65 
66  return strstr;
67 }
68 
69 char *GBS_strclose(GBS_strstruct *strstr) {
70  // returns a char* copy of the memory file
71  char *str = strstr->get_copy();
72  GBS_strforget(strstr);
73  return str;
74 }
75 
77  size_t last_bsize = last_used.get_buffer_size();
78  size_t curr_bsize = strstr->get_buffer_size();
79 
80  if (last_bsize < curr_bsize) { // last_used is smaller -> keep this
81  last_used.reassign_mem(*strstr);
82  }
83  delete strstr;
84 }
85 
86 char *GBS_mempntr(GBS_strstruct *strstr) {
87  // returns the memory file (with write access)
88  return (char*)strstr->get_data();
89 }
90 
92  // returns the offset into the memory file
93  return strstr->get_position();
94 }
95 
96 void GBS_str_cut_tail(GBS_strstruct *strstr, size_t byte_count) {
97  // Removes byte_count characters at the tail of a memfile
98  strstr->cut_tail(byte_count);
99 }
100 
101 void GBS_strncat(GBS_strstruct *strstr, const char *ptr, size_t len) {
102  /* append some bytes string to strstruct
103  * (caution : copies zero byte and mem behind if used with wrong len!)
104  */
105  strstr->ncat(ptr, len);
106 }
107 
108 void GBS_strcat(GBS_strstruct *strstr, const char *ptr) {
109  // append string to strstruct
110  strstr->cat(ptr);
111 }
112 
113 void GBS_strnprintf(GBS_strstruct *strstr, long maxlen, const char *templat, ...) {
114  va_list parg;
115  va_start(parg, templat);
116  strstr->vnprintf(maxlen+2, templat, parg);
117 }
118 
119 void GBS_chrcat(GBS_strstruct *strstr, char ch) {
120  strstr->put(ch);
121 }
122 
123 void GBS_chrncat(GBS_strstruct *strstr, char ch, size_t n) {
124  strstr->nput(ch, n);
125 }
126 
127 void GBS_intcat(GBS_strstruct *strstr, long val) {
128  char buffer[100];
129  long len = sprintf(buffer, "%li", val);
130  GBS_strncat(strstr, buffer, len);
131 }
132 
133 void GBS_floatcat(GBS_strstruct *strstr, double val) {
134  char buffer[100];
135  long len = sprintf(buffer, "%f", val);
136  GBS_strncat(strstr, buffer, len);
137 }
138 
139 // --------------------------------------------------------------------------------
140 
141 #ifdef UNIT_TESTS
142 #ifndef TEST_UNIT_H
143 #include <test_unit.h>
144 #endif
145 
146 void TEST_GBS_strstruct() {
147  { GBS_strstruct buf; buf.put ('c'); TEST_EXPECT_EQUAL(buf.get_data(), "c"); }
148  { GBS_strstruct buf; buf.cat ("abc"); TEST_EXPECT_EQUAL(buf.get_data(), "abc"); }
149  { GBS_strstruct buf; buf.nput('x', 0); TEST_EXPECT_EQUAL(buf.get_data(), ""); }
150 
151  { GBS_strstruct buf; buf.ncat("abc", 0); TEST_EXPECT_EQUAL(buf.get_data(), ""); }
152  { GBS_strstruct buf; buf.cat (""); TEST_EXPECT_EQUAL(buf.get_data(), ""); }
153 
154  { GBS_strstruct buf; TEST_EXPECT_EQUAL(buf.get_data(), ""); }
155 }
156 
157 #define EXPECT_CONTENT(content) TEST_EXPECT_EQUAL(GBS_mempntr(strstr), content)
158 
159 void TEST_GBS_strstruct_old_interface() {
160  // test the old, out-dated interface to GBS_strstruct (comes from pre-OO-times).
161 
162  {
163  GBS_strstruct *strstr = GBS_stropen(1000); EXPECT_CONTENT("");
164 
165  GBS_chrncat(strstr, 'b', 3); EXPECT_CONTENT("bbb");
166  GBS_intcat(strstr, 17); EXPECT_CONTENT("bbb17");
167  GBS_chrcat(strstr, '_'); EXPECT_CONTENT("bbb17_");
168  GBS_floatcat(strstr, 3.5); EXPECT_CONTENT("bbb17_3.500000");
169 
170  TEST_EXPECT_EQUAL(GBS_memoffset(strstr), 14);
171  GBS_str_cut_tail(strstr, 13); EXPECT_CONTENT("b");
172  GBS_strcat(strstr, "utter"); EXPECT_CONTENT("butter");
173  GBS_strncat(strstr, "flying", 3); EXPECT_CONTENT("butterfly");
174 
175  GBS_strnprintf(strstr, 200, "%c%s", ' ', "flutters");
176  EXPECT_CONTENT("butterfly flutters");
177 
178  GBS_strforget(strstr);
179  }
180  {
181  // re-alloc smaller
182  GBS_strstruct *strstr = GBS_stropen(500); EXPECT_CONTENT("");
183  GBS_strforget(strstr);
184  }
185 
186  // trigger downsize of oversized block
187  for (int i = 0; i<12; ++i) {
188  GBS_strstruct *strstr = GBS_stropen(10);
189  GBS_strforget(strstr);
190  }
191 
192  {
193  GBS_strstruct *strstr = GBS_stropen(10);
194  size_t oldbufsize = strstr->get_buffer_size();
195  GBS_chrncat(strstr, 'x', 20); // trigger reallocation of buffer
196 
197  TEST_EXPECT_DIFFERENT(oldbufsize, strstr->get_buffer_size()); // did we reallocate?
198  EXPECT_CONTENT("xxxxxxxxxxxxxxxxxxxx");
199  GBS_strforget(strstr);
200  }
201 }
202 
203 #endif // UNIT_TESTS
204 
205 // --------------------------------------------------------------------------------
206 
#define arb_assert(cond)
Definition: arb_assert.h:245
void cut_tail(size_t byte_count)
Definition: arb_strbuf.h:134
void vnprintf(size_t maxlen, const char *templat, va_list &parg) __ATTR__VFORMAT_MEMBER(2)
Definition: arb_strbuf.cxx:13
void GBS_strnprintf(GBS_strstruct *strstr, long maxlen, const char *templat,...)
Definition: arb_strbuf.cxx:113
void GBS_intcat(GBS_strstruct *strstr, long val)
Definition: arb_strbuf.cxx:127
void GBS_strncat(GBS_strstruct *strstr, const char *ptr, size_t len)
Definition: arb_strbuf.cxx:101
void nput(char c, size_t count)
Definition: arb_strbuf.h:143
void cat(const char *from)
Definition: arb_strbuf.h:158
char * release_mem(size_t &size)
Definition: arb_strbuf.h:73
char buffer[MESSAGE_BUFFERSIZE]
Definition: seq_search.cxx:34
GBS_strstruct * GBS_stropen(long init_size)
Definition: arb_strbuf.cxx:39
size_t get_buffer_size() const
Definition: arb_strbuf.h:64
void alloc_mem(size_t blocksize)
Definition: arb_strbuf.h:106
void GBS_chrncat(GBS_strstruct *strstr, char ch, size_t n)
Definition: arb_strbuf.cxx:123
char * get_copy() const
Definition: arb_strbuf.h:71
long GBS_memoffset(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:91
void GBS_strcat(GBS_strstruct *strstr, const char *ptr)
Definition: arb_strbuf.cxx:108
char * str
Definition: defines.h:20
void GBS_str_cut_tail(GBS_strstruct *strstr, size_t byte_count)
Definition: arb_strbuf.cxx:96
void GBS_strforget(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:76
static GBS_strstruct last_used
Definition: arb_strbuf.cxx:37
void GBS_chrcat(GBS_strstruct *strstr, char ch)
Definition: arb_strbuf.cxx:119
void ensure_mem(size_t needed_size)
Definition: arb_strbuf.h:123
void ncat(const char *from, size_t count)
Definition: arb_strbuf.h:151
char * GBS_mempntr(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:86
#define assert_or_exit(cond)
Definition: arb_assert.h:263
void reassign_mem(GBS_strstruct &from)
Definition: arb_strbuf.h:94
void nprintf(size_t maxlen, const char *templat,...) __ATTR__FORMAT_MEMBER(2)
Definition: arb_strbuf.cxx:29
va_start(argPtr, format)
char * GBS_strclose(GBS_strstruct *strstr)
Definition: arb_strbuf.cxx:69
void GBS_floatcat(GBS_strstruct *strstr, double val)
Definition: arb_strbuf.cxx:133
#define TEST_EXPECT_DIFFERENT(expr, want)
Definition: test_unit.h:1290
const char * get_data() const
Definition: arb_strbuf.h:70
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
size_t get_position() const
Definition: arb_strbuf.h:65
void put(char c)
Definition: arb_strbuf.h:138