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

stream.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      stream.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program 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
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <limits.h>
00024 #include <string.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <sys/stat.h>   /* for mode definitions */
00028 #include <unistd.h>
00029 
00030 #include "htdebug.h"
00031 #include "htexcept.h"
00032 #include "htsys.h"
00033 #include "stream.h"
00034 #include "tools.h"
00035 
00036 /*
00037  *      CLASS ht_stream
00038  */
00039 
00040 #define STREAM_COPYBUF_SIZE     (64*1024)
00041 
00042 ht_stream::~ht_stream()
00043 {
00044 }
00045 
00046 void    ht_stream::init()
00047 {
00048         stream_error_func = NULL;
00049         error = 0;
00050         access_mode = FAM_NULL;
00051 }
00052 
00053 void    ht_stream::done()
00054 {
00055 }
00056 
00057 int     ht_stream::call_error_func()
00058 {
00059         if (stream_error_func) return stream_error_func(this); else
00060                 return SERR_FAIL;
00061 }
00062 
00063 void    ht_stream::copy_to(ht_stream *stream)
00064 {
00065         const UINT bufsize=STREAM_COPYBUF_SIZE;
00066         byte *buf=(byte*)malloc(bufsize);
00067         UINT r;
00068         do {
00069                 r=read(buf, bufsize);
00070                 stream->write(buf, r);
00071         } while (r == bufsize);
00072         free(buf);
00073 }
00074 
00075 UINT    ht_stream::get_access_mode()
00076 {
00077         return access_mode;
00078 }
00079 
00080 int     ht_stream::get_error()
00081 {
00082         return error;
00083 }
00084 
00085 const char *ht_stream::get_desc()
00086 {
00087         return NULL;
00088 }
00089 
00090 bool    ht_stream::set_access_mode(UINT a)
00091 {
00092         access_mode=a;
00093         return true;
00094 }
00095 
00096 void    ht_stream::set_error(int e)
00097 {
00098         error=e;
00099 }
00100 
00101 void    ht_stream::set_error_func(stream_error_func_ptr s)
00102 {
00103         stream_error_func=s;
00104 }
00105 
00106 UINT    ht_stream::read(void *buf, UINT size)
00107 {
00108         return 0;
00109 }
00110 
00111 UINT    ht_stream::write(const void *buf, UINT size)
00112 {
00113         return 0;
00114 }
00115 
00116 /*
00117  *      ht_layer_stream
00118  */
00119 
00120 void    ht_layer_stream::init(ht_stream *s, bool own)
00121 {
00122         ht_stream::init();
00123         stream=s;
00124         own_stream=own;
00125 }
00126 
00127 void    ht_layer_stream::done()
00128 {
00129         if (own_stream) {
00130                 stream->done();
00131                 delete stream;
00132         }
00133         ht_stream::done();
00134 }
00135 
00136 void    ht_layer_stream::copy_to(ht_stream *stream)
00137 {
00138         return ht_stream::copy_to(stream);
00139 }
00140 
00141 UINT    ht_layer_stream::get_access_mode()
00142 {
00143         return stream->get_access_mode();
00144 }
00145 
00146 int     ht_layer_stream::get_error()
00147 {
00148         return stream->get_error();
00149 }
00150 
00151 const char *ht_layer_stream::get_desc()
00152 {
00153         return stream->get_desc();
00154 }
00155 
00156 bool    ht_layer_stream::set_access_mode(UINT access_mode)
00157 {
00158         return stream->set_access_mode(access_mode);
00159 }
00160 
00161 void    ht_layer_stream::set_error(int error)
00162 {
00163         stream->set_error(error);
00164 }
00165 
00166 void    ht_layer_stream::set_error_func(stream_error_func_ptr stream_error_func)
00167 {
00168         stream->set_error_func(stream_error_func);
00169 }
00170 
00171 void    ht_layer_stream::set_stream_ownership(bool own)
00172 {
00173         own_stream=own;
00174 }
00175 
00176 UINT    ht_layer_stream::read(void *buf, UINT size)
00177 {
00178         return stream->read(buf, size);
00179 }
00180 
00181 UINT    ht_layer_stream::write(const void *buf, UINT size)
00182 {
00183         return stream->write(buf, size);
00184 }
00185 
00186 /*
00187  *      CLASS ht_object_stream
00188  */
00189  
00190 void ht_object_stream::init(ht_stream *s)
00191 {
00192         ht_layer_stream::init(s, false);
00193 }
00194 
00195 void ht_object_stream::done()
00196 {
00197         ht_layer_stream::done();
00198 }
00199 
00200 int  ht_object_stream::getInt(int size, char *desc)
00201 {
00202         return getIntHex(size, desc);
00203 }
00204 
00205 UINT ht_object_stream::recordStart(UINT size)
00206 {
00207         return 0;
00208 }
00209 
00210 void ht_object_stream::recordEnd(UINT a)
00211 {
00212 }
00213 
00214 void ht_object_stream::putInt(int a, int size, char *desc)
00215 {
00216         putIntHex(a, size, desc);
00217 }
00218 
00219 /*
00220  *      CLASS ht_streamfile
00221  */
00222 
00223 int     ht_streamfile::cntl(UINT cmd, ...)
00224 {
00225         va_list vargs;
00226         va_start(vargs, cmd);
00227         int ret=vcntl(cmd, vargs);
00228         va_end(vargs);
00229         return ret;
00230 }
00231 
00232 int     ht_streamfile::extend(UINT newsize)
00233 {
00234         return ENOSYS;
00235 }
00236 
00237 const char *ht_streamfile::get_filename()
00238 {
00239         return NULL;
00240 }
00241 
00242 UINT    ht_streamfile::get_size()
00243 {
00244         return 0;
00245 }
00246 
00247 void    ht_streamfile::pstat(pstat_t *s)
00248 {
00249         s->caps=0;
00250 }
00251 
00252 int ht_streamfile::seek(FILEOFS offset)
00253 {
00254         return ENOSYS;
00255 }
00256 
00257 FILEOFS ht_streamfile::tell()
00258 {
00259         return 0;
00260 }
00261 
00262 int     ht_streamfile::truncate(UINT newsize)
00263 {
00264         return ENOSYS;
00265 }
00266 
00267 int     ht_streamfile::vcntl(UINT cmd, va_list vargs)
00268 {
00269         return ENOSYS;
00270 }
00271 
00272 ht_streamfile *ht_streamfile::get_layered()
00273 {
00274         return NULL;
00275 }
00276 
00277 void ht_streamfile::set_layered(ht_streamfile *s)
00278 {
00279 }
00280 
00281 /*
00282  *      CLASS ht_layer_streamfile
00283  */
00284 
00285 void    ht_layer_streamfile::init(ht_streamfile *s, bool own)
00286 {
00287         ht_streamfile::init();
00288         streamfile=s;
00289         own_streamfile=own;
00290 }
00291 
00292 void    ht_layer_streamfile::done()
00293 {
00294         if (own_streamfile) {
00295                 streamfile->done();
00296                 delete streamfile;
00297         }
00298         ht_streamfile::done();
00299 }
00300 
00301 void    ht_layer_streamfile::copy_to(ht_stream *stream)
00302 {
00303         return ht_streamfile::copy_to(stream);
00304 }
00305 
00306 int     ht_layer_streamfile::extend(UINT newsize)
00307 {
00308         return streamfile->extend(newsize);
00309 }
00310 
00311 UINT    ht_layer_streamfile::get_access_mode()
00312 {
00313         return streamfile->get_access_mode();
00314 }
00315 
00316 int     ht_layer_streamfile::get_error()
00317 {
00318         return streamfile->get_error();
00319 }
00320 
00321 ht_streamfile *ht_layer_streamfile::get_layered()
00322 {
00323         ht_streamfile *q = streamfile->get_layered();
00324         return q ? q : streamfile;
00325 }
00326 
00327 const char *ht_layer_streamfile::get_desc()
00328 {
00329         return streamfile->get_desc();
00330 }
00331 
00332 const char *ht_layer_streamfile::get_filename()
00333 {
00334         return streamfile->get_filename();
00335 }
00336 
00337 UINT    ht_layer_streamfile::get_size()
00338 {
00339         return streamfile->get_size();
00340 }
00341 
00342 void    ht_layer_streamfile::pstat(pstat_t *s)
00343 {
00344         streamfile->pstat(s);
00345 }
00346 
00347 UINT    ht_layer_streamfile::read(void *buf, UINT size)
00348 {
00349         return streamfile->read(buf, size);
00350 }
00351 
00352 int     ht_layer_streamfile::seek(FILEOFS offset)
00353 {
00354         return streamfile->seek(offset);
00355 }
00356 
00357 bool    ht_layer_streamfile::set_access_mode(UINT access_mode)
00358 {
00359         return streamfile->set_access_mode(access_mode);
00360 }
00361 
00362 void    ht_layer_streamfile::set_error(int error)
00363 {
00364         streamfile->set_error(error);
00365 }
00366 
00367 void    ht_layer_streamfile::set_error_func(stream_error_func_ptr stream_error_func)
00368 {
00369         streamfile->set_error_func(stream_error_func);
00370 }
00371 
00372 void ht_layer_streamfile::set_layered(ht_streamfile *s)
00373 {
00374         ht_streamfile *q = streamfile->get_layered();
00375         if (q) streamfile->set_layered(s); else streamfile = s;
00376 }
00377         
00378 void    ht_layer_streamfile::set_streamfile_ownership(bool own)
00379 {
00380         own_streamfile=own;
00381 }
00382 
00383 FILEOFS ht_layer_streamfile::tell()
00384 {
00385         return streamfile->tell();
00386 }
00387 
00388 int     ht_layer_streamfile::truncate(UINT newsize)
00389 {
00390         return streamfile->truncate(newsize);
00391 }
00392 
00393 int     ht_layer_streamfile::vcntl(UINT cmd, va_list vargs)
00394 {
00395         return streamfile->vcntl(cmd, vargs);
00396 }
00397 
00398 UINT    ht_layer_streamfile::write(const void *buf, UINT size)
00399 {
00400         return streamfile->write(buf, size);
00401 }
00402 
00403 /*
00404  *      CLASS ht_sys_file
00405  */
00406 
00407 void    ht_sys_file::init(int f, bool ofd, UINT am)
00408 {
00409         ht_streamfile::init();
00410         fd = f;
00411         offset = 0;
00412         own_fd = ofd;
00413         set_access_mode(am);
00414 }
00415 
00416 void    ht_sys_file::done()
00417 {
00418         if (own_fd && (fd>=0)) close(fd);
00419         ht_streamfile::done();
00420 }
00421 
00422 #define EXTEND_BUFSIZE 1024
00423 int ht_sys_file::extend(UINT newsize)
00424 {
00425         int r=0;
00426 
00427         UINT oldmode=get_access_mode();
00428         if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode | FAM_WRITE);
00429 
00430         UINT s=get_size();
00431         char buf[EXTEND_BUFSIZE];
00432         memset(buf, 0, sizeof buf);
00433         newsize-=s;
00434         if ((r = seek(s))) return r;
00435         while (newsize) {
00436                 UINT k=MIN(sizeof buf, newsize);
00437                 UINT l=write(buf, k);
00438                 if (l!=k) {
00439                         r=EIO;
00440                         break;
00441                 }
00442                 newsize-=l;
00443         }
00444 
00445         if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode);
00446         return r;
00447 }
00448 
00449 const char *ht_sys_file::get_desc()
00450 {
00451         return "file descriptor based file";
00452 }
00453 
00454 UINT    ht_sys_file::get_size()
00455 {
00456         int t = tell();
00457         UINT r = lseek(fd, 0, SEEK_END);
00458         lseek(fd, t, SEEK_SET);
00459         return r;
00460 }
00461 
00462 UINT    ht_sys_file::read(void *buf, UINT size)
00463 {
00464         if (!(access_mode & FAM_READ)) return 0;
00465         UINT r = ::read(fd, buf, size);
00466         offset += r;
00467         return r;
00468 }
00469 
00470 int     ht_sys_file::seek(FILEOFS o)
00471 {
00472         if (o == offset) return 0;
00473         off_t r = lseek(fd, o, SEEK_SET);
00474         offset = r;
00475         return (offset == o) ? 0 : EIO;
00476 }
00477 
00478 FILEOFS ht_sys_file::tell()
00479 {
00480         return offset;
00481 }
00482 
00483 UINT    ht_sys_file::write(const void *buf, UINT size)
00484 {
00485         if (!(access_mode & FAM_WRITE)) return 0;
00486         UINT r = ::write(fd, buf, size);
00487         offset += r;
00488         return r;
00489 }
00490 
00491 /*
00492  *      CLASS ht_stdio_file
00493  */
00494 
00495 void    ht_stdio_file::init(FILE *f, bool ofile, UINT am)
00496 {
00497         ht_streamfile::init();
00498         file = f;
00499         offset = 0;
00500         own_file = ofile;
00501         set_access_mode(am);
00502 }
00503 
00504 void    ht_stdio_file::done()
00505 {
00506         if (own_file && file) fclose(file);
00507         ht_streamfile::done();
00508 }
00509 
00510 #define EXTEND_BUFSIZE 1024
00511 int ht_stdio_file::extend(UINT newsize)
00512 {
00513         int r=0;
00514 
00515         UINT oldmode=get_access_mode();
00516         if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode | FAM_WRITE);
00517 
00518         UINT s=get_size();
00519         char buf[EXTEND_BUFSIZE];
00520         memset(buf, 0, sizeof buf);
00521         newsize-=s;
00522         if ((r = seek(s))) return r;
00523         while (newsize) {
00524                 UINT k=MIN(sizeof buf, newsize);
00525                 UINT l=write(buf, k);
00526                 if (l!=k) {
00527                         r=EIO;
00528                         break;
00529                 }
00530                 newsize-=l;
00531         }
00532 
00533         if (!(oldmode & FAM_WRITE)) set_access_mode(oldmode);
00534         return r;
00535 }
00536 
00537 const char *ht_stdio_file::get_desc()
00538 {
00539         return "FILE based file";
00540 }
00541 
00542 UINT    ht_stdio_file::get_size()
00543 {
00544         int t = tell();
00545         fseek(file, 0, SEEK_END);       /* zero is allowed */
00546         int r = ftell(file);
00547         fseek(file, t, SEEK_SET);
00548         return r;
00549 }
00550 
00551 UINT    ht_stdio_file::read(void *buf, UINT size)
00552 {
00553         if (!(access_mode & FAM_READ)) return 0;
00554         UINT r = fread(buf, 1, size, file);
00555         offset += r;
00556         return r;
00557 }
00558 
00559 int     ht_stdio_file::seek(FILEOFS o)
00560 {
00561         if (o == offset) return 0;
00562         int r = fseek(file, o, SEEK_SET);
00563         if (r == 0) offset = o;
00564         return r;
00565 }
00566 
00567 FILEOFS ht_stdio_file::tell()
00568 {
00569         return offset;
00570 }
00571 
00572 UINT    ht_stdio_file::write(const void *buf, UINT size)
00573 {
00574         if (!(access_mode & FAM_WRITE)) return 0;
00575         UINT r = fwrite(buf, 1, size, file);
00576         offset += r;
00577         return r;
00578 }
00579 
00580 /*
00581  *      CLASS ht_file
00582  */
00583 
00584 void    ht_file::init(const char *fn, UINT am, UINT om)
00585 {
00586         filename = strdup(fn);
00587         open_mode = om;
00588         ht_stdio_file::init(NULL, true, am);
00589         open_mode = FOM_EXISTS;
00590 }
00591 
00592 void    ht_file::done()
00593 {
00594         if (filename) free(filename);
00595         ht_stdio_file::done();
00596 }
00597 
00598 const char *ht_file::get_desc()
00599 {
00600         return filename;
00601 }
00602 
00603 const char *ht_file::get_filename()
00604 {
00605         return filename;
00606 }
00607 
00608 void    ht_file::pstat(pstat_t *s)
00609 {
00610         sys_pstat(s, filename);
00611 }
00612 
00613 bool    ht_file::set_access_mode(UINT am)
00614 {
00615         UINT orig_access_mode = access_mode;
00616         bool r = set_access_mode_internal(am);
00617         if (!r && !set_access_mode_internal(orig_access_mode))
00618                 throw new ht_io_exception("fatal error: couldn't restore file access mode. %s possibly damaged...", get_filename());
00619         return r;
00620 }
00621 
00622 bool    ht_file::set_access_mode_internal(UINT am)
00623 {
00624 RETRY:
00625         if (access_mode == am) return true;
00626         if (file) {
00627                 fclose(file);
00628                 file = NULL;
00629         }
00630         access_mode = FAM_NULL;
00631         char *mode = NULL;
00632 
00633         if (open_mode & FOM_APPEND) {
00634                 mode = "ab+";
00635         } else if (open_mode & FOM_CREATE) {
00636                 if (am & FAM_WRITE) mode = "wb";
00637                 if (am & FAM_READ) mode = "wb+";
00638         } else {
00639                 if (am & FAM_READ) mode = "rb";
00640                 if (am & FAM_WRITE) mode = "rb+";
00641         }
00642 
00643         bool retval = true;
00644         if (am != FAM_NULL) {
00645                 int e = 0;
00646                 if (open_mode != FOM_CREATE) {
00647                         pstat_t s;
00648                         e = sys_pstat(&s, filename);
00649                         if (!e) {
00650                                 if ((!(s.caps & pstat_mode_type) || !HT_S_ISREG(s.mode)) && (am & FAM_WRITE)) {
00651                                         // disable write-access to non-regular files
00652                                         e = EACCES;
00653                                 } else if (HT_S_ISDIR(s.mode)) {
00654                                         e = EISDIR;
00655                                 } else if (!HT_S_ISREG(s.mode) && !HT_S_ISBLK(s.mode)) {
00656                                         e = EINVAL;
00657                                 }
00658                         }
00659                 }
00660                 if (!e) {
00661                         file = fopen(filename, mode);
00662                         if (!file) e = errno;
00663                 }
00664                 if (e) {
00665                         set_error(e | STERR_SYSTEM);
00666                         if ((stream_error_func) && (stream_error_func(this) == SERR_RETRY))
00667                                 goto RETRY;
00668                         retval = false;
00669                 }
00670         }
00671         return retval && ht_streamfile::set_access_mode(am);
00672 }
00673 
00674 int     ht_file::truncate(UINT newsize)
00675 {
00676         int e;
00677         int old_access_mode = access_mode;
00678         if (set_access_mode(FAM_NULL)) {
00679                 e = sys_truncate(filename, newsize);
00680         } else {
00681                 e = EACCES;
00682         }
00683 
00684         set_access_mode(old_access_mode);
00685         return e;
00686 }
00687 
00688 int     ht_file::vcntl(UINT cmd, va_list vargs)
00689 {
00690         switch (cmd) {
00691                 case FCNTL_FLUSH_STAT: {
00692                         UINT m = get_access_mode();
00693                         set_access_mode(FAM_NULL);
00694                         set_access_mode(m);
00695                         return 0;
00696                 }
00697         }
00698         return ht_streamfile::vcntl(cmd, vargs);
00699 }
00700 
00701 /*
00702  *      CLASS ht_temp_file
00703  */
00704 
00705 void    ht_temp_file::init(UINT am)
00706 {
00707         ht_stdio_file::init(tmpfile(), true, am);
00708 }
00709 
00710 void    ht_temp_file::done()
00711 {
00712         ht_stdio_file::done();
00713 }
00714 
00715 const char *ht_temp_file::get_desc()
00716 {
00717         return "temporary file";
00718 }
00719 
00720 void    ht_temp_file::pstat(pstat_t *s)
00721 {
00722         s->caps = pstat_size;
00723         s->size = get_size();
00724         s->size_high = 0;
00725 }
00726 
00727 /*
00728  *      CLASS ht_memmap_file
00729  */
00730 
00731 void ht_memmap_file::init(byte *b, UINT s)
00732 {
00733         ht_streamfile::init();
00734         buf = b;
00735         pos = 0;
00736         size = s;
00737 }
00738 
00739 void ht_memmap_file::done()
00740 {
00741 }
00742 
00743 const char *ht_memmap_file::get_desc()
00744 {
00745         return "memmap";
00746 }
00747 
00748 UINT ht_memmap_file::get_size()
00749 {
00750         return size;
00751 }
00752 
00753 UINT ht_memmap_file::read(void *b, UINT s)
00754 {
00755         if (pos+s > size) s = size-pos;
00756         memmove(b, (char*)buf+pos, s);
00757         pos += s;
00758         return s;
00759 }
00760 
00761 int ht_memmap_file::seek(FILEOFS offset)
00762 {
00763         pos = offset;
00764         if (pos > size) pos = size;
00765         return 0;
00766 }
00767 
00768 FILEOFS ht_memmap_file::tell()
00769 {
00770         return pos;
00771 }
00772 
00773 UINT ht_memmap_file::write(const void *b, UINT s)
00774 {
00775         if (pos+s > size) s = size-pos;
00776         memmove(((byte*)buf)+pos, b, s);
00777         pos += s;
00778         return s;
00779 }
00780 
00781 /*
00782  *      CLASS ht_null_file
00783  */
00784 
00785 void ht_null_file::init()
00786 {
00787         ht_streamfile::init();
00788 }
00789 
00790 void ht_null_file::done()
00791 {
00792         ht_streamfile::done();
00793 }
00794 
00795 int ht_null_file::extend(UINT newsize)
00796 {
00797         return newsize ? EINVAL : 0;
00798 }
00799 
00800 UINT ht_null_file::get_access_mode()
00801 {
00802         return access_mode;
00803 }
00804 
00805 const char *ht_null_file::get_desc()
00806 {
00807         return "null device";
00808 }
00809 
00810 UINT ht_null_file::get_size()
00811 {
00812         return 0;
00813 }
00814 
00815 void ht_null_file::pstat(pstat_t *s)
00816 {
00817         s->caps = pstat_size;
00818         s->size = get_size();
00819         s->size_high = 0;
00820 }
00821 
00822 UINT ht_null_file::read(void *buf, UINT size)
00823 {
00824         return 0;
00825 }
00826 
00827 int ht_null_file::seek(FILEOFS offset)
00828 {
00829         return offset ? EINVAL : 0;
00830 }
00831 
00832 bool ht_null_file::set_access_mode(UINT am)
00833 {
00834         return (am == access_mode);
00835 }
00836 
00837 FILEOFS ht_null_file::tell()
00838 {
00839         return 0;
00840 }
00841 
00842 int ht_null_file::truncate(UINT newsize)
00843 {
00844         return newsize ? EINVAL : 0;
00845 }
00846 
00847 UINT ht_null_file::write(const void *buf, UINT size)
00848 {
00849         return 0;
00850 }
00851 
00852 /*
00853  *      CLASS ht_mem_file
00854  */
00855 
00856 #define HTMEMFILE_INITIAL_SIZE          1024
00857 #define HTMEMFILE_GROW_FACTOR_NUM               4
00858 #define HTMEMFILE_GROW_FACTOR_DENOM     3
00859 
00860 void ht_mem_file::init()
00861 {
00862         ht_mem_file::init(0, HTMEMFILE_INITIAL_SIZE, FAM_READ | FAM_WRITE);
00863 }
00864 
00865 void ht_mem_file::init(FILEOFS o, UINT size, UINT am)
00866 {
00867         ht_streamfile::init();
00868         ofs = o;
00869         buf = (byte*)malloc(size ? size : 1);
00870         ibufsize = size;
00871         bufsize = size;
00872         memset(buf, 0, size);
00873         pos = 0;
00874         dsize = 0;
00875         access_mode = 0;
00876         if (!set_access_mode(am)) throw new ht_io_exception("unable to open memfile");
00877 }
00878 
00879 void ht_mem_file::done()
00880 {
00881         free(buf);
00882         ht_stream::done();
00883 }
00884 
00885 void *ht_mem_file::bufptr()
00886 {
00887         return buf;
00888 }
00889 
00890 int ht_mem_file::extend(UINT newsize)
00891 {
00892         while (bufsize<newsize) extendbuf();
00893         dsize = newsize;
00894         return 0;
00895 }
00896 
00897 void ht_mem_file::extendbuf()
00898 {
00899         resizebuf(extendbufsize(bufsize));
00900 }
00901 
00902 UINT ht_mem_file::extendbufsize(UINT bufsize)
00903 {
00904         return bufsize * HTMEMFILE_GROW_FACTOR_NUM / HTMEMFILE_GROW_FACTOR_DENOM;
00905 }
00906 
00907 UINT    ht_mem_file::get_access_mode()
00908 {
00909         return ht_stream::get_access_mode();
00910 }
00911 
00912 const char *ht_mem_file::get_desc()
00913 {
00914         return "memfile";
00915 }
00916 
00917 UINT ht_mem_file::get_size()
00918 {
00919         return dsize;
00920 }
00921 
00922 void ht_mem_file::pstat(pstat_t *s)
00923 {
00924         s->caps = pstat_size;
00925         s->size = get_size();
00926         s->size_high = 0;
00927 }
00928 
00929 UINT ht_mem_file::read(void *b, UINT size)
00930 {
00931         if (pos+size>dsize) {
00932                 if (pos >= dsize) return 0;
00933                 size=dsize-pos;
00934         }
00935         memmove(b, buf+pos, size);
00936         pos+=size;
00937         return size;
00938 }
00939 
00940 void ht_mem_file::resizebuf(UINT newsize)
00941 {
00942         bufsize=newsize;
00943 
00944         assert(dsize <= bufsize);
00945 
00946         byte *t=(byte*)malloc(bufsize ? bufsize : 1);
00947         memset(t, 0, bufsize);
00948         memmove(t, buf, dsize);
00949         free(buf);
00950         buf=t;
00951 }
00952 
00953 int ht_mem_file::seek(FILEOFS o)
00954 {
00955         if (o<ofs) return EINVAL;
00956         pos=o-ofs;
00957         return 0;
00958 }
00959 
00960 bool    ht_mem_file::set_access_mode(UINT access_mode)
00961 {
00962         if (ht_stream::set_access_mode(access_mode)) {
00963                 if (seek(ofs) != 0) return false;
00964                 return true;
00965         }
00966         return false;
00967 }
00968 
00969 UINT ht_mem_file::shrinkbufsize(UINT bufsize)
00970 {
00971         return bufsize * HTMEMFILE_GROW_FACTOR_DENOM / HTMEMFILE_GROW_FACTOR_NUM;
00972 }
00973 
00974 void ht_mem_file::shrinkbuf()
00975 {
00976         resizebuf(shrinkbufsize(bufsize));
00977 }
00978 
00979 FILEOFS ht_mem_file::tell()
00980 {
00981         return pos+ofs;
00982 }
00983 
00984 int ht_mem_file::truncate(UINT newsize)
00985 {
00986         dsize=newsize;
00987 
00988         UINT s=ibufsize;
00989         while (s<dsize) s=extendbufsize(s);
00990         
00991         resizebuf(s);
00992         
00993         return 0;
00994 }
00995 
00996 UINT ht_mem_file::write(const void *b, UINT size)
00997 {
00998         while (pos+size>=bufsize) extendbuf();
00999         memmove(((byte*)buf)+pos, b, size);
01000         pos+=size;
01001         if (pos>dsize) dsize=pos;
01002         return size;
01003 }
01004 
01005 /*
01006  *      string stream functions
01007  */
01008 
01009 char *fgetstrz(ht_streamfile *file)
01010 {
01011         FILEOFS o=file->tell();
01012         /* get string size */
01013         char buf[64];
01014         int s, z=0;
01015         int found=0;
01016         while (!found) {
01017                 if (!(s=file->read(buf, 64))) return NULL;
01018                 for (int i=0; i<s; i++) {
01019                         z++;
01020                         if (!buf[i]) {
01021                                 found=1;
01022                                 break;
01023                         }
01024                 }
01025         }
01026         /* read string */
01027         char *str=(char *)malloc(z);
01028         file->seek(o);
01029         file->read(str, z);
01030         return str;
01031 }
01032 
01033 // FIXME: more dynamical solution appreciated
01034 #define REASONABLE_STRING_LIMIT 1024
01035  
01036 char *getstrz(ht_stream *stream)
01037 {
01038         /* get string size */
01039         char buf[REASONABLE_STRING_LIMIT];
01040         int s, z=0;
01041         while (1) {
01042                 if ((s=stream->read(buf+z, 1))!=1) return NULL;
01043                 z++;
01044                 if (z>=REASONABLE_STRING_LIMIT) {
01045                         z=REASONABLE_STRING_LIMIT;
01046                         break;
01047                 }
01048                 if (!buf[z-1]) break;
01049         }
01050         if (!z) return NULL;
01051         char *str=(char *)malloc(z);
01052         memmove(str, buf, z-1);
01053         str[z-1]=0;
01054         return str;
01055 }
01056 
01057 void putstrz(ht_stream *stream, const char *str)
01058 {
01059         stream->write(str, strlen(str)+1);
01060 }
01061 
01062 char *getstrp(ht_stream *stream)
01063 {
01064         unsigned char l;
01065         stream->read(&l, 1);
01066         char *str=(char*)malloc(l+1);
01067         stream->read(str, l);
01068         *(str+l)=0;
01069         return str;
01070 }
01071 
01072 void putstrp(ht_stream *stream, const char *str)
01073 {
01074         unsigned char l=strlen(str);
01075         stream->write(&l, 1);
01076         stream->write(str, l);
01077 }
01078 
01079 char *getstrw(ht_stream *stream)
01080 {
01081         short t;
01082         byte lbuf[2];
01083         stream->read(lbuf, 2);
01084         int l = lbuf[0] | lbuf[1] << 8;
01085         char *a=(char*)malloc(l+1);
01086         for (int i=0; i<l; i++) {
01087                 stream->read(&t, 2);
01088                 *(a+i)=(char)t;
01089         }
01090         *(a+l)=0;
01091         return a;
01092 }
01093 
01094 void putstrw(ht_stream *stream, const char *str)
01095 {
01096         /* FIXME: someone implement me ? */
01097 }
01098 
01099 char *ht_strerror(int error)
01100 {
01101         return strerror(error & (~STERR_SYSTEM));
01102 }
01103 

Generated on Fri May 7 21:15:43 2004 by doxygen 1.3.5