source: trunk/libdjvu/DjVuPort.h @ 280

Last change on this file since 280 was 280, checked in by rbri, 11 years ago

DJVU plugin: djvulibre updated to version 3.5.22

File size: 23.3 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: DjVuPort.h,v 1.11 2007/07/14 01:21:56 leonb Exp $
57// $Name: release_3_5_22 $
58
59#ifndef _DJVUPORT_H
60#define _DJVUPORT_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 "GThreads.h"
70#include "GURL.h"
71
72#ifdef HAVE_NAMESPACES
73namespace DJVU {
74# ifdef NOT_DEFINED // Just to fool emacs c++ mode
75}
76#endif
77#endif
78
79class DataPool;
80
81/** @name DjVuPort.h
82    Files #"DjVuPort.h"# and #"DjVuPort.cpp"# implement a communication
83    mechanism between different parties involved in decoding DjVu files.
84    It should be pretty clear that the creator of \Ref{DjVuDocument} and
85    \Ref{DjVuFile} would like to receive some information about the progress
86    of decoding, errors occurred, etc. It may also want to provide source data
87    for decoders (like it's done in the plugin where the real data is downloaded
88    from the net and is fed into DjVu decoders).
89
90    Normally this functionality is implemented by means of callbacks which are
91    run when a given condition comes true. Unfortunately it's not quite easy
92    to implement this strategy in our case. The reason is that there may be
93    more than one "client" working with the same document, and the document
94    should send the information to each of the clients. This could be done by
95    means of callback {\em lists}, of course, but we want to achieve more
96    bulletproof results: we want to be sure that the client that we're about
97    to contact is still alive, and is not being destroyed by another thread.
98    Besides, we are going to call these "callbacks" from many places, from
99    many different classes.  Maintaining multi-thread safe callback lists is
100    very difficult.
101
102    Finally, we want to provide some default implementation of these
103    "callbacks" in the library, which should attempt to process the requests
104    themselves if they can, and contact the client only if they're unable to
105    do it (like in the case of \Ref{DjVuPort::request_data}() with local URL
106    where \Ref{DjVuDocument} can get the data from the hard drive itself not
107    disturbing the document's creator.
108
109    Two classes implement a general communication mechanism: \Ref{DjVuPort} and
110    \Ref{DjVuPortcaster}. Any sender and recipient of requests should be a
111    subclass of \Ref{DjVuPort}.  \Ref{DjVuPortcaster} maintains a map of
112    routes between \Ref{DjVuPort}s, which should be configured by somebody
113    else. Whenever a port wants to send a request, it calls the corresponding
114    function of \Ref{DjVuPortcaster}, and the portcaster relays the request to
115    all the destinations that it sees in the internal map.
116
117    The \Ref{DjVuPortcaster} is responsible for keeping the map up to date by
118    getting rid of destinations that have been destroyed.  Map updates are
119    performed from a single place and are serialized by a global monitor.
120   
121    @memo DjVu decoder communication mechanism.
122    @author Andrei Erofeev <eaf@geocities.com>\\
123            L\'eon Bottou <leonb@research.att.com>
124    @version #$Id: DjVuPort.h,v 1.11 2007/07/14 01:21:56 leonb Exp $# */
125//@{
126
127class DjVuPort;
128class DjVuPortcaster;
129class DjVuFile;
130
131/** Base class for notification targets.
132    #DjVuPort# provides base functionality for classes willing to take part in
133    sending and receiving messages generated during decoding process.  You
134    need to derive your class from #DjVuPort# if you want it to be able to
135    send or receive requests. In addition, for receiving requests you should
136    override one or more virtual function.
137
138    {\bf Important remark} --- All ports should be allocated on the heap using
139    #operator new# and immediately secured using a \Ref{GP} smart pointer.
140    Ports which are not secured by a smart-pointer are not considered
141    ``alive'' and never receive notifications! */
142
143class DJVUAPI DjVuPort : public GPEnabled
144{
145public:
146   DjVuPort();
147   virtual ~DjVuPort();
148   static void *operator new (size_t sz);
149   static void operator delete(void *addr);
150
151      /**  Use this function to get a copy of the global \Ref{DjVuPortcaster}. */
152   static DjVuPortcaster *get_portcaster(void);
153
154      /** Copy constructor. When #DjVuPort#s are copied, the portcaster
155          copies all incoming and outgoing routes of the original. */
156   DjVuPort(const DjVuPort & port);
157
158      /** Copy operator. Similarly to the copy constructor, the portcaster
159          copies all incoming and outgoing coming routes of the original. */
160   DjVuPort & operator=(const DjVuPort & port);
161
162      /** Should return 1 if the called class inherits class #class_name#.
163          When a destination receives a request, it can retrieve the pointer
164          to the source #DjVuPort#. This virtual function should be able
165          to help to identify the source of the request. For example,
166          \Ref{DjVuFile} is also derived from #DjVuPort#. In order for
167          the receiver to recognize the sender, the \Ref{DjVuFile} should
168          override this function to return #TRUE# when the #class_name#
169          is either #DjVuPort# or #DjVuFile# */
170   virtual bool         inherits(const GUTF8String &class_name) const;
171
172      /** @name Notifications.
173          These virtual functions may be overridden by the subclasses
174          of #DjVuPort#.  They are called by the \Ref{DjVuPortcaster}
175          when the port is alive and when there is a route between the
176          source of the notification and this port. */
177      //@{
178
179      /** This request is issued to request translation of the ID, used
180          in an DjVu INCL chunk to a URL, which may be used to request
181          data associated with included file. \Ref{DjVuDocument} usually
182          intercepts all such requests, and the user doesn't have to
183          worry about the translation */
184   virtual GURL         id_to_url(const DjVuPort * source, const GUTF8String &id);
185
186      /** This request is used to get a file corresponding to the
187          given ID. \Ref{DjVuDocument} is supposed to intercept it
188          and either create a new instance of \Ref{DjVuFile} or reuse
189          an existing one from the cache. */
190   virtual GP<DjVuFile> id_to_file(const DjVuPort * source, const GUTF8String &id);
191
192      /** This request is issued when decoder needs additional data
193          for decoding.  Both \Ref{DjVuFile} and \Ref{DjVuDocument} are
194          initialized with a URL, not the document data.  As soon as
195          they need the data, they call this function, whose responsibility
196          is to locate the source of the data basing on the #URL# passed
197          and return it back in the form of the \Ref{DataPool}. If this
198          particular receiver is unable to fullfil the request, it should
199          return #0#. */
200   virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url);
201
202      /** This notification is sent when an error occurs and the error message
203          should be shown to the user.  The receiver should return #0# if it is
204          unable to process the request. Otherwise the receiver should return 1. */
205   virtual bool         notify_error(const DjVuPort * source, const GUTF8String &msg);
206
207      /** This notification is sent to update the decoding status.  The
208          receiver should return #0# if it is unable to process the
209          request. Otherwise the receiver should return 1. */
210   virtual bool         notify_status(const DjVuPort * source, const GUTF8String &msg);
211
212      /** This notification is sent by \Ref{DjVuImage} when it should be
213          redrawn. It may be used to implement progressive redisplay.
214
215          @param source The sender of the request */
216   virtual void         notify_redisplay(const class DjVuImage * source);
217
218      /** This notification is sent by \ref{DjVuImage} when its geometry
219          has been changed as a result of decoding. It may be used to
220          implement progressive redisplay. */
221   virtual void         notify_relayout(const class DjVuImage * source);
222
223      /** This notification is sent when a new chunk has been decoded. */
224   virtual void         notify_chunk_done(const DjVuPort * source, const GUTF8String &name);
225
226      /** This notification is sent after the \Ref{DjVuFile} flags have
227          been changed. This happens, for example, when:
228          \begin{itemize}
229            \item Decoding succeeded, failed or just stopped
230            \item All data has been received
231            \item All included files have been created
232          \end{itemize}
233         
234          @param source \Ref{DjVuFile}, which flags have been changed
235          @param set_mask bits, which have been set
236          @param clr_mask bits, which have been cleared */
237   virtual void         notify_file_flags_changed(const class DjVuFile * source,
238                                                  long set_mask, long clr_mask);
239
240      /** This notification is sent after the \Ref{DjVuDocument} flags have
241          been changed. This happens, for example, after it receives enough
242          data and can determine its structure (#BUNDLED#, #OLD_INDEXED#, etc.).
243
244          @param source \Ref{DjVuDocument}, which flags have been changed
245          @param set_mask bits, which have been set
246          @param clr_mask bits, which have been cleared */
247   virtual void         notify_doc_flags_changed(const class DjVuDocument * source,
248                                                 long set_mask, long clr_mask);
249   
250      /** This notification is sent from time to time while decoding is in
251          progress. The purpose is obvious: to provide a way to know how much
252          is done and how long the decoding will continue.  Argument #done# is
253          a number from 0 to 1 reflecting the progress. */
254   virtual void         notify_decode_progress(const DjVuPort * source, float done);
255
256      /** This is the standard types for defining what to do in case of errors.
257          This is only used by some of the subclasses, but it needs to be
258          defined here to guarantee all subclasses use the same enum types.
259          In general, many errors are non recoverable.  Using a setting
260          other than ABORT may just result in even more errors. */
261   enum ErrorRecoveryAction {ABORT=0,SKIP_PAGES=1,SKIP_CHUNKS=2,KEEP_ALL=3 }; 
262      //@}
263public:
264   class DjVuPortCorpse;
265private:
266   static GCriticalSection      * corpse_lock;
267   static DjVuPortCorpse        * corpse_head;
268   static DjVuPortCorpse        * corpse_tail;
269   static int                   corpse_num;
270};
271
272/** Simple port. 
273    An instance of #DjVuSimplePort# is automatically created when you create a
274    \Ref{DjVuFile} or a \Ref{DjVuDocument} without specifying a port.  This
275    simple port can retrieve data for local urls (i.e. urls referring to local
276    files) and display error messages on #stderr#.  All other notifications
277    are ignored. */
278
279class DJVUAPI DjVuSimplePort : public DjVuPort
280{
281public:
282      /// Returns 1 if #class_name# is #"DjVuPort"# or #"DjVuSimplePort"#.
283   virtual bool         inherits(const GUTF8String &class_name) const;
284
285      /** If #url# is local, it created a \Ref{DataPool}, connects it to the
286          file with the given name and returns.  Otherwise returns #0#. */
287   virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url);
288
289      /// Displays error on #stderr#. Always returns 1.
290   virtual bool         notify_error(const DjVuPort * source, const GUTF8String &msg);
291   
292      /// Displays status on #stderr#. Always returns 1.
293   virtual bool         notify_status(const DjVuPort * source, const GUTF8String &msg);
294};
295
296
297/** Memory based port.
298    This \Ref{DjVuPort} maintains a map associating pseudo urls with data
299    segments.  It processes the #request_data# notifications according to this
300    map.  After initializing the port, you should add as many pairs #<url,
301    pool># as needed need and add a route from a \Ref{DjVuDocument} or
302    \Ref{DjVuFile} to this port. */
303
304class DJVUAPI DjVuMemoryPort : public DjVuPort
305{
306public:
307      /// Returns 1 if #class_name# is #"DjVuPort"# or #"DjVuMemoryPort"#
308   virtual bool         inherits(const GUTF8String &class_name) const;
309
310      /** If #url# is one of those, that have been added before by means
311          of \Ref{add_data}() function, it will return the associated
312          \Ref{DataPool}. #ZERO# otherwize. */
313   virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url);
314
315      /** Adds #<url, pool># pair to the internal map. From now on, if
316          somebody asks for data corresponding to the #url#, it will
317          be returning the #pool# */
318   void         add_data(const GURL & url, const GP<DataPool> & pool);
319private:
320   GCriticalSection     lock;
321   GPMap<GURL, DataPool>map;
322};
323
324
325
326/** Maintains associations between ports.
327    It monitors the status of all ports (have they been destructed yet?),
328    accepts requests and notifications from them and forwards them to
329    destinations according to internally maintained map of routes.
330
331    The caller can modify the route map any way he likes (see
332    \Ref{add_route}(), \Ref{del_route}(), \Ref{copy_routes}(),
333    etc. functions). Any port can be either a sender of a message, an
334    intermediary receiver or a final destination. 
335
336    When a request is sent, the #DjVuPortcaster# computes the list of
337    destinations by consulting with the route map.  Notifications are only
338    sent to ``alive'' ports.  A port is alive if it is referenced by a valid
339    \Ref{GP} smartpointer.  As a consequence, a port usually becomes alive
340    after running the constructor (since the returned pointer is then assigned
341    to a smartpointer) and is no longer alive when the port is destroyed
342    (because it would not be destroyed if a smartpointer was referencing it).
343
344    Destination ports are sorted according to their distance from the source.
345    For example, if port {\bf A} is connected to ports {\bf B} and {\bf C}
346    directly, and port {\bf B} is connected to {\bf D}, then {\bf B} and {\bf
347    C} are assumed to be one hop away from {\bf A}, while {\bf D} is two hops
348    away from {\bf A}.
349
350    In some cases the requests and notifications are sent to every possible
351    destination, and the order is not significant (like it is for
352    \Ref{notify_file_flags_changed}() request). Others should be sent to the closest
353    destinations first, and only then to the farthest, in case if they have
354    not been processed by the closest. The examples are \Ref{request_data}(),
355    \Ref{notify_error}() and \Ref{notify_status}().
356
357    The user is not expected to create the #DjVuPortcaster# itself. He should
358    use \Ref{get_portcaster}() global function instead.  */
359class DJVUAPI DjVuPortcaster
360{
361public:
362      /**  Use this function to get a copy of the global \Ref{DjVuPortcaster}. */
363   static DjVuPortcaster *get_portcaster(void)
364    { return DjVuPort::get_portcaster(); } ;
365
366      /** The default constructor. */
367   DjVuPortcaster(void);
368
369   virtual ~DjVuPortcaster(void);
370
371      /** Removes the specified port from all routes. It will no longer
372          be able to receive or generate messages and will be considered
373    {\bf "dead"} by \Ref{is_port_alive}() function. */
374   void         del_port(const DjVuPort * port);
375   
376      /** Adds route from #src# to #dst#. Whenever a request is
377          sent or received by #src#, it will be forwarded to #dst# as well.
378          @param src The source
379          @param dst The destination */
380   void         add_route(const DjVuPort *src, DjVuPort *dst);
381
382      /** The opposite of \Ref{add_route}(). Removes the association
383          between #src# and #dst# */
384   void         del_route(const DjVuPort *src, DjVuPort *dst);
385
386      /** Copies all incoming and outgoing routes from #src# to
387          #dst#. This function should be called when a \Ref{DjVuPort} is
388          copied, if you want to preserve the connectivity. */
389   void         copy_routes(DjVuPort *dst, const DjVuPort *src);
390
391      /** Returns a smart pointer to the port if #port# is a valid pointer
392          to an existing #DjVuPort#.  Returns a null pointer otherwise. */
393   GP<DjVuPort> is_port_alive(DjVuPort *port);
394
395      /** Assigns one more {\em alias} for the specified \Ref{DjVuPort}.
396          {\em Aliases} are names, which can be used later to retrieve this
397          \Ref{DjVuPort}, if it still exists. Any \Ref{DjVuPort} may have
398          more than one {\em alias}. But every {\em alias} must correspond
399          to only one \Ref{DjVuPort}. Thus, if the specified alias is
400          already associated with another port, this association will be
401          removed. */
402   void         add_alias(const DjVuPort * port, const GUTF8String &alias);
403
404      /** Removes all the aliases */
405   static void          clear_all_aliases(void);
406
407      /** Removes all aliases associated with the given \Ref{DjVuPort}. */
408   void         clear_aliases(const DjVuPort * port);
409
410      /** Returns \Ref{DjVuPort} associated with the given #alias#. If nothing
411          is known about name #alias#, or the port associated with it has
412          already been destroyed #ZERO# pointer will be returned. */
413   GP<DjVuPort> alias_to_port(const GUTF8String &name);
414
415      /** Returns a list of \Ref{DjVuPort}s with aliases starting with
416          #prefix#. If no \Ref{DjVuPort}s have been found, empty
417          list is returned. */
418   GPList<DjVuPort>     prefix_to_ports(const GUTF8String &prefix);
419
420      /** Computes destination list for #source# and calls the corresponding
421          function in each of the ports from the destination list starting from
422          the closest until one of them returns non-empty \Ref{GURL}. */
423   virtual GURL         id_to_url(const DjVuPort * source, const GUTF8String &id);
424
425      /** Computes destination list for #source# and calls the corresponding
426          function in each of the ports from the destination list starting from
427          the closest until one of them returns non-zero pointer to
428          \Ref{DjVuFile}. */
429   virtual GP<DjVuFile> id_to_file(const DjVuPort * source, const GUTF8String &id);
430
431      /** Computes destination list for #source# and calls the corresponding
432          function in each of the ports from the destination list starting from
433          the closest until one of them returns non-zero \Ref{DataPool}. */
434   virtual GP<DataPool> request_data(const DjVuPort * source, const GURL & url);
435
436      /** Computes destination list for #source# and calls the corresponding.
437          function in each of the ports from the destination starting from
438          the closest until one of them returns 1. */
439   virtual bool         notify_error(const DjVuPort * source, const GUTF8String &msg);
440
441      /** Computes destination list for #source# and calls the corresponding
442          function in each of the ports from the destination list starting from
443          the closest until one of them returns 1. */
444   virtual bool         notify_status(const DjVuPort * source, const GUTF8String &msg);
445
446      /** Computes destination list for #source# and calls the corresponding
447          function in each of the ports from the destination list starting from
448          the closest. */
449   virtual void         notify_redisplay(const class DjVuImage * source);
450
451      /** Computes destination list for #source# and calls the corresponding
452          function in each of the ports from the destination list starting from
453          the closest. */
454   virtual void         notify_relayout(const class DjVuImage * source);
455
456      /** Computes destination list for #source# and calls the corresponding
457          function in each of the ports from the destination list starting from
458          the closest. */
459   virtual void         notify_chunk_done(const DjVuPort * source, const GUTF8String &name);
460
461      /** Computes destination list for #source# and calls the corresponding
462          function in each of the ports from the destination list starting from
463          the closest. */
464   virtual void         notify_file_flags_changed(const class DjVuFile * source,
465                                                  long set_mask, long clr_mask);
466
467      /** Computes destination list for #source# and calls the corresponding
468          function in each of the ports from the destination list starting from
469          the closest. */
470   virtual void         notify_doc_flags_changed(const class DjVuDocument * source,
471                                                 long set_mask, long clr_mask);
472   
473      /** Computes destination list for #source# and calls the corresponding
474          function in each of the ports from the destination list starting from
475          the closest. */
476   virtual void         notify_decode_progress(const DjVuPort * source, float done);
477
478private:
479      // We use these 'void *' to minimize template instantiations.
480   friend class DjVuPort;
481   GCriticalSection             map_lock;
482   GMap<const void *, void *>   route_map;      // GMap<DjVuPort *, GList<DjVuPort *> *>
483   GMap<const void *, void *>   cont_map;       // GMap<DjVuPort *, DjVuPort *>
484   GMap<GUTF8String, const void *>      a2p_map;        // GMap<GUTF8String, DjVuPort *>
485   void add_to_closure(GMap<const void*, void*> & set,
486                       const DjVuPort *dst, int distance);
487   void compute_closure(const DjVuPort *src, GPList<DjVuPort> &list,
488                        bool sorted=false);
489};
490
491
492inline bool
493DjVuPort::inherits(const GUTF8String &class_name) const
494{
495   return (class_name == "DjVuPort");
496}
497
498inline bool
499DjVuSimplePort::inherits(const GUTF8String &class_name) const
500{
501   return
502      (class_name == "DjVuSimplePort") || DjVuPort::inherits(class_name);
503}
504
505inline bool
506DjVuMemoryPort::inherits(const GUTF8String &class_name) const
507{
508   return
509      (class_name == "DjVuMemoryPort") || DjVuPort::inherits(class_name);
510}
511
512//@}
513
514
515#ifdef HAVE_NAMESPACES
516}
517# ifndef NOT_USING_DJVU_NAMESPACE
518using namespace DJVU;
519# endif
520#endif
521#endif
Note: See TracBrowser for help on using the repository browser.