00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #ifdef HAVE_CONFIG_H
00064 # include "config.h"
00065 #endif
00066 #if NEED_GNUG_PRAGMAS
00067 # pragma implementation
00068 #endif
00069
00070
00071
00072 #include "DjVuGlobal.h"
00073 #include "ByteStream.h"
00074 #include "GOS.h"
00075 #include "GURL.h"
00076 #include "DjVuMessage.h"
00077 #include <fcntl.h>
00078 #if defined(WIN32) || defined(__CYGWIN32__)
00079 # include <io.h>
00080 #endif
00081
00082 #ifdef UNIX
00083 # ifndef HAS_MEMMAP
00084 # define HAS_MEMMAP 1
00085 # endif
00086 #endif
00087
00088 #if defined(UNIX)
00089 # include <sys/types.h>
00090 # include <sys/stat.h>
00091 # include <unistd.h>
00092 # include <errno.h>
00093 # ifdef HAS_MEMMAP
00094 # include <sys/mman.h>
00095 # endif
00096 #elif defined(macintosh)
00097 # include <unistd.h>
00098 _MSL_IMP_EXP_C int _dup(int);
00099 _MSL_IMP_EXP_C int _dup2(int,int);
00100 _MSL_IMP_EXP_C int _close(int);
00101 __inline int dup(int _a ) { return _dup(_a);}
00102 __inline int dup2(int _a, int _b ) { return _dup2(_a, _b);}
00103 #endif
00104
00105 #ifdef HAVE_NAMESPACES
00106 namespace DJVU {
00107 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00108 }
00109 #endif
00110 #endif
00111
00112 const char *ByteStream::EndOfFile=ERR_MSG("EOF");
00113
00119 class ByteStream::Stdio : public ByteStream {
00120 public:
00121 Stdio(void);
00122
00131 GUTF8String init(const GURL &url, const char * const mode);
00132
00137 GUTF8String init(FILE * const f, const char * const mode="rb", const bool closeme=false);
00138
00140 GUTF8String init(const char mode[]);
00141
00142
00143 ~Stdio();
00144 virtual size_t read(void *buffer, size_t size);
00145 virtual size_t write(const void *buffer, size_t size);
00146 virtual void flush(void);
00147 virtual int seek(long offset, int whence = SEEK_SET, bool nothrow=false);
00148 virtual long tell(void) const;
00149 private:
00150
00151 Stdio(const Stdio &);
00152 Stdio & operator=(const Stdio &);
00153 private:
00154
00155 bool can_read;
00156 bool can_write;
00157 bool must_close;
00158 protected:
00159 FILE *fp;
00160 long pos;
00161 };
00162
00163 inline GUTF8String
00164 ByteStream::Stdio::init(FILE * const f,const char mode[],const bool closeme)
00165 {
00166 fp=f;
00167 must_close=closeme;
00168 return init(mode);
00169 }
00170
00171
00177 class ByteStream::Memory : public ByteStream
00178 {
00179 public:
00184 Memory();
00188 GUTF8String init(const void * const buffer, const size_t size);
00189
00190 ~Memory();
00191 virtual size_t read(void *buffer, size_t size);
00192 virtual size_t write(const void *buffer, size_t size);
00193 virtual int seek(long offset, int whence=SEEK_SET, bool nothrow=false);
00194 virtual long tell(void) const;
00197 void empty();
00201 virtual int size(void) const;
00205 char &operator[] (int n);
00207 private:
00208
00209 Memory(const Memory &);
00210 Memory & operator=(const Memory &);
00211
00212 int where;
00213 protected:
00217 virtual size_t readat(void *buffer, size_t sz, int pos);
00219 int bsize;
00221 int nblocks;
00223 char **blocks;
00225 GPBuffer<char *> gblocks;
00226 };
00227
00228
00229
00230 inline int
00231 ByteStream::Memory::size(void) const
00232 {
00233 return bsize;
00234 }
00235
00236 inline char &
00237 ByteStream::Memory::operator[] (int n)
00238 {
00239 return blocks[n>>12][n&0xfff];
00240 }
00241
00242
00243
00250 class ByteStream::Static : public ByteStream
00251 {
00252 public:
00253 class Allocate;
00254 class Duplicate;
00255 friend class Duplicate;
00256
00259 Static(const void * const buffer, const size_t sz);
00260 ~Static();
00261
00262 virtual size_t read(void *buffer, size_t sz);
00263 virtual int seek(long offset, int whence = SEEK_SET, bool nothrow=false);
00264 virtual long tell(void) const;
00268 virtual int size(void) const;
00269 virtual GP<ByteStream> duplicate(const size_t xsize) const;
00271 virtual bool is_static(void) const { return true; }
00272 protected:
00273 const char *data;
00274 int bsize;
00275 private:
00276 int where;
00277 };
00278
00279 ByteStream::Static::~Static() {}
00280
00281 class ByteStream::Static::Allocate : public ByteStream::Static
00282 {
00283 public:
00284 friend class ByteStream;
00285 protected:
00286 char *buf;
00287 GPBuffer<char> gbuf;
00288 public:
00289 Allocate(const size_t size) : Static(0,size), gbuf(buf,size) { data=buf; }
00290 virtual ~Allocate();
00291 };
00292
00293 ByteStream::Static::Allocate::~Allocate() {}
00294
00295 inline int
00296 ByteStream::Static::size(void) const
00297 {
00298 return bsize;
00299 }
00300
00301 class ByteStream::Static::Duplicate : public ByteStream::Static
00302 {
00303 protected:
00304 GP<ByteStream> gbs;
00305 public:
00306 Duplicate(const ByteStream::Static &bs, const size_t size);
00307 };
00308
00309 ByteStream::Static::Duplicate::Duplicate(
00310 const ByteStream::Static &bs, const size_t xsize)
00311 : ByteStream::Static(0,0)
00312 {
00313 if(xsize&&(bs.bsize<bs.where))
00314 {
00315 const size_t bssize=(size_t)bs.bsize-(size_t)bs.where;
00316 bsize=(size_t)((xsize>bssize)?bssize:xsize);
00317 gbs=const_cast<ByteStream::Static *>(&bs);
00318 data=bs.data+bs.where;
00319 }
00320 }
00321
00322 GP<ByteStream>
00323 ByteStream::Static::duplicate(const size_t xsize) const
00324 {
00325 return new ByteStream::Static::Duplicate(*this,xsize);
00326 }
00327
00328 #if HAS_MEMMAP
00329
00333 class MemoryMapByteStream : public ByteStream::Static
00334 {
00335 public:
00336 MemoryMapByteStream(void);
00337 virtual ~MemoryMapByteStream();
00338 private:
00339 GUTF8String init(const int fd, const bool closeme);
00340 GUTF8String init(FILE *const f,const bool closeme);
00341 friend class ByteStream;
00342 };
00343 #endif
00344
00346
00347
00348 ByteStream::~ByteStream()
00349 {
00350 }
00351
00352 int
00353 ByteStream::scanf(const char *fmt, ...)
00354 {
00355 G_THROW( ERR_MSG("ByteStream.not_implemented") );
00356 return 0;
00357 }
00358
00359 size_t
00360 ByteStream::read(void *buffer, size_t sz)
00361 {
00362 G_THROW( ERR_MSG("ByteStream.cant_read") );
00363 return 0;
00364 }
00365
00366 size_t
00367 ByteStream::write(const void *buffer, size_t sz)
00368 {
00369 G_THROW( ERR_MSG("ByteStream.cant_write") );
00370 return 0;
00371 }
00372
00373 void
00374 ByteStream::flush()
00375 {
00376 }
00377
00378 int
00379 ByteStream::seek(long offset, int whence, bool nothrow)
00380 {
00381 int nwhere = 0;
00382 int ncurrent = tell();
00383 switch (whence)
00384 {
00385 case SEEK_SET:
00386 nwhere=0; break;
00387 case SEEK_CUR:
00388 nwhere=ncurrent; break;
00389 case SEEK_END:
00390 {
00391 if(offset)
00392 {
00393 if (nothrow)
00394 return -1;
00395 G_THROW( ERR_MSG("ByteStream.backward") );
00396 }
00397 char buffer[1024];
00398 int bytes;
00399 while((bytes=read(buffer, sizeof(buffer))))
00400 EMPTY_LOOP;
00401 return 0;
00402 }
00403 default:
00404 G_THROW( ERR_MSG("ByteStream.bad_arg") );
00405 }
00406 nwhere += offset;
00407 if (nwhere < ncurrent)
00408 {
00409
00410 if (nothrow)
00411 return -1;
00412 G_THROW( ERR_MSG("ByteStream.backward") );
00413 }
00414 while (nwhere>ncurrent)
00415 {
00416 char buffer[1024];
00417 const int xbytes=(ncurrent+(int)sizeof(buffer)>nwhere)
00418 ?(nwhere - ncurrent):(int)sizeof(buffer);
00419 const int bytes = read(buffer, xbytes);
00420 ncurrent += bytes;
00421 if (!bytes)
00422 G_THROW( ByteStream::EndOfFile );
00423
00424 if (ncurrent!=tell())
00425 G_THROW( ERR_MSG("ByteStream.seek") );
00426 }
00427 return 0;
00428 }
00429
00430 size_t
00431 ByteStream::readall(void *buffer, size_t size)
00432 {
00433 size_t total = 0;
00434 while (size > 0)
00435 {
00436 int nitems = read(buffer, size);
00437
00438
00439
00440
00441 if(nitems < 0)
00442 G_THROW(strerror(errno));
00443 if (nitems == 0)
00444 break;
00445 total += nitems;
00446 size -= nitems;
00447 buffer = (void*)((char*)buffer + nitems);
00448 }
00449 return total;
00450 }
00451
00452 size_t
00453 ByteStream::format(const char *fmt, ... )
00454 {
00455 va_list args;
00456 va_start(args, fmt);
00457 const GUTF8String message(fmt,args);
00458 return writestring(message);
00459 }
00460
00461 size_t
00462 ByteStream::writestring(const GNativeString &s)
00463 {
00464 int retval;
00465 if(cp != UTF8)
00466 {
00467 retval=writall((const char *)s,s.length());
00468 if(cp == AUTO)
00469 cp=NATIVE;
00470 }else
00471 {
00472 const GUTF8String msg(s.getNative2UTF8());
00473 retval=writall((const char *)msg,msg.length());
00474 }
00475 return retval;
00476 }
00477
00478 size_t
00479 ByteStream::writestring(const GUTF8String &s)
00480 {
00481 int retval;
00482 if(cp != NATIVE)
00483 {
00484 retval=writall((const char *)s,s.length());
00485 if(cp == AUTO)
00486 cp=UTF8;
00487 }else
00488 {
00489 const GNativeString msg(s.getUTF82Native());
00490 retval=writall((const char *)msg,msg.length());
00491 }
00492 return retval;
00493 }
00494
00495 size_t
00496 ByteStream::writall(const void *buffer, size_t size)
00497 {
00498 size_t total = 0;
00499 while (size > 0)
00500 {
00501 size_t nitems = write(buffer, size);
00502 if (nitems == 0)
00503 G_THROW( ERR_MSG("ByteStream.write_error") );
00504 total += nitems;
00505 size -= nitems;
00506 buffer = (void*)((char*)buffer + nitems);
00507 }
00508 return total;
00509 }
00510
00511 size_t
00512 ByteStream::copy(ByteStream &bsfrom, size_t size)
00513 {
00514 size_t total = 0;
00515 const size_t max_buffer_size=200*1024;
00516 const size_t buffer_size=(size>0 && size<max_buffer_size)
00517 ?size:max_buffer_size;
00518 char *buffer;
00519 GPBuffer<char> gbuf(buffer,buffer_size);
00520 for(;;)
00521 {
00522 size_t bytes = buffer_size;
00523 if (size>0 && bytes+total>size)
00524 bytes = size - total;
00525 if (bytes == 0)
00526 break;
00527 bytes = bsfrom.read((void*)buffer, bytes);
00528 if (bytes == 0)
00529 break;
00530 writall((void*)buffer, bytes);
00531 total += bytes;
00532 }
00533 return total;
00534 }
00535
00536
00537 void
00538 ByteStream::write8 (unsigned int card)
00539 {
00540 unsigned char c[1];
00541 c[0] = (card) & 0xff;
00542 if (write((void*)c, sizeof(c)) != sizeof(c))
00543 G_THROW(strerror(errno));
00544 }
00545
00546 void
00547 ByteStream::write16(unsigned int card)
00548 {
00549 unsigned char c[2];
00550 c[0] = (card>>8) & 0xff;
00551 c[1] = (card) & 0xff;
00552 if (writall((void*)c, sizeof(c)) != sizeof(c))
00553 G_THROW(strerror(errno));
00554 }
00555
00556 void
00557 ByteStream::write24(unsigned int card)
00558 {
00559 unsigned char c[3];
00560 c[0] = (card>>16) & 0xff;
00561 c[1] = (card>>8) & 0xff;
00562 c[2] = (card) & 0xff;
00563 if (writall((void*)c, sizeof(c)) != sizeof(c))
00564 G_THROW(strerror(errno));
00565 }
00566
00567 void
00568 ByteStream::write32(unsigned int card)
00569 {
00570 unsigned char c[4];
00571 c[0] = (card>>24) & 0xff;
00572 c[1] = (card>>16) & 0xff;
00573 c[2] = (card>>8) & 0xff;
00574 c[3] = (card) & 0xff;
00575 if (writall((void*)c, sizeof(c)) != sizeof(c))
00576 G_THROW(strerror(errno));
00577 }
00578
00579 unsigned int
00580 ByteStream::read8 ()
00581 {
00582 unsigned char c[1];
00583 if (readall((void*)c, sizeof(c)) != sizeof(c))
00584 G_THROW( ByteStream::EndOfFile );
00585 return c[0];
00586 }
00587
00588 unsigned int
00589 ByteStream::read16()
00590 {
00591 unsigned char c[2];
00592 if (readall((void*)c, sizeof(c)) != sizeof(c))
00593 G_THROW( ByteStream::EndOfFile );
00594 return (c[0]<<8)+c[1];
00595 }
00596
00597 unsigned int
00598 ByteStream::read24()
00599 {
00600 unsigned char c[3];
00601 if (readall((void*)c, sizeof(c)) != sizeof(c))
00602 G_THROW( ByteStream::EndOfFile );
00603 return (((c[0]<<8)+c[1])<<8)+c[2];
00604 }
00605
00606 unsigned int
00607 ByteStream::read32()
00608 {
00609 unsigned char c[4];
00610 if (readall((void*)c, sizeof(c)) != sizeof(c))
00611 G_THROW( ByteStream::EndOfFile );
00612 return (((((c[0]<<8)+c[1])<<8)+c[2])<<8)+c[3];
00613 }
00614
00615
00616
00618
00619 ByteStream::Stdio::Stdio(void)
00620 : can_read(false),can_write(false),must_close(true),fp(0),pos(0)
00621 {}
00622
00623 ByteStream::Stdio::~Stdio()
00624 {
00625 if (fp && must_close)
00626 fclose(fp);
00627 }
00628
00629 GUTF8String
00630 ByteStream::Stdio::init(const char mode[])
00631 {
00632 char const *mesg=0;
00633 bool binary=false;
00634 if(!fp)
00635 must_close=false;
00636 for (const char *s=mode; s && *s; s++)
00637 {
00638 switch(*s)
00639 {
00640 case 'r':
00641 can_read=true;
00642 if(!fp) fp=stdin;
00643 break;
00644 case 'w':
00645 case 'a':
00646 can_write=true;
00647 if(!fp) fp=stdout;
00648 break;
00649 case '+':
00650 can_read=can_write=true;
00651 break;
00652 case 'b':
00653 binary=true;
00654 break;
00655 default:
00656 mesg= ERR_MSG("ByteStream.bad_mode");
00657 }
00658 }
00659 if(binary && fp) {
00660 #if defined(__CYGWIN32__)
00661 setmode(fileno(fp), O_BINARY);
00662 #elif defined(WIN32)
00663 _setmode(_fileno(fp), _O_BINARY);
00664 #endif
00665 }
00666 GUTF8String retval;
00667 if(!mesg)
00668 {
00669 tell();
00670 }else
00671 {
00672 retval=mesg;
00673 }
00674 if(mesg &&(fp && must_close))
00675 {
00676 fclose(fp);
00677 fp=0;
00678 must_close=false;
00679 }
00680 return retval;
00681 }
00682
00683 static FILE *
00684 urlfopen(const GURL &url,const char mode[])
00685 {
00686 #ifdef WIN32
00687 FILE *retval=0;
00688 const GUTF8String filename(url.UTF8Filename());
00689 wchar_t *wfilename;
00690 const size_t wfilename_size=filename.length()+1;
00691 GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
00692 if(filename.ncopy(wfilename,wfilename_size) > 0)
00693 {
00694 const GUTF8String gmode(mode);
00695 wchar_t *wmode;
00696 const size_t wmode_size=gmode.length()+1;
00697 GPBuffer<wchar_t> gwmode(wmode,wmode_size);
00698 if(gmode.ncopy(wmode,wmode_size) > 0)
00699 {
00700 retval=_wfopen(wfilename,wmode);
00701 }
00702 }
00703 return retval?retval:fopen((const char *)url.NativeFilename(),mode);
00704 #else
00705 return fopen((const char *)url.NativeFilename(),mode);
00706 #endif
00707 }
00708
00709 #ifdef UNIX
00710 static int
00711 urlopen(const GURL &url, const int mode, const int perm)
00712 {
00713 return open((const char *)url.NativeFilename(),mode,perm);
00714 }
00715 #endif
00716
00717 GUTF8String
00718 ByteStream::Stdio::init(const GURL &url, const char mode[])
00719 {
00720 GUTF8String retval;
00721 if (url.fname() != "-")
00722 {
00723 fp = urlfopen(url,mode);
00724 if (!fp)
00725 {
00726
00727 G_THROW( ERR_MSG("ByteStream.open_fail") "\t" + url.name()
00728 +"\t"+GNativeString(strerror(errno)).getNative2UTF8());
00729 }
00730 }
00731 return retval.length()?retval:init(mode);
00732 }
00733
00734 size_t
00735 ByteStream::Stdio::read(void *buffer, size_t size)
00736 {
00737 if (!can_read)
00738 G_THROW( ERR_MSG("ByteStream.no_read") );
00739 size_t nitems;
00740 do
00741 {
00742 clearerr(fp);
00743 nitems = fread(buffer, 1, size, fp);
00744 if (nitems<=0 && ferror(fp))
00745 {
00746 #ifdef EINTR
00747 if (errno!=EINTR)
00748 #endif
00749 G_THROW(strerror(errno));
00750 }
00751 else
00752 break;
00753 } while(true);
00754 pos += nitems;
00755 return nitems;
00756 }
00757
00758 size_t
00759 ByteStream::Stdio::write(const void *buffer, size_t size)
00760 {
00761 if (!can_write)
00762 G_THROW( ERR_MSG("ByteStream.no_write") );
00763 size_t nitems;
00764 do
00765 {
00766 clearerr(fp);
00767 nitems = fwrite(buffer, 1, size, fp);
00768 if (nitems<=0 && ferror(fp))
00769 {
00770 #ifdef EINTR
00771 if (errno!=EINTR)
00772 #endif
00773 G_THROW(strerror(errno));
00774 }
00775 else
00776 break;
00777 } while(true);
00778 pos += nitems;
00779 return nitems;
00780 }
00781
00782 void
00783 ByteStream::Stdio::flush()
00784 {
00785 if (fflush(fp) < 0)
00786 G_THROW(strerror(errno));
00787 }
00788
00789 long
00790 ByteStream::Stdio::tell(void) const
00791 {
00792 long x = ftell(fp);
00793 if (x >= 0)
00794 {
00795 Stdio *sbs=const_cast<Stdio *>(this);
00796 (sbs->pos) = x;
00797 }else
00798 {
00799 x=pos;
00800 }
00801 return x;
00802 }
00803
00804 int
00805 ByteStream::Stdio::seek(long offset, int whence, bool nothrow)
00806 {
00807 if (whence==SEEK_SET && offset>=0 && offset==ftell(fp))
00808 return 0;
00809 clearerr(fp);
00810 if (fseek(fp, offset, whence))
00811 {
00812 if (nothrow)
00813 return -1;
00814 G_THROW(strerror(errno));
00815 }
00816 return tell();
00817 }
00818
00819
00820
00821
00823
00824 ByteStream::Memory::Memory()
00825 : where(0), bsize(0), nblocks(0), gblocks(blocks,0)
00826 {
00827 }
00828
00829 GUTF8String
00830 ByteStream::Memory::init(void const * const buffer, const size_t sz)
00831 {
00832 GUTF8String retval;
00833 G_TRY
00834 {
00835 writall(buffer, sz);
00836 where = 0;
00837 }
00838 G_CATCH(ex)
00839 {
00840 retval=ex.get_cause();
00841 }
00842 G_ENDCATCH;
00843 return retval;
00844 }
00845
00846 void
00847 ByteStream::Memory::empty()
00848 {
00849 for (int b=0; b<nblocks; b++)
00850 {
00851 delete [] blocks[b];
00852 blocks[b]=0;
00853 }
00854 bsize = 0;
00855 where = 0;
00856 nblocks = 0;
00857 }
00858
00859 ByteStream::Memory::~Memory()
00860 {
00861 empty();
00862 }
00863
00864 size_t
00865 ByteStream::Memory::write(const void *buffer, size_t sz)
00866 {
00867 int nsz = (int)sz;
00868 if (nsz <= 0)
00869 return 0;
00870
00871 if ( (where+nsz) > ((bsize+0xfff)&~0xfff) )
00872 {
00873
00874 if ( (where+nsz) > (nblocks<<12) )
00875 {
00876 const int old_nblocks=nblocks;
00877 nblocks = (((where+nsz)+0xffff)&~0xffff) >> 12;
00878 gblocks.resize(nblocks);
00879 char const ** eblocks=(char const **)(blocks+old_nblocks);
00880 for(char const * const * const new_eblocks=blocks+nblocks;
00881 eblocks <new_eblocks; eblocks++)
00882 {
00883 *eblocks = 0;
00884 }
00885 }
00886
00887 for (int b=(where>>12); (b<<12)<(where+nsz); b++)
00888 {
00889 if (! blocks[b])
00890 blocks[b] = new char[0x1000];
00891 }
00892 }
00893
00894 while (nsz > 0)
00895 {
00896 int n = (where|0xfff) + 1 - where;
00897 n = ((nsz < n) ? nsz : n);
00898 memcpy( (void*)&blocks[where>>12][where&0xfff], buffer, n);
00899 buffer = (void*) ((char*)buffer + n);
00900 where += n;
00901 nsz -= n;
00902 }
00903
00904 if (where > bsize)
00905 bsize = where;
00906 return sz;
00907 }
00908
00909 size_t
00910 ByteStream::Memory::readat(void *buffer, size_t sz, int pos)
00911 {
00912 if ((int) sz > bsize - pos)
00913 sz = bsize - pos;
00914 int nsz = (int)sz;
00915 if (nsz <= 0)
00916 return 0;
00917
00918 while (nsz > 0)
00919 {
00920 int n = (pos|0xfff) + 1 - pos;
00921 n = ((nsz < n) ? nsz : n);
00922 memcpy(buffer, (void*)&blocks[pos>>12][pos&0xfff], n);
00923 buffer = (void*) ((char*)buffer + n);
00924 pos += n;
00925 nsz -= n;
00926 }
00927 return sz;
00928 }
00929
00930 size_t
00931 ByteStream::Memory::read(void *buffer, size_t sz)
00932 {
00933 sz = readat(buffer,sz,where);
00934 where += sz;
00935 return sz;
00936 }
00937
00938 long
00939 ByteStream::Memory::tell(void) const
00940 {
00941 return where;
00942 }
00943
00944 int
00945 ByteStream::Memory::seek(long offset, int whence, bool nothrow)
00946 {
00947 int nwhere = 0;
00948 switch (whence)
00949 {
00950 case SEEK_SET: nwhere = 0; break;
00951 case SEEK_CUR: nwhere = where; break;
00952 case SEEK_END: nwhere = bsize; break;
00953 default: G_THROW( ERR_MSG("bad_arg") "\tByteStream::Memory::seek()");
00954 }
00955 nwhere += offset;
00956 if (nwhere<0)
00957 G_THROW( ERR_MSG("ByteStream.seek_error2") );
00958 where = nwhere;
00959 return 0;
00960 }
00961
00962
00963
00967 #ifdef DO_NOT_MOVE_GET_DATA_TO_ARRAYS_CPP
00968 TArray<char>
00969 ByteStream::get_data(void)
00970 {
00971 TArray<char> data(0, size()-1);
00972 readat((char*)data, size(), 0);
00973 return data;
00974 }
00975 #endif
00976
00977
00979
00980 ByteStream::Static::Static(const void * const buffer, const size_t sz)
00981 : data((const char *)buffer), bsize(sz), where(0)
00982 {
00983 }
00984
00985 size_t
00986 ByteStream::Static::read(void *buffer, size_t sz)
00987 {
00988 int nsz = (int)sz;
00989 if (nsz > bsize - where)
00990 nsz = bsize - where;
00991 if (nsz <= 0)
00992 return 0;
00993 memcpy(buffer, data+where, nsz);
00994 where += nsz;
00995 return nsz;
00996 }
00997
00998 int
00999 ByteStream::Static::seek(long offset, int whence, bool nothrow)
01000 {
01001 int nwhere = 0;
01002 switch (whence)
01003 {
01004 case SEEK_SET: nwhere = 0; break;
01005 case SEEK_CUR: nwhere = where; break;
01006 case SEEK_END: nwhere = bsize; break;
01007 default: G_THROW("bad_arg\tByteStream::Static::seek()");
01008 }
01009 nwhere += offset;
01010 if (nwhere<0)
01011 G_THROW( ERR_MSG("ByteStream.seek_error2") );
01012 where = nwhere;
01013 return 0;
01014 }
01015
01016 long
01017 ByteStream::Static::tell(void) const
01018 {
01019 return where;
01020 }
01021
01022 GP<ByteStream>
01023 ByteStream::create(void)
01024 {
01025 return new Memory();
01026 }
01027
01028 GP<ByteStream>
01029 ByteStream::create(void const * const buffer, const size_t size)
01030 {
01031 Memory *mbs=new Memory();
01032 GP<ByteStream> retval=mbs;
01033 mbs->init(buffer,size);
01034 return retval;
01035 }
01036
01037 GP<ByteStream>
01038 ByteStream::create(const GURL &url,char const * const xmode)
01039 {
01040 GP<ByteStream> retval;
01041 const char *mode = ((xmode) ? xmode : "rb");
01042 #ifdef UNIX
01043 if (!strcmp(mode,"rb"))
01044 {
01045 int fd = urlopen(url,O_RDONLY,0777);
01046 if (fd >= 0)
01047 {
01048 #if HAS_MEMMAP && defined(S_IFREG)
01049 struct stat buf;
01050 if ( (fstat(fd, &buf) >= 0) && (buf.st_mode & S_IFREG) )
01051 {
01052 MemoryMapByteStream *rb = new MemoryMapByteStream();
01053 retval = rb;
01054 GUTF8String errmessage = rb->init(fd,true);
01055 if(errmessage.length())
01056 retval=0;
01057 }
01058 #endif
01059 if (! retval)
01060 {
01061 FILE *f = fdopen(fd, mode);
01062 if (f)
01063 {
01064 Stdio *sbs=new Stdio();
01065 retval=sbs;
01066 GUTF8String errmessage=sbs->init(f, mode, true);
01067 if(errmessage.length())
01068 retval=0;
01069 }
01070 }
01071 if (! retval)
01072 close(fd);
01073 }
01074 }
01075 #endif
01076 if (! retval)
01077 {
01078 Stdio *sbs=new Stdio();
01079 retval=sbs;
01080 GUTF8String errmessage=sbs->init(url, mode);
01081 if(errmessage.length())
01082 G_THROW(errmessage);
01083 }
01084 return retval;
01085 }
01086
01087 GP<ByteStream>
01088 ByteStream::create(char const * const mode)
01089 {
01090 GP<ByteStream> retval;
01091 Stdio *sbs=new Stdio();
01092 retval=sbs;
01093 GUTF8String errmessage=sbs->init(mode?mode:"rb");
01094 if(errmessage.length())
01095 {
01096 G_THROW(errmessage);
01097 }
01098 return retval;
01099 }
01100
01101 GP<ByteStream>
01102 ByteStream::create(const int fd,char const * const mode,const bool closeme)
01103 {
01104 GP<ByteStream> retval;
01105 const char *default_mode="rb";
01106 #if HAS_MEMMAP
01107 if ( (!mode&&(fd!=0)&&(fd!=1)&&(fd!=2))
01108 || (mode&&(GUTF8String("rb") == mode)))
01109 {
01110 MemoryMapByteStream *rb=new MemoryMapByteStream();
01111 retval=rb;
01112 GUTF8String errmessage=rb->init(fd,closeme);
01113 if(errmessage.length())
01114 {
01115 retval=0;
01116 }
01117 }
01118 if(!retval)
01119 #endif
01120 {
01121 int fd2 = fd;
01122 FILE *f = 0;
01123 if (fd == 0 && !closeme
01124 && (!mode || mode[0]=='r') )
01125 {
01126 f=stdin;
01127 default_mode = "r";
01128 fd2=(-1);
01129 }
01130 else if (fd == 1 && !closeme
01131 && (!mode || mode[0]=='a' || mode[0]=='w') )
01132 {
01133 default_mode = "a";
01134 f=stdout;
01135 fd2 = -1;
01136 }
01137 else if (fd == 2 && !closeme
01138 && (!mode || mode[0]=='a' || mode[0]=='w') )
01139 {
01140 default_mode = "a";
01141 f=stderr;
01142 fd2 = -1;
01143 }
01144 else
01145 {
01146 if (! closeme)
01147 fd2 = dup(fd);
01148 f = fdopen(fd2,(char*)(mode?mode:default_mode));
01149 }
01150
01151 if(!f)
01152 {
01153 if ( fd2 >= 0)
01154 close(fd2);
01155 G_THROW( ERR_MSG("ByteStream.open_fail2") );
01156 }
01157 Stdio *sbs=new Stdio();
01158 retval=sbs;
01159 GUTF8String errmessage=sbs->init(f,mode?mode:default_mode,(fd2>=0));
01160 if(errmessage.length())
01161 G_THROW(errmessage);
01162 }
01163 return retval;
01164 }
01165
01166 GP<ByteStream>
01167 ByteStream::create(FILE * const f,char const * const mode,const bool closeme)
01168 {
01169 GP<ByteStream> retval;
01170 #if HAS_MEMMAP
01171 if (!mode || (GUTF8String("rb") == mode))
01172 {
01173 MemoryMapByteStream *rb=new MemoryMapByteStream();
01174 retval=rb;
01175 GUTF8String errmessage=rb->init(fileno(f),false);
01176 if(errmessage.length())
01177 {
01178 retval=0;
01179 }else
01180 {
01181 fclose(f);
01182 }
01183 }
01184 if(!retval)
01185 #endif
01186 {
01187 Stdio *sbs=new Stdio();
01188 retval=sbs;
01189 GUTF8String errmessage=sbs->init(f,mode?mode:"rb",closeme);
01190 if(errmessage.length())
01191 {
01192 G_THROW(errmessage);
01193 }
01194 }
01195 return retval;
01196 }
01197
01198 GP<ByteStream>
01199 ByteStream::create_static(const void * const buffer, size_t sz)
01200 {
01201 return new Static(buffer, sz);
01202 }
01203
01204 GP<ByteStream>
01205 ByteStream::duplicate(const size_t xsize) const
01206 {
01207 GP<ByteStream> retval;
01208 const long int pos=tell();
01209 const int tsize=size();
01210 ByteStream &self=*(const_cast<ByteStream *>(this));
01211 if(tsize < 0 || pos < 0 || (unsigned int)tsize < 1+(unsigned int)pos)
01212 {
01213 retval=ByteStream::create();
01214 retval->copy(self,xsize);
01215 retval->seek(0L);
01216 }else
01217 {
01218 const size_t s=(size_t)tsize-(size_t)pos;
01219 const int size=(!xsize||(s<xsize))?s:xsize;
01220 ByteStream::Static::Allocate *bs=new ByteStream::Static::Allocate(size);
01221 retval=bs;
01222 self.readall(bs->buf,size);
01223 }
01224 self.seek(pos,SEEK_SET,true);
01225 return retval;
01226 }
01227
01228
01229 #if HAS_MEMMAP
01230 MemoryMapByteStream::MemoryMapByteStream(void)
01231 : ByteStream::Static(0,0)
01232 {}
01233
01234 GUTF8String
01235 MemoryMapByteStream::init(FILE *const f,const bool closeme)
01236 {
01237 GUTF8String retval;
01238 retval=init(fileno(f),false);
01239 if(closeme)
01240 {
01241 fclose(f);
01242 }
01243 return retval;
01244 }
01245
01246 GUTF8String
01247 MemoryMapByteStream::init(const int fd,const bool closeme)
01248 {
01249 GUTF8String retval;
01250 #if defined(PROT_READ) && defined(MAP_SHARED)
01251 struct stat statbuf;
01252 if(!fstat(fd,&statbuf))
01253 {
01254 if(statbuf.st_size)
01255 {
01256 bsize=statbuf.st_size;
01257 data=(char *)mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,fd,0);
01258 }
01259 }else
01260 {
01261 if(closeme)
01262 {
01263 close(fd);
01264 }
01265 retval= ERR_MSG("ByteStream.open_fail2");
01266 }
01267 #else
01268 retval= ERR_MSG("ByteStream.open_fail2");
01269 #endif
01270 if(closeme)
01271 {
01272 close(fd);
01273 }
01274 return retval;
01275 }
01276
01277 MemoryMapByteStream::~MemoryMapByteStream()
01278 {
01279 if(data)
01280 {
01281 munmap(const_cast<char *>(data),bsize);
01282 }
01283 }
01284
01285 #endif
01286
01287 ByteStream::Wrapper::~Wrapper() {}
01288
01289
01290 GP<ByteStream>
01291 ByteStream::get_stdin(char const * const mode)
01292 {
01293 static GP<ByteStream> gp = ByteStream::create(0,mode,false);
01294 return gp;
01295 }
01296
01297 GP<ByteStream>
01298 ByteStream::get_stdout(char const * const mode)
01299 {
01300 static GP<ByteStream> gp = ByteStream::create(1,mode,false);
01301 return gp;
01302 }
01303
01304 GP<ByteStream>
01305 ByteStream::get_stderr(char const * const mode)
01306 {
01307 static GP<ByteStream> gp = ByteStream::create(2,mode,false);
01308 return gp;
01309 }
01310
01311
01313 void ByteStream::formatmessage( const char *fmt, ... )
01314 {
01315 va_list args;
01316 va_start(args, fmt);
01317 const GUTF8String message(fmt,args);
01318 writemessage( message );
01319 }
01320
01322 void ByteStream::writemessage( const char *message )
01323 {
01324 writestring( DjVuMessage::LookUpUTF8( message ) );
01325 }
01326
01327 static void
01328 read_file(ByteStream &bs,char *&buffer,GPBuffer<char> &gbuffer)
01329 {
01330 const int size=bs.size();
01331 int pos=0;
01332 if(size>0)
01333 {
01334 size_t readsize=size+1;
01335 gbuffer.resize(readsize);
01336 for(int i;readsize&&(i=bs.read(buffer+pos,readsize))>0;pos+=i,readsize-=i)
01337 EMPTY_LOOP;
01338 }else
01339 {
01340 const size_t readsize=32768;
01341 gbuffer.resize(readsize);
01342 for(int i;((i=bs.read(buffer+pos,readsize))>0);
01343 gbuffer.resize((pos+=i)+readsize))
01344 EMPTY_LOOP;
01345 }
01346 buffer[pos]=0;
01347 }
01348
01349 GNativeString
01350 ByteStream::getAsNative(void)
01351 {
01352 char *buffer;
01353 GPBuffer<char> gbuffer(buffer);
01354 read_file(*this,buffer,gbuffer);
01355 return GNativeString(buffer);
01356 }
01357
01358 GUTF8String
01359 ByteStream::getAsUTF8(void)
01360 {
01361 char *buffer;
01362 GPBuffer<char> gbuffer(buffer);
01363 read_file(*this,buffer,gbuffer);
01364 return GUTF8String(buffer);
01365 }
01366
01367
01368 #ifdef HAVE_NAMESPACES
01369 }
01370 # ifndef NOT_USING_DJVU_NAMESPACE
01371 using namespace DJVU;
01372 # endif
01373 #endif
01374
01375 void
01376 DjVuPrintErrorUTF8(const char *fmt, ... )
01377 {
01378 G_TRY {
01379 GP<ByteStream> errout = ByteStream::get_stderr();
01380 if (errout)
01381 {
01382 errout->cp=ByteStream::NATIVE;
01383 va_list args;
01384 va_start(args, fmt);
01385 const GUTF8String message(fmt,args);
01386 errout->writestring(message);
01387 }
01388
01389
01390 } G_CATCH_ALL { } G_ENDCATCH;
01391 }
01392
01393 void
01394 DjVuPrintErrorNative(const char *fmt, ... )
01395 {
01396 G_TRY {
01397 GP<ByteStream> errout = ByteStream::get_stderr();
01398 if (errout)
01399 {
01400 errout->cp=ByteStream::NATIVE;
01401 va_list args;
01402 va_start(args, fmt);
01403 const GNativeString message(fmt,args);
01404 errout->writestring(message);
01405 }
01406
01407
01408 } G_CATCH_ALL { } G_ENDCATCH;
01409 }
01410
01411 void
01412 DjVuPrintMessageUTF8(const char *fmt, ... )
01413 {
01414 G_TRY {
01415 GP<ByteStream> strout = ByteStream::get_stdout();
01416 if (strout)
01417 {
01418 strout->cp=ByteStream::NATIVE;
01419 va_list args;
01420 va_start(args, fmt);
01421 const GUTF8String message(fmt,args);
01422 strout->writestring(message);
01423 }
01424
01425
01426 } G_CATCH_ALL { } G_ENDCATCH;
01427 }
01428
01429 void
01430 DjVuPrintMessageNative(const char *fmt, ... )
01431 {
01432 G_TRY {
01433 GP<ByteStream> strout = ByteStream::get_stdout();
01434 if (strout)
01435 {
01436 strout->cp=ByteStream::NATIVE;
01437 va_list args;
01438 va_start(args, fmt);
01439 const GNativeString message(fmt,args);
01440 strout->writestring(message);
01441 }
01442
01443
01444 } G_CATCH_ALL { } G_ENDCATCH;
01445 }