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