WvStreams
wvstring.h
00001 /* -*- Mode: C++ -*-
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * Implementation of a simple and efficient printable-string class.
00006  * 
00007  * It leaves out many of the notational conveniences provided by other
00008  * string classes, because they waste too much CPU time and space.
00009  * It does the one thing really missing from char* strings, that is,
00010  * dynamic buffer management.
00011  * 
00012  * The 'str' member is the actual (char*) string.  You should never
00013  * need to access it directly.
00014  */
00015 #ifndef __WVSTRING_H
00016 #define __WVSTRING_H
00017 
00018 #include <string.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string> // no code is actually used from here
00022 
00023 
00024 /* 1 byte for terminating NUL */
00025 #define WVSTRING_EXTRA 1
00026 
00027 
00028 #define __WVS_F(n) WvStringParm __wvs_##n
00029 #define __WVS_FORM(n) WvStringParm __wvs_##n = WvFastString::null
00030 #define WVSTRING_FORMAT_DECL WvStringParm __wvs_format, \
00031                 WvStringParm __wvs_a0, \
00032                 __WVS_FORM( a1), __WVS_FORM( a2), __WVS_FORM( a3), \
00033                 __WVS_FORM( a4), __WVS_FORM( a5), __WVS_FORM( a6), \
00034                 __WVS_FORM( a7), __WVS_FORM( a8), __WVS_FORM( a9), \
00035                 __WVS_FORM(a10), __WVS_FORM(a11), __WVS_FORM(a12), \
00036                 __WVS_FORM(a13), __WVS_FORM(a14), __WVS_FORM(a15), \
00037                 __WVS_FORM(a16), __WVS_FORM(a17), __WVS_FORM(a18), \
00038                 __WVS_FORM(a19)
00039 #define WVSTRING_FORMAT_DEFN WvStringParm __wvs_format, \
00040                 WvStringParm __wvs_a0, \
00041                 __WVS_F( a1), __WVS_F( a2), __WVS_F( a3), \
00042                 __WVS_F( a4), __WVS_F( a5), __WVS_F( a6), \
00043                 __WVS_F( a7), __WVS_F( a8), __WVS_F( a9), \
00044                 __WVS_F(a10), __WVS_F(a11), __WVS_F(a12), \
00045                 __WVS_F(a13), __WVS_F(a14), __WVS_F(a15), \
00046                 __WVS_F(a16), __WVS_F(a17), __WVS_F(a18), \
00047                 __WVS_F(a19)
00048 #define WVSTRING_FORMAT_CALL __wvs_format, __wvs_a0, \
00049                 __wvs_a1, __wvs_a2, __wvs_a3, __wvs_a4, __wvs_a5, \
00050                 __wvs_a6, __wvs_a7, __wvs_a8, __wvs_a9, __wvs_a10, \
00051                 __wvs_a11, __wvs_a12, __wvs_a13, __wvs_a14, __wvs_a15, \
00052                 __wvs_a16, __wvs_a17, __wvs_a18, __wvs_a19
00053 
00054 struct WvStringBuf;
00055 class WvFastString;
00056 class WvString;
00057 class QString; // for operator QString()
00058 class QCString;
00059 
00060 // all WvFastString objects are const - they should _only_ be created
00061 // automatically by automatic typecasting in parameter passing.  So let's
00062 // create a handy alias.
00063 typedef const WvFastString &   WvStringParm;
00064 
00065 
00066 
00067 struct WvStringBuf
00068 {
00069     size_t size;        // string length - if zero, use strlen!!
00070     unsigned links;     // number of WvStrings using this buf.
00071     char data[1];       // optional room for extra string data
00072 };
00073 
00074 
00075 // the _actual_ space taken by a WvStringBuf, without the data[] array
00076 // (which is variable-sized, not really 1 byte)
00077 #define WVSTRINGBUF_SIZE(s) (s->data - (char *)s)
00078 
00093 class WvFastString
00094 {
00095     friend class WvString; // so WvString can access members of _other_ objects
00096     
00097 protected:
00098     WvStringBuf *buf;
00099     char *str;
00100     
00101     // WvStringBuf used for char* strings that have not been cloned.
00102     static WvStringBuf nullbuf;
00103     
00104 public:
00105     // a null string, converted to char* as "(nil)"
00106     static const WvFastString null;
00107 
00114     WvFastString();
00115     void setsize(size_t i);
00116 
00121     WvFastString offset(size_t i) const;
00122     
00129     WvFastString(const WvFastString &s);
00130     WvFastString(const WvString &s);
00131     
00138     WvFastString(const char *_str);
00139     
00144     WvFastString(const QString &s);
00145     WvFastString(const QCString &s);
00146     
00151     inline WvFastString(const std::string &s);
00152 
00157     WvFastString(short i);
00158     WvFastString(unsigned short i);
00159     WvFastString(int i);
00160     WvFastString(unsigned int i);
00161     WvFastString(long i);
00162     WvFastString(unsigned long i);
00163     WvFastString(long long i);
00164     WvFastString(unsigned long long i);
00165     WvFastString(double i);
00166     
00168     static void do_format(WvFastString &output, const char *format,
00169                           const WvFastString * const *a);
00170     
00171     
00188     WvFastString(WVSTRING_FORMAT_DECL) 
00189     {
00190         const WvFastString *x[20];
00191 
00192         x[ 0] = (&__wvs_a0  != &null)? &__wvs_a0 : 0;
00193         x[ 1] = (&__wvs_a1  != &null)? &__wvs_a1 : 0;
00194         x[ 2] = (&__wvs_a2  != &null)? &__wvs_a2 : 0;
00195         x[ 3] = (&__wvs_a3  != &null)? &__wvs_a3 : 0;
00196         x[ 4] = (&__wvs_a4  != &null)? &__wvs_a4 : 0;
00197         x[ 5] = (&__wvs_a5  != &null)? &__wvs_a5 : 0;
00198         x[ 6] = (&__wvs_a6  != &null)? &__wvs_a6 : 0;
00199         x[ 7] = (&__wvs_a7  != &null)? &__wvs_a7 : 0;
00200         x[ 8] = (&__wvs_a8  != &null)? &__wvs_a8 : 0;
00201         x[ 9] = (&__wvs_a9  != &null)? &__wvs_a9 : 0;
00202         x[10] = (&__wvs_a10 != &null)? &__wvs_a10 : 0;
00203         x[11] = (&__wvs_a11 != &null)? &__wvs_a11 : 0;
00204         x[12] = (&__wvs_a12 != &null)? &__wvs_a12 : 0;
00205         x[13] = (&__wvs_a13 != &null)? &__wvs_a13 : 0;
00206         x[14] = (&__wvs_a14 != &null)? &__wvs_a14 : 0;
00207         x[15] = (&__wvs_a15 != &null)? &__wvs_a15 : 0;
00208         x[16] = (&__wvs_a16 != &null)? &__wvs_a16 : 0;
00209         x[17] = (&__wvs_a17 != &null)? &__wvs_a17 : 0;
00210         x[18] = (&__wvs_a18 != &null)? &__wvs_a18 : 0;
00211         x[19] = (&__wvs_a19 != &null)? &__wvs_a19 : 0;
00212 
00213         link(&nullbuf, NULL);
00214         do_format(*this, __wvs_format.str, x);
00215     }
00216     
00217     ~WvFastString();
00218     
00219     /*
00220      * Figure out the length of this string.  ==0 if NULL or empty.
00221      */
00222     size_t len() const;
00223 
00224 protected:
00225     void construct(const char *_str);
00226 
00227     // this doesn't exist - it's just here to keep it from being auto-created
00228     // by stupid C++.
00229     WvFastString &operator= (const WvFastString &s2);
00230     
00231     // connect/disconnect ourselves from a WvStringBuf.
00232     void link(WvStringBuf *_buf, const char *_str);
00233     void unlink();
00234     
00235     // allocate new space for buffers - needed only by the (int i) constructor,
00236     // for now.
00237     WvStringBuf *alloc(size_t size);
00238     void newbuf(size_t size);
00239     
00240 public:
00241     // string comparison
00242     bool operator== (WvStringParm s2) const;
00243     bool operator!= (WvStringParm s2) const;
00244     bool operator< (WvStringParm s2) const;
00245     bool operator== (const char *s2) const;
00246     bool operator!= (const char *s2) const;
00247     bool operator< (const char *s2) const;
00248     
00250     bool operator! () const;
00251 
00252     // pointer arithmetic
00253     const char *operator+ (int i) const
00254         { return str + i; }
00255     const char *operator- (int i) const
00256         { return str - i; }
00257     
00259     operator const char*() const
00260         { return str; }
00261     
00267     const char *cstr() const
00268         { return str; }
00269     
00274     operator QString() const;
00275     
00280     //inline operator std::string() const;
00281     
00286     int num() const
00287         { return str ? atoi(str) : 0; }
00288     
00290     bool isnull() const
00291         { return str == NULL; }
00292     
00294     const WvFastString &ifnull(WvStringParm defval) const
00295         { return isnull() ? defval : *this; }
00296 };
00297 
00298 
00329 class WvString : public WvFastString
00330 {
00331 public:
00332     // an empty string, converted to char* as ""
00333     static const WvString empty;
00334  
00335     WvString() {} // nothing special needed
00336     WvString(short i) : WvFastString(i) { } // nothing special
00337     WvString(unsigned short i) : WvFastString(i) { } // nothing special
00338     WvString(int i) : WvFastString(i) { } // nothing special
00339     WvString(unsigned int i) : WvFastString(i) { } // nothing special
00340     WvString(long i) : WvFastString(i) { } // nothing special
00341     WvString(unsigned long i) : WvFastString(i) { } // nothing special
00342     WvString(long long i) : WvFastString(i) { } // nothing special
00343     WvString(unsigned long long i) : WvFastString(i) { } // nothing special
00344     WvString(double i) : WvFastString(i) { } // nothing special
00345     
00352     WvString(const WvString &s)
00353         { copy_constructor(s); }
00354     WvString(const WvFastString &s)
00355         { copy_constructor(s); }
00356     
00363     WvString(const char *_str);
00364 
00369     WvString(const QString &);
00370     WvString(const QCString &);
00371 
00376     inline WvString(const std::string &s);
00377 
00378     WvString(WVSTRING_FORMAT_DECL) : WvFastString(WVSTRING_FORMAT_CALL)
00379         { }
00380     
00381     WvString &append(WvStringParm s);
00382     WvString &append(WVSTRING_FORMAT_DECL)
00383         { return append(WvString(WVSTRING_FORMAT_CALL)); }
00384 
00385     WvString &operator= (int i);
00386     WvString &operator= (const WvFastString &s2);
00387     WvString &operator= (const char *s2)
00388         { return *this = WvFastString(s2); }
00389     
00391     WvString &unique();
00392     
00394     bool is_unique() const;
00395 
00397     char *edit()
00398         { return unique().str; }
00399     
00400 protected:
00401     void copy_constructor(const WvFastString &s);
00402     inline void construct(const char *_str)
00403         {
00404             link(&nullbuf, _str);
00405     
00406             // apenwarr (2002/04/24): from now on, all WvString objects are created
00407             // with unique(), so you should _never_ have to call it explicitly.  We
00408             // still can (and should!) use fast parameter passing via WvFastString.
00409             unique();
00410         }
00411 };
00412 
00413 
00420 class WvStringStar : public WvFastString
00421 {
00422 public:
00423     WvStringStar(WvStringParm s) : WvFastString(s)
00424         { }
00425     WvFastString *operator -> ()
00426         { return this; }
00427 };
00428 
00429 
00430 inline bool operator== (const char *s1, WvStringParm s2)
00431 {
00432     return s2 == s1;
00433 }
00434 
00435 
00436 inline bool operator!= (const char *s1, WvStringParm s2)
00437 {
00438     return s2 != s1;
00439 }
00440 
00441 #endif // __WVSTRING_H