00001
00002
00003
00004
00005
00006
00007
00008 #include "wvstring.h"
00009 #include <ctype.h>
00010 #include <assert.h>
00011
00012 WvStringBuf __wvs_nb = { 0, 1 };
00013 const WvString __wvs_n;
00014
00015
00016
00017 static inline int _max(int x, int y)
00018 {
00019 return x>y ? x : y;
00020 }
00021
00022
00023 void WvString::setsize(size_t i)
00024 {
00025 unlink();
00026 newbuf(i);
00027 }
00028
00029
00030
00031 WvString::WvString()
00032 {
00033 buf = NULL;
00034 str = NULL;
00035 }
00036
00037
00038 WvString::WvString(const WvString &s)
00039 {
00040 link(s.buf, s.str);
00041 }
00042
00043
00044 WvString::WvString(const char *_str)
00045 {
00046 if (_str)
00047 link(&__wvs_nb, _str);
00048 else
00049 {
00050 buf = NULL;
00051 str = NULL;
00052 }
00053 }
00054
00055
00056
00057
00058 WvString::WvString(int i)
00059 {
00060 newbuf(32);
00061 sprintf(str, "%d", i);
00062 }
00063
00064
00065 WvString::~WvString()
00066 {
00067 unlink();
00068 }
00069
00070
00071 void WvString::unlink()
00072 {
00073 if (!buf) return;
00074 if (! --buf->links)
00075 free(buf);
00076 }
00077
00078 void WvString::link(WvStringBuf *_buf, const char *_str)
00079 {
00080 buf = _buf;
00081 if (buf) buf->links++;
00082 str = (char *)_str;
00083 }
00084
00085
00086 WvStringBuf *WvString::alloc(size_t size)
00087 {
00088 WvStringBuf *buf = (WvStringBuf *)malloc(WVSTRINGBUF_SIZE(buf)
00089 + size + WVSTRING_EXTRA);
00090 buf->links = 0;
00091 buf->size = size;
00092 return buf;
00093 }
00094
00095
00096 void WvString::append(const WvString &s)
00097 {
00098 if (buf)
00099 *this = WvString("%s%s", *this, s);
00100 else
00101 {
00102 *this = s;
00103 unique();
00104 }
00105 }
00106
00107
00108 size_t WvString::len() const
00109 {
00110 if (!buf) return 0;
00111 return buf->size ? buf->size-1 : strlen(str);
00112 }
00113
00114
00115 void WvString::newbuf(size_t size)
00116 {
00117 buf = alloc(size);
00118 buf->links = 1;
00119 str = buf->data;
00120 }
00121
00122
00123
00124
00125 WvString &WvString::unique()
00126 {
00127 if (buf->links > 1)
00128 {
00129 WvStringBuf *newb = alloc(len() + 1);
00130 memcpy(newb->data, str, newb->size);
00131 unlink();
00132 link(newb, newb->data);
00133 }
00134
00135 return *this;
00136 }
00137
00138
00139 WvString& WvString::operator= (const WvString &s2)
00140 {
00141 if (s2.buf == buf && s2.str == str)
00142 return *this;
00143 unlink();
00144 link(s2.buf, s2.str);
00145 return *this;
00146 }
00147
00148
00149
00150 bool WvString::operator== (const WvString &s2) const
00151 {
00152 return (str==s2.str) || (str && s2.str && !strcmp(str, s2.str));
00153 }
00154
00155
00156 bool WvString::operator!= (const WvString &s2) const
00157 {
00158 return (str!=s2.str) && (!str || !s2.str || strcmp(str, s2.str));
00159 }
00160
00161
00162 bool WvString::operator== (const char *s2) const
00163 {
00164 return (str==s2) || (str && s2 && !strcmp(str, s2));
00165 }
00166
00167
00168 bool WvString::operator!= (const char *s2) const
00169 {
00170 return (str!=s2) && (!str || !s2 || strcmp(str, s2));
00171 }
00172
00173
00174
00175 bool WvString::operator! () const
00176 {
00177 return !buf || !str[0];
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 static char *pparse(char *cptr, bool &zeropad, int &justify, int &maxlen)
00190 {
00191 assert(*cptr == '%');
00192 cptr++;
00193
00194 zeropad = (*cptr == '0');
00195
00196 justify = atoi(cptr);
00197
00198 for (; *cptr && *cptr!='.' && *cptr!='%' && !isalpha(*cptr); cptr++)
00199 ;
00200 if (!*cptr) return cptr;
00201
00202 if (*cptr == '.')
00203 maxlen = atoi(cptr+1);
00204 else
00205 maxlen = 0;
00206
00207 for (; *cptr && *cptr!='%' && !isalpha(*cptr); cptr++)
00208 ;
00209
00210 return cptr;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 void WvString::do_format(WvString &output, char *format, const WvString **a)
00227 {
00228 static WvString blank("(nil)");
00229 const WvString **aptr = a;
00230 char *iptr = format, *optr;
00231 int total = 0, aplen, ladd, justify, maxlen;
00232 bool zeropad;
00233
00234 while (*iptr)
00235 {
00236 if (*iptr != '%')
00237 {
00238 total++;
00239 iptr++;
00240 continue;
00241 }
00242
00243
00244 iptr = pparse(iptr, zeropad, justify, maxlen);
00245 if (*iptr == '%')
00246 {
00247 total++;
00248 iptr++;
00249 continue;
00250 }
00251
00252 assert(*iptr == 's');
00253
00254 if (*iptr++ == 's')
00255 {
00256 if (!*aptr || !(const char *)**aptr)
00257 *aptr = ␣
00258 ladd = _max(abs(justify), strlen(**aptr));
00259 if (maxlen && maxlen < ladd)
00260 ladd = maxlen;
00261 total += ladd;
00262 aptr++;
00263 }
00264 }
00265
00266 output.setsize(total + 1);
00267
00268 iptr = format;
00269 optr = output.edit();
00270 aptr = a;
00271 while (*iptr)
00272 {
00273 if (*iptr != '%')
00274 {
00275 *optr++ = *iptr++;
00276 continue;
00277 }
00278
00279
00280 iptr = pparse(iptr, zeropad, justify, maxlen);
00281 if (*iptr == '%')
00282 {
00283 *optr++ = *iptr++;
00284 continue;
00285 }
00286 if (*iptr++ == 's')
00287 {
00288 aplen = strlen(**aptr);
00289 if (maxlen && maxlen < aplen)
00290 aplen = maxlen;
00291
00292 if (justify > aplen)
00293 {
00294 if (zeropad)
00295 memset(optr, '0', justify-aplen);
00296 else
00297 memset(optr, ' ', justify-aplen);
00298 optr += justify-aplen;
00299 }
00300
00301 strncpy(optr, **aptr, aplen);
00302 optr += aplen;
00303
00304 if (justify < 0 && -justify > aplen)
00305 {
00306 if (zeropad)
00307 memset(optr, '0', -justify-aplen);
00308 else
00309 memset(optr, ' ', -justify-aplen);
00310 optr += -justify - aplen;
00311 }
00312
00313 aptr++;
00314 }
00315 }
00316 *optr = 0;
00317 }