00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "subStreamBuf.h"
00016 #include "pnotify.h"
00017
00018 #ifndef HAVE_STREAMSIZE
00019
00020 typedef int streamsize;
00021 #endif
00022
00023 static const size_t substream_buffer_size = 4096;
00024
00025
00026
00027
00028
00029
00030 SubStreamBuf::
00031 SubStreamBuf() {
00032 _source = (IStreamWrapper *)NULL;
00033 _dest = (OStreamWrapper *)NULL;
00034
00035
00036
00037 _start = 0;
00038
00039
00040
00041
00042 _end = 0;
00043
00044
00045
00046
00047
00048 _gpos = 0;
00049 _ppos = 0;
00050
00051 #ifdef PHAVE_IOSTREAM
00052 _buffer = (char *)PANDA_MALLOC_ARRAY(substream_buffer_size * 2);
00053 char *ebuf = _buffer + substream_buffer_size * 2;
00054 char *mbuf = _buffer + substream_buffer_size;
00055 setg(_buffer, mbuf, mbuf);
00056 setp(mbuf, ebuf);
00057
00058 #else
00059 allocate();
00060
00061
00062 char *b = base();
00063 char *t = ebuf();
00064 char *m = b + (t - b) / 2;
00065 setg(b, m, m);
00066 setp(b, m);
00067 #endif
00068 }
00069
00070
00071
00072
00073
00074
00075 SubStreamBuf::
00076 ~SubStreamBuf() {
00077 close();
00078 #ifdef PHAVE_IOSTREAM
00079 PANDA_FREE_ARRAY(_buffer);
00080 #endif
00081 }
00082
00083
00084
00085
00086
00087
00088 void SubStreamBuf::
00089 open(IStreamWrapper *source, OStreamWrapper *dest, streampos start, streampos end, bool append) {
00090 _source = source;
00091 _dest = dest;
00092 _start = start;
00093 _end = end;
00094 _append = append;
00095 _gpos = _start;
00096 _ppos = _start;
00097 }
00098
00099
00100
00101
00102
00103
00104 void SubStreamBuf::
00105 close() {
00106
00107 sync();
00108
00109 _source = (IStreamWrapper *)NULL;
00110 _dest = (OStreamWrapper *)NULL;
00111 _start = 0;
00112 _end = 0;
00113
00114 _gpos = 0;
00115 _ppos = 0;
00116
00117 pbump(pbase() - pptr());
00118 gbump(egptr() - gptr());
00119 }
00120
00121
00122
00123
00124
00125
00126 streampos SubStreamBuf::
00127 seekoff(streamoff off, ios_seekdir dir, ios_openmode which) {
00128 streampos result = -1;
00129
00130
00131 sync();
00132
00133 if (which & ios::in) {
00134
00135 size_t n = egptr() - gptr();
00136 gbump(n);
00137 _gpos -= n;
00138 nassertr(_gpos >= 0, EOF);
00139 streampos cur_pos = _gpos;
00140 streampos new_pos = cur_pos;
00141
00142
00143 switch (dir) {
00144 case ios::beg:
00145 new_pos = (streampos)off + _start;
00146 break;
00147
00148 case ios::cur:
00149 new_pos = (streampos)((streamoff)cur_pos + off);
00150 break;
00151
00152 case ios::end:
00153 if (_end == (streampos)0) {
00154
00155
00156 new_pos = _source->seek_gpos_eof() + off;
00157
00158 } else {
00159 new_pos = _end + off;
00160 }
00161 break;
00162
00163 default:
00164
00165 break;
00166 }
00167
00168 if (new_pos < _start) {
00169
00170 return EOF;
00171 }
00172
00173 if (_end != (streampos)0 && new_pos > _end) {
00174
00175 return EOF;
00176 }
00177
00178 _gpos = new_pos;
00179 nassertr(_gpos >= 0, EOF);
00180 result = new_pos - _start;
00181 }
00182
00183 if (which & ios::out) {
00184
00185 size_t n = pptr() - pbase();
00186 streampos cur_pos = _ppos + (streamoff)n;
00187 streampos new_pos = cur_pos;
00188
00189
00190 switch (dir) {
00191 case ios::beg:
00192 new_pos = (streampos)off + _start;
00193 break;
00194
00195 case ios::cur:
00196 new_pos = (streampos)((streamoff)cur_pos + off);
00197 break;
00198
00199 case ios::end:
00200 if (_end == (streampos)0) {
00201
00202
00203 new_pos = _dest->seek_ppos_eof() + off;
00204
00205 } else {
00206 new_pos = _end + off;
00207 }
00208 break;
00209
00210 default:
00211
00212 break;
00213 }
00214
00215 if (new_pos < _start) {
00216
00217 return EOF;
00218 }
00219
00220 if (_end != (streampos)0 && new_pos > _end) {
00221
00222 return EOF;
00223 }
00224
00225 _ppos = new_pos;
00226 nassertr(_ppos >= 0, EOF);
00227 result = new_pos - _start;
00228 }
00229
00230 return result;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 streampos SubStreamBuf::
00248 seekpos(streampos pos, ios_openmode which) {
00249 return seekoff(pos, ios::beg, which);
00250 }
00251
00252
00253
00254
00255
00256
00257
00258 int SubStreamBuf::
00259 overflow(int ch) {
00260 bool okflag = true;
00261
00262 size_t n = pptr() - pbase();
00263 if (n != 0) {
00264 if (_end != (streampos)0 && _ppos + (streampos)n > _end) {
00265
00266 n = (size_t)(_end - _ppos);
00267 if (n == 0) {
00268
00269 return EOF;
00270 }
00271 }
00272
00273 nassertr(_dest != NULL, EOF);
00274 bool fail = false;
00275 if (_append) {
00276 _dest->seek_eof_write(pbase(), n, fail);
00277 } else {
00278 _dest->seek_write(_ppos, pbase(), n, fail);
00279 }
00280 _ppos += n;
00281 pbump(-(int)n);
00282 if (fail) {
00283 okflag = false;
00284 }
00285 }
00286
00287 if (okflag && ch != EOF) {
00288 if (pptr() != epptr()) {
00289
00290 *(pptr()) = ch;
00291 pbump(1);
00292 } else {
00293
00294 okflag = false;
00295 }
00296 }
00297
00298 if (!okflag) {
00299 return EOF;
00300 }
00301 return 0;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310 int SubStreamBuf::
00311 sync() {
00312 size_t n = pptr() - pbase();
00313
00314 if (n != 0) {
00315 nassertr(_dest != NULL, EOF);
00316 bool fail = false;
00317 if (_append) {
00318 _dest->seek_eof_write(pbase(), n, fail);
00319 } else {
00320 _dest->seek_write(_ppos, pbase(), n, fail);
00321 }
00322 _ppos += n;
00323 pbump(-(int)n);
00324
00325 if (fail) {
00326 return EOF;
00327 }
00328 }
00329
00330 return 0;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339 int SubStreamBuf::
00340 underflow() {
00341
00342 if (gptr() >= egptr()) {
00343 sync();
00344
00345
00346 size_t buffer_size = egptr() - eback();
00347 gbump(-(int)buffer_size);
00348
00349 streamsize num_bytes = buffer_size;
00350 if (_end != (streampos)0 && _gpos + (streampos)num_bytes > _end) {
00351
00352 streamsize new_num_bytes = _end - _gpos;
00353 if (new_num_bytes == 0) {
00354 gbump(buffer_size);
00355 return EOF;
00356 }
00357
00358
00359
00360 size_t delta = num_bytes - new_num_bytes;
00361 gbump(delta);
00362 num_bytes = new_num_bytes;
00363 nassertr(egptr() - gptr() == num_bytes, EOF);
00364 }
00365
00366 nassertr(_source != NULL, EOF);
00367 streamsize read_count;
00368 bool eof;
00369 _source->seek_read(_gpos, gptr(), num_bytes, read_count, eof);
00370 _gpos += read_count;
00371
00372 if (read_count != num_bytes) {
00373
00374 if (read_count == 0) {
00375 gbump(num_bytes);
00376 return EOF;
00377 }
00378
00379
00380 nassertr(read_count < num_bytes, EOF);
00381 size_t delta = num_bytes - read_count;
00382 memmove(gptr() + delta, gptr(), read_count);
00383 gbump(delta);
00384 }
00385 }
00386
00387 return (unsigned char)*gptr();
00388 }