• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

ByteStream.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: ByteStream.cpp,v 1.18 2004/08/06 14:50:05 leonb Exp $
00055 // $Name: release_3_5_15 $
00056 
00057 // From: Leon Bottou, 1/31/2002
00058 // This file has very little to do with my initial implementation.
00059 // It has been practically rewritten by Lizardtech for i18n changes.
00060 // Our original implementation consisted of multiple classes.
00061 // <http://prdownloads.sourceforge.net/djvu/DjVu2_2b-src.tgz>.
00062 
00063 #ifdef HAVE_CONFIG_H
00064 # include "config.h"
00065 #endif
00066 #if NEED_GNUG_PRAGMAS
00067 # pragma implementation
00068 #endif
00069 
00070 // - Author: Leon Bottou, 04/1997
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   // Virtual functions
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   // Cancel C++ default stuff
00151   Stdio(const Stdio &);
00152   Stdio & operator=(const Stdio &);
00153 private:
00154   // Implementation
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   // Virtual functions
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   // Cancel C++ default stuff
00209   Memory(const Memory &);
00210   Memory & operator=(const Memory &);
00211   // Current position
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   // Virtual functions
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") ); // This is a place holder function.
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") );      //  Cannot read from a ByteStream created for writing
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") );      //  Cannot write from a ByteStream created for reading
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") );       //  Illegal argument in seek
00405     }
00406   nwhere += offset;
00407   if (nwhere < ncurrent) 
00408   {
00409     //  Seeking backwards is not supported by this ByteStream
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     //  Seeking works funny on this ByteStream (ftell() acts strange)
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       // Replaced perror() below with G_THROW(). It still makes little sense
00438       // as there is no guarantee, that errno is right. Still, throwing
00439       // exception instead of continuing to loop is better.
00440       // - eaf
00441       if(nitems < 0) 
00442         G_THROW(strerror(errno));               //  (No error in the DjVuMessageFile)
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; // Avoid mixing string types.
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; // Avoid mixing string types.
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") );      //  Unknown error in write
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));   //  (No error in the DjVuMessageFile)
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));   //  (No error in the DjVuMessageFile)
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));   //  (No error in the DjVuMessageFile)
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));   //  (No error in the DjVuMessageFile)
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"); //  Illegal mode in Stdio
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 /* UNIX */
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       //  Failed to open '%s': %s
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") ); //  Stdio not opened for reading
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)); //  (No error in the DjVuMessageFile)
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") ); //  Stdio not opened for writing
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)); //  (No error in the DjVuMessageFile)
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)); //  (No error in the DjVuMessageFile)
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)); //  (No error in the DjVuMessageFile)
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) // The only error that should be thrown is out of memory...
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   // check memory
00871   if ( (where+nsz) > ((bsize+0xfff)&~0xfff) )
00872     {
00873       // reallocate pointer array
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       // allocate blocks
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   // write data to buffer
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   // adjust size
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   // read data from buffer
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()");      // Illegal argument in ByteStream::Memory::seek()
00954     }
00955   nwhere += offset;
00956   if (nwhere<0)
00957     G_THROW( ERR_MSG("ByteStream.seek_error2") );                          //  Attempt to seek before the beginning of the file
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()");      //  Illegal argument to ByteStream::Static::seek()
01008     }
01009   nwhere += offset;
01010   if (nwhere<0)
01011     G_THROW( ERR_MSG("ByteStream.seek_error2") );                          //  Attempt to seek before the beginning of the file
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     // Need to catch all exceptions because these might be 
01389     // called from an outer exception handler (with prejudice)
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     // Need to catch all exceptions because these might be 
01407     // called from an outer exception handler (with prejudice)
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     // Need to catch all exceptions because these might be 
01425     // called from an outer exception handler (with prejudice)
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     // Need to catch all exceptions because these might be 
01443     // called from an outer exception handler (with prejudice)
01444   } G_CATCH_ALL { } G_ENDCATCH;
01445 }

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal