Blame libdjvu/ByteStream.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
// From: Leon Bottou, 1/31/2002
Packit df99a1
// This file has very little to do with my initial implementation.
Packit df99a1
// It has been practically rewritten by Lizardtech for i18n changes.
Packit df99a1
// Our original implementation consisted of multiple classes.
Packit df99a1
// <http://prdownloads.sourceforge.net/djvu/DjVu2_2b-src.tgz>.
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
// - Author: Leon Bottou, 04/1997
Packit df99a1
Packit df99a1
#include "DjVuGlobal.h"
Packit df99a1
#include "ByteStream.h"
Packit df99a1
#include "GOS.h"
Packit df99a1
#include "GURL.h"
Packit df99a1
#include "DjVuMessage.h"
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <fcntl.h>
Packit df99a1
#if defined(_WIN32) || defined(__CYGWIN32__)
Packit df99a1
# include <io.h>
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifdef UNIX
Packit df99a1
# ifndef HAS_MEMMAP
Packit df99a1
#  define HAS_MEMMAP 1
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifdef UNIX
Packit df99a1
# include <sys/types.h>
Packit df99a1
# include <sys/stat.h>
Packit df99a1
# include <unistd.h>
Packit df99a1
# include <errno.h>
Packit df99a1
# ifdef HAS_MEMMAP
Packit df99a1
#  include <sys/mman.h>
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifdef macintosh
Packit df99a1
# ifndef UNIX
Packit df99a1
#  include <unistd.h>
Packit df99a1
_MSL_IMP_EXP_C int _dup(int);
Packit df99a1
_MSL_IMP_EXP_C int _dup2(int,int);
Packit df99a1
_MSL_IMP_EXP_C int _close(int);
Packit df99a1
__inline int dup(int _a ) { return _dup(_a);}
Packit df99a1
__inline int dup2(int _a, int _b ) { return _dup2(_a, _b);}
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#if defined(_WIN32) && !defined(__CYGWIN32__)
Packit df99a1
#  define close _close
Packit df99a1
#  define fdopen _fdopen
Packit df99a1
#  define dup _dup
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
const char *ByteStream::EndOfFile=ERR_MSG("EOF");
Packit df99a1
Packit df99a1
/** ByteStream interface for stdio files. 
Packit df99a1
    The virtual member functions #read#, #write#, #tell# and #seek# are mapped
Packit df99a1
    to the well known stdio functions #fread#, #fwrite#, #ftell# and #fseek#.
Packit df99a1
    @see Unix man page fopen(3), fread(3), fwrite(3), ftell(3), fseek(3) */
