Blame libdjvu/GIFFManager.h

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
#ifndef _GIFFMANAGER_H
Packit df99a1
#define _GIFFMANAGER_H
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
#include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma interface
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
#include "IFFByteStream.h"
Packit df99a1
#include "GContainer.h"
Packit df99a1
#include "Arrays.h"
Packit df99a1
#include "GSmartPointer.h"
Packit df99a1
#include "GString.h"
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
Packit df99a1
/** @name GIFFManager.h
Packit df99a1
Packit df99a1
    Files #"GIFFManager.h"# and #"GIFFManager.cpp"# define more convenient
Packit df99a1
    interface to IFF files. You may want to use the {\Ref GIFFManager} class
Packit df99a1
    instead of coping with {\Ref IFFByteStream} especially when you have to
Packit df99a1
    insert or move chunks, which is a kind of tricky with sequential access
Packit df99a1
    provided by {\Ref IFFByteStream}.
Packit df99a1
Packit df99a1
    You will mostly deal with {\Ref GIFFManager} class, but sometimes you may
Packit df99a1
    want to use {\Ref GIFFChunk}s as well thus bypassing {\Ref GIFFManager}'s
Packit df99a1
    interface and working with the chunks hierarchy yourself.
Packit df99a1
    
Packit df99a1
    Interface to IFF files.
Packit df99a1
    @author 
Packit df99a1
    Andrei Erofeev <eaf@geocities.com> -- Initial implementation.
Packit df99a1
*/
Packit df99a1
Packit df99a1
/** #GIFFChunk# is the base class for other IFF chunks understood by
Packit df99a1
    {\Ref GIFFManager}. It provides some basic interface, and is not supposed
Packit df99a1
    to be used on its own. */
Packit df99a1
Packit df99a1
class GIFFChunk : public GPEnabled
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
   GIFFChunk(void);
Packit df99a1
   GIFFChunk(const GUTF8String &name);
Packit df99a1
   GIFFChunk(const GUTF8String &name, const TArray<char> & data);
Packit df99a1
public:
Packit df99a1
      /// Default creator.
Packit df99a1
   static GP<GIFFChunk> create(void) {return new GIFFChunk();}
Packit df99a1
Packit df99a1
      /** Creates the chunk with the given name. The {\em name} may not
Packit df99a1
	  contain dots colons or brackets */
Packit df99a1
   static GP<GIFFChunk> create(const GUTF8String &name)
Packit df99a1
   {return new GIFFChunk(name);}
Packit df99a1
Packit df99a1
      /** Creates the {\em plain chunk} containing raw data */
Packit df99a1
   static GP<GIFFChunk> create(const GUTF8String &name, const TArray<char> & data)
Packit df99a1
   { return new GIFFChunk(name,data); }
Packit df99a1
Packit df99a1
      /// Destructor
Packit df99a1
   virtual ~GIFFChunk(void);
Packit df99a1
Packit df99a1
      /// Returns the name of the chunk (without possible #FORM:# or similar prefixes)
Packit df99a1
   GUTF8String	get_name(void) const;
Packit df99a1
      /// Returns full chunk name, with possible container specification
Packit df99a1
   GUTF8String	get_full_name(void) const;
Packit df99a1
      /// Returns the chunk type, like #CAT# for chunk #CAT:DJVU#
Packit df99a1
   GUTF8String	get_type(void) const;
Packit df99a1
      /// Returns TRUE if the chunk may contain other chunks or FALSE otherwise
Packit df99a1
   bool		is_container(void) const;
Packit df99a1
      /** Sets the chunk name. The {\em name} may not contain dots or brackets,
Packit df99a1
	  but {\bf may} contain colons. */
Packit df99a1
   void		set_name(GUTF8String name);
Packit df99a1
      /** Parses the {\em name} probably containing colon and compares it
Packit df99a1
	  with its own name returning TRUE if they are the same */
Packit df99a1
   bool		check_name(GUTF8String name);
Packit df99a1
Packit df99a1
      /** Adds the {\em chunk} to the chunks list at position {\em order}.
Packit df99a1
	  Set {\em order} to #-1# to append the chunk to the list.
Packit df99a1
          {\bf Note!} By adding chunk #PROP# you will convert this chunk
Packit df99a1
          to type #LIST# {\em automatically}. */
Packit df99a1
   void		add_chunk(const GP<GIFFChunk> & chunk, int order=-1);
Packit df99a1
      /** Removes the chunk with given {\em name}. The {\em name} may not
Packit df99a1
	  contain dots, but MAY contain colons and brackets (the latter -
Packit df99a1
	  for specifying the chunk number) */
Packit df99a1
   void		del_chunk(const GUTF8String &name);
