g4tools  5.4.0
cstr
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_cstr
5 #define tools_cstr
6 
7 #include <cstring> // strcpy
8 #include <cstdlib> // malloc,free
9 
10 #ifdef TOOLS_MEM
11 #include "mem"
12 //#define TOOLS_CSTR_DEBUG_MEM
13 #ifdef TOOLS_CSTR_DEBUG_MEM
14 #include <cstdio>
15 #endif
16 #endif
17 
18 namespace tools {
19 
20 // NOTE : have str_ to avoid clashes with various strxxx cpp macro
21 // that may come from C or system headers.
22 
23 #ifdef TOOLS_MEM
24 inline const std::string& s_cstr() {
25  static const std::string s_v("tools::cstr");
26  return s_v;
27 }
28 #endif
29 
30 inline char* str_dup(const char* a_cstr
31 #ifdef TOOLS_MEM
32  ,bool a_inc = true
33 #endif
34  ) {
35 #ifdef TOOLS_MEM
36  if(a_inc) {
37 #ifdef TOOLS_CSTR_DEBUG_MEM
38  ::printf("debug : str_dup \"%s\"\n",a_cstr);
39 #endif
40  mem::increment(s_cstr().c_str());
41  }
42 #endif
43  return ::strcpy((char*)::malloc(::strlen(a_cstr)+1),a_cstr);
44 }
45 
46 inline char* str_from_buffer(const char* a_buffer,size_t a_len
47 #ifdef TOOLS_MEM
48  ,bool a_inc = true
49 #endif
50  ) {
51 #ifdef TOOLS_MEM
52  if(a_inc) {
53 #ifdef TOOLS_CSTR_DEBUG_MEM
54  ::printf("debug : str_from_buffer.\n");
55 #endif
56  mem::increment(s_cstr().c_str());
57  }
58 #endif
59  char* s = (char*)::malloc(a_len+1);
60  if(s==NULL) return NULL;
61  s = ::strncpy(s,a_buffer,a_len);
62  s[a_len] = 0;
63  return s;
64 }
65 
66 inline void str_del(char*& a_cstr) {
67  if(a_cstr==NULL) return;
68 #ifdef TOOLS_MEM
69 #ifdef TOOLS_CSTR_DEBUG_MEM
70  ::printf("debug : str_del \"%s\"\n",a_cstr);
71 #endif
72  mem::decrement(s_cstr().c_str());
73 #endif
74  ::free(a_cstr);
75  a_cstr = NULL;
76 }
77 
78 inline char* str_new(size_t a_l = 0,char a_char = ' ') {
79  char* s = (char*)::malloc((a_l+1)*sizeof(char));
80  if(s==NULL) return NULL;
81 #ifdef TOOLS_MEM
82 #ifdef TOOLS_CSTR_DEBUG_MEM
83  ::printf("debug : str_new : len %lu\n",a_l);
84 #endif
85  mem::increment(s_cstr().c_str());
86 #endif
87  char* pos = s;
88  for(size_t c=0;c<a_l;c++,pos++) *pos = a_char;
89  *(s+a_l) = 0;
90  return s;
91 }
92 
93 inline bool str_cat(char*& a_1,const char a_c) {
94  size_t l1 = ::strlen(a_1);
95  char* s = (char*)::malloc(l1+1+1);
96  if(!s) return false;
97 #ifdef TOOLS_MEM
98 #ifdef TOOLS_CSTR_DEBUG_MEM
99  ::printf("debug : str_cat \"%s\", char %d\n",a_1,a_c);
100 #endif
101  mem::increment(s_cstr().c_str());
102 #endif
103  ::memcpy(s,a_1,l1);
104  ::memcpy(s+l1,&a_c,1);
105  *(s+l1+1) = 0;
106  ::free(a_1);
107 #ifdef TOOLS_MEM
108 #ifdef TOOLS_CSTR_DEBUG_MEM
109  ::printf("debug : str_cat : dec\n");
110 #endif
111  mem::decrement(s_cstr().c_str());
112 #endif
113  a_1 = s;
114  return true;
115 }
116 
117 inline bool str_cat(char*& a_1,const char* a_2) {
118  size_t l1 = ::strlen(a_1);
119  size_t l2 = ::strlen(a_2);
120  char* s = (char*)::malloc(l1+l2+1);
121  if(!s) return false;
122 #ifdef TOOLS_MEM
123 #ifdef TOOLS_CSTR_DEBUG_MEM
124  ::printf("debug : str_cat \"%s\" \"%s\"\n",a_1,a_2);
125 #endif
126  mem::increment(s_cstr().c_str());
127 #endif
128  ::memcpy(s,a_1,l1);
129  ::memcpy(s+l1,a_2,l2);
130  *(s+l1+l2) = 0;
131  ::free(a_1);
132 #ifdef TOOLS_MEM
133 #ifdef TOOLS_CSTR_DEBUG_MEM
134  ::printf("debug : str_cat : dec\n");
135 #endif
136  mem::decrement(s_cstr().c_str());
137 #endif
138  a_1 = s;
139  return true;
140 }
141 
142 inline void str_rev(char* a_s) {
143  size_t l = ::strlen(a_s);
144  size_t hl = l/2;
145  char* beg = a_s;
146  char* end = a_s+l-1;
147  for(size_t i=0;i<hl;i++) {
148  char c = *end;
149  *end = *beg;
150  *beg = c;
151  beg++;end--;
152  }
153 }
154 
155 inline char* str_sub(const char* a_s,
156  unsigned int a_pos,
157  unsigned int a_sz = 0) { //0 = take up end.
158  size_t l = ::strlen(a_s);
159  if(a_pos>=l) return 0; //throw std::out_of_range
160  size_t ls;
161  if(a_sz) {
162  ls = (a_sz<(l-a_pos)?a_sz:(l-a_pos)); //min(a_sz,l-a_pos)
163  } else {
164  ls = l-a_pos;
165  }
166  char* s = (char*)::malloc(ls+1);
167  if(!s) return 0;
168 #ifdef TOOLS_MEM
169 #ifdef TOOLS_CSTR_DEBUG_MEM
170  ::printf("debug : str_sub \"%s\"\n",a_s);
171 #endif
172  mem::increment(s_cstr().c_str());
173 #endif
174  //abcdefgh l=8
175  //0123456789
176  ::memcpy(s,a_s+a_pos,ls);
177  *(s+ls) = 0;
178  return s;
179 }
180 
181 inline char* str_rep(const char* a_s,unsigned int a_pos,unsigned int a_sz,const char* a_new) {
182  //not tested yet.
183  size_t las = ::strlen(a_s);
184  if(a_pos>=las) return 0; //throw std::out_of_range
185  if(a_pos+a_sz>las) return 0;
186  size_t lan = ::strlen(a_new);
187  unsigned int num = a_sz<lan?a_sz:(unsigned int)lan;
188  //abcdefghij : l = 10
189  //0123456789
190  // p
191  size_t le = las-(a_pos+a_sz);
192  size_t ls = a_pos+num+le;
193  char* s = (char*)::malloc(ls+1);
194  if(!s) return 0;
195 #ifdef TOOLS_MEM
196 #ifdef TOOLS_CSTR_DEBUG_MEM
197  ::printf("debug : str_rep \"%s\"\n",a_s);
198 #endif
199  mem::increment(s_cstr().c_str());
200 #endif
201  ::memcpy(s,a_s,a_pos);
202  ::memcpy(s+a_pos,a_new,num);
203  if(le) ::memcpy(s+a_pos+num,a_s+a_pos+a_sz,le);
204  *(s+ls) = 0;
205  return s;
206 }
207 
208 inline void str_skip(char*& a_cstr,char a_c) {
209  while(true) {
210  if(*a_cstr!=a_c) break;
211  a_cstr++;
212  }
213 }
214 
215 }
216 
217 #include <clocale>
218 
219 namespace tools {
220 
221 inline char* beg_LC_NUMERIC() {
222  char* _sl = ::setlocale(LC_NUMERIC,0);
223  char* old = _sl?str_dup(_sl):0;
224  ::setlocale(LC_NUMERIC,"C");
225  return old;
226 }
227 inline void end_LC_NUMERIC(char*& a_s) {
228  if(a_s) {
229  ::setlocale(LC_NUMERIC,a_s);
230  str_del(a_s);
231  }
232 }
233 
234 inline bool str_2d(const char* a_s,double& a_v) {
235  char* olcn = beg_LC_NUMERIC();
236 
237  char* end;
238  a_v = ::strtod(a_s,&end);
239  if(end==a_s) {
240  a_v = 0;
241  end_LC_NUMERIC(olcn);
242  return false;
243  }
244 
245  end_LC_NUMERIC(olcn);
246  return true;
247 }
248 
249 /*
250 inline bool str_2d(const char* a_s,double& a_v) {
251  char* _sl = ::setlocale(LC_NUMERIC,0);
252  char* old = _sl?str_dup(_sl):0;
253  ::setlocale(LC_NUMERIC,"C");
254 
255  char* end;
256  a_v = ::strtod(a_s,&end);
257  bool status = true;
258  if(end==a_s) {
259  status = false;
260  a_v = 0;
261  }
262 
263  if(old) {
264  ::setlocale(LC_NUMERIC,old);
265  str_del(old);
266  }
267 
268  return status;
269 }
270 */
271 
272 inline size_t str_lcpy(char *dst, const char *src, size_t siz) {
273  // Copy src to string dst of size siz. At most siz-1 characters
274  // will be copied. Always NUL terminates (unless siz == 0).
275  // Returns strlen(src); if retval >= siz, truncation occurred.
276 
277  // code taken from CERN-ROOT/core/clib to compile exlib/tests/h2root.cpp.
278  // strlcpy, strlcat are in string.h on BSD based systems.
279 
280  // Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>.
281 
282  /*register*/ char* d = dst;
283  /*register*/ const char* s = src;
284  /*register*/ size_t n = siz;
285 
286  // Copy as many bytes as will fit :
287  if (n != 0 && --n != 0) {
288  do {
289  if ((*d++ = *s++) == 0) break;
290  } while (--n != 0);
291  }
292 
293  // Not enough room in dst, add NUL and traverse rest of src :
294  if (n == 0) {
295  if (siz != 0) *d = '\0'; // NUL-terminate dst.
296  while (*s++);
297  }
298 
299  return(s - src - 1); // count does not include NUL.
300 }
301 
302 inline size_t str_lcat(char *dst, const char *src, size_t siz) {
303  // Appends src to string dst of size siz (unlike strncat, siz is the
304  // full size of dst, not space left). At most siz-1 characters
305  // will be copied. Always NUL terminates (unless siz <= strlen(dst)).
306  // Returns strlen(src) + MIN(siz, strlen(initial dst)).
307  // If retval >= siz, truncation occurred.
308 
309  // code taken from CERN-ROOT/core/clib to compile exlib/tests/h2root.cpp.
310  // strlcpy, strlcat are in string.h on BSD based systems.
311 
312  // Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>.
313 
314  /*register*/ char* d = dst;
315  /*register*/ const char* s = src;
316  /*register*/ size_t n = siz;
317  size_t dlen;
318 
319  // Find the end of dst and adjust bytes left but don't go past end :
320  while (n-- != 0 && *d != '\0') d++;
321  dlen = d - dst;
322  n = siz - dlen;
323 
324  if (n == 0) return(dlen + strlen(s));
325 
326  while (*s != '\0') {
327  if (n != 1) {
328  *d++ = *s;
329  n--;
330  }
331  s++;
332  }
333  *d = '\0';
334 
335  return(dlen + (s - src)); // count does not include NUL.
336 }
337 
338 template <class VECTOR>
339 inline bool str_2ds(char* a_s,const char* a_sep,VECTOR& a_v) {
340  a_v.clear();
341  const char* tok;
342  double d;
343  for (tok = ::strtok(a_s,a_sep);tok && *tok;tok = ::strtok(NULL,a_sep)) {
344  if(!str_2d(tok,d)) {a_v.clear();return false;}
345  a_v.push_back(d);
346  }
347  return true;
348 }
349 
350 }
351 
352 #endif
tools::str_from_buffer
char * str_from_buffer(const char *a_buffer, size_t a_len)
Definition: cstr:46
tools::str_rep
char * str_rep(const char *a_s, unsigned int a_pos, unsigned int a_sz, const char *a_new)
Definition: cstr:181
tools::str_lcat
size_t str_lcat(char *dst, const char *src, size_t siz)
Definition: cstr:302
tools::str_cat
bool str_cat(char *&a_1, const char a_c)
Definition: cstr:93
tools::str_2d
bool str_2d(const char *a_s, double &a_v)
Definition: cstr:234
tools::beg_LC_NUMERIC
char * beg_LC_NUMERIC()
Definition: cstr:221
tools::end_LC_NUMERIC
void end_LC_NUMERIC(char *&a_s)
Definition: cstr:227
mem
tools::str_skip
void str_skip(char *&a_cstr, char a_c)
Definition: cstr:208
tools::str_sub
char * str_sub(const char *a_s, unsigned int a_pos, unsigned int a_sz=0)
Definition: cstr:155
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::str_rev
void str_rev(char *a_s)
Definition: cstr:142
tools::waxml::end
void end(std::ostream &a_writer)
Definition: begend:31
tools::str_del
void str_del(char *&a_cstr)
Definition: cstr:66
tools::str_dup
char * str_dup(const char *a_cstr)
Definition: cstr:30
tools::str_2ds
bool str_2ds(char *a_s, const char *a_sep, VECTOR &a_v)
Definition: cstr:339
tools::str_lcpy
size_t str_lcpy(char *dst, const char *src, size_t siz)
Definition: cstr:272
tools::str_new
char * str_new(size_t a_l=0, char a_char=' ')
Definition: cstr:78