00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #ifndef OW32_auto_buf_h
00030 #define OW32_auto_buf_h
00031
00032 #include <cstddef>
00033 #include <stdexcept>
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
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
00086 if (max_sz - m_pos < n)
00087 throw std::length_error("auto_buf<E> length overflow");
00088
00089
00090 if (m_pos + n > m_capacity)
00091 {
00092
00093 size_t newcap;
00094
00095
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
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() :
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
00190 grow(rhs.m_capacity);
00191
00192
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
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
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 }
00600
00601 #endif // OW32_auto_buf_h