Packit df99a1
      /** Returns the chunk with given {\em name}. The {\em name} may not
Packit df99a1
	  contain dots, but MAY contain colons and brackets (the latter -
Packit df99a1
	  for specifying the chunk number). If {\em position} is not zero
Packit df99a1
	  then the chunk position in its parent will be put into #*position# */
Packit df99a1
   GP<GIFFChunk>get_chunk(const GUTF8String &name, int * position=0);
Packit df99a1
      /** Returns the number of chunks with given {\em name}. The {\em name}
Packit df99a1
	  may not contain dots and brackets. If {\em name} is ZERO, the
Packit df99a1
	  total number of chunks will be returned. */
Packit df99a1
   int		get_chunks_number(const GUTF8String &name);
Packit df99a1
   int		get_chunks_number(void);
Packit df99a1
      /** Returns the data array for plain chunks */
Packit df99a1
   TArray<char>	get_data(void) const;
Packit df99a1
   
Packit df99a1
      /** Saves the chunk into the {\Ref IFFByteStream}.
Packit df99a1
	  Set {\em use_trick} to #1# if this is a top-level chunk */
Packit df99a1
   void		save(IFFByteStream & istr, bool use_trick=0);
Packit df99a1
private:
Packit df99a1
   char			name[5];
Packit df99a1
   GUTF8String		type;
Packit df99a1
   GPList<GIFFChunk>	chunks;
Packit df99a1
   TArray<char>		data;
Packit df99a1
   static GUTF8String decode_name(const GUTF8String &name, int &number);
Packit df99a1
};
Packit df99a1
Packit df99a1
inline GUTF8String
Packit df99a1
GIFFChunk::get_name(void) const { return GUTF8String(name, 4); }
Packit df99a1
Packit df99a1
inline GUTF8String
Packit df99a1
GIFFChunk::get_type(void) const { return type; };
Packit df99a1
Packit df99a1
inline GUTF8String
Packit df99a1
GIFFChunk::get_full_name(void) const { return get_type()+":"+get_name(); };
Packit df99a1
Packit df99a1
inline bool
Packit df99a1
GIFFChunk::is_container(void) const { return type.length()!=0; };
Packit df99a1
Packit df99a1
inline TArray<char>
Packit df99a1
GIFFChunk::get_data(void) const { return data; };
Packit df99a1
Packit df99a1
inline
Packit df99a1
GIFFChunk::GIFFChunk(void) { name[0]=0; }
Packit df99a1
Packit df99a1
inline
Packit df99a1
GIFFChunk::GIFFChunk(const GUTF8String &name) { set_name(name); }
Packit df99a1
Packit df99a1
inline
Packit df99a1
GIFFChunk::GIFFChunk(const GUTF8String &name, const TArray<char> & data_in) :
Packit df99a1
      data(data_in)
Packit df99a1
{
Packit df99a1
   set_name(name);
Packit df99a1
}
Packit df99a1
Packit df99a1
//************************************************************************
Packit df99a1
Packit df99a1
/** Intuitive interface to IFF files.
Packit df99a1
Packit df99a1
    It's too terrible to keep reading/writing IFF files chunk after chunk
Packit df99a1
    using {\Ref IFFByteStream}s. This class allows you to operate with chunks
Packit df99a1
    as with structures or arrays without even caring about the byte streams.
Packit df99a1
Packit df99a1
    Some of the examples are below:
Packit df99a1
    \begin{verbatim}
Packit df99a1
       GP<GIFFChunk> chunk;
Packit df99a1
       chunk=manager1.get_chunk("BG44[2]");
Packit df99a1
       manager2.add_chunk(".FORM:DJVU.BG44[-1]", chunk);
Packit df99a1
    \end{verbatim}
Packit df99a1
Packit df99a1
    {\bf Chunk name}
Packit df99a1
    \begin{itemize}
Packit df99a1
       \item Every chunk name may contain optional prefix #FORM:#, #LIST:#,
Packit df99a1
             #PROP:# or #CAT:#. If the prefix is omitted and the chunk happens
Packit df99a1
	     to contain other chunks, #FORM:# will be assumed.
Packit df99a1
       \item Every chunk name may be {\em short} or {\em complete}.
Packit df99a1
             {\em short} chunk names may not contain dots as they're a
Packit df99a1
	     subchunks names with respect to a given chunk.
Packit df99a1
	     {\em complete} chunk names may contain dots. But there may be
Packit df99a1
	     or may not be the {\em leading dot} in the name. If the
Packit df99a1
	     {\em leading dot} is present, then the name is assumed to contain
Packit df99a1
	     the name of the top-level chunk as well. Otherwise it's treated
Packit df99a1
	     {\em with respect} to the top-level chunk. You may want to use
Packit df99a1
	     the leading dot only when you add a chunk to an empty document,
Packit df99a1
	     since a command like #manager.addChunk(".FORM:DJVU.BG44", chunk)#
Packit df99a1
	     will create the top level chunk of the requested type (#FORM:DJVU#)
Packit df99a1
	     and will add chunk #BG44# to it {\em automatically}.
Packit df99a1
       \item You may use {\em brackets} in the name to specify the chunk's
Packit df99a1
             position. The meaning of the number inside the brackets depends
Packit df99a1
	     on the function you call. In most of the cases this is the number
Packit df99a1
	     of the chunk with the given name in the parent chunk. But sometimes
Packit df99a1
	     (as in #addChunk(name, buffer, length)#) the brackets at the
Packit df99a1
	     end of the #name# actually specify the {\em position} of the
Packit df99a1
	     chunk in the parent. For example, to insert #INCL# chunk into
Packit df99a1
	     #DJVU# form at position #1# (make it the second) you may want to
Packit df99a1
	     use #manager.addChunk(".DJVU.INCL[1]", data, size)#. At the same
Packit df99a1
	     time, to get 2-nd chunk with name #BG44# from form #DJVU# you
Packit df99a1
	     should do smth like #chunk=manager.getChunk("BG44[1]")#. Note, that
Packit df99a1
	     here the manager will search for chunk #BG44# in form #DJVU# and
Packit df99a1
	     will take the second {\em found} one.
Packit df99a1
    \end{itemize} */
