Geant4 Cross Reference |
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