Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

auto_buf.h

Go to the documentation of this file.
00001 /*  auto_buf.h - Growable buffer class, munged from ostream
00002     Copyright (C) 2001-2004 Mark Weaver
00003     Written by Mark Weaver <mark@npsl.co.uk>
00004 
00005     Part of the Open-Win32 library.
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public
00017     License along with this library; if not, write to the
00018     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA  02111-1307, USA.
00020 */
00021 
00029 #ifndef OW32_auto_buf_h
00030 #define OW32_auto_buf_h
00031 
00032 #include <cstddef>   // for size_t
00033 #include <stdexcept> // for bad_alloc, logic_error
00034 
00035 namespace OW32
00036 {
00037 
00046 template <class E>
00047 class auto_buf
00048 {
00049 protected:
00051     size_t  m_length;
00053     size_t  m_capacity;
00055     size_t  m_pos;
00057     E*      m_buf;
00058 
00064     void grow(size_t n) {
00065         // any need to realloc?
00066         if (n <= m_capacity)
00067             return;
00068 
00069         E* newbuf = (E*)realloc(m_buf, sizeof(E*)*n);
00070         if (!newbuf)
00071             throw std::bad_alloc();
00072 
00073         m_capacity = n;
00074         m_buf = newbuf;
00075     }
00076 
00082     void extendp(size_t n) {
00083         size_t max_sz = static_cast<size_t>(-1);
00084 
00085         // Check for integer overflow
00086         if (max_sz - m_pos < n)
00087             throw std::length_error("auto_buf<E> length overflow");
00088 
00089         // Check for capacity overflow
00090         if (m_pos + n > m_capacity)
00091         {
00092             // +50% growth policy
00093             size_t newcap;
00094 
00095             // Check for overflow in growth
00096             if (max_sz - m_capacity / 2 < m_capacity)
00097                 newcap = m_pos + n;
00098             else
00099             {
00100                 newcap = m_capacity + m_capacity / 2;
00101                 if (newcap < m_pos + n)
00102                     newcap = m_pos + n;
00103             }
00104 
00105             // Grow to fit
00106             E* newbuf = (E*)realloc(m_buf, sizeof(E*)*newcap);
00107             if (!newbuf)
00108                 throw std::bad_alloc();
00109 
00110             m_capacity = newcap;
00111             m_buf = newbuf;
00112         }
00113     }
00114 
00115 public:
00117     enum seekdir { 
00119         beg,
00121         cur,
00123         end
00124     };
00125 
00131     auto_buf() : /* throw() */
00132         m_capacity(0),
00133         m_length(0),
00134         m_pos(0),
00135         m_buf(0)
00136     {
00137     }
00138 
00146     auto_buf(const E* s) :
00147         m_capacity(0),
00148         m_length(0),
00149         m_pos(0),
00150         m_buf(0)
00151     {
00152         (void)write(s);
00153     }
00154 
00163     auto_buf(const E* s, size_t n) :
00164         m_capacity(0),
00165         m_length(0),
00166         m_pos(0),
00167         m_buf(0)
00168     {
00169         (void)write(s,n);
00170     }
00171 
00177     auto_buf(const auto_buf& rhs)
00178     {
00179         (void)operator=(rhs);
00180     }
00181 
00187     auto_buf& operator= (const auto_buf& rhs)
00188     {
00189         // allocate
00190         grow(rhs.m_capacity);
00191 
00192         // copy
00193         memcpy(m_buf, rhs.m_buf, rhs.m_capacity);
00194         m_capacity = rhs.m_capacity;
00195         m_length = rhs.m_length;
00196         m_pos = rhs.m_pos;
00197 
00198         return *this;
00199     }
00200 
00204     ~auto_buf()
00205     {
00206         if (m_buf) free(m_buf);
00207     }
00208 
00214     size_t length() const { return m_length; }
00215 
00221     size_t count() const { return m_length; }
00222 
00228     size_t size() const { return m_length; }
00229 
00238     E* detach() {
00239         E* buf = m_buf;
00240         m_buf = 0;
00241         m_capacity = m_length = m_pos = 0;
00242         return buf;
00243     }
00244 
00257     void attach(E* buf, size_t capacity) {
00258         if (m_buf) free(m_buf);
00259         m_buf = buf;
00260         m_length = m_capacity = capacity;
00261         m_pos = 0;
00262     }
00263 
00273     void resize(size_t n) {
00274         grow(n);
00275         m_length = n;
00276         if (m_pos > m_length) m_pos = m_length;
00277     }
00278 
00284     void reserve(size_t n) {
00285         grow(n);
00286     }
00287 
00293     size_t capacity() const {
00294         return m_capacity;
00295     }
00296 
00303     void clear() {
00304         m_length = m_pos = 0;
00305     }
00306 
00312     void reset() {
00313         if (m_buf) {
00314             free(m_buf);
00315             m_buf = 0;
00316         }
00317         m_length = m_pos = m_capacity = 0;
00318     }
00319 
00325     void put(E c) {
00326         extendp(1);
00327         m_buf[m_pos++] = c;
00328         // extend the buffer if required
00329         if (m_pos > m_length) m_length = m_pos;
00330     }
00331 
00339     size_t write(const E* s, size_t n) {
00340         extendp(n);
00341         memcpy(m_buf + m_pos, s, sizeof(E)*n);
00342         m_pos += n;
00343         // extend the buffer if required
00344         if (m_pos > m_length) m_length = m_pos;
00345         return n;
00346     }
00347 
00356     size_t write(const E* s) {
00357         size_t n = 0;
00358         const E* p = s;
00359         while (*p++ != E(0)) ++n;
00360         return write(s, n);
00361     }
00362 
00368     size_t tellp() const {
00369         return m_pos;
00370     }
00371 
00379     void seekp(size_t p) {
00380         if (p > m_length) {
00381             grow(p);
00382             m_length = p;
00383         }
00384         m_pos = p;
00385     }
00386 
00395     void seekp(int off, seekdir way) {
00396         size_t newpos;
00397 
00398         switch (way) {
00399         case beg:
00400             seekp((size_t)off);
00401             return;
00402         case cur:
00403             newpos = size_t(m_pos+off);
00404             break;
00405         case end:
00406             newpos = size_t(m_length+off);
00407             break;
00408         default:
00409             throw std::logic_error("auto_buf::seekp - invalid way parameter");
00410         }
00411         if (newpos > m_length) {
00412             grow(newpos);
00413             m_length = newpos;
00414         }
00415         m_pos = newpos;
00416     }
00417 
00423     E* str() const {
00424         return m_buf;
00425     }
00426 
00432     E* cstr() const {
00433         return m_buf + m_pos;
00434     }
00435 
00441     auto_buf& operator<< (const E& c) {
00442         put(c);
00443         return *this;
00444     }
00445 
00451     auto_buf& operator<< (const E* s) {
00452         (void)write(s);
00453         return *this;
00454     }
00455 
00462     E& operator[](size_t offset) {
00463         return m_buf[offset];
00464     }
00465 
00471     const E& operator[](size_t offset) const {
00472         return m_buf[offset];
00473     }
00474 };
00475 
00476 typedef auto_buf<char> auto_char_buf;
00477 
00482 class auto_byte_buf : public auto_buf<unsigned char>
00483 {
00484 public:
00490     auto_byte_buf() {}
00491 
00500     auto_byte_buf(const unsigned char* s, size_t n) :
00501         auto_buf<unsigned char>(s, n) {}
00502 
00510     auto_byte_buf(const unsigned char* s) :
00511         auto_buf<unsigned char>(s) {}
00512 
00520     size_t write(const void* s, size_t n) {
00521         return auto_buf<unsigned char>::write((const unsigned char*)s, n);
00522     }
00523 
00532     size_t write(const unsigned char* s) {
00533         return auto_buf<unsigned char>::write((const unsigned char*)s);
00534     }
00535 
00544     size_t write(const char* s) {
00545         return auto_buf<unsigned char>::write((const unsigned char*)s);
00546     }
00547 
00553     auto_byte_buf& operator<< (const char c) {
00554         put((unsigned char)c);
00555         return *this;
00556     }
00557 
00563     auto_byte_buf& operator<< (const char* s) {
00564         (void)auto_buf<unsigned char>::write((const unsigned char*)s);
00565         return *this;
00566     }
00567 
00573     auto_byte_buf& operator<< (const unsigned char& c) {
00574         put(c);
00575         return *this;
00576     }
00577 
00583     auto_byte_buf& operator<< (const unsigned char* s) {
00584         (void)auto_buf<unsigned char>::write(s);
00585         return *this;
00586     }
00587 };
00588 
00590 typedef auto_buf<short> auto_short_buf;
00592 typedef auto_buf<unsigned short> auto_ushort_buf;
00593 
00595 typedef auto_buf<int> auto_int_buf;
00597 typedef auto_buf<unsigned int> auto_uint_buf;
00598 
00599 } // namespace OW32
00600 
00601 #endif // OW32_auto_buf_h

Generated on Sun Jun 5 01:29:17 2005 for OW32 by  doxygen 1.3.9.1