00001
00002
00003
00004
00005
00006
00007
00008
#include "wvstring.h"
00009
#include <ctype.h>
00010
#include <assert.h>
00011
00012 WvStringBuf WvFastString::nullbuf = { 0, 1 };
00013 const WvFastString WvFastString::null;
00014
00015
const WvString WvString::empty(
"");
00016
00017
00018
00019 static inline int _max(
int x,
int y)
00020 {
00021
return x>y ? x : y;
00022 }
00023
00024
00025 void WvFastString::setsize(size_t i)
00026 {
00027
unlink();
00028
newbuf(i);
00029 }
00030
00031
00032
00033 WvFastString::WvFastString()
00034 {
00035
link(&
nullbuf, NULL);
00036 }
00037
00038
00039 WvFastString::WvFastString(
const WvFastString &s)
00040 {
00041
link(s.
buf, s.
str);
00042 }
00043
00044
00045 WvFastString::WvFastString(
const WvString &s)
00046 {
00047
link(s.
buf, s.
str);
00048 }
00049
00050
00051 WvFastString::WvFastString(
const char *_str)
00052 {
00053
00054
str = (
char *)_str;
00055
buf = NULL;
00056 }
00057
00058
00059 void WvString::copy_constructor(
const WvFastString &s)
00060 {
00061
if (!s.
buf)
00062 {
00063 link(&nullbuf, s.
str);
00064
unique();
00065 }
00066
else
00067 link(s.
buf, s.
str);
00068 }
00069
00070
00071 WvString::WvString(
const char *_str)
00072 {
00073 link(&nullbuf, _str);
00074
00075
00076
00077
00078
unique();
00079 }
00080
00081
00082
00083
00084 WvFastString::WvFastString(
short i)
00085 {
00086
newbuf(32);
00087 sprintf(
str,
"%hd", i);
00088 }
00089
00090
00091 WvFastString::WvFastString(
unsigned short i)
00092 {
00093
newbuf(32);
00094 sprintf(
str,
"%hu", i);
00095 }
00096
00097
00098 WvFastString::WvFastString(
int i)
00099 {
00100
newbuf(32);
00101 sprintf(
str,
"%d", i);
00102 }
00103
00104
00105 WvFastString::WvFastString(
unsigned int i)
00106 {
00107
newbuf(32);
00108 sprintf(
str,
"%u", i);
00109 }
00110
00111
00112 WvFastString::WvFastString(
long i)
00113 {
00114
newbuf(32);
00115 sprintf(
str,
"%ld", i);
00116 }
00117
00118
00119 WvFastString::WvFastString(
unsigned long i)
00120 {
00121
newbuf(32);
00122 sprintf(
str,
"%lu", i);
00123 }
00124
00125
00126 WvFastString::WvFastString(
long long i)
00127 {
00128
newbuf(32);
00129 sprintf(
str,
"%lld", i);
00130 }
00131
00132
00133 WvFastString::WvFastString(
unsigned long long i)
00134 {
00135
newbuf(32);
00136 sprintf(
str,
"%llu", i);
00137 }
00138
00139
00140 WvFastString::WvFastString(
double i)
00141 {
00142
newbuf(32);
00143 sprintf(
str,
"%g", i);
00144 }
00145
00146
00147 WvFastString::~WvFastString()
00148 {
00149
unlink();
00150 }
00151
00152
00153 void WvFastString::unlink()
00154 {
00155
if (
buf && ! --
buf->
links)
00156 {
00157 free(
buf);
00158
buf = NULL;
00159 }
00160 }
00161
00162
00163 void WvFastString::link(
WvStringBuf *_buf,
const char *_str)
00164 {
00165
buf = _buf;
00166
if (
buf)
00167
buf->
links++;
00168
str = (
char *)_str;
00169 }
00170
00171
00172 WvStringBuf *
WvFastString::alloc(size_t size)
00173 {
00174
WvStringBuf *abuf = (
WvStringBuf *)malloc(
WVSTRINGBUF_SIZE(
buf)
00175 + size +
WVSTRING_EXTRA);
00176 abuf->
links = 0;
00177 abuf->
size = size;
00178
return abuf;
00179 }
00180
00181
00182 WvString &
WvString::append(
WvStringParm s)
00183 {
00184
if (s)
00185 {
00186
if (*this)
00187 *
this =
WvString(
"%s%s", *
this, s);
00188
else
00189 *
this = s;
00190 }
00191
00192
return *
this;
00193 }
00194
00195
00196 size_t
WvFastString::len()
const
00197
{
00198
return str ? strlen(
str) : 0;
00199 }
00200
00201
00202 void WvFastString::newbuf(size_t size)
00203 {
00204
buf =
alloc(size);
00205
buf->
links = 1;
00206
str =
buf->
data;
00207 }
00208
00209
00210
00211
00212 WvString &
WvString::unique()
00213 {
00214
if (buf->
links > 1 && str)
00215 {
00216
WvStringBuf *newb = alloc(
len() + 1);
00217 memcpy(newb->
data, str, newb->
size);
00218
unlink();
00219 link(newb, newb->
data);
00220 }
00221
00222
return *
this;
00223 }
00224
00225
00226 WvFastString &WvFastString::operator= (
const WvFastString &s2)
00227 {
00228
if (s2.
buf ==
buf && s2.
str ==
str)
00229
return *
this;
00230
else
00231 {
00232
unlink();
00233
link(s2.
buf, s2.
str);
00234 }
00235
return *
this;
00236 }
00237
00238
00239 WvString &WvString::operator= (
int i)
00240 {
00241
unlink();
00242 newbuf(32);
00243 sprintf(str,
"%d", i);
00244
return *
this;
00245 }
00246
00247
00248 WvString &WvString::operator= (
const WvFastString &s2)
00249 {
00250
if (s2.
buf == buf && s2.
str == str)
00251
return *
this;
00252
else if (!s2.
buf)
00253 {
00254
00255
unlink();
00256 link(&nullbuf, s2.
str);
00257
unique();
00258 }
00259
else
00260 {
00261
00262
unlink();
00263 link(s2.
buf, s2.
str);
00264 }
00265
return *
this;
00266 }
00267
00268
00269
00270 bool WvFastString::operator== (
WvStringParm s2)
const
00271
{
00272
return (
str==s2.
str) || (
str && s2.
str && !strcmp(
str, s2.
str));
00273 }
00274
00275
00276 bool WvFastString::operator!= (
WvStringParm s2)
const
00277
{
00278
return (
str!=s2.
str) && (!
str || !s2.
str || strcmp(
str, s2.
str));
00279 }
00280
00281
00282 bool WvFastString::operator< (
WvStringParm s2)
const
00283
{
00284
if (
str == s2.
str)
return false;
00285
if (
str == 0)
return true;
00286
if (s2.
str == 0)
return false;
00287
return strcmp(
str, s2.
str) < 0;
00288 }
00289
00290
00291 bool WvFastString::operator== (
const char *s2)
const
00292
{
00293
return (
str==s2) || (
str && s2 && !strcmp(
str, s2));
00294 }
00295
00296
00297 bool WvFastString::operator!= (
const char *s2)
const
00298
{
00299
return (
str!=s2) && (!
str || !s2 || strcmp(
str, s2));
00300 }
00301
00302
00303 bool WvFastString::operator< (
const char *s2)
const
00304
{
00305
if (
str == s2)
return false;
00306
if (
str == 0)
return true;
00307
if (s2 == 0)
return false;
00308
return strcmp(
str, s2) < 0;
00309 }
00310
00311
00312
00313 bool WvFastString::operator! ()
const
00314
{
00315
return !
str || !
str[0];
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 static const char *
pparse(
const char *cptr,
00328
bool &zeropad,
int &justify,
int &maxlen)
00329 {
00330 assert(*cptr ==
'%');
00331 cptr++;
00332
00333 zeropad = (*cptr ==
'0');
00334
00335 justify = atoi(cptr);
00336
00337
for (; *cptr && *cptr!=
'.' && *cptr!=
'%' && !isalpha(*cptr); cptr++)
00338 ;
00339
if (!*cptr)
return cptr;
00340
00341
if (*cptr ==
'.')
00342 maxlen = atoi(cptr+1);
00343
else
00344 maxlen = 0;
00345
00346
for (; *cptr && *cptr!=
'%' && !isalpha(*cptr); cptr++)
00347 ;
00348
00349
return cptr;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 void WvFastString::do_format(
WvFastString &output,
const char *format,
00366
const WvFastString *
const *a)
00367 {
00368
static const char blank[] =
"(nil)";
00369
const WvFastString *
const *argptr = a;
00370
const char *iptr = format, *arg;
00371
char *optr;
00372
int total = 0, aplen, ladd, justify, maxlen;
00373
bool zeropad;
00374
00375
00376
while (*iptr)
00377 {
00378
if (*iptr !=
'%')
00379 {
00380 total++;
00381 iptr++;
00382
continue;
00383 }
00384
00385
00386 iptr =
pparse(iptr, zeropad, justify, maxlen);
00387
if (*iptr ==
'%')
00388 {
00389 total++;
00390 iptr++;
00391
continue;
00392 }
00393
00394 assert(*iptr ==
's' || *iptr ==
'c');
00395
00396
if (*iptr ==
's')
00397 {
00398
if (!*argptr || !(**argptr).
cstr())
00399 arg = blank;
00400
else
00401 arg = (**argptr).cstr();
00402 ladd =
_max(abs(justify), strlen(arg));
00403
if (maxlen && maxlen < ladd)
00404 ladd = maxlen;
00405 total += ladd;
00406 argptr++;
00407 iptr++;
00408
continue;
00409 }
00410
00411
if (*iptr++ ==
'c')
00412 {
00413 argptr++;
00414 total++;
00415 }
00416 }
00417
00418 output.
setsize(total + 1);
00419
00420
00421 iptr = format;
00422 optr = output.
str;
00423 argptr = a;
00424
while (*iptr)
00425 {
00426
if (*iptr !=
'%')
00427 {
00428 *optr++ = *iptr++;
00429
continue;
00430 }
00431
00432
00433 iptr =
pparse(iptr, zeropad, justify, maxlen);
00434
if (*iptr ==
'%')
00435 {
00436 *optr++ = *iptr++;
00437
continue;
00438 }
00439
if (*iptr ==
's')
00440 {
00441
if (!*argptr || !(**argptr).
cstr())
00442 arg = blank;
00443
else
00444 arg = (**argptr).cstr();
00445 aplen = strlen(arg);
00446
if (maxlen && maxlen < aplen)
00447 aplen = maxlen;
00448
00449
if (justify > aplen)
00450 {
00451
if (zeropad)
00452 memset(optr,
'0', justify-aplen);
00453
else
00454 memset(optr,
' ', justify-aplen);
00455 optr += justify-aplen;
00456 }
00457
00458 strncpy(optr, arg, aplen);
00459 optr += aplen;
00460
00461
if (justify < 0 && -justify > aplen)
00462 {
00463
if (zeropad)
00464 memset(optr,
'0', -justify-aplen);
00465
else
00466 memset(optr,
' ', -justify-aplen);
00467 optr += -justify - aplen;
00468 }
00469
00470 argptr++;
00471 iptr++;
00472
continue;
00473 }
00474
if (*iptr++ ==
'c')
00475 {
00476 arg = **argptr++;
00477 *optr++ = (
char)atoi(arg);
00478
00479 argptr++;
00480 }
00481 }
00482 *optr = 0;
00483 }
00484
00485