home *** CD-ROM | disk | FTP | other *** search
- //========================================================================
- //
- // mystdio.cc
- //
- // Copyright 1999 Emmanuel Lesueur
- //
- //========================================================================
-
- #define DB(x) //x
-
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <dos/dos.h>
- #include <dos/dosextens.h>
- #include <dos/dostags.h>
- #include <exec/memory.h>
- #include <stdarg.h>
- #include "mystdio.h"
- #include "gmem.h"
-
- #ifdef __SASC
- # define throw(x)
- #endif
-
- #ifdef __PPC__
- # include <powerup/ppcproto/dos.h>
- # include <powerup/gcclib/powerup_protos.h>
-
- inline BPTR myOpen(const char* n,LONG m) {
- BPTR r=PPCOpen((char*)n,m);
- DB(printf("Open(%s)=%lx\n",n,r);)
- return r;
- }
- inline LONG myClose(BPTR f) {
- DB(printf("Close(%lx)\n",f);)
- return PPCClose(f);
- }
- inline LONG mySeek(BPTR f,LONG b,LONG m) {
- LONG r=PPCSeek(f,b,m);
- DB(printf("Seek(%lx,%ld,%ld)=%ld\n",f,b,m,r);)
- return r;
- }
- inline LONG myRead(BPTR f,void* b,size_t sz) {
- LONG r=PPCRead(f,b,sz);
- DB(printf("Read(%lx,%p,%u)=%ld\n",f,b,sz,r);)
- return r;
- }
- #else
- # include <proto/dos.h>
-
- inline BPTR myOpen(const char* n,LONG m) {
- return Open((char*)n,m);
- }
- inline LONG myClose(BPTR f) {
- return Close(f);
- }
- inline LONG mySeek(BPTR f,LONG o,LONG m) {
- return Seek(f,o,m);
- }
- inline LONG myRead(BPTR f,void* b,size_t sz) {
- return Read(f,b,sz);
- }
- #endif
-
- size_t myFILE::max_buf;
- size_t myFILE::glb_chunk_size;
-
- void myFILE::bufsizes(size_t sz1,size_t sz2) {
- if(sz1>1<<20)
- sz1=1<<20;
- else if(sz1==0)
- sz1=1;
- if(sz2>1<<20)
- sz2=1<<20;
- sz1*=1024;
- sz2*=1024;
- if(sz2==0)
- max_buf=0x7fffffff;
- else {
- if(sz1<4096)
- sz1=4096;
- glb_chunk_size=sz1;
- if(sz2<2*sz1)
- sz2=2*sz1;
- max_buf=sz2;
- }
- }
-
- myFILE::myFILE(const char* name) {
- if(file=myOpen(name,MODE_OLDFILE)) {
- BOOL ok=FALSE;
- if(FileInfoBlock* fib=(FileInfoBlock*)AllocDosObject(DOS_FIB,NULL)) {
- if(ExamineFH(file,fib)) {
- total_size=fib->fib_Size;
- if(total_size<max_buf) {
- chunk_size=total_size;
- max_loaded_chunks=2;
- } else {
- chunk_size=glb_chunk_size;
- max_loaded_chunks=max_buf/chunk_size;
- }
- num_chunks=(total_size+chunk_size-1)/chunk_size;
- chunks=new chunk [num_chunks];
- pos=0;
- last_pos=0;
- num_loaded_chunks=0;
- loaded_chunks=NULL;
- oldest_chunk=NULL;
- ok=TRUE;
- }
- FreeDosObject(DOS_FIB,fib);
- }
- if(ok)
- return;
- }
- throw("");
- }
-
- myFILE::~myFILE() {
- myClose(file);
- delete [] chunks;
- }
-
- size_t myFILE::read(void* p,size_t sz) {
- //printf("read(%p,%u)\n",p,sz);
- if(sz>total_size-pos)
- sz=total_size-pos;
- size_t r=sz;
- unsigned n=pos/chunk_size;
- unsigned offs=pos%chunk_size;
- unsigned char* q=static_cast<unsigned char*>(p);
- //bool xx=false;
- while(sz) {
- //printf("sz=%u pos=%u, last_pos=%u, chunk=%u, offs=%u\n",sz,pos,last_pos,n,offs);
- chunk* c=chunks+n;
- size_t sz1=chunk_size;
- if(!c->buf) {
- /*if(!xx) {
- printf("read(%u)\n",sz);
- xx=true;
- }*/
- unsigned char* buf=NULL;
- if(num_loaded_chunks==max_loaded_chunks) {
- buf=oldest_chunk->buf;
- oldest_chunk->buf=NULL;
- oldest_chunk=oldest_chunk->prev;
- oldest_chunk->next=NULL;
- } else {
- ++num_loaded_chunks;
- buf=new unsigned char [chunk_size];
- }
- c->buf=buf;
- c->next=loaded_chunks;
- c->prev=NULL;
- if(loaded_chunks)
- loaded_chunks->prev=c;
- else
- oldest_chunk=c;
- loaded_chunks=c;
- unsigned pos2=n*chunk_size;
- if(last_pos!=pos2)
- mySeek(file,pos2,OFFSET_BEGINNING);
- sz1=myRead(file,buf,chunk_size);/* error handling... */
- if(sz1==-1) {
- r-=sz;
- break;
- }
- last_pos=pos2+sz1;
- } else if(pos-offs+chunk_size>total_size)
- sz1=total_size-pos+offs;
- if(c->prev) {
- c->prev->next=c->next;
- if(c->next)
- c->next->prev=c->prev;
- else {
- oldest_chunk=c->prev;
- oldest_chunk->next=NULL;
- }
- if(loaded_chunks)
- loaded_chunks->prev=c;
- c->next=loaded_chunks;
- c->prev=NULL;
- loaded_chunks=c;
- }
- const unsigned char* s=c->buf+offs;
- if(sz1<=offs) {
- r-=sz;
- break;
- }
- size_t len=sz1-offs;
- size_t sz2=sz<=len?sz:len;
- memcpy(q,s,sz2);
- q+=sz2;
- sz-=sz2;
- pos+=sz2;
- ++n;
- offs=0;
- }
- //printf("->read=%u\n",r);
- return r;
- }
-
-
- myFILE* myfopen(const char* name,const char* mode) {
- if(*mode=='w')
- throw("invalid open mode.");
- myFILE* f=NULL;
- try {
- f=new myFILE(name);
- }
- catch(...) {
- }
- return f;
- }
-
- int myFILE::seek(long p,int mode) {
- switch(mode) {
- case SEEK_SET:
- pos=p;
- break;
- case SEEK_CUR:
- pos+=p;
- break;
- case SEEK_END:
- pos=total_size+p;
- break;
- default:
- return -1;
- }
- if(pos>total_size) {
- pos=total_size;
- return -1;
- } else
- return 0;
- }
-
-