Changeset 793 for cpp/frams/util/sstring.cpp
- Timestamp:
- 05/29/18 16:51:14 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
cpp/frams/util/sstring.cpp
r395 r793 26 26 #ifdef MULTITHREADED 27 27 #include <pthread.h> 28 static pthread_mutex_t sstring_ref_lock =PTHREAD_MUTEX_INITIALIZER;28 static pthread_mutex_t sstring_ref_lock = PTHREAD_MUTEX_INITIALIZER; 29 29 #define REF_LOCK pthread_mutex_lock(&sstring_ref_lock); 30 30 #define REF_UNLOCK pthread_mutex_unlock(&sstring_ref_lock) … … 36 36 static int guessMemSize(int request) 37 37 { 38 return request+min(request/2,10000)+8;38 return request + min(request / 2, 10000) + 8; 39 39 } 40 40 41 41 SBuf::SBuf() 42 42 { 43 txt=(char*)"";44 size=used=0;45 refcount=1;43 txt = (char*)""; 44 size = used = 0; 45 refcount = 1; 46 46 } 47 47 48 48 SBuf::SBuf(int initsize) 49 49 { 50 size=guessMemSize(initsize);51 if (size>0) { txt=(char*)malloc(size+1); txt[0]=0; }52 else txt =(char*)"";53 used=0;54 refcount=1;50 size = guessMemSize(initsize); 51 if (size > 0) { txt = (char*)malloc(size + 1); txt[0] = 0; } 52 else txt = (char*)""; 53 used = 0; 54 refcount = 1; 55 55 } 56 56 57 57 SBuf::~SBuf() 58 58 { 59 freeBuf();59 freeBuf(); 60 60 } 61 61 62 62 void SBuf::initEmpty() 63 63 { 64 txt=(char*)"";65 used=size=0;66 refcount=1;64 txt = (char*)""; 65 used = size = 0; 66 refcount = 1; 67 67 } 68 68 69 69 void SBuf::freeBuf() 70 70 { 71 if (!size) return; 72 free(txt); used=0; 73 } 74 75 void SBuf::copyFrom(const char *ch,int chlen) 76 { 77 if (chlen==-1) chlen=strlen(ch); 78 if (chlen>0) 79 { 80 if (chlen<size) 71 if (!size) return; 72 free(txt); used = 0; 73 } 74 75 void SBuf::copyFrom(const char *ch, int chlen) 76 { 77 if (chlen == -1) chlen = strlen(ch); 78 if (chlen > 0) 81 79 { 82 memmove(txt,ch,chlen); 83 } 84 else 80 if (chlen < size) 81 { 82 memmove(txt, ch, chlen); 83 } 84 else 85 { 86 size = guessMemSize(chlen); 87 char *newtxt = (char*)malloc(size + 1); 88 memcpy(newtxt, ch, chlen); 89 free(txt); 90 txt = newtxt; 91 } 92 } 93 txt[chlen] = 0; 94 used = chlen; 95 } 96 97 void SBuf::append(const char *ch, int chlen) 98 { // doesn't check anything! 99 memmove(txt + used, ch, chlen); 100 used += chlen; 101 txt[used] = 0; 102 } 103 104 void SBuf::ensureSize(int needed) 105 { 106 if (size >= needed) return; 107 needed = guessMemSize(needed); 108 txt = (char*)realloc(txt, needed + 1); 109 size = needed; 110 } 111 112 ///////////////////////////////////////////// 113 114 SString::SString() 115 { 116 initEmpty(); 117 } 118 119 SString::~SString() 120 { 121 REF_LOCK; 122 detach(); 123 REF_UNLOCK; 124 } 125 126 SString::SString(int x) 127 { 128 buf = new SBuf(x); 129 } 130 131 SString::SString(const char *t, int t_len) 132 { 133 initEmpty(); 134 if (!t) return; 135 copyFrom(t, t_len); 136 } 137 138 SString::SString(SString&& from) 139 { 140 buf = from.buf; 141 from.buf = &SBuf::empty(); 142 } 143 144 SString::SString(const SString &from) 145 { 146 if (from.buf == &SBuf::empty()) 147 buf = &SBuf::empty(); 148 else 85 149 { 86 size=guessMemSize(chlen); 87 char *newtxt=(char*)malloc(size+1); 88 memcpy(newtxt,ch,chlen); 89 free(txt); 90 txt=newtxt; 91 } 92 } 93 txt[chlen]=0; 94 used=chlen; 95 } 96 97 void SBuf::append(const char *ch,int chlen) 98 { // doesn't check anything! 99 memmove(txt+used,ch,chlen); 100 used+=chlen; 101 txt[used]=0; 102 } 103 104 void SBuf::ensureSize(int needed) 105 { 106 if (size>=needed) return; 107 needed=guessMemSize(needed); 108 txt=(char*)realloc(txt,needed+1); 109 size=needed; 110 } 111 112 ///////////////////////////////////////////// 113 114 SString::SString() 115 { 116 initEmpty(); 117 } 118 119 SString::~SString() 120 { 121 REF_LOCK; 122 detach(); 123 REF_UNLOCK; 124 } 125 126 SString::SString(int x) 127 { 128 buf=new SBuf(x); 129 } 130 131 SString::SString(const char *t,int t_len) 132 { 133 initEmpty(); 134 if (!t) return; 135 copyFrom(t,t_len); 136 } 137 138 SString::SString(SString&& from) 139 { 140 buf=from.buf; 141 from.buf=&SBuf::empty(); 142 } 143 144 SString::SString(const SString &from) 145 { 146 if (from.buf==&SBuf::empty()) 147 buf=&SBuf::empty(); 148 else 150 REF_LOCK; 151 buf = from.buf; 152 if (buf->size) 153 buf->refcount++; 154 REF_UNLOCK; 155 } 156 } 157 158 void SString::initEmpty() 159 { 160 buf = &SBuf::empty(); 161 } 162 163 void SString::memoryHint(int howbig) 164 { 165 detachCopy(howbig); 166 } 167 168 void SString::detachEmpty(int ensuresize) 169 { 170 if (buf == &SBuf::empty()) { buf = new SBuf(ensuresize); return; } 171 if (buf->refcount < 2) buf->ensureSize(ensuresize); 172 else 149 173 { 150 REF_LOCK; 151 buf=from.buf; 152 if (buf->size) 153 buf->refcount++; 154 REF_UNLOCK; 155 } 156 } 157 158 void SString::initEmpty() 159 { 160 buf=&SBuf::empty(); 161 } 162 163 void SString::memoryHint(int howbig) 164 { 165 detachCopy(howbig); 166 } 167 168 void SString::detachEmpty(int ensuresize) 169 { 170 if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize); return; } 171 if (buf->refcount<2) buf->ensureSize(ensuresize); 172 else 174 buf->refcount--; 175 buf = new SBuf(ensuresize); 176 } 177 } 178 179 void SString::detach() 180 { 181 if (buf == &SBuf::empty()) return; 182 if (!--buf->refcount) delete buf; 183 } 184 185 void SString::detachCopy(int ensuresize) 186 { 187 if (buf == &SBuf::empty()) { buf = new SBuf(ensuresize); return; } 188 if (buf->refcount < 2) 173 189 { 190 buf->ensureSize(ensuresize); 191 return; 192 } 174 193 buf->refcount--; 175 buf=new SBuf(ensuresize); 176 } 177 } 178 179 void SString::detach() 180 { 181 if (buf==&SBuf::empty()) return; 182 if (!--buf->refcount) delete buf; 183 } 184 185 void SString::detachCopy(int ensuresize) 186 { 187 if (buf==&SBuf::empty()) { buf=new SBuf(ensuresize); return; } 188 if (buf->refcount<2) 189 { 190 buf->ensureSize(ensuresize); 191 return; 192 } 193 buf->refcount--; 194 SBuf *newbuf=new SBuf(ensuresize); 195 newbuf->copyFrom(buf->txt,min(ensuresize,buf->used)); 196 buf=newbuf; 194 SBuf *newbuf = new SBuf(ensuresize); 195 newbuf->copyFrom(buf->txt, min(ensuresize, buf->used)); 196 buf = newbuf; 197 197 } 198 198 199 199 char *SString::directWrite(int ensuresize) 200 200 { 201 if (ensuresize<0) ensuresize=len();202 REF_LOCK;203 detachCopy(ensuresize);204 REF_UNLOCK;205 appending=buf->used;206 return buf->txt;201 if (ensuresize < 0) ensuresize = len(); 202 REF_LOCK; 203 detachCopy(ensuresize); 204 REF_UNLOCK; 205 appending = buf->used; 206 return buf->txt; 207 207 } 208 208 … … 215 215 char *SString::directAppend(int maxappend) 216 216 { 217 REF_LOCK;218 detachCopy(buf->used+maxappend);219 REF_UNLOCK;220 appending=buf->used;221 return buf->txt+appending;217 REF_LOCK; 218 detachCopy(buf->used + maxappend); 219 REF_UNLOCK; 220 appending = buf->used; 221 return buf->txt + appending; 222 222 } 223 223 224 224 void SString::endWrite(int newlength) 225 225 { 226 if (newlength<0) newlength=strlen(buf->txt);227 else buf->txt[newlength]=0;228 buf->used=newlength;226 if (newlength < 0) newlength = strlen(buf->txt); 227 else buf->txt[newlength] = 0; 228 buf->used = newlength; 229 229 } 230 230 231 231 void SString::endAppend(int newappend) 232 232 { 233 if (newappend<0) newappend=strlen(buf->txt+appending);234 else buf->txt[appending+newappend]=0;235 buf->used=appending+newappend;233 if (newappend < 0) newappend = strlen(buf->txt + appending); 234 else buf->txt[appending + newappend] = 0; 235 buf->used = appending + newappend; 236 236 } 237 237 … … 240 240 void SString::operator+=(const char *s) 241 241 { 242 if (!s) return;243 int x=strlen(s);244 if (!x) return;245 append(s,x);246 } 247 248 void SString::append(const char *txt, int count)249 { 250 if (!count) return;251 REF_LOCK;252 detachCopy(buf->used+count);253 REF_UNLOCK;254 buf->append(txt,count);242 if (!s) return; 243 int x = strlen(s); 244 if (!x) return; 245 append(s, x); 246 } 247 248 void SString::append(const char *txt, int count) 249 { 250 if (!count) return; 251 REF_LOCK; 252 detachCopy(buf->used + count); 253 REF_UNLOCK; 254 buf->append(txt, count); 255 255 } 256 256 257 257 void SString::operator+=(const SString&s) 258 258 { 259 append(s.c_str(),s.len());259 append(s.c_str(), s.len()); 260 260 } 261 261 262 262 SString SString::operator+(const SString& s) const 263 263 { 264 SString ret(*this);265 ret+=s;266 return ret;264 SString ret(*this); 265 ret += s; 266 return ret; 267 267 } 268 268 269 269 ///////////////////////////// 270 270 271 void SString::copyFrom(const char *ch, int chlen)272 { 273 if (!ch) chlen=0;274 else if (chlen<0) chlen=strlen(ch);275 REF_LOCK;276 detachEmpty(chlen);277 REF_UNLOCK;278 memmove(buf->txt,ch,chlen);279 buf->txt[chlen]=0; buf->used=chlen;271 void SString::copyFrom(const char *ch, int chlen) 272 { 273 if (!ch) chlen = 0; 274 else if (chlen < 0) chlen = strlen(ch); 275 REF_LOCK; 276 detachEmpty(chlen); 277 REF_UNLOCK; 278 memmove(buf->txt, ch, chlen); 279 buf->txt[chlen] = 0; buf->used = chlen; 280 280 } 281 281 282 282 void SString::operator=(const char *ch) 283 283 { 284 copyFrom(ch);284 copyFrom(ch); 285 285 } 286 286 287 287 void SString::operator=(const SString&s) 288 288 { 289 if (s.buf==buf) return;290 REF_LOCK;291 detach();292 buf=s.buf;293 if (buf->size) buf->refcount++;294 REF_UNLOCK;289 if (s.buf == buf) return; 290 REF_LOCK; 291 detach(); 292 buf = s.buf; 293 if (buf->size) buf->refcount++; 294 REF_UNLOCK; 295 295 } 296 296 /////////////////////////////////////// … … 298 298 SString SString::substr(int begin, int length) const 299 299 { 300 if (begin<0) { length+=begin; begin=0; }301 if (length>=(len()-begin)) length=len()-begin;302 if (length<=0) return SString();303 if (length==len()) return *this;304 return SString((*this)(begin),length);300 if (begin < 0) { length += begin; begin = 0; } 301 if (length >= (len() - begin)) length = len() - begin; 302 if (length <= 0) return SString(); 303 if (length == len()) return *this; 304 return SString((*this)(begin), length); 305 305 } 306 306 … … 309 309 bool SString::equals(const SString& s) const 310 310 { 311 if (s.buf==buf) return true;312 return strcmp(buf->txt,s.buf->txt)==0;311 if (s.buf == buf) return true; 312 return strcmp(buf->txt, s.buf->txt) == 0; 313 313 } 314 314 315 315 /////////////////////////////////////// 316 316 317 int SString::indexOf(int character, int start) const318 { 319 const char *found=strchr(buf->txt+start,character);320 return found?found-buf->txt:-1;321 } 322 323 int SString::indexOf(const char *substring, int start) const324 { 325 char *found=strstr(buf->txt+start,substring);326 return found?found-buf->txt:-1;327 } 328 329 int SString::indexOf(const SString & substring, int start) const330 { 331 char *found=strstr(buf->txt+start,substring.c_str());332 return found?found-buf->txt:-1;333 } 334 335 bool SString::getNextToken (int& pos,SString &token,char separator) const336 { 337 if (pos>=len()) {token=0;return false;}338 int p1=pos,p2;339 const char *t1=buf->txt+pos;340 const char *t2=strchr(t1,separator);341 if (t2) pos=(p2=(t2-buf->txt))+1; else p2=pos=len();342 strncpy(token.directWrite(p2-p1),t1,p2-p1);343 token.endWrite(p2-p1);344 return true;317 int SString::indexOf(int character, int start) const 318 { 319 const char *found = strchr(buf->txt + start, character); 320 return found ? found - buf->txt : -1; 321 } 322 323 int SString::indexOf(const char *substring, int start) const 324 { 325 char *found = strstr(buf->txt + start, substring); 326 return found ? found - buf->txt : -1; 327 } 328 329 int SString::indexOf(const SString & substring, int start) const 330 { 331 char *found = strstr(buf->txt + start, substring.c_str()); 332 return found ? found - buf->txt : -1; 333 } 334 335 bool SString::getNextToken(int& pos, SString &token, char separator) const 336 { 337 if (pos >= len()) { token = 0; return false; } 338 int p1 = pos, p2; 339 const char *t1 = buf->txt + pos; 340 const char *t2 = strchr(t1, separator); 341 if (t2) pos = (p2 = (t2 - buf->txt)) + 1; else p2 = pos = len(); 342 strncpy(token.directWrite(p2 - p1), t1, p2 - p1); 343 token.endWrite(p2 - p1); 344 return true; 345 345 } 346 346 347 347 bool SString::startsWith(const char *pattern) const 348 348 { 349 const char *t=this->c_str();350 for (;*pattern;pattern++,t++)351 if (*t != *pattern) return false;352 return true;349 const char *t = this->c_str(); 350 for (; *pattern; pattern++, t++) 351 if (*t != *pattern) return false; 352 return true; 353 353 } 354 354 355 355 SString SString::valueOf(int i) 356 356 { 357 return SString::sprintf("%d",i);357 return SString::sprintf("%d", i); 358 358 } 359 359 SString SString::valueOf(long i) 360 360 { 361 return SString::sprintf("%d",i);361 return SString::sprintf("%d", i); 362 362 } 363 363 SString SString::valueOf(double d) 364 364 { 365 SString tmp=SString::sprintf("%.15g",d);366 if ((!strchr(tmp.c_str(),'.'))&&(!strchr(tmp.c_str(),'e'))) tmp+=".0";367 return tmp;365 SString tmp = SString::sprintf("%.15g", d); 366 if ((!strchr(tmp.c_str(), '.')) && (!strchr(tmp.c_str(), 'e'))) tmp += ".0"; 367 return tmp; 368 368 } 369 369 SString SString::valueOf(const SString& s) 370 370 { 371 return s;371 return s; 372 372 } 373 373 374 374 #if 0 //testing _vscprintf 375 375 #define USE_VSCPRINTF 376 int _vscprintf(const char *format, va_list argptr)377 { 378 return vsnprintf("",0,format,argptr);376 int _vscprintf(const char *format, va_list argptr) 377 { 378 return vsnprintf("", 0, format, argptr); 379 379 } 380 380 #endif … … 382 382 SString SString::sprintf(const char* format, ...) 383 383 { 384 int n, size = 30;385 va_list ap;386 387 SString ret;384 int n, size = 30; 385 va_list ap; 386 387 SString ret; 388 388 389 389 #ifdef USE_VSCPRINTF 390 va_start(ap, format);391 size=_vscprintf(format, ap);392 va_end(ap);393 #endif 394 395 while (1)390 va_start(ap, format); 391 size = _vscprintf(format, ap); 392 va_end(ap); 393 #endif 394 395 while (1) 396 396 { 397 char* p=ret.directWrite(size);398 assert(p!=NULL);399 size=ret.directMaxLen()+1;400 /* Try to print in the allocated space. */401 va_start(ap, format);402 n = vsnprintf(p, size, format, ap);403 va_end(ap);404 /* If that worked, return the string. */405 if (n > -1 && n < size)397 char* p = ret.directWrite(size); 398 assert(p != NULL); 399 size = ret.directMaxLen() + 1; 400 /* Try to print in the allocated space. */ 401 va_start(ap, format); 402 n = vsnprintf(p, size, format, ap); 403 va_end(ap); 404 /* If that worked, return the string. */ 405 if (n > -1 && n < size) 406 406 { 407 ret.endWrite(n);408 return ret;407 ret.endWrite(n); 408 return ret; 409 409 } 410 /* Else try again with more space. */410 /* Else try again with more space. */ 411 411 #ifdef VSNPRINTF_RETURNS_REQUIRED_SIZE 412 if (n > -1) /* glibc 2.1 */413 size = n; /* precisely what is needed */414 else /* glibc 2.0 */415 #endif 416 size *= 2; /* twice the old size */412 if (n > -1) /* glibc 2.1 */ 413 size = n; /* precisely what is needed */ 414 else /* glibc 2.0 */ 415 #endif 416 size *= 2; /* twice the old size */ 417 417 } 418 418 } … … 420 420 SString &SString::empty() 421 421 { 422 static SString empty;423 return empty;422 static SString empty; 423 return empty; 424 424 } 425 425 426 426 SBuf &SBuf::empty() 427 427 { 428 static SBuf empty;429 return empty;428 static SBuf empty; 429 return empty; 430 430 } 431 431 … … 443 443 Fnv32_t fnv_32a_buf(void *buf, size_t len, Fnv32_t hval) 444 444 { 445 446 447 448 449 450 /* xor the bottom with the current octet */451 hval ^= (Fnv32_t)*bp++;452 453 /* multiply by the 32 bit FNV magic prime mod 2^32 */445 unsigned char *bp = (unsigned char *)buf; /* start of buffer */ 446 unsigned char *be = bp + len; /* beyond end of buffer */ 447 448 while (bp < be) { 449 450 /* xor the bottom with the current octet */ 451 hval ^= (Fnv32_t)*bp++; 452 453 /* multiply by the 32 bit FNV magic prime mod 2^32 */ 454 454 #if defined(NO_FNV_GCC_OPTIMIZATION) 455 hval *= FNV_32_PRIME;455 hval *= FNV_32_PRIME; 456 456 #else 457 hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);458 #endif 459 460 461 462 463 457 hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); 458 #endif 459 460 } 461 462 /* return our new hash value */ 463 return hval; 464 464 } 465 465 ////////////////////////////////////////////////// … … 468 468 uint32_t SString::hash() const 469 469 { 470 return fnv_32a_buf(txt,used,FNV1_32A_INIT);470 return fnv_32a_buf(txt, used, FNV1_32A_INIT); 471 471 } 472 472 #else 473 473 uint32_t SBuf::hash() const 474 474 { 475 return fnv_32a_buf(txt,used,FNV1_32A_INIT);476 } 477 #endif 475 return fnv_32a_buf(txt, used, FNV1_32A_INIT); 476 } 477 #endif
Note: See TracChangeset
for help on using the changeset viewer.