00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <assert.h>
00022 #include <string.h>
00023
00024 #include "BufStream.H"
00025 #include "Basics.H"
00026
00027 Basics::BufStreambuf::BufStreambuf(unsigned int initial_buf_len)
00028 : buf(NEW_PTRFREE_ARRAY(char, initial_buf_len)),
00029 buf_len(initial_buf_len), delete_buf(true), allocate_new_buf(true),
00030 get_pos(0), put_pos(0), valid_limit(0)
00031 {
00032 setp(buf, buf+(buf_len-1));
00033 }
00034
00035 void Basics::BufStreambuf::update_get_pos()
00036 {
00037 if(gptr() != 0)
00038 get_pos = gptr() - buf;
00039 }
00040
00041 void Basics::BufStreambuf::update_put_pos()
00042 {
00043 if(pptr() != 0)
00044 put_pos = pptr() - buf;
00045 if(put_pos > valid_limit)
00046 valid_limit = put_pos;
00047 }
00048
00049 bool Basics::BufStreambuf::alloc_if_needed(unsigned int new_byte_count)
00050 {
00051
00052 update_put_pos();
00053
00054
00055
00056 if(((unsigned int) valid_limit + new_byte_count + 1) > buf_len)
00057 {
00058
00059
00060 if(!allocate_new_buf)
00061 {
00062 return false;
00063 }
00064
00065
00066 update_get_pos();
00067
00068
00069
00070
00071 unsigned int new_buf_len;
00072 if((buf_len + new_byte_count) < BUFSIZ)
00073 new_buf_len = (buf_len + new_byte_count) * 2;
00074 else
00075 new_buf_len = buf_len + new_byte_count + BUFSIZ;
00076
00077
00078 char *new_buf = NEW_PTRFREE_ARRAY(char, new_buf_len);
00079
00080
00081 memcpy(new_buf, buf, valid_limit);
00082
00083
00084 if(delete_buf)
00085 delete [] buf;
00086
00087
00088 buf = new_buf;
00089 buf_len = new_buf_len;
00090
00091
00092
00093 setp(buf, buf+(buf_len-1));
00094 pbump(put_pos);
00095
00096
00097 setg(buf, buf+get_pos, buf+valid_limit);
00098
00099
00100 delete_buf = true;
00101
00102
00103 assert(((unsigned int) valid_limit + new_byte_count + 1) < buf_len);
00104 }
00105
00106 return true;
00107 }
00108
00109 Basics::BufStreambuf::pos_type
00110 Basics::BufStreambuf::seekoff(off_type offset,
00111 seekdir way,
00112 openmode mode)
00113 {
00114 pos_type result = 0;
00115
00116 if(mode & std::ios::out)
00117 {
00118 update_put_pos();
00119
00120 if(way == std::ios::beg)
00121 put_pos = offset;
00122 else if(way == std::ios::cur)
00123 put_pos += offset;
00124 else
00125 put_pos = valid_limit + offset;
00126
00127 if(put_pos < 0)
00128 put_pos = 0;
00129 if(put_pos > valid_limit)
00130 put_pos = valid_limit;
00131
00132 if((buf != 0) && (buf_len > 0) && (put_pos < (pos_type) (buf_len-1)))
00133 setp(buf+put_pos, buf+(buf_len-1));
00134 else
00135 setp(0,0);
00136
00137 result = put_pos;
00138 }
00139
00140 if(mode & std::ios::in)
00141 {
00142 update_get_pos();
00143
00144 if(way == std::ios::beg)
00145 get_pos = offset;
00146 else if(way == std::ios::cur)
00147 get_pos += offset;
00148 else
00149 get_pos = valid_limit + offset;
00150
00151 if(get_pos < 0)
00152 get_pos = 0;
00153 if(get_pos > valid_limit)
00154 get_pos = valid_limit;
00155
00156
00157
00158 if((buf != 0) && (valid_limit > 0) && (get_pos < valid_limit))
00159
00160 setg(buf, buf+get_pos, buf+valid_limit);
00161 else
00162 setg(0,0,0);
00163
00164 result = get_pos;
00165 }
00166
00167 return result;
00168 }
00169
00170 Basics::BufStreambuf::pos_type
00171 Basics::BufStreambuf::seekpos(pos_type pos,
00172 openmode mode)
00173 {
00174
00175
00176 update_put_pos();
00177
00178 if(pos < 0)
00179 pos = 0;
00180 if(pos > valid_limit)
00181 pos = valid_limit;
00182
00183 if(mode & std::ios::in)
00184 {
00185 get_pos = pos;
00186
00187
00188
00189 if((buf != 0) && (valid_limit > 0) && (get_pos < valid_limit))
00190
00191 setg(buf, buf+get_pos, buf+valid_limit);
00192 else
00193 setg(0,0,0);
00194 }
00195
00196 if(mode & std::ios::out)
00197 {
00198 put_pos = pos;
00199
00200 assert(buf != 0);
00201 assert(put_pos <= (pos_type) (buf_len-1));
00202 setp(buf+put_pos, buf+(buf_len-1));
00203 }
00204
00205 return pos;
00206 }
00207
00208 int Basics::BufStreambuf::underflow()
00209 {
00210
00211
00212 update_put_pos();
00213
00214 update_get_pos();
00215
00216
00217
00218 if((buf != 0) && (valid_limit > 0) && (get_pos < valid_limit))
00219 {
00220
00221 setg(buf, buf+get_pos, buf+valid_limit);
00222
00223
00224 return ((*gptr())&0x00ff);
00225 }
00226
00227
00228 return EOF;
00229 }
00230
00231 std::streamsize Basics::BufStreambuf::xsgetn(char* s, std::streamsize n)
00232 {
00233 std::streamsize result = 0;
00234
00235
00236
00237 update_put_pos();
00238
00239 update_get_pos();
00240
00241 if(buf != 0)
00242 {
00243 if(get_pos < valid_limit)
00244 {
00245 unsigned int unread_count = valid_limit - get_pos;
00246
00247 unsigned int use_count = (unread_count < n) ? unread_count : n;
00248
00249 memcpy(s, buf + get_pos, use_count);
00250
00251 result += use_count;
00252 get_pos += (pos_type) use_count;
00253 }
00254
00255
00256 setg(buf, buf+get_pos, buf+valid_limit);
00257 }
00258
00259 return result;
00260 }
00261
00262 int Basics::BufStreambuf::overflow(int c)
00263 {
00264
00265 if(c != EOF)
00266 {
00267
00268
00269 if(!alloc_if_needed(1))
00270 return EOF;
00271
00272 assert(pptr() != 0);
00273
00274 *(pptr()) = (char) c;
00275 pbump(1);
00276 }
00277
00278
00279
00280 return (c & 0x00ff);
00281 }
00282
00283 std::streamsize Basics::BufStreambuf::xsputn(const char* s, std::streamsize n)
00284 {
00285
00286
00287 if(!alloc_if_needed(n))
00288 return -1;
00289
00290 assert(pptr() != 0);
00291
00292
00293 memcpy(pptr(), s, n);
00294 pbump(n);
00295 return n;
00296 }