|
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 |
}
|