source: trunk/libdjvu/GIFFManager.h @ 209

Last change on this file since 209 was 206, checked in by Eugene Romanenko, 14 years ago

DJVU plugin: djvulibre updated to version 3.5.19

File size: 15.5 KB
Line 
1//C-  -*- C++ -*-
2//C- -------------------------------------------------------------------
3//C- DjVuLibre-3.5
4//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5//C- Copyright (c) 2001  AT&T
6//C-
7//C- This software is subject to, and may be distributed under, the
8//C- GNU General Public License, either Version 2 of the license,
9//C- or (at your option) any later version. The license should have
10//C- accompanied the software or you may obtain a copy of the license
11//C- from the Free Software Foundation at http://www.fsf.org .
12//C-
13//C- This program is distributed in the hope that it will be useful,
14//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16//C- GNU General Public License for more details.
17//C-
18//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19//C- Lizardtech Software.  Lizardtech Software has authorized us to
20//C- replace the original DjVu(r) Reference Library notice by the following
21//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22//C-
23//C-  ------------------------------------------------------------------
24//C- | DjVu (r) Reference Library (v. 3.5)
25//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26//C- | The DjVu Reference Library is protected by U.S. Pat. No.
27//C- | 6,058,214 and patents pending.
28//C- |
29//C- | This software is subject to, and may be distributed under, the
30//C- | GNU General Public License, either Version 2 of the license,
31//C- | or (at your option) any later version. The license should have
32//C- | accompanied the software or you may obtain a copy of the license
33//C- | from the Free Software Foundation at http://www.fsf.org .
34//C- |
35//C- | The computer code originally released by LizardTech under this
36//C- | license and unmodified by other parties is deemed "the LIZARDTECH
37//C- | ORIGINAL CODE."  Subject to any third party intellectual property
38//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39//C- | non-exclusive license to make, use, sell, or otherwise dispose of
40//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42//C- | General Public License.   This grant only confers the right to
43//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44//C- | the extent such infringement is reasonably necessary to enable
45//C- | recipient to make, have made, practice, sell, or otherwise dispose
46//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47//C- | any greater extent that may be necessary to utilize further
48//C- | modifications or combinations.
49//C- |
50//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54//C- +------------------------------------------------------------------
55//
56// $Id: GIFFManager.h,v 1.9 2007/03/25 20:48:31 leonb Exp $
57// $Name: release_3_5_19 $
58
59#ifndef _GIFFMANAGER_H
60#define _GIFFMANAGER_H
61#ifdef HAVE_CONFIG_H
62#include "config.h"
63#endif
64#if NEED_GNUG_PRAGMAS
65# pragma interface
66#endif
67
68
69#include "IFFByteStream.h"
70#include "GContainer.h"
71#include "Arrays.h"
72#include "GSmartPointer.h"
73#include "GString.h"
74
75#ifdef HAVE_NAMESPACES
76namespace DJVU {
77# ifdef NOT_DEFINED // Just to fool emacs c++ mode
78}
79#endif
80#endif
81
82
83/** @name GIFFManager.h
84
85    Files #"GIFFManager.h"# and #"GIFFManager.cpp"# define more convenient
86    interface to IFF files. You may want to use the {\Ref GIFFManager} class
87    instead of coping with {\Ref IFFByteStream} especially when you have to
88    insert or move chunks, which is a kind of tricky with sequential access
89    provided by {\Ref IFFByteStream}.
90
91    You will mostly deal with {\Ref GIFFManager} class, but sometimes you may
92    want to use {\Ref GIFFChunk}s as well thus bypassing {\Ref GIFFManager}'s
93    interface and working with the chunks hierarchy yourself.
94   
95    Interface to IFF files.
96    @author
97    Andrei Erofeev <eaf@geocities.com> -- Initial implementation.
98    @version
99    #$Id: GIFFManager.h,v 1.9 2007/03/25 20:48:31 leonb Exp $# */
100
101/** #GIFFChunk# is the base class for other IFF chunks understood by
102    {\Ref GIFFManager}. It provides some basic interface, and is not supposed
103    to be used on its own. */
104
105class GIFFChunk : public GPEnabled
106{
107protected:
108   GIFFChunk(void);
109   GIFFChunk(const GUTF8String &name);
110   GIFFChunk(const GUTF8String &name, const TArray<char> & data);
111public:
112      /// Default creator.
113   static GP<GIFFChunk> create(void) {return new GIFFChunk();}
114
115      /** Creates the chunk with the given name. The {\em name} may not
116          contain dots colons or brackets */
117   static GP<GIFFChunk> create(const GUTF8String &name)
118   {return new GIFFChunk(name);}
119
120      /** Creates the {\em plain chunk} containing raw data */
121   static GP<GIFFChunk> create(const GUTF8String &name, const TArray<char> & data)
122   { return new GIFFChunk(name,data); }
123
124      /// Destructor
125   virtual ~GIFFChunk(void);
126
127      /// Returns the name of the chunk (without possible #FORM:# or similar prefixes)
128   GUTF8String  get_name(void) const;
129      /// Returns full chunk name, with possible container specification
130   GUTF8String  get_full_name(void) const;
131      /// Returns the chunk type, like #CAT# for chunk #CAT:DJVU#
132   GUTF8String  get_type(void) const;
133      /// Returns TRUE if the chunk may contain other chunks or FALSE otherwise
134   bool         is_container(void) const;
135      /** Sets the chunk name. The {\em name} may not contain dots or brackets,
136          but {\bf may} contain colons. */
137   void         set_name(GUTF8String name);
138      /** Parses the {\em name} probably containing colon and compares it
139          with its own name returning TRUE if they are the same */
140   bool         check_name(GUTF8String name);
141
142      /** Adds the {\em chunk} to the chunks list at position {\em order}.
143          Set {\em order} to #-1# to append the chunk to the list.
144          {\bf Note!} By adding chunk #PROP# you will convert this chunk
145          to type #LIST# {\em automatically}. */
146   void         add_chunk(const GP<GIFFChunk> & chunk, int order=-1);
147      /** Removes the chunk with given {\em name}. The {\em name} may not
148          contain dots, but MAY contain colons and brackets (the latter -
149          for specifying the chunk number) */
150   void         del_chunk(const GUTF8String &name);
151      /** Returns the chunk with given {\em name}. The {\em name} may not
152          contain dots, but MAY contain colons and brackets (the latter -
153          for specifying the chunk number). If {\em position} is not zero
154          then the chunk position in its parent will be put into #*position# */
155   GP<GIFFChunk>get_chunk(const GUTF8String &name, int * position=0);
156      /** Returns the number of chunks with given {\em name}. The {\em name}
157          may not contain dots and brackets. If {\em name} is ZERO, the
158          total number of chunks will be returned. */
159   int          get_chunks_number(const GUTF8String &name);
160   int          get_chunks_number(void);
161      /** Returns the data array for plain chunks */
162   TArray<char> get_data(void) const;
163   
164      /** Saves the chunk into the {\Ref IFFByteStream}.
165          Set {\em use_trick} to #1# if this is a top-level chunk */
166   void         save(IFFByteStream & istr, bool use_trick=0);
167private:
168   char                 name[5];
169   GUTF8String          type;
170   GPList<GIFFChunk>    chunks;
171   TArray<char>         data;
172   static GUTF8String decode_name(const GUTF8String &name, int &number);
173};
174
175inline GUTF8String
176GIFFChunk::get_name(void) const { return GUTF8String(name, 4); }
177
178inline GUTF8String
179GIFFChunk::get_type(void) const { return type; };
180
181inline GUTF8String
182GIFFChunk::get_full_name(void) const { return get_type()+":"+get_name(); };
183
184inline bool
185GIFFChunk::is_container(void) const { return type.length()!=0; };
186
187inline TArray<char>
188GIFFChunk::get_data(void) const { return data; };
189
190inline
191GIFFChunk::GIFFChunk(void) { name[0]=0; }
192
193inline
194GIFFChunk::GIFFChunk(const GUTF8String &name) { set_name(name); }
195
196inline
197GIFFChunk::GIFFChunk(const GUTF8String &name, const TArray<char> & data_in) :
198      data(data_in)
199{
200   set_name(name);
201}
202
203//************************************************************************
204
205/** Intuitive interface to IFF files.
206
207    It's too terrible to keep reading/writing IFF files chunk after chunk
208    using {\Ref IFFByteStream}s. This class allows you to operate with chunks
209    as with structures or arrays without even caring about the byte streams.
210
211    Some of the examples are below:
212    \begin{verbatim}
213       GP<GIFFChunk> chunk;
214       chunk=manager1.get_chunk("BG44[2]");
215       manager2.add_chunk(".FORM:DJVU.BG44[-1]", chunk);
216    \end{verbatim}
217
218    {\bf Chunk name}
219    \begin{itemize}
220       \item Every chunk name may contain optional prefix #FORM:#, #LIST:#,
221             #PROP:# or #CAT:#. If the prefix is omitted and the chunk happens
222             to contain other chunks, #FORM:# will be assumed.
223       \item Every chunk name may be {\em short} or {\em complete}.
224             {\em short} chunk names may not contain dots as they're a
225             subchunks names with respect to a given chunk.
226             {\em complete} chunk names may contain dots. But there may be
227             or may not be the {\em leading dot} in the name. If the
228             {\em leading dot} is present, then the name is assumed to contain
229             the name of the top-level chunk as well. Otherwise it's treated
230             {\em with respect} to the top-level chunk. You may want to use
231             the leading dot only when you add a chunk to an empty document,
232             since a command like #manager.addChunk(".FORM:DJVU.BG44", chunk)#
233             will create the top level chunk of the requested type (#FORM:DJVU#)
234             and will add chunk #BG44# to it {\em automatically}.
235       \item You may use {\em brackets} in the name to specify the chunk's
236             position. The meaning of the number inside the brackets depends
237             on the function you call. In most of the cases this is the number
238             of the chunk with the given name in the parent chunk. But sometimes
239             (as in #addChunk(name, buffer, length)#) the brackets at the
240             end of the #name# actually specify the {\em position} of the
241             chunk in the parent. For example, to insert #INCL# chunk into
242             #DJVU# form at position #1# (make it the second) you may want to
243             use #manager.addChunk(".DJVU.INCL[1]", data, size)#. At the same
244             time, to get 2-nd chunk with name #BG44# from form #DJVU# you
245             should do smth like #chunk=manager.getChunk("BG44[1]")#. Note, that
246             here the manager will search for chunk #BG44# in form #DJVU# and
247             will take the second {\em found} one.
248    \end{itemize} */
249
250class GIFFManager : public GPEnabled
251{
252protected:
253   GIFFManager(void);
254   void init(void);
255   void init(const GUTF8String &name);
256public:
257      /// Default creator.
258   static GP<GIFFManager> create(void);
259
260      /** Creates the {\Ref GIFFManager} and assigns name {\em name} to
261          the top-level chunk. you may use chunk type names (before colon)
262          to set the top-level chunk type, or omit it to work with #FORM# */
263   static GP<GIFFManager> create(const GUTF8String &name);
264
265      /// Virtual destructor.
266   virtual ~GIFFManager(void);
267
268      /// Sets the name of the top level chunk to {\em name}
269   void         set_name(const GUTF8String &name);
270      /** Adds the chunk {\em chunk} to chunk with name {\em parent_name} at
271          position {\em pos}. {\em parent_name} may contain dots, brackets
272          and colons. All missing chunks in the chain will be created.
273
274          {\bf Examples:}
275          \begin{verbatim}
276             ;; To set the top-level chunk to 'ch'
277             m.addChunk(".", ch);
278             ;; To add 'ch' to the top-level chunk "DJVU" creating it if necessary
279             m.addChunk(".DJVU", ch);
280             ;; Same as above regardless of top-level chunk name
281             m.addChunk("", ch);
282             ;; To add 'ch' to 2nd FORM DJVU in top-level form DJVM
283             m.addChunk(".FORM:DJVM.FORM:DJVU[1]", ch);
284             ;; Same thing regardless of the top-level chunk name
285             m.addChunk("FORM:DJVU[1]", ch);
286          \end{verbatim} */
287   void         add_chunk(GUTF8String parent_name, const GP<GIFFChunk> & chunk, int pos=-1);
288      /** If {\em name}={\em name1}.{\em name2} where {\em name2} doesn't
289          contain dots, then #addChunk()# will create plain chunk with
290          name {\em name2} with data {\em buffer} of size {\em length} and
291          will add it to chunk {\em name1} in the same way as
292          #addChunk(name, chunk, pos)# function would do it. The #pos# in
293          this case is either #-1# (append) or is extracted from between
294          brackets if the {\em name} ends with them.
295         
296          {\bf Examples:}
297          \begin{verbatim}
298             ;; To insert INCL chunk at position 2 (make it 3rd)
299             m.addChunk("INCL[2]", data, length);
300             ;; To append chunk BG44 to 2nd DjVu file inside DjVm archive:
301             m.addChunk(".DJVM.DJVU[1].BG44", data, length);
302          \end{verbatim} */
303   void         add_chunk(GUTF8String name, const TArray<char> & data);
304      /** Will remove chunk with name {\em name}. You may use dots, colons
305          and brackets to specify the chunk uniquely.
306
307          {\bf Examples:}
308          \begin{verbatim}
309             ;; To remove 2nd DjVu document from DjVm archive use
310             m.delChunk(".DJVM.DJVU[1]");
311             ;; Same thing without top-level chunk name specification
312             m.delChunk("DJVU[1]");
313             ;; Same thing for the first DJVU chunk
314             m.delChunk("DJVU");
315          \end{verbatim}
316      */
317   void         del_chunk(GUTF8String name);
318   void         del_chunk(void);
319      /** Will return the number of chunks with given name. The {\em name} may
320          not end with brackets, but may contain them inside. It may also
321          contain dots and colons. If {\em name} is ZERO, the total number
322          of chunks will be returned.
323
324          {\bf Examples:}
325          \begin{verbatim}
326             ;; To get the number of DJVU forms inside DjVm document
327             m.getChunksNumber(".DJVM.DJVU");
328             ;; Same thing without top-level chunk name specification
329             m.getChunksNumber("DJVU");
330          \end{verbatim}
331      */
332   int          get_chunks_number(const GUTF8String &name);
333   int          get_chunks_number(void);
334
335      /** Returns the chunk with name {\em name}. The {\em name} may contain dots
336          colons and slashes. If {\em position} is not zero, #*position# will
337          be assigned the position of the found chunk in the parent chunk.
338
339          {\bf Examples:}
340          \begin{verbatim}
341             ;; To get the directory chunk of DjVm document
342             m.getChunk(".DJVM.DIR0");
343             ;; To get chunk corresponding to 2nd DJVU form
344             m.getChunk(".DJVU[1]");
345          \end{verbatim} */
346   GP<GIFFChunk>get_chunk(GUTF8String name, int * position=0);
347
348      /** Loads the composite {\em chunk}'s contents from stream {\em istr}. */
349   void         load_chunk(IFFByteStream & istr, GP<GIFFChunk> chunk);
350      /** Loads the file contents from stream {\em str} */
351   void         load_file(GP<ByteStream> str);
352      /** Loads the file contents from the data array {\em data} */
353   void         load_file(const TArray<char> & data);
354      /** Saves all the chunks into stream {\em str} */
355   void         save_file(GP<ByteStream> str);
356      /** Saves all the chunks into the data array {\em data} */
357   void         save_file(TArray<char> & data);
358
359private:
360   GP<GIFFChunk>        top_level;
361
362   static const char *  check_leading_dot(const GUTF8String &name);
363private: //dummy methods
364   static void save_file(ByteStream *);
365   static void load_file(ByteStream *);
366};
367
368inline void
369GIFFManager::set_name(const GUTF8String &name)
370{
371   top_level->set_name(name);
372}
373
374inline
375GIFFManager::GIFFManager(void) {}
376
377inline  void
378GIFFManager::init(void)
379{
380  top_level=GIFFChunk::create();
381}
382
383inline  void
384GIFFManager::init(const GUTF8String &name)
385{
386  top_level=GIFFChunk::create(name);
387}
388
389
390#ifdef HAVE_NAMESPACES
391}
392# ifndef NOT_USING_DJVU_NAMESPACE
393using namespace DJVU;
394# endif
395#endif
396#endif
Note: See TracBrowser for help on using the repository browser.