Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

wvstring.h

Go to the documentation of this file.
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 
00022 
00023 /*
00024  * 1 byte for terminating NUL, 4 more to kludge around libc5+efence
00025  * incompatibility with strcat().
00026  */
00027 #define WVSTRING_EXTRA 5
00028 
00029 
00030 #define __WVS_FORM(n) WvStringParm __wvs_##n = WvFastString::null
00031 #define WVSTRING_FORMAT_DECL WvStringParm __wvs_format, \
00032                 WvStringParm __wvs_a0, \
00033                 __WVS_FORM( a1), __WVS_FORM( a2), __WVS_FORM( a3), \
00034                 __WVS_FORM( a4), __WVS_FORM( a5), __WVS_FORM( a6), \
00035                 __WVS_FORM( a7), __WVS_FORM( a8), __WVS_FORM( a9), \
00036                 __WVS_FORM(a10), __WVS_FORM(a11), __WVS_FORM(a12), \
00037                 __WVS_FORM(a13), __WVS_FORM(a14), __WVS_FORM(a15), \
00038                 __WVS_FORM(a16), __WVS_FORM(a17), __WVS_FORM(a18), \
00039                 __WVS_FORM(a19)
00040 #define WVSTRING_FORMAT_CALL __wvs_format, __wvs_a0, \
00041                 __wvs_a1, __wvs_a2, __wvs_a3, __wvs_a4, __wvs_a5, \
00042                 __wvs_a6, __wvs_a7, __wvs_a8, __wvs_a9, __wvs_a10, \
00043                 __wvs_a11, __wvs_a12, __wvs_a13, __wvs_a14, __wvs_a15, \
00044                 __wvs_a16, __wvs_a17, __wvs_a18, __wvs_a19
00045 
00046 struct WvStringBuf;
00047 class WvFastString;
00048 class WvString;
00049 class QString; // for operator QString()
00050 class QCString;
00051 
00052 // all WvFastString objects are const - they should _only_ be created
00053 // automatically by automatic typecasting in parameter passing.  So let's
00054 // create a handy alias.
00055 typedef const WvFastString &   WvStringParm;
00056 
00057 
00058 
00059 struct WvStringBuf
00060 {
00061     size_t size;        // string length - if zero, use strlen!!
00062     unsigned links;     // number of WvStrings using this buf.
00063     char data[1];       // optional room for extra string data
00064 };
00065 
00066 
00067 // the _actual_ space taken by a WvStringBuf, without the data[] array
00068 // (which is variable-sized, not really 1 byte)
00069 #define WVSTRINGBUF_SIZE(s) (s->data - (char *)s)
00070 
00071 /**
00072  * A WvFastString acts exactly like a WvString, but can take (const char *)
00073  * strings without needing to allocate any memory, thus making it faster.
00074  * 
00075  * When we copy to a normal WvString object, _then_ we allocate the memory.
00076  * If that never happens, we never need to allocate.
00077  * 
00078  * DON'T CREATE INSTANCES OF THIS!  It's mostly useful for parameter passing,
00079  * and for that you should use WvStringParm.  You can get yourself into _big_
00080  * trouble if you have an instance of a WvFastString created from a (char *)
00081  * object and then you modify the original (char *).
00082  * 
00083  * For almost all purposes, use WvString instead.  At worst, it's a bit slower.
00084  */
00085 class WvFastString
00086 {
00087     friend class WvString; // so WvString can access members of _other_ objects
00088     
00089 protected:
00090     WvStringBuf *buf;
00091     char *str;
00092     
00093     // WvStringBuf used for char* strings that have not been cloned.
00094     static WvStringBuf nullbuf;
00095     
00096 public:
00097     // a null string, converted to char* as "(nil)"
00098     static const WvFastString null;
00099 
00100     /**
00101      * Create an empty, NULL string.  In the past, these were dangerous
00102      * and could only be filled with operator= or setsize(); nowadays, NULL
00103      * strings are explicitly allowed, since it's useful to express the
00104      * difference between a zero-length string and a NULL result.
00105      */
00106     WvFastString();
00107     void setsize(size_t i);
00108     
00109     /**
00110      * Copy constructor.  We can safely copy from a normal WvString like this
00111      * too, since no special behaviour is required in this direction.  (Note
00112      * that copying from a WvFastString to a WvString _does_ require special
00113      * care!)
00114      */
00115     WvFastString(const WvFastString &s);
00116     WvFastString(const WvString &s);
00117     
00118     /**
00119      * Create a string out of a (char *)-style string _without_ copying any
00120      * memory.  It's fast, but we have to trust that the _str won't change
00121      * for the lifetime of our WvFastString.  That's usually safe, if you
00122      * didn't use WvFastString where you should have used a WvString.
00123      */
00124     WvFastString(const char *_str);
00125     
00126     /**
00127      * Create a string out of a Qt library QString.  If you use this,
00128      * you need to link with libwvqt.so.
00129      */
00130     WvFastString(const QString &s);
00131     WvFastString(const QCString &s);
00132 
00133     /**
00134      * NOTE: make sure that 32 bytes is big enough for your longest
00135      * int.  This is true up to at least 64 bits.
00136      */
00137     WvFastString(short i);
00138     WvFastString(unsigned short i);
00139     WvFastString(int i);
00140     WvFastString(unsigned int i);
00141     WvFastString(long i);
00142     WvFastString(unsigned long i);
00143     WvFastString(long long i);
00144     WvFastString(unsigned long long i);
00145     WvFastString(double i);
00146     
00147     /** when this is called, we assume output.str == NULL; it will be filled. */
00148     static void do_format(WvFastString &output, const char *format,
00149                           const WvFastString * const *a);
00150     
00151     
00152     /**
00153      * Now, you're probably thinking to yourself: Boy, does this ever
00154      * look ridiculous.  And indeed it does.  However, it is
00155      * completely type-safe and when functions are enabled, it
00156      * reduces automatically to its minimum possible implementation.
00157      * (ie. all extra comparisons with wv_null go away if the
00158      * parameter really _is_ wv_null, and that is the default!)
00159      *
00160      * I failed to find a way to optimize out the comparisons for
00161      * parameters that _are_ provided, however.
00162      *
00163      * There is a small problem, which is that only up to 20 (numbers
00164      * 0 to 19) additional arguments are allowed.  Luckily, no one has
00165      * ever used that many on one "printf"-type line in the history of
00166      * the world.
00167      */
00168     WvFastString(WVSTRING_FORMAT_DECL) 
00169     {
00170         const WvFastString *x[20];
00171         
00172         if (&__wvs_a0  != &null) x[ 0] = &__wvs_a0;
00173         if (&__wvs_a1  != &null) x[ 1] = &__wvs_a1;
00174         if (&__wvs_a2  != &null) x[ 2] = &__wvs_a2;
00175         if (&__wvs_a3  != &null) x[ 3] = &__wvs_a3;
00176         if (&__wvs_a4  != &null) x[ 4] = &__wvs_a4;
00177         if (&__wvs_a5  != &null) x[ 5] = &__wvs_a5;
00178         if (&__wvs_a6  != &null) x[ 6] = &__wvs_a6;
00179         if (&__wvs_a7  != &null) x[ 7] = &__wvs_a7;
00180         if (&__wvs_a8  != &null) x[ 8] = &__wvs_a8;
00181         if (&__wvs_a9  != &null) x[ 9] = &__wvs_a9;
00182         if (&__wvs_a10 != &null) x[10] = &__wvs_a10;
00183         if (&__wvs_a11 != &null) x[11] = &__wvs_a11;
00184         if (&__wvs_a12 != &null) x[12] = &__wvs_a12;
00185         if (&__wvs_a13 != &null) x[13] = &__wvs_a13;
00186         if (&__wvs_a14 != &null) x[14] = &__wvs_a14;
00187         if (&__wvs_a15 != &null) x[15] = &__wvs_a15;
00188         if (&__wvs_a16 != &null) x[16] = &__wvs_a16;
00189         if (&__wvs_a17 != &null) x[17] = &__wvs_a17;
00190         if (&__wvs_a18 != &null) x[18] = &__wvs_a18;
00191         if (&__wvs_a19 != &null) x[19] = &__wvs_a19;
00192         
00193         link(&nullbuf, NULL);
00194         do_format(*this, __wvs_format.str, x);
00195     }
00196     
00197     ~WvFastString();
00198     
00199     /*
00200      * Figure out the length of this string.  ==0 if NULL or empty.
00201      */
00202     size_t len() const;
00203 
00204 protected:
00205     // this doesn't exist - it's just here to keep it from being auto-created
00206     // by stupid C++.
00207     WvFastString &operator= (const WvFastString &s2);
00208     
00209     // connect/disconnect ourselves from a WvStringBuf.
00210     void link(WvStringBuf *_buf, const char *_str);
00211     void unlink();
00212     
00213     // allocate new space for buffers - needed only by the (int i) constructor,
00214     // for now.
00215     WvStringBuf *alloc(size_t size);
00216     void newbuf(size_t size);
00217     
00218 public:
00219     // string comparison
00220     bool operator== (WvStringParm s2) const;
00221     bool operator!= (WvStringParm s2) const;
00222     bool operator< (WvStringParm s2) const;
00223     bool operator== (const char *s2) const;
00224     bool operator!= (const char *s2) const;
00225     bool operator< (const char *s2) const;
00226     
00227     /** the not operator is 'true' if string is empty */
00228     bool operator! () const;
00229 
00230     // pointer arithmetic
00231     const char *operator+ (int i) const
00232         { return str + i; }
00233     const char *operator- (int i) const
00234         { return str - i; }
00235     
00236     /** auto-convert WvString to (const char *), when needed. */
00237     operator const char*() const
00238         { return str; }
00239     
00240     /**
00241      * return a (const char *) for this string.  The typecast operator does
00242      * this automatically when needed, but sometimes (especially with varargs
00243      * like in printf()) that isn't convenient enough.
00244      */
00245     const char *cstr() const
00246         { return str; }
00247     
00248     /**
00249      * return a Qt library QString containing the contents of this string.
00250      * You need to link to libwvqt.so if you use this.
00251      */
00252     operator QString() const;
00253     
00254     /**
00255      * used to convert WvString to int, when needed.
00256      * we no longer provide a typecast, because it causes annoyance.
00257      */
00258     int num() const
00259         { return str ? atoi(str) : 0; }
00260 
00261     /** returns true if this string is null */
00262     bool isnull() const
00263         { return str == NULL; }
00264 };
00265 
00266 
00267 /**
00268  * WvString is an implementation of a simple and efficient
00269  * printable-string class. It leaves out many of the notational
00270  * conveniences provided by other string classes, because they waste
00271  * too much CPU time and space.
00272  *
00273  * It does the one thing really missing from char* strings, that is,
00274  * dynamic buffer management.
00275  *
00276  * When you copy one WvString to another, it does _not_ duplicate the
00277  * buffer; it just creates another pointer to it. To really duplicate
00278  * the buffer, call the unique() member function.
00279  *
00280  * To change the contents of a WvString, you need to run its edit()
00281  * member function, which executes unique() and then returns a char*
00282  * pointer to the WvString contents.
00283  *
00284  * The most annoying side-effect of this implementation is that if you
00285  * construct a WvString from a char* buffer or static string, WvString
00286  * won't duplicate it. Usually this is okay and much faster (for
00287  * example, if you just want to print a static string). However, if
00288  * you construct a WvString from a dynamic variable, changing the
00289  * dynamic variable will change the WvString unless you run unique()
00290  * or edit(). Worse still, deleting the dynamic variable will make
00291  * WvString act unpredictably.
00292  *
00293  * But it does cut out extra dynamic memory allocation for the most
00294  * common cases, and it almost always avoids manual 'new' and 'delete'
00295  * of string objects.
00296  */
00297 class WvString : public WvFastString
00298 {
00299 public:
00300     // an empty string, converted to char* as ""
00301     static const WvString empty;
00302  
00303     WvString() {} // nothing special needed
00304     WvString(short i) : WvFastString(i) { } // nothing special
00305     WvString(unsigned short i) : WvFastString(i) { } // nothing special
00306     WvString(int i) : WvFastString(i) { } // nothing special
00307     WvString(unsigned int i) : WvFastString(i) { } // nothing special
00308     WvString(long i) : WvFastString(i) { } // nothing special
00309     WvString(unsigned long i) : WvFastString(i) { } // nothing special
00310     WvString(long long i) : WvFastString(i) { } // nothing special
00311     WvString(unsigned long long i) : WvFastString(i) { } // nothing special
00312     WvString(double i) : WvFastString(i) { } // nothing special
00313     
00314     /**
00315      * Magic copy constructor for "fast" char* strings.  When we copy from
00316      * a "fast" string to a real WvString, we might need to allocate memory
00317      * (equivalent to unique()) so the original char* can be safely changed
00318      * or destroyed.
00319      */
00320     WvString(const WvString &s)
00321         { copy_constructor(s); }
00322     WvString(const WvFastString &s)
00323         { copy_constructor(s); }
00324     
00325     /**
00326      * Create a WvString out of a char* string.  We always allocate memory
00327      * and make a copy here.  To avoid memory copies, you can (carefully)
00328      * use a WvFastString.  To just have quick parameter passing, use a
00329      * WvStringParm instead.
00330      */
00331     WvString(const char *_str);
00332 
00333     /**
00334      * Create a WvString out of a Qt library QString.  You have to link with
00335      * libwvqt.so if you want to use this.
00336      */
00337     WvString(const QString &);
00338     WvString(const QCString &);
00339 
00340     WvString(WVSTRING_FORMAT_DECL) : WvFastString(WVSTRING_FORMAT_CALL)
00341         { }
00342     
00343     WvString &append(WvStringParm s);
00344     WvString &append(WVSTRING_FORMAT_DECL)
00345         { return append(WvString(WVSTRING_FORMAT_CALL)); }
00346     
00347     WvString &operator= (int i);
00348     WvString &operator= (const WvFastString &s2);
00349     WvString &operator= (const char *s2)
00350         { return *this = WvFastString(s2); }
00351     
00352     /** make the buf and str pointers owned only by this WvString. */
00353     WvString &unique();
00354 
00355     /** make the string editable, and return a non-const (char*) */
00356     char *edit()
00357         { return unique().str; }
00358     
00359 protected:
00360     void copy_constructor(const WvFastString &s);
00361 
00362 };
00363 
00364 
00365 inline bool operator== (const char *s1, WvStringParm s2)
00366 {
00367     return s2 == s1;
00368 }
00369 
00370 
00371 inline bool operator!= (const char *s1, WvStringParm s2)
00372 {
00373     return s2 != s1;
00374 }
00375 
00376 #endif // __WVSTRING_H

Generated on Wed Dec 15 15:08:11 2004 for WvStreams by  doxygen 1.3.9.1