Packit df99a1
Packit df99a1
class ByteStream::Stdio : public ByteStream {
Packit df99a1
public:
Packit df99a1
  Stdio(void);
Packit df99a1
Packit df99a1
  /** Constructs a ByteStream for accessing the file named #url#.
Packit df99a1
      Arguments #url# and #mode# are similar to the arguments of the well
Packit df99a1
      known stdio function #fopen#. In addition a url of #-# will be
Packit df99a1
      interpreted as the standard output or the standard input according to
Packit df99a1
      #mode#.  This constructor will open a stdio file and construct a
Packit df99a1
      ByteStream object accessing this file. Destroying the ByteStream object
Packit df99a1
      will flush and close the associated stdio file.  Returns an error code
Packit df99a1
      if the stdio file cannot be opened. */
Packit df99a1
  GUTF8String init(const GURL &url, const char * const mode);
Packit df99a1
Packit df99a1
  /** Constructs a ByteStream for accessing the stdio file #f#.
Packit df99a1
      Argument #mode# indicates the type of the stdio file, as in the
Packit df99a1
      well known stdio function #fopen#.  Destroying the ByteStream
Packit df99a1
      object will not close the stdio file #f# unless closeme is true. */
Packit df99a1
  GUTF8String init(FILE * const f, const char * const mode="rb", const bool closeme=false);
Packit df99a1
Packit df99a1
  /** Initializes from stdio */
Packit df99a1
  GUTF8String init(const char mode[]);
Packit df99a1
Packit df99a1
  // Virtual functions
Packit df99a1
  ~Stdio();
Packit df99a1
  virtual size_t read(void *buffer, size_t size);
Packit df99a1
  virtual size_t write(const void *buffer, size_t size);
Packit df99a1
  virtual void flush(void);
Packit df99a1
  virtual int seek(long offset, int whence = SEEK_SET, bool nothrow=false);
Packit df99a1
  virtual long tell(void) const;
Packit df99a1
private:
Packit df99a1
  // Cancel C++ default stuff
Packit df99a1
  Stdio(const Stdio &);
Packit df99a1
  Stdio & operator=(const Stdio &);
Packit df99a1
private:
Packit df99a1
  // Implementation
Packit df99a1
  bool can_read;
Packit df99a1
  bool can_write;
Packit df99a1
  bool must_close;
Packit df99a1
protected:
Packit df99a1
  FILE *fp;
Packit df99a1
  long pos;
Packit df99a1
};
Packit df99a1
Packit df99a1
inline GUTF8String
Packit df99a1
ByteStream::Stdio::init(FILE * const f,const char mode[],const bool closeme)
Packit df99a1
{
Packit df99a1
  fp=f;
Packit df99a1
  must_close=closeme;
Packit df99a1
  return init(mode);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/** ByteStream interface managing a memory buffer.  
Packit df99a1
    Class #ByteStream::Memory# manages a dynamically resizable buffer from
Packit df99a1
    which data can be read or written.  The buffer itself is organized as an
Packit df99a1
    array of blocks of 4096 bytes.  */
Packit df99a1
Packit df99a1
class ByteStream::Memory : public ByteStream
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  /** Constructs an empty ByteStream::Memory.
Packit df99a1
      The buffer is initially empty. You must first use function #write#
Packit df99a1
      to store data into the buffer, use function #seek# to rewind the
Packit df99a1
      current position, and function #read# to read the data back. */
Packit df99a1
  Memory();
Packit df99a1
  /** Constructs a Memory by copying initial data.  The
Packit df99a1
      Memory buffer is initialized with #size# bytes copied from the
Packit df99a1
      memory area pointed to by #buffer#. */
Packit df99a1
  GUTF8String init(const void * const buffer, const size_t size);
Packit df99a1
  // Virtual functions
Packit df99a1
  ~Memory();
Packit df99a1
  virtual size_t read(void *buffer, size_t size);
Packit df99a1
  virtual size_t write(const void *buffer, size_t size);
Packit df99a1
  virtual int    seek(long offset, int whence=SEEK_SET, bool nothrow=false);
Packit df99a1
  virtual long   tell(void) const;
Packit df99a1
  /** Erases everything in the Memory.
Packit df99a1
      The current location is reset to zero. */
Packit df99a1
  void empty();
Packit df99a1
  /** Returns the total number of bytes contained in the buffer.  Valid
Packit df99a1
      offsets for function #seek# range from 0 to the value returned by this
Packit df99a1
      function. */
Packit df99a1
  virtual int size(void) const;
Packit df99a1
  /** Returns a reference to the byte at offset #n#. This reference can be
Packit df99a1
      used to read (as in #mbs[n]#) or modify (as in #mbs[n]=c#) the contents
Packit df99a1
      of the buffer. */
Packit df99a1
  char &operator[] (int n);
Packit df99a1
  /** Copies all internal data into \Ref{TArray} and returns it */
Packit df99a1
private:
Packit df99a1
  // Cancel C++ default stuff
Packit df99a1
  Memory(const Memory &);
Packit df99a1
  Memory & operator=(const Memory &);
Packit df99a1
  // Current position
Packit df99a1
  int where;
Packit df99a1
protected:
Packit df99a1
  /** Reads data from a random position. This function reads at most #sz#
Packit df99a1
      bytes at position #pos# into #buffer# and returns the actual number of
Packit df99a1
      bytes read.  The current position is unchanged. */
Packit df99a1
  virtual size_t readat(void *buffer, size_t sz, int pos);
Packit df99a1
  /** Number of bytes in internal buffer. */
Packit df99a1
  int bsize;
Packit df99a1
  /** Number of 4096 bytes blocks. */
Packit df99a1
  int nblocks;
Packit df99a1
  /** Pointers (possibly null) to 4096 bytes blocks. */
Packit df99a1
  char **blocks;
Packit df99a1
  /** Pointers (possibly null) to 4096 bytes blocks. */
Packit df99a1
  GPBuffer<char *> gblocks;
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
inline int
Packit df99a1
ByteStream::Memory::size(void) const
Packit df99a1
{
Packit df99a1
  return bsize;
Packit df99a1
}
Packit df99a1
Packit df99a1
inline char &
Packit df99a1
ByteStream::Memory::operator[] (int n)
Packit df99a1
{
Packit df99a1
  return blocks[n>>12][n&0xfff];
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/** Read-only ByteStream interface to a memory area.  
Packit df99a1
    Class #ByteStream::Static# implements a read-only ByteStream interface for a
Packit df99a1
    memory area specified by the user at construction time. Calls to function
Packit df99a1
    #read# directly access this memory area.  The user must therefore make
Packit df99a1
    sure that its content remain valid long enough.  */
Packit df99a1
Packit df99a1
class ByteStream::Static : public ByteStream
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
Packit df99a1
  /** Creates a Static object for allocating the memory area of
Packit df99a1
      length #sz# starting at address #buffer#. */
Packit df99a1
  Static(const void * const buffer, const size_t sz);
Packit df99a1
  ~Static();
Packit df99a1
  // Virtual functions
Packit df99a1
  virtual size_t read(void *buffer, size_t sz);
Packit df99a1
  virtual int    seek(long offset, int whence = SEEK_SET, bool nothrow=false);
Packit df99a1
  virtual long tell(void) const;
Packit df99a1
  /** Returns the total number of bytes contained in the buffer, file, etc.
Packit df99a1
      Valid offsets for function #seek# range from 0 to the value returned
Packit df99a1
      by this function. */
Packit df99a1
  virtual int size(void) const;
Packit df99a1
protected:
Packit df99a1
  const char *data;
Packit df99a1
  int bsize;
Packit df99a1
private:
Packit df99a1
  int where;
Packit df99a1
};
Packit df99a1
Packit df99a1
ByteStream::Static::~Static() {}
Packit df99a1
Packit df99a1
inline int
Packit df99a1
ByteStream::Static::size(void) const
Packit df99a1
{
Packit df99a1
  return bsize;
Packit df99a1
}
Packit df99a1
Packit df99a1
#if HAS_MEMMAP
Packit df99a1
/** Read-only ByteStream interface to a memmap area.
Packit df99a1
    Class #MemoryMapByteStream# implements a read-only ByteStream interface
Packit df99a1
    for a memory map to a file. */
Packit df99a1
Packit df99a1
class MemoryMapByteStream : public ByteStream::Static
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  MemoryMapByteStream(void);
Packit df99a1
  virtual ~MemoryMapByteStream();  
Packit df99a1
private:
Packit df99a1
  GUTF8String init(const int fd, const bool closeme);
Packit df99a1
  GUTF8String init(FILE *const f,const bool closeme);
Packit df99a1
  friend class ByteStream;
Packit df99a1
};
Packit df99a1
#endif
Packit df99a1
Packit df99a1
//// CLASS BYTESTREAM
Packit df99a1
Packit df99a1
Packit df99a1
ByteStream::~ByteStream()
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
int 
Packit df99a1
ByteStream::scanf(const char *fmt, ...)
Packit df99a1
{
Packit df99a1
  G_THROW( ERR_MSG("ByteStream.not_implemented") ); // This is a place holder function.
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::read(void *buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  G_THROW( ERR_MSG("ByteStream.cant_read") );      //  Cannot read from a ByteStream created for writing
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::write(const void *buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  G_THROW( ERR_MSG("ByteStream.cant_write") );      //  Cannot write from a ByteStream created for reading
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
ByteStream::flush()
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
ByteStream::seek(long offset, int whence, bool nothrow)
Packit df99a1
{
Packit df99a1
  int nwhere = 0;
Packit df99a1
  int ncurrent = tell();
Packit df99a1
  switch (whence)
Packit df99a1
    {
Packit df99a1
    case SEEK_SET:
Packit df99a1
      nwhere=0; break;
Packit df99a1
    case SEEK_CUR:
Packit df99a1
      nwhere=ncurrent; break;
Packit df99a1
    case SEEK_END: 
Packit df99a1
    {
Packit df99a1
      if(offset)
Packit df99a1
      {
Packit df99a1
        if (nothrow)
Packit df99a1
          return -1;
Packit df99a1
        G_THROW( ERR_MSG("ByteStream.backward") );
Packit df99a1
      }
Packit df99a1
      char buffer[1024];
Packit df99a1
      int bytes;
Packit df99a1
      while((bytes=read(buffer, sizeof(buffer))))
Packit df99a1
        EMPTY_LOOP;
Packit df99a1
      return 0;
Packit df99a1
    }
Packit df99a1
    default:
Packit df99a1
      G_THROW( ERR_MSG("ByteStream.bad_arg") );       //  Illegal argument in seek
Packit df99a1
    }
Packit df99a1
  nwhere += offset;
Packit df99a1
  if (nwhere < ncurrent) 
Packit df99a1
  {
Packit df99a1
    //  Seeking backwards is not supported by this ByteStream
Packit df99a1
    if (nothrow)
Packit df99a1
      return -1;
Packit df99a1
    G_THROW( ERR_MSG("ByteStream.backward") );
Packit df99a1
  }
Packit df99a1
  while (nwhere>ncurrent)
Packit df99a1
  {
Packit df99a1
    char buffer[1024];
Packit df99a1
    const int xbytes=(ncurrent+(int)sizeof(buffer)>nwhere)
Packit df99a1
      ?(nwhere - ncurrent):(int)sizeof(buffer);
Packit df99a1
    const int bytes = read(buffer, xbytes);
Packit df99a1
    ncurrent += bytes;
Packit df99a1
    if (!bytes)
Packit df99a1
      G_THROW( ByteStream::EndOfFile );
Packit df99a1
    //  Seeking works funny on this ByteStream (ftell() acts strange)
Packit df99a1
    if (ncurrent!=tell())
Packit df99a1
      G_THROW( ERR_MSG("ByteStream.seek") );
Packit df99a1
  }
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::readall(void *buffer, size_t size)
Packit df99a1
{
Packit df99a1
  size_t total = 0;
Packit df99a1
    while (size > 0)
Packit df99a1
    {
Packit df99a1
      int nitems = read(buffer, size);
Packit df99a1
      // Replaced perror() below with G_THROW(). It still makes little sense
Packit df99a1
      // as there is no guarantee, that errno is right. Still, throwing
Packit df99a1
      // exception instead of continuing to loop is better.
Packit df99a1
      // - eaf
Packit df99a1
      if(nitems < 0) 
Packit df99a1
        G_THROW(strerror(errno));               //  (No error in the DjVuMessageFile)
Packit df99a1
      if (nitems == 0)
Packit df99a1
        break;
Packit df99a1
      total += nitems;
Packit df99a1
      size -= nitems; 
Packit df99a1
      buffer = (void*)((char*)buffer + nitems);
Packit df99a1
    }
Packit df99a1
  return total;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t
Packit df99a1
ByteStream::format(const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  va_list args;
Packit df99a1
  va_start(args, fmt); 
Packit df99a1
  const GUTF8String message(fmt,args);
Packit df99a1
  return writestring(message);
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t
Packit df99a1
ByteStream::writestring(const GNativeString &s)
Packit df99a1
{
Packit df99a1
  int retval;
Packit df99a1
  if(cp != UTF8)
Packit df99a1
  {
Packit df99a1
    retval=writall((const char *)s,s.length());
Packit df99a1
    if(cp == AUTO)
Packit df99a1
      cp=NATIVE; // Avoid mixing string types.
Packit df99a1
  }else
Packit df99a1
  { 
Packit df99a1
    const GUTF8String msg(s.getNative2UTF8());
Packit df99a1
    retval=writall((const char *)msg,msg.length());
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t
Packit df99a1
ByteStream::writestring(const GUTF8String &s)
Packit df99a1
{
Packit df99a1
  int retval;
Packit df99a1
  if(cp != NATIVE)
Packit df99a1
  {
Packit df99a1
    retval=writall((const char *)s,s.length());
Packit df99a1
    if(cp == AUTO)
Packit df99a1
      cp=UTF8; // Avoid mixing string types.
Packit df99a1
  }else
Packit df99a1
  { 
Packit df99a1
    const GNativeString msg(s.getUTF82Native());
Packit df99a1
    retval=writall((const char *)msg,msg.length());
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::writall(const void *buffer, size_t size)
Packit df99a1
{
Packit df99a1
  size_t total = 0;
Packit df99a1
  while (size > 0)
Packit df99a1
    {
Packit df99a1
      size_t nitems = write(buffer, size);
Packit df99a1
      if (nitems == 0)
Packit df99a1
        G_THROW( ERR_MSG("ByteStream.write_error") );      //  Unknown error in write
Packit df99a1
      total += nitems;
Packit df99a1
      size -= nitems; 
Packit df99a1
      buffer = (void*)((char*)buffer + nitems);
Packit df99a1
    }
Packit df99a1
  return total;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::copy(ByteStream &bsfrom, size_t size)
Packit df99a1
{
Packit df99a1
  size_t total = 0;
Packit df99a1
  const size_t max_buffer_size=200*1024;
Packit df99a1
  const size_t buffer_size=(size>0 && size
Packit df99a1
    ?size:max_buffer_size;
Packit df99a1
  char *buffer;
Packit df99a1
  GPBuffer<char> gbuf(buffer,buffer_size);
Packit df99a1
  for(;;)
Packit df99a1
    {
Packit df99a1
      size_t bytes = buffer_size;
Packit df99a1
      if (size>0 && bytes+total>size)
Packit df99a1
        bytes = size - total;
Packit df99a1
      if (bytes == 0)
Packit df99a1
        break;
Packit df99a1
      bytes = bsfrom.read((void*)buffer, bytes);
Packit df99a1
      if (bytes == 0)
Packit df99a1
        break;
Packit df99a1
      writall((void*)buffer, bytes);
Packit df99a1
      total += bytes;
Packit df99a1
    }
Packit df99a1
  return total;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
ByteStream::write8 (unsigned int card)
Packit df99a1
{
Packit df99a1
  unsigned char c[1];
Packit df99a1
  c[0] = (card) & 0xff;
Packit df99a1
  if (write((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW(strerror(errno));   //  (No error in the DjVuMessageFile)
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
ByteStream::write16(unsigned int card)
Packit df99a1
{
Packit df99a1
  unsigned char c[2];
Packit df99a1
  c[0] = (card>>8) & 0xff;
Packit df99a1
  c[1] = (card) & 0xff;
Packit df99a1
  if (writall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW(strerror(errno));   //  (No error in the DjVuMessageFile)
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
ByteStream::write24(unsigned int card)
Packit df99a1
{
Packit df99a1
  unsigned char c[3];
Packit df99a1
  c[0] = (card>>16) & 0xff;
Packit df99a1
  c[1] = (card>>8) & 0xff;
Packit df99a1
  c[2] = (card) & 0xff;
Packit df99a1
  if (writall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW(strerror(errno));   //  (No error in the DjVuMessageFile)
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
ByteStream::write32(unsigned int card)
Packit df99a1
{
Packit df99a1
  unsigned char c[4];
Packit df99a1
  c[0] = (card>>24) & 0xff;
Packit df99a1
  c[1] = (card>>16) & 0xff;
Packit df99a1
  c[2] = (card>>8) & 0xff;
Packit df99a1
  c[3] = (card) & 0xff;
Packit df99a1
  if (writall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW(strerror(errno));   //  (No error in the DjVuMessageFile)
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
ByteStream::read8 ()
Packit df99a1
{
Packit df99a1
  unsigned char c[1];
Packit df99a1
  if (readall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW( ByteStream::EndOfFile );
Packit df99a1
  return c[0];
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
ByteStream::read16()
Packit df99a1
{
Packit df99a1
  unsigned char c[2];
Packit df99a1
  if (readall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW( ByteStream::EndOfFile );
Packit df99a1
  return (c[0]<<8)+c[1];
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
ByteStream::read24()
Packit df99a1
{
Packit df99a1
  unsigned char c[3];
Packit df99a1
  if (readall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW( ByteStream::EndOfFile );
Packit df99a1
  return (((c[0]<<8)+c[1])<<8)+c[2];
Packit df99a1
}
Packit df99a1
Packit df99a1
unsigned int 
Packit df99a1
ByteStream::read32()
Packit df99a1
{
Packit df99a1
  unsigned char c[4];
Packit df99a1
  if (readall((void*)c, sizeof(c)) != sizeof(c))
Packit df99a1
    G_THROW( ByteStream::EndOfFile );
Packit df99a1
  return (((((c[0]<<8)+c[1])<<8)+c[2])<<8)+c[3];
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
//// CLASS ByteStream::Stdio
Packit df99a1
Packit df99a1
ByteStream::Stdio::Stdio(void)
Packit df99a1
: can_read(false),can_write(false),must_close(true),fp(0),pos(0)
Packit df99a1
{}
Packit df99a1
Packit df99a1
ByteStream::Stdio::~Stdio()
Packit df99a1
{
Packit df99a1
  if (fp && must_close)
Packit df99a1
    fclose(fp);
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
ByteStream::Stdio::init(const char mode[])
Packit df99a1
{
Packit df99a1
  char const *mesg=0;
Packit df99a1
  bool binary=false;
Packit df99a1
  if(!fp)
Packit df99a1
    must_close=false;
Packit df99a1
  for (const char *s=mode; s && *s; s++)
Packit df99a1
  {
Packit df99a1
    switch(*s) 
Packit df99a1
    {
Packit df99a1
      case 'r':
Packit df99a1
        can_read=true;
Packit df99a1
        if(!fp) fp=stdin;
Packit df99a1
        break;
Packit df99a1
      case 'w': 
Packit df99a1
      case 'a':
Packit df99a1
        can_write=true;
Packit df99a1
        if(!fp) fp=stdout;
Packit df99a1
        break;
Packit df99a1
      case '+':
Packit df99a1
        can_read=can_write=true;
Packit df99a1
        break;
Packit df99a1
      case 'b':
Packit df99a1
        binary=true;
Packit df99a1
        break;
Packit df99a1
      default:
Packit df99a1
        mesg= ERR_MSG("ByteStream.bad_mode"); //  Illegal mode in Stdio
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if(binary && fp) {
Packit df99a1
#if defined(__CYGWIN32__)
Packit df99a1
    setmode(fileno(fp), O_BINARY);
Packit df99a1
#elif defined(_WIN32)
Packit df99a1
    _setmode(_fileno(fp), _O_BINARY);
Packit df99a1
#endif
Packit df99a1
  }
Packit df99a1
  GUTF8String retval;
Packit df99a1
  if(!mesg)
Packit df99a1
  {
Packit df99a1
    tell();
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    retval=mesg;
Packit df99a1
  }
Packit df99a1
  if(mesg &&(fp && must_close))
Packit df99a1
  {
Packit df99a1
    fclose(fp);
Packit df99a1
    fp=0;
Packit df99a1
    must_close=false;
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
static FILE *
Packit df99a1
urlfopen(const GURL &url,const char mode[])
Packit df99a1
{
Packit df99a1
#if defined(_WIN32)
Packit df99a1
  FILE *retval=0;
Packit df99a1
  const GUTF8String filename(url.UTF8Filename());
Packit df99a1
  wchar_t *wfilename;
Packit df99a1
  const size_t wfilename_size=filename.length()+1;
Packit df99a1
  GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
Packit df99a1
  if(filename.ncopy(wfilename,wfilename_size) > 0)
Packit df99a1
  {
Packit df99a1
    const GUTF8String gmode(mode);
Packit df99a1
    wchar_t *wmode;
Packit df99a1
    const size_t wmode_size=gmode.length()+1;
Packit df99a1
    GPBuffer<wchar_t> gwmode(wmode,wmode_size);
Packit df99a1
	if(gmode.ncopy(wmode,wmode_size) > 0)
Packit df99a1
	{
Packit df99a1
	  retval=_wfopen(wfilename,wmode);
Packit df99a1
	}
Packit df99a1
  }
Packit df99a1
  return retval?retval:fopen((const char *)url.NativeFilename(),mode);
Packit df99a1
#elif defined(__APPLE__)
Packit df99a1
  return fopen((const char *)url.UTF8Filename(),mode);
Packit df99a1
#else
Packit df99a1
  return fopen((const char *)url.NativeFilename(),mode);
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
Packit df99a1
#ifdef UNIX
Packit df99a1
static int
Packit df99a1
urlopen(const GURL &url, const int mode, const int perm)
Packit df99a1
{
Packit df99a1
#if defined(__APPLE__)
Packit df99a1
  return open((const char *)url.UTF8Filename(),mode,perm);
Packit df99a1
#else
Packit df99a1
  return open((const char *)url.NativeFilename(),mode,perm);
Packit df99a1
#endif
Packit df99a1
}
Packit df99a1
#endif /* UNIX */
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
ByteStream::Stdio::init(const GURL &url, const char mode[])
Packit df99a1
{
Packit df99a1
  GUTF8String retval;
Packit df99a1
  if (url.fname() != "-")
Packit df99a1
  {
Packit df99a1
    fp = urlfopen(url,mode);
Packit df99a1
    if (!fp)
Packit df99a1
    {
Packit df99a1
      //  Failed to open '%s': %s
Packit df99a1
      G_THROW( ERR_MSG("ByteStream.open_fail") "\t" + url.name()
Packit df99a1
               +"\t"+GNativeString(strerror(errno)).getNative2UTF8());
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return retval.length()?retval:init(mode);
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Stdio::read(void *buffer, size_t size)
Packit df99a1
{
Packit df99a1
  if (!can_read)
Packit df99a1
    G_THROW( ERR_MSG("ByteStream.no_read") ); //  Stdio not opened for reading
Packit df99a1
  size_t nitems;
Packit df99a1
  do
Packit df99a1
  {
Packit df99a1
    clearerr(fp);
Packit df99a1
    nitems = fread(buffer, 1, size, fp); 
Packit df99a1
    if (nitems<=0 && ferror(fp))
Packit df99a1
    {
Packit df99a1
#ifdef EINTR
Packit df99a1
      if (errno!=EINTR)
Packit df99a1
#endif
Packit df99a1
        G_THROW(strerror(errno)); //  (No error in the DjVuMessageFile)
Packit df99a1
    }
Packit df99a1
    else
Packit df99a1
      break;
Packit df99a1
  } while(true);
Packit df99a1
  pos += nitems;
Packit df99a1
  return nitems;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Stdio::write(const void *buffer, size_t size)
Packit df99a1
{
Packit df99a1
  if (!can_write)
Packit df99a1
    G_THROW( ERR_MSG("ByteStream.no_write") ); //  Stdio not opened for writing
Packit df99a1
  size_t nitems;
Packit df99a1
  do
Packit df99a1
  {
Packit df99a1
    clearerr(fp);
Packit df99a1
    nitems = fwrite(buffer, 1, size, fp);
Packit df99a1
    if (nitems<=0 && ferror(fp))
Packit df99a1
    {
Packit df99a1
#ifdef EINTR
Packit df99a1
      if (errno!=EINTR)
Packit df99a1
#endif
Packit df99a1
        G_THROW(strerror(errno)); //  (No error in the DjVuMessageFile)
Packit df99a1
    }
Packit df99a1
    else
Packit df99a1
      break;
Packit df99a1
  } while(true);
Packit df99a1
  pos += nitems;
Packit df99a1
  return nitems;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
ByteStream::Stdio::flush()
Packit df99a1
{
Packit df99a1
  if (fflush(fp) < 0)
Packit df99a1
    G_THROW(strerror(errno)); //  (No error in the DjVuMessageFile)
Packit df99a1
}
Packit df99a1
Packit df99a1
long 
Packit df99a1
ByteStream::Stdio::tell(void) const
Packit df99a1
{
Packit df99a1
  long x = ftell(fp);
Packit df99a1
  if (x >= 0)
Packit df99a1
  {
Packit df99a1
    Stdio *sbs=const_cast<Stdio *>(this);
Packit df99a1
    (sbs->pos) = x;
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    x=pos;
Packit df99a1
  }
Packit df99a1
  return x;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
ByteStream::Stdio::seek(long offset, int whence, bool nothrow)
Packit df99a1
{
Packit df99a1
  if (whence==SEEK_SET && offset>=0 && offset==ftell(fp))
Packit df99a1
    return 0;
Packit df99a1
  clearerr(fp);
Packit df99a1
  if (fseek(fp, offset, whence)) 
Packit df99a1
    {
Packit df99a1
      if (nothrow) 
Packit df99a1
        return -1;
Packit df99a1
      G_THROW(strerror(errno)); //  (No error in the DjVuMessageFile)
Packit df99a1
    }
Packit df99a1
  return tell();
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
///////// ByteStream::Memory
Packit df99a1
Packit df99a1
ByteStream::Memory::Memory()
Packit df99a1
  : where(0), bsize(0), nblocks(0), gblocks(blocks,0)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
ByteStream::Memory::init(void const * const buffer, const size_t sz)
Packit df99a1
{
Packit df99a1
  GUTF8String retval;
Packit df99a1
  G_TRY
Packit df99a1
  {
Packit df99a1
    writall(buffer, sz);
Packit df99a1
    where = 0;
Packit df99a1
  }
Packit df99a1
  G_CATCH(ex) // The only error that should be thrown is out of memory...
Packit df99a1
  {
Packit df99a1
    retval=ex.get_cause();
Packit df99a1
  }
Packit df99a1
  G_ENDCATCH;
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
ByteStream::Memory::empty()
Packit df99a1
{
Packit df99a1
  for (int b=0; b
Packit df99a1
  {
Packit df99a1
    delete [] blocks[b];
Packit df99a1
    blocks[b]=0;
Packit df99a1
  }
Packit df99a1
  bsize = 0;
Packit df99a1
  where = 0;
Packit df99a1
  nblocks = 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
ByteStream::Memory::~Memory()
Packit df99a1
{
Packit df99a1
  empty();
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Memory::write(const void *buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  int nsz = (int)sz;
Packit df99a1
  if (nsz <= 0)
Packit df99a1
    return 0;
Packit df99a1
  // check memory
Packit df99a1
  if ( (where+nsz) > ((bsize+0xfff)&~0xfff) )
Packit df99a1
    {
Packit df99a1
      // reallocate pointer array
Packit df99a1
      if ( (where+nsz) > (nblocks<<12) )
Packit df99a1
        {
Packit df99a1
          const int old_nblocks=nblocks;
Packit df99a1
          nblocks = (((where+nsz)+0xffff)&~0xffff) >> 12;
Packit df99a1
          gblocks.resize(nblocks);
Packit df99a1
          char const ** eblocks=(char const **)(blocks+old_nblocks);
Packit df99a1
          for(char const * const * const new_eblocks=blocks+nblocks;
Packit df99a1
            eblocks 
Packit df99a1
          {
Packit df99a1
            *eblocks = 0;
Packit df99a1
          }
Packit df99a1
        }
Packit df99a1
      // allocate blocks
Packit df99a1
      for (int b=(where>>12); (b<<12)<(where+nsz); b++)
Packit df99a1
      {
Packit df99a1
        if (! blocks[b])
Packit df99a1
          blocks[b] = new char[0x1000];
Packit df99a1
      }
Packit df99a1
    }
Packit df99a1
  // write data to buffer
Packit df99a1
  while (nsz > 0)
Packit df99a1
    {
Packit df99a1
      int n = (where|0xfff) + 1 - where;
Packit df99a1
      n = ((nsz < n) ? nsz : n);
Packit df99a1
      memcpy( (void*)&blocks[where>>12][where&0xfff], buffer, n);
Packit df99a1
      buffer = (void*) ((char*)buffer + n);
Packit df99a1
      where += n;
Packit df99a1
      nsz -= n;
Packit df99a1
    }
Packit df99a1
  // adjust size
Packit df99a1
  if (where > bsize)
Packit df99a1
    bsize = where;
Packit df99a1
  return sz;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Memory::readat(void *buffer, size_t sz, int pos)
Packit df99a1
{
Packit df99a1
  if ((int) sz > bsize - pos)
Packit df99a1
    sz = bsize - pos;
Packit df99a1
  int nsz = (int)sz;
Packit df99a1
  if (nsz <= 0)
Packit df99a1
    return 0;
Packit df99a1
  // read data from buffer
Packit df99a1
  while (nsz > 0)
Packit df99a1
    {
Packit df99a1
      int n = (pos|0xfff) + 1 - pos;
Packit df99a1
      n = ((nsz < n) ? nsz : n);
Packit df99a1
      memcpy(buffer, (void*)&blocks[pos>>12][pos&0xfff], n);
Packit df99a1
      buffer = (void*) ((char*)buffer + n);
Packit df99a1
      pos += n;
Packit df99a1
      nsz -= n;
Packit df99a1
    }
Packit df99a1
  return sz;
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Memory::read(void *buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  sz = readat(buffer,sz,where);
Packit df99a1
  where += sz;
Packit df99a1
  return sz;
Packit df99a1
}
Packit df99a1
Packit df99a1
long 
Packit df99a1
ByteStream::Memory::tell(void) const
Packit df99a1
{
Packit df99a1
  return where;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
ByteStream::Memory::seek(long offset, int whence, bool nothrow)
Packit df99a1
{
Packit df99a1
  int nwhere = 0;
Packit df99a1
  switch (whence)
Packit df99a1
    {
Packit df99a1
    case SEEK_SET: nwhere = 0; break;
Packit df99a1
    case SEEK_CUR: nwhere = where; break;
Packit df99a1
    case SEEK_END: nwhere = bsize; break;
Packit df99a1
    default: G_THROW( ERR_MSG("bad_arg") "\tByteStream::Memory::seek()");      // Illegal argument in ByteStream::Memory::seek()
Packit df99a1
    }
Packit df99a1
  nwhere += offset;
Packit df99a1
  if (nwhere<0)
Packit df99a1
    G_THROW( ERR_MSG("ByteStream.seek_error2") );                          //  Attempt to seek before the beginning of the file
Packit df99a1
  where = nwhere;
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/** This function has been moved into Arrays.cpp
Packit df99a1
    In order to avoid dependencies from ByteStream.o
Packit df99a1
    to Arrays.o */
Packit df99a1
#ifdef DO_NOT_MOVE_GET_DATA_TO_ARRAYS_CPP
Packit df99a1
TArray<char>
Packit df99a1
ByteStream::get_data(void)
Packit df99a1
{
Packit df99a1
   TArray<char> data(0, size()-1);
Packit df99a1
   readat((char*)data, size(), 0);
Packit df99a1
   return data;
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
///////// ByteStream::Static
Packit df99a1
Packit df99a1
ByteStream::Static::Static(const void * const buffer, const size_t sz)
Packit df99a1
  : data((const char *)buffer), bsize(sz), where(0)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
size_t 
Packit df99a1
ByteStream::Static::read(void *buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  int nsz = (int)sz;
Packit df99a1
  if (nsz > bsize - where)
Packit df99a1
    nsz = bsize - where;
Packit df99a1
  if (nsz <= 0)
Packit df99a1
    return 0;
Packit df99a1
  memcpy(buffer, data+where, nsz);
Packit df99a1
  where += nsz;
Packit df99a1
  return nsz;
Packit df99a1
}
Packit df99a1
Packit df99a1
int
Packit df99a1
ByteStream::Static::seek(long offset, int whence, bool nothrow)
Packit df99a1
{
Packit df99a1
  int nwhere = 0;
Packit df99a1
  switch (whence)
Packit df99a1
    {
Packit df99a1
    case SEEK_SET: nwhere = 0; break;
Packit df99a1
    case SEEK_CUR: nwhere = where; break;
Packit df99a1
    case SEEK_END: nwhere = bsize; break;
Packit df99a1
    default: G_THROW("bad_arg\tByteStream::Static::seek()");      //  Illegal argument to ByteStream::Static::seek()
Packit df99a1
    }
Packit df99a1
  nwhere += offset;
Packit df99a1
  if (nwhere<0)
Packit df99a1
    G_THROW( ERR_MSG("ByteStream.seek_error2") );                          //  Attempt to seek before the beginning of the file
Packit df99a1
  where = nwhere;
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
long 
Packit df99a1
ByteStream::Static::tell(void) const
Packit df99a1
{
Packit df99a1
  return where;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(void)
Packit df99a1
{
Packit df99a1
  return new Memory();
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(void const * const buffer, const size_t size)
Packit df99a1
{
Packit df99a1
  Memory *mbs=new Memory();
Packit df99a1
  GP<ByteStream> retval=mbs;
Packit df99a1
  mbs->init(buffer,size);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(const GURL &url,char const * const xmode)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> retval;
Packit df99a1
  const char *mode = ((xmode) ? xmode : "rb");
Packit df99a1
#ifdef UNIX
Packit df99a1
  if (!strcmp(mode,"rb")) 
Packit df99a1
    {
Packit df99a1
      int fd = urlopen(url,O_RDONLY,0777);
Packit df99a1
      if (fd >= 0)
Packit df99a1
        {
Packit df99a1
#if HAS_MEMMAP && defined(S_IFREG)
Packit df99a1
          struct stat buf;
Packit df99a1
          if ( (fstat(fd, &buf) >= 0) && (buf.st_mode & S_IFREG) )
Packit df99a1
            {
Packit df99a1
              MemoryMapByteStream *rb = new MemoryMapByteStream();
Packit df99a1
              retval = rb;
Packit df99a1
              GUTF8String errmessage = rb->init(fd,true);
Packit df99a1
              if(errmessage.length())
Packit df99a1
                retval=0;
Packit df99a1
            }
Packit df99a1
#endif
Packit df99a1
          if (! retval)
Packit df99a1
            {
Packit df99a1
              FILE *f = fdopen(fd, mode);
Packit df99a1
              if (f) 
Packit df99a1
                {
Packit df99a1
                  Stdio *sbs=new Stdio();
Packit df99a1
                  retval=sbs;
Packit df99a1
                  GUTF8String errmessage=sbs->init(f, mode, true);
Packit df99a1
                  if(errmessage.length())
Packit df99a1
                    retval=0;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          if (! retval)
Packit df99a1
            close(fd);
Packit df99a1
        }     
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
  if (! retval)
Packit df99a1
    {
Packit df99a1
      Stdio *sbs=new Stdio();
Packit df99a1
      retval=sbs;
Packit df99a1
      GUTF8String errmessage=sbs->init(url, mode);
Packit df99a1
      if(errmessage.length())
Packit df99a1
        G_THROW(errmessage);
Packit df99a1
    }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(char const * const mode)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> retval;
Packit df99a1
  Stdio *sbs=new Stdio();
Packit df99a1
  retval=sbs;
Packit df99a1
  GUTF8String errmessage=sbs->init(mode?mode:"rb");
Packit df99a1
  if(errmessage.length())
Packit df99a1
  {
Packit df99a1
    G_THROW(errmessage);
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(const int fd,char const * const mode,const bool closeme)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> retval;
Packit df99a1
  const char *default_mode="rb";
Packit df99a1
#if HAS_MEMMAP
Packit df99a1
  if (   (!mode&&(fd!=0)&&(fd!=1)&&(fd!=2)) 
Packit df99a1
      || (mode&&(GUTF8String("rb") == mode)))
Packit df99a1
  {
Packit df99a1
    MemoryMapByteStream *rb=new MemoryMapByteStream();
Packit df99a1
    retval=rb;
Packit df99a1
    GUTF8String errmessage=rb->init(fd,closeme);
Packit df99a1
    if(errmessage.length())
Packit df99a1
    {
Packit df99a1
      retval=0;
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if(!retval)
Packit df99a1
#endif
Packit df99a1
  {
Packit df99a1
    int fd2 = fd;
Packit df99a1
    FILE *f = 0;
Packit df99a1
    if (fd == 0 && !closeme 
Packit df99a1
        && (!mode || mode[0]=='r') )
Packit df99a1
      {
Packit df99a1
        f=stdin;
Packit df99a1
        default_mode = "r";
Packit df99a1
        fd2=(-1);
Packit df99a1
      }
Packit df99a1
    else if (fd == 1 && !closeme 
Packit df99a1
             && (!mode || mode[0]=='a' || mode[0]=='w') )
Packit df99a1
      {
Packit df99a1
        default_mode = "a";
Packit df99a1
        f=stdout;
Packit df99a1
        fd2 = -1;
Packit df99a1
      }
Packit df99a1
    else if (fd == 2 && !closeme
Packit df99a1
             && (!mode || mode[0]=='a' || mode[0]=='w') )
Packit df99a1
      {
Packit df99a1
        default_mode = "a";
Packit df99a1
        f=stderr;
Packit df99a1
        fd2 = -1;
Packit df99a1
      }
Packit df99a1
    else
Packit df99a1
      {
Packit df99a1
        if (! closeme)
Packit df99a1
          fd2 = dup(fd);
Packit df99a1
        f = fdopen(fd2,(char*)(mode?mode:default_mode));
Packit df99a1
      }
Packit df99a1
Packit df99a1
    if(!f)
Packit df99a1
      {
Packit df99a1
        if ( fd2 >= 0)
Packit df99a1
          close(fd2);
Packit df99a1
        G_THROW( ERR_MSG("ByteStream.open_fail2") );
Packit df99a1
      }
Packit df99a1
    Stdio *sbs=new Stdio();
Packit df99a1
    retval=sbs;
Packit df99a1
    GUTF8String errmessage=sbs->init(f,mode?mode:default_mode,(fd2>=0));
Packit df99a1
    if(errmessage.length())
Packit df99a1
      G_THROW(errmessage);
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create(FILE * const f,char const * const mode,const bool closeme)
Packit df99a1
{
Packit df99a1
  GP<ByteStream> retval;
Packit df99a1
#if HAS_MEMMAP
Packit df99a1
  if (!mode || (GUTF8String("rb") == mode))
Packit df99a1
  {
Packit df99a1
    MemoryMapByteStream *rb=new MemoryMapByteStream();
Packit df99a1
    retval=rb;
Packit df99a1
    GUTF8String errmessage=rb->init(fileno(f),false);
Packit df99a1
    if(errmessage.length())
Packit df99a1
    {
Packit df99a1
      retval=0;
Packit df99a1
    }else
Packit df99a1
    {
Packit df99a1
      fclose(f);
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  if(!retval)
Packit df99a1
#endif
Packit df99a1
  {
Packit df99a1
    Stdio *sbs=new Stdio();
Packit df99a1
    retval=sbs;
Packit df99a1
    GUTF8String errmessage=sbs->init(f,mode?mode:"rb",closeme);
Packit df99a1
    if(errmessage.length())
Packit df99a1
    {
Packit df99a1
      G_THROW(errmessage);
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream>
Packit df99a1
ByteStream::create_static(const void * buffer, size_t sz)
Packit df99a1
{
Packit df99a1
  return new Static(buffer, sz);
Packit df99a1
}
Packit df99a1
Packit df99a1
#if HAS_MEMMAP
Packit df99a1
MemoryMapByteStream::MemoryMapByteStream(void)
Packit df99a1
: ByteStream::Static(0,0)
Packit df99a1
{}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
MemoryMapByteStream::init(FILE *const f,const bool closeme)
Packit df99a1
{
Packit df99a1
  GUTF8String retval;
Packit df99a1
  retval=init(fileno(f),false);
Packit df99a1
  if(closeme)
Packit df99a1
  {
Packit df99a1
    fclose(f);
Packit df99a1
  }
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
MemoryMapByteStream::init(const int fd,const bool closeme)
Packit df99a1
{
Packit df99a1
  GUTF8String retval;
Packit df99a1
  data = (char*)(-1);
Packit df99a1
#if defined(PROT_READ) && defined(MAP_SHARED)
Packit df99a1
  struct stat statbuf;
Packit df99a1
  if(!fstat(fd,&statbuf) && statbuf.st_size)
Packit df99a1
    {
Packit df99a1
      bsize=statbuf.st_size;
Packit df99a1
      data=(char *)mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,fd,0);
Packit df99a1
    }
Packit df99a1
#endif
Packit df99a1
  if(data == (char *)(-1))
Packit df99a1
    retval = ERR_MSG("ByteStream.open_fail2");
Packit df99a1
  if(closeme)
Packit df99a1
    close(fd);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
MemoryMapByteStream::~MemoryMapByteStream()
Packit df99a1
{
Packit df99a1
  if(data)
Packit df99a1
  {
Packit df99a1
    munmap(const_cast<char *>(data),bsize);
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
#endif
Packit df99a1
Packit df99a1
ByteStream::Wrapper::~Wrapper() {}
Packit df99a1
Packit df99a1
Packit df99a1
GP<ByteStream> 
Packit df99a1
ByteStream::get_stdin(char const *mode)
Packit df99a1
{
Packit df99a1
  static GP<ByteStream> gp = ByteStream::create(0,mode,false);
Packit df99a1
  return gp;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream> 
Packit df99a1
ByteStream::get_stdout(char const *mode)
Packit df99a1
{
Packit df99a1
  static GP<ByteStream> gp = ByteStream::create(1,mode,false);
Packit df99a1
  return gp;
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<ByteStream> 
Packit df99a1
ByteStream::get_stderr(char const *mode)
Packit df99a1
{
Packit df99a1
  static GP<ByteStream> gp = ByteStream::create(2,mode,false);
Packit df99a1
  return gp;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/** Looks up the message and writes it to the specified stream. */
Packit df99a1
void ByteStream::formatmessage( const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  va_list args;
Packit df99a1
  va_start(args, fmt);
Packit df99a1
  const GUTF8String message(fmt,args);
Packit df99a1
  writemessage( message );
Packit df99a1
}
Packit df99a1
Packit df99a1
/** Looks up the message and writes it to the specified stream. */
Packit df99a1
void ByteStream::writemessage( const char *message )
Packit df99a1
{
Packit df99a1
  writestring( DjVuMessage::LookUpUTF8( message ) );
Packit df99a1
}
Packit df99a1
Packit df99a1
static void 
Packit df99a1
read_file(ByteStream &bs,char *&buffer,GPBuffer<char> &gbuffer)
Packit df99a1
{
Packit df99a1
  const int size=bs.size();
Packit df99a1
  int pos=0;
Packit df99a1
  if(size>0)
Packit df99a1
  {
Packit df99a1
    size_t readsize=size+1;
Packit df99a1
    gbuffer.resize(readsize);
Packit df99a1
    for(int i;readsize&&(i=bs.read(buffer+pos,readsize))>0;pos+=i,readsize-=i)
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
  }else
Packit df99a1
  {
Packit df99a1
    const size_t readsize=32768;
Packit df99a1
    gbuffer.resize(readsize);
Packit df99a1
    for(int i;((i=bs.read(buffer+pos,readsize))>0);
Packit df99a1
      gbuffer.resize((pos+=i)+readsize))
Packit df99a1
      EMPTY_LOOP;
Packit df99a1
  }
Packit df99a1
  buffer[pos]=0;
Packit df99a1
}
Packit df99a1
Packit df99a1
GNativeString
Packit df99a1
ByteStream::getAsNative(void)
Packit df99a1
{
Packit df99a1
  char *buffer;
Packit df99a1
  GPBuffer<char> gbuffer(buffer);
Packit df99a1
  read_file(*this,buffer,gbuffer);
Packit df99a1
  return GNativeString(buffer);
Packit df99a1
}
Packit df99a1
Packit df99a1
GUTF8String
Packit df99a1
ByteStream::getAsUTF8(void)
Packit df99a1
{
Packit df99a1
  char *buffer;
Packit df99a1
  GPBuffer<char> gbuffer(buffer);
Packit df99a1
  read_file(*this,buffer,gbuffer);
Packit df99a1
  return GUTF8String(buffer);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVuPrintErrorUTF8(const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  G_TRY {
Packit df99a1
    GP<ByteStream> errout = ByteStream::get_stderr();
Packit df99a1
    if (errout)
Packit df99a1
      {
Packit df99a1
        errout->cp=ByteStream::NATIVE;
Packit df99a1
        va_list args;
Packit df99a1
        va_start(args, fmt); 
Packit df99a1
        const GUTF8String message(fmt,args);
Packit df99a1
        errout->writestring(message);
Packit df99a1
      }
Packit df99a1
    // Need to catch all exceptions because these might be 
Packit df99a1
    // called from an outer exception handler (with prejudice)
Packit df99a1
  } G_CATCH_ALL { } G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVuPrintErrorNative(const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  G_TRY {
Packit df99a1
    GP<ByteStream> errout = ByteStream::get_stderr();
Packit df99a1
    if (errout)
Packit df99a1
      {
Packit df99a1
        errout->cp=ByteStream::NATIVE;
Packit df99a1
        va_list args;
Packit df99a1
        va_start(args, fmt); 
Packit df99a1
        const GNativeString message(fmt,args);
Packit df99a1
        errout->writestring(message);
Packit df99a1
      }
Packit df99a1
    // Need to catch all exceptions because these might be 
Packit df99a1
    // called from an outer exception handler (with prejudice)
Packit df99a1
  } G_CATCH_ALL { } G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVuPrintMessageUTF8(const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  G_TRY {
Packit df99a1
    GP<ByteStream> strout = ByteStream::get_stdout();
Packit df99a1
    if (strout)
Packit df99a1
      {
Packit df99a1
        strout->cp=ByteStream::NATIVE;
Packit df99a1
        va_list args;
Packit df99a1
        va_start(args, fmt);
Packit df99a1
        const GUTF8String message(fmt,args);
Packit df99a1
        strout->writestring(message);
Packit df99a1
      }
Packit df99a1
    // Need to catch all exceptions because these might be 
Packit df99a1
    // called from an outer exception handler (with prejudice)
Packit df99a1
  } G_CATCH_ALL { } G_ENDCATCH;
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
DjVuPrintMessageNative(const char *fmt, ... )
Packit df99a1
{
Packit df99a1
  G_TRY {
Packit df99a1
    GP<ByteStream> strout = ByteStream::get_stdout();
Packit df99a1
    if (strout)
Packit df99a1
      {
Packit df99a1
        strout->cp=ByteStream::NATIVE;
Packit df99a1
        va_list args;
Packit df99a1
        va_start(args, fmt);
Packit df99a1
        const GNativeString message(fmt,args);
Packit df99a1
        strout->writestring(message);
Packit df99a1
      }
Packit df99a1
    // Need to catch all exceptions because these might be 
Packit df99a1
    // called from an outer exception handler (with prejudice)
Packit df99a1
  } G_CATCH_ALL { } G_ENDCATCH;
Packit df99a1
}