home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 110
/
EnigmaAmiga110CD.iso
/
indispensabili
/
utility
/
apdf
/
xpdf-0.80
/
xpdf
/
mystdio.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1999-06-21
|
5KB
|
239 lines
//========================================================================
//
// 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;
}