00001
00013 #ifndef tchar
00014 #error These templates require 'tchar' to be defined so they know what sort of \
00015 characters to make. 'tchar' may be 'wchar_t' or 'char'.
00016 #endif
00017
00018 #ifndef handler
00019 #error These templates require 'handler' to be defined so they know what to do \
00020 when the end of the buffer is reached. 'handler' may be 'grow' or 'fixed'
00021 #endif
00022
00024 #define ctl_mstring_growcode(tchar,handler, self, addLen) ppConcat3(ctl_mstring_,handler,_growcode)(tchar, self, addLen )
00025
00026 #define ctl_mstring_check(tchar,handler, self, addLen) ppConcat3(ctl_mstring_,handler,_check)(tchar, self, addLen )
00027
00028 #define ctl_mstring_checkabort(tchar,handler, self, addLen) ppConcat3(ctl_mstring_,handler,_checkabort)(tchar, self, addLen )
00029
00030
00032 #define ctl_mstring_grow_growcode(tchar, self, addLen ) \
00033 { \
00034 tchar* begin; \
00035 size_t need; \
00036 assertobjptr(self);\
00037 begin = (self)->begin; \
00038 need = ((self)->end+(addLen)+1-begin); \
00039 if( need > (size_t)((self)->endBuff - (self)->begin) ) \
00040 {\
00041 need += ctl_mstring_delta;\
00042 if( (self)->begin == ctl_mstring_(tchar,handler,0) )\
00043 (self)->begin = NULL;\
00044 ctl_realloc((self)->begin,ctl_chsize(tchar,need)); \
00045 (self)->end = (self)->begin + ((self)->end - begin);\
00046 *(self)->end = 0;\
00047 (self)->endBuff = (self)->begin + need-1;\
00048 }\
00049 }
00050 #define ctl_mstring_grow_check(tchar, self, addLen ) ctl_mstring_(tchar,grow, grow )( self, addLen )
00051 #define ctl_mstring_grow_checkabort(tchar, self, addLen ) ctl_mstring_(tchar,grow, grow )( self, addLen )
00052 #define ctl_mstring_delta 64
00053
00055 #define ctl_mstring_fixed_growcode(tchar, self, addLen ) {}
00056
00058 #define ctl_mstring_fixed_check(tchar, self, addLen )\
00059 { \
00060 assertobjptr(self);\
00061 if( (size_t)(addLen) > (size_t)((self)->endBuff-(self)->end) ) \
00062 (addLen) = (size_t)((self)->endBuff-(self)->end); \
00063 if( !(addLen) ) \
00064 {\
00065 *(self)->endBuff = 0;\
00066 return; \
00067 }\
00068 }
00069
00071 #define ctl_mstring_fixed_checkabort(tchar, self, addLen )\
00072 { \
00073 assertobjptr(self);\
00074 if( (size_t)(addLen) > (size_t)((self)->endBuff-(self)->end) ) \
00075 {\
00076 *(self)->endBuff = 0;\
00077 return; \
00078 }\
00079 }
00080
00081
00087 ctl_mstring_xgrow(tchar,handler, const tchar ctl_mstring_(tchar,handler,0)[1] = szconst(tchar,""); )
00088
00096 void ctl_mstring_(tchar,handler, grow )( ctl_mstring(tchar,handler)* self, size_t addLen ) \
00097 ctl_mstring_growcode(tchar,handler, self, addLen)
00098
00107 void ctl_mstring_(tchar,handler, fill )( ctl_mstring(tchar,handler)* self, tchar fillVal, size_t count )
00108 {
00109 ctl_mstring_check(tchar,handler, self, count );
00110 {
00111 tchar* p = self->end;
00112 const tchar* e = p + count;
00113 while( p < e )
00114 *p++ = fillVal;
00115 self->end = p;
00116 *p = 0;
00117 }
00118 }
00119
00128 void ctl_mstring_(tchar,handler, filltab )( ctl_mstring(tchar,handler)* self, tchar fillVal, size_t tabPos )
00129 {
00130 size_t index = self->end - self->begin;
00131 if( index < tabPos )
00132 ctl_mstring_(tchar,handler, fill )( self, fillVal, tabPos - index );
00133 }
00134
00142 void ctl_mstring_(tchar,handler, putint32 )( ctl_mstring(tchar,handler)* self, int32 value )
00143 {
00144 size_t need = int32_NumPlaces( value );
00145 size_t count = need;
00146 ctl_mstring_check(tchar,handler, self, count );
00147 ctl_mstring_xfixed(tchar,handler, if( count < need ) return );
00148 {
00149 tchar* p = self->end;
00150 if( value < 0 )
00151 *p++ = chconst(tchar,'-');
00152 p = self->end += need;
00153 *p-- = 0;
00154 do
00155 {
00156 int32 digit = abs_mod(int32,value,10);
00157 value = value/10;
00158 *p-- = (tchar)(chconst(tchar,'0')+digit);
00159 }
00160 while( value );
00161 }
00162 }
00163
00171 void ctl_mstring_(tchar,handler, putuint32 )( ctl_mstring(tchar,handler)* self, uint32 value )
00172 {
00173 size_t need = uint32_NumPlaces( value );
00174 size_t count = need;
00175 ctl_mstring_check(tchar,handler, self, count );
00176 ctl_mstring_xfixed(tchar,handler, if( count < need ) return );
00177 {
00178 tchar* p = self->end;
00179 p = self->end += need;
00180 *p-- = 0;
00181 do
00182 {
00183 uint32 digit = abs_mod(uint32,value,10);
00184 value = value/10;
00185 *p-- = (tchar)(chconst(tchar,'0')+digit);
00186 }
00187 while( value );
00188 }
00189 }
00190
00198 void ctl_mstring_(tchar,handler, putint64 )( ctl_mstring(tchar,handler)* self, int64 value )
00199 {
00200 size_t need = int64_NumPlaces( value );
00201 size_t count = need;
00202 ctl_mstring_check(tchar,handler, self, count );
00203 ctl_mstring_xfixed(tchar,handler, if( count < need ) return );
00204 {
00205 tchar* p = self->end;
00206 if( value < 0 )
00207 *p++ = chconst(tchar,'-');
00208 p = self->end += need;
00209 *p-- = 0;
00210 do
00211 {
00212 int64 digit = abs_mod(int64,value,10);
00213 value = value/10;
00214 *p-- = (tchar)(chconst(tchar,'0')+digit);
00215 }
00216 while( value );
00217 }
00218 }
00219
00227 void ctl_mstring_(tchar,handler, putuint64 )( ctl_mstring(tchar,handler)* self, uint64 value )
00228 {
00229 size_t need = uint64_NumPlaces( value );
00230 size_t count = need;
00231 ctl_mstring_check(tchar,handler, self, count );
00232 ctl_mstring_xfixed(tchar,handler, if( count < need ) return );
00233 {
00234 tchar* p = self->end;
00235 if( value < 0 )
00236 *p++ = chconst(tchar,'-');
00237 p = self->end += need;
00238 *p-- = 0;
00239 do
00240 {
00241 uint64 digit = abs_mod(uint64,value,10);
00242 value = value/10;
00243 *p-- = (tchar)(chconst(tchar,'0')+digit);
00244 }
00245 while( value );
00246 }
00247 }
00248
00256 void ctl_mstring_(tchar,handler, putfloat64 )( ctl_mstring(tchar,handler)* self, float64 value )
00257 {
00258
00259 char buff[32];
00260
00261 csnprintf(char)(buff,32, szconst(char,"%.6f"), (double)(value) );
00262 ppCtypeSelect(tchar,ctl_mstring_(tchar,handler, strncat )( self, buff, countof(buff) );,{ char* pbuff = buff; while( *pbuff ) { ctl_mstring_(tchar,handler, fill )((self), (tchar)*pbuff, 1 ); pbuff++; } })
00263 }
00264
00272 void ctl_mstring_(tchar,handler, putxuint32 )( ctl_mstring(tchar,handler)* self, uint32 value, size_t places )
00273 {
00274 size_t count = places;
00275 ctl_mstring_check(tchar,handler, self, count );
00276 ctl_mstring_xfixed(tchar,handler, if( count < places ) return );
00277 {
00278 tchar* p = self->end += places;
00279 *p-- = 0;
00280 while( p >= self->end )
00281 {
00282 tchar ch = (tchar)(chconst(tchar,'0') + (value & 0xf));
00283 if( ch > chconst(tchar,'9') )
00284 ch += (chconst(tchar,'A')-(chconst(tchar,'9')+1));
00285 *p-- = ch;
00286 value>>=4;
00287 }
00288 }
00289 }
00290
00298 void ctl_mstring_(tchar,handler, putxuint64 )( ctl_mstring(tchar,handler)* self, uint64 value, size_t places )
00299 {
00300 size_t count = places;
00301 ctl_mstring_check(tchar,handler, self, count );
00302 ctl_mstring_xfixed(tchar,handler, if( count < places ) return );
00303 {
00304 tchar* p = self->end += places;
00305 *p-- = 0;
00306 while( p >= self->end )
00307 {
00308 tchar ch = (tchar)(chconst(tchar,'0') + (value & 0xf));
00309 if( ch > chconst(tchar,'9') )
00310 ch += (chconst(tchar,'A')-(chconst(tchar,'9')+1));
00311 *p-- = ch;
00312 value>>=4;
00313 }
00314 }
00315 }
00316
00326 void ctl_mstring_(tchar,handler, putenum )( ctl_mstring(tchar,handler)* self, int value, const tchar* const* const szzList, int max, const tchar* szUndefined )
00327 {
00328 if( value >= max )
00329 ctl_mstring_(tchar,handler, strncat )( self, szUndefined, ~0u );
00330 else
00331 ctl_mstring_(tchar,handler, strncat )( self, szzList[value], ~0u );
00332 }
00333
00342 void ctl_mstring_(tchar,handler, strncat )( ctl_mstring(tchar,handler)* self, const tchar* sz, size_t maxLen )
00343 {
00344 size_t count = cstrnlen(tchar)(sz,maxLen);
00345 ctl_mstring_check(tchar,handler, self, count );
00346 cmemcpy(tchar, self->end, sz, count );
00347 self->end += count;
00348 *self->end = 0;
00349 }
00350
00360 void ctl_mstring_(tchar,handler, strncpy )( ctl_mstring(tchar,handler)* self, const tchar* sz, size_t maxLen )
00361 {
00362 size_t count;
00363 assertconst(sz,sizeof(tchar));
00364 count = cstrnlen(tchar)(sz,maxLen);
00365 ctl_mstring_check(tchar,handler, self, count );
00366 cmemcpy(tchar, self->begin, sz, count );
00367 self->end = self->begin + count;
00368 *self->end = 0;
00369 }
00370
00381 void ctl_mstring_(tchar,handler, strninsert )( ctl_mstring(tchar,handler)* self, size_t position, const tchar* sz, size_t maxLen )
00382 {
00383 size_t count;
00384 assertconst(sz,sizeof(tchar));
00385 count = cstrnlen(tchar)(sz,maxLen);
00386 ctl_mstring_check(tchar,handler, self, count );
00387 {
00388 size_t countAfter = (self->end-self->begin) - position;
00389 if( countAfter < 0 )
00390 ctl_mstring_(tchar,handler, fill )( self, szconst(tchar,' '), count );
00391 else if( countAfter > 0 )
00392 cmemmove(tchar, self->begin + position + count, self->begin + position, countAfter );
00393 cmemcpy(tchar, self->begin + position, sz, count );
00394 self->end += count;
00395 *self->end = 0;
00396 }
00397 }
00398
00408 void ctl_mstring_(tchar,handler, vsprintf )( ctl_mstring(tchar,handler)* self, const tchar* fmt, va_list args )
00409 {
00410 int count;
00411 int result;
00412 assertconst(fmt,sizeof(tchar));
00413 assertobjptr(self);
00414 count = (int)(self->endBuff - self->end);
00415 result = cvsnprintf(tchar)( self->end, count, fmt, args );
00416 if( 0 > result )
00417 {
00418 tchar* tmp = NULL;
00419 size_t len = 128;
00420 do {
00421 ctl_realloc(tmp,len);
00422 result = cvsnprintf(tchar)(tmp, len, fmt, args );
00423 len <<= 1;
00424 } while(result < 0);
00425 ctl_free(tmp);
00426 }
00427 if( result < count )
00428 {
00429 self->end += result;
00430 *self->end = 0;
00431 return;
00432 }
00433 ctl_mstring_checkabort(tchar,handler, self, result );
00434 ctl_mstring_xgrow(tchar,handler, self->end += cvsnprintf(tchar)(self->end, self->endBuff - self->end, fmt, args ); *self->end = 0; )
00435 }
00444 void ctl_mstring_(tchar,handler, sprintf )( ctl_mstring(tchar,handler)* self, const tchar* fmt, ... )
00445 {
00446 va_list args;
00447 va_start(args, fmt);
00448 ctl_mstring_(tchar,handler, vsprintf )( self, fmt, args );
00449 }
00450
00458 void ctl_mstring_(tchar,handler, makeClabel )( ctl_mstring(tchar,handler)* self )
00459 {
00460 tchar* e, *p;
00461 assertobjptr(self);
00462 e = self->end;
00463 for( p = self->begin; p < e; ++p )
00464 if( !cisalpha(tchar)(*p) && !cisdigit(tchar)(*p) )
00465 *p = '_';
00466 }
00467
00476 void ctl_mstring_(tchar,handler, truncate )( ctl_mstring(tchar,handler)* self, size_t newsize )
00477 {
00478 assertobjptr(self);
00479 if( newsize <= (size_t)(self->end - self->begin) )
00480 {
00481 self->end = self->begin + newsize;
00482 *self->end = 0;
00483 }
00484 }
00485
00495 int ctl_mstring_(tchar,handler, rcompare )( const ctl_mstring(tchar,handler)* p1, const ctl_mstring(tchar,handler)* p2 )
00496 {
00497 assertobjconst(p1);
00498 assertobjconst(p2);
00499 return ctl_mstring_(tchar,handler, compare )( p1, p1 );
00500 }
00501
00511 int ctl_mstring_(tchar,handler, compare )( const ctl_mstring(tchar,handler)* p1, const ctl_mstring(tchar,handler)* p2 )
00512 {
00513 assertobjconst(p1);
00514 assertobjconst(p2);
00515 {
00516 int diff;
00517 size_t lenp1 = (p1->end-p1->begin);
00518 size_t lenp2 = (p2->end-p2->begin);
00519 size_t count = min(lenp1,lenp2);
00520 const tchar* pp1 = p1->begin;
00521 const tchar* pp2 = p2->begin;
00522 while( count-- )
00523 {
00524 diff = *pp1++ - *pp2++;
00525 if( diff )
00526 return diff;
00527 }
00528 if( lenp1 > lenp2 )
00529 return 1;
00530 if( lenp1 < lenp2 )
00531 return -1;
00532 }
00533 return 0;
00534 }
00535
00546 int ctl_mstring_(tchar,handler, strncmp )( const ctl_mstring(tchar,handler)* p1, const tchar* p2, size_t p2len )
00547 {
00548 assertobjconst(p1);
00549 assertconst(p2,sizeof(tchar));
00550 {
00551 const tchar* pp1 = p1->begin;
00552 const tchar* pp2 = p2;
00553 size_t lenp1 = (p1->end-p1->begin);
00554 size_t lenp2 = cstrnlen(tchar)(p2,p2len);
00555 size_t count = min(lenp2,lenp1);
00556 while( count-- )
00557 {
00558 int diff = *pp1++ - *pp2++;
00559 if( diff )
00560 return diff;
00561 }
00562 if( lenp1 > lenp2 )
00563 return 1;
00564 if( lenp1 < lenp2 )
00565 return -1;
00566 }
00567 return 0;
00568 }
00569
00580 int ctl_mstring_(tchar,handler, strnicmp )( const ctl_mstring(tchar,handler)* p1, const tchar* p2, size_t p2len )
00581 {
00582 assertobjconst(p1);
00583 assertconst(p2,sizeof(tchar));
00584 {
00585 const tchar* pp1 = p1->begin;
00586 const tchar* pp2 = p2;
00587 size_t lenp1 = (p1->end-p1->begin);
00588 size_t lenp2 = cstrnlen(tchar)(p2,p2len);
00589 size_t count = min(lenp2,lenp1);
00590 while( count-- )
00591 {
00592 int diff = toupper(*pp1++) - toupper(*pp2++);
00593 if( diff )
00594 return diff;
00595 }
00596 if( lenp1 > lenp2 )
00597 return 1;
00598 if( lenp1 < lenp2 )
00599 return -1;
00600 }
00601 return 0;
00602 }