Packit df99a1
Packit df99a1
class GIFFManager : public GPEnabled
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
   GIFFManager(void);
Packit df99a1
   void init(void);
Packit df99a1
   void init(const GUTF8String &name);
Packit df99a1
public:
Packit df99a1
      /// Default creator.
Packit df99a1
   static GP<GIFFManager> create(void);
Packit df99a1
Packit df99a1
      /** Creates the {\Ref GIFFManager} and assigns name {\em name} to
Packit df99a1
	  the top-level chunk. you may use chunk type names (before colon)
Packit df99a1
	  to set the top-level chunk type, or omit it to work with #FORM# */
Packit df99a1
   static GP<GIFFManager> create(const GUTF8String &name);
Packit df99a1
Packit df99a1
      /// Virtual destructor.
Packit df99a1
   virtual ~GIFFManager(void);
Packit df99a1
Packit df99a1
      /// Sets the name of the top level chunk to {\em name}
Packit df99a1
   void		set_name(const GUTF8String &name);
Packit df99a1
      /** Adds the chunk {\em chunk} to chunk with name {\em parent_name} at
Packit df99a1
	  position {\em pos}. {\em parent_name} may contain dots, brackets
Packit df99a1
	  and colons. All missing chunks in the chain will be created.
Packit df99a1
Packit df99a1
	  {\bf Examples:}
Packit df99a1
	  \begin{verbatim}
Packit df99a1
	     ;; To set the top-level chunk to 'ch'
Packit df99a1
	     m.addChunk(".", ch);
Packit df99a1
	     ;; To add 'ch' to the top-level chunk "DJVU" creating it if necessary
Packit df99a1
	     m.addChunk(".DJVU", ch);
Packit df99a1
	     ;; Same as above regardless of top-level chunk name
Packit df99a1
	     m.addChunk("", ch);
Packit df99a1
	     ;; To add 'ch' to 2nd FORM DJVU in top-level form DJVM
Packit df99a1
	     m.addChunk(".FORM:DJVM.FORM:DJVU[1]", ch);
Packit df99a1
	     ;; Same thing regardless of the top-level chunk name
Packit df99a1
	     m.addChunk("FORM:DJVU[1]", ch);
Packit df99a1
	  \end{verbatim} */
Packit df99a1
   void		add_chunk(GUTF8String parent_name, const GP<GIFFChunk> & chunk, int pos=-1);
Packit df99a1
      /** If {\em name}={\em name1}.{\em name2} where {\em name2} doesn't
Packit df99a1
	  contain dots, then #addChunk()# will create plain chunk with
Packit df99a1
	  name {\em name2} with data {\em buffer} of size {\em length} and
Packit df99a1
	  will add it to chunk {\em name1} in the same way as
Packit df99a1
	  #addChunk(name, chunk, pos)# function would do it. The #pos# in
Packit df99a1
	  this case is either #-1# (append) or is extracted from between
Packit df99a1
          brackets if the {\em name} ends with them.
Packit df99a1
	  
Packit df99a1
          {\bf Examples:}
Packit df99a1
          \begin{verbatim}
Packit df99a1
             ;; To insert INCL chunk at position 2 (make it 3rd)
Packit df99a1
             m.addChunk("INCL[2]", data, length);
Packit df99a1
             ;; To append chunk BG44 to 2nd DjVu file inside DjVm archive:
Packit df99a1
             m.addChunk(".DJVM.DJVU[1].BG44", data, length);
Packit df99a1
          \end{verbatim} */
Packit df99a1
   void		add_chunk(GUTF8String name, const TArray<char> & data);
Packit df99a1
      /** Will remove chunk with name {\em name}. You may use dots, colons
Packit df99a1
	  and brackets to specify the chunk uniquely.
Packit df99a1
Packit df99a1
	  {\bf Examples:}
Packit df99a1
	  \begin{verbatim}
Packit df99a1
	     ;; To remove 2nd DjVu document from DjVm archive use
Packit df99a1
	     m.delChunk(".DJVM.DJVU[1]");
Packit df99a1
	     ;; Same thing without top-level chunk name specification
Packit df99a1
	     m.delChunk("DJVU[1]");
Packit df99a1
	     ;; Same thing for the first DJVU chunk
Packit df99a1
	     m.delChunk("DJVU");
Packit df99a1
	  \end{verbatim}
Packit df99a1
      */
Packit df99a1
   void		del_chunk(GUTF8String name);
Packit df99a1
   void		del_chunk(void);
Packit df99a1
      /** Will return the number of chunks with given name. The {\em name} may
Packit df99a1
	  not end with brackets, but may contain them inside. It may also
Packit df99a1
	  contain dots and colons. If {\em name} is ZERO, the total number
Packit df99a1
	  of chunks will be returned.
Packit df99a1
Packit df99a1
	  {\bf Examples:}
Packit df99a1
	  \begin{verbatim}
Packit df99a1
	     ;; To get the number of DJVU forms inside DjVm document
Packit df99a1
	     m.getChunksNumber(".DJVM.DJVU");
Packit df99a1
	     ;; Same thing without top-level chunk name specification
Packit df99a1
	     m.getChunksNumber("DJVU");
Packit df99a1
	  \end{verbatim}
Packit df99a1
      */
Packit df99a1
   int		get_chunks_number(const GUTF8String &name);
Packit df99a1
   int		get_chunks_number(void);
Packit df99a1
Packit df99a1
      /** Returns the chunk with name {\em name}. The {\em name} may contain dots
Packit df99a1
	  colons and slashes. If {\em position} is not zero, #*position# will
Packit df99a1
	  be assigned the position of the found chunk in the parent chunk.
Packit df99a1
Packit df99a1
	  {\bf Examples:}
Packit df99a1
	  \begin{verbatim}
Packit df99a1
	     ;; To get the directory chunk of DjVm document
Packit df99a1
	     m.getChunk(".DJVM.DIR0");
Packit df99a1
	     ;; To get chunk corresponding to 2nd DJVU form
Packit df99a1
	     m.getChunk(".DJVU[1]");
Packit df99a1
	  \end{verbatim} */
Packit df99a1
   GP<GIFFChunk>get_chunk(GUTF8String name, int * position=0);
Packit df99a1
Packit df99a1
      /** Loads the composite {\em chunk}'s contents from stream {\em istr}. */
Packit df99a1
   void		load_chunk(IFFByteStream & istr, GP<GIFFChunk> chunk);
Packit df99a1
      /** Loads the file contents from stream {\em str} */
Packit df99a1
   void		load_file(GP<ByteStream> str);
Packit df99a1
      /** Loads the file contents from the data array {\em data} */
Packit df99a1
   void		load_file(const TArray<char> & data);
Packit df99a1
      /** Saves all the chunks into stream {\em str} */
Packit df99a1
   void		save_file(GP<ByteStream> str);
Packit df99a1
      /** Saves all the chunks into the data array {\em data} */
Packit df99a1
   void		save_file(TArray<char> & data);
Packit df99a1
Packit df99a1
private:
Packit df99a1
   GP<GIFFChunk>	top_level;
Packit df99a1
Packit df99a1
   static const char *	check_leading_dot(const GUTF8String &name);
Packit df99a1
private: //dummy methods
Packit df99a1
   static void save_file(ByteStream *);
Packit df99a1
   static void load_file(ByteStream *);
Packit df99a1
};
Packit df99a1
Packit df99a1
inline void
Packit df99a1
GIFFManager::set_name(const GUTF8String &name)
Packit df99a1
{
Packit df99a1
   top_level->set_name(name);
Packit df99a1
}
Packit df99a1
Packit df99a1
inline
Packit df99a1
GIFFManager::GIFFManager(void) {}
Packit df99a1
Packit df99a1
inline  void
Packit df99a1
GIFFManager::init(void)
Packit df99a1
{
Packit df99a1
  top_level=GIFFChunk::create();
Packit df99a1
}
Packit df99a1
Packit df99a1
inline  void
Packit df99a1
GIFFManager::init(const GUTF8String &name)
Packit df99a1
{
Packit df99a1
  top_level=GIFFChunk::create(name);
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
